/* sawmill-capplet.c -- embed sawmill-ui in the gnome control center $Id: sawmill-capplet.c,v 1.18 2003/01/12 20:30:41 jsh Exp $ Copyright (C) 1999 John Harper This file is part of sawmill. sawmill is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. sawmill is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sawmill; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* this was initially based on mouse-properties.c */ #ifdef HAVE_CONFIG_H #include #endif #include "../build.h" #include "../src/libclient.h" #include #include #include #ifdef HAVE_UNISTD_H #include #endif #if HAVE_SYS_WAIT_H # include #endif #include #include static GtkWidget *ui_socket; static GtkWidget *capplet; static int ui_pid; static int ui_stdin[2]; static int ui_stdout[2]; static guint ui_handler_id; static char *group; static gboolean no_flatten = FALSE; /* communicating with sawfish-ui */ #define X_IO(op, fd, buf, len) \ char *buf__ = (char *)buf; \ int todo__ = len; \ while(todo__ > 0) { \ int this__ = op (fd, buf__, todo__); \ if(this__ < 0) { \ if (errno != EINTR) \ return -1; \ } \ else if(this__ == 0) \ break; \ else { \ todo__ -= this__; \ buf__ += this__; \ } \ } \ return len - todo__; static int x_write (int fd, void *buf, size_t len) { X_IO (write, fd, buf, len); } static int x_read (int fd, void *buf, size_t len) { X_IO (read, fd, buf, len); } static int ui_command (char *str) { if (ui_pid != 0) { u_char ret; x_write (ui_stdin[1], str, strlen(str)); x_read (ui_stdout[0], &ret, 1); return ret; } else return 0; } static void display_error (const char *message) { GtkWidget *label; if (ui_handler_id != 0) { gtk_input_remove (ui_handler_id); ui_handler_id = 0; } if (ui_pid != 0 && waitpid (ui_pid, 0, WNOHANG) == ui_pid) { ui_pid = 0; } if (ui_socket != 0) { gtk_container_remove (GTK_CONTAINER (capplet), ui_socket); gtk_object_destroy (GTK_OBJECT (ui_socket)); ui_socket = 0; } label = gtk_label_new (_("The applet encountered an error")); gtk_container_add (GTK_CONTAINER (capplet), label); gtk_widget_show (label); } static void ui_output_callback (gpointer data, gint fd, GdkInputCondition cond) { char out; int bytes_read; bytes_read = x_read (ui_stdout[0], &out, 1); if (bytes_read == 1) { switch (out) { case 'c': capplet_widget_state_changed (CAPPLET_WIDGET (capplet), TRUE); break; case 'g': /* group doesn't exist */ display_error (_("That group doesn't exist")); } } else { /* EOF or error of some sort */ display_error (_("The applet encountered an error")); } } /* capplet button callbacks */ static void sawmill_help (void) { } static void sawmill_apply (void) { ui_command("apply\n"); } static void sawmill_revert (void) { ui_command ("revert\n"); } static void sawmill_ok (void) { gtk_container_remove (GTK_CONTAINER (capplet), ui_socket); ui_command ("ok\n"); } static void sawmill_cancel (void) { gtk_container_remove (GTK_CONTAINER (capplet), ui_socket); ui_command ("cancel\n"); } /* initialisation */ /* returns non-zero if sawfish is running */ static gint sawmill_running_p (void) { int ret = client_open (0); /* 0 == $DISPLAY */ if (ret == 0) client_close (); return (ret == 0); } static void sawmill_setup (void) { capplet = capplet_widget_new (); if (!sawmill_running_p ()) { GtkWidget *label = gtk_label_new (_("Sawfish isn't running")); gtk_container_add (GTK_CONTAINER (capplet), label); return; } gtk_signal_connect (GTK_OBJECT (capplet), "help", GTK_SIGNAL_FUNC (sawmill_help), NULL); gtk_signal_connect (GTK_OBJECT (capplet), "try", GTK_SIGNAL_FUNC (sawmill_apply), NULL); gtk_signal_connect (GTK_OBJECT (capplet), "revert", GTK_SIGNAL_FUNC (sawmill_revert), NULL); gtk_signal_connect (GTK_OBJECT (capplet), "ok", GTK_SIGNAL_FUNC (sawmill_ok), NULL); gtk_signal_connect (GTK_OBJECT (capplet), "cancel", GTK_SIGNAL_FUNC (sawmill_cancel), NULL); ui_socket = gtk_socket_new (); gtk_container_add (GTK_CONTAINER (capplet), ui_socket); /* show this here so the widget gets realized */ gtk_widget_show_all (capplet); /* now fork the sawmill-ui script */ pipe (ui_stdin); pipe (ui_stdout); switch (ui_pid = fork ()) { char buf[64]; char *argv[10]; int i; case -1: exit (5); case 0: /* child */ dup2 (ui_stdin[0], 0); dup2 (ui_stdout[1], 1); close (ui_stdin[0]); close (ui_stdin[1]); close (ui_stdout[0]); close (ui_stdout[1]); sprintf (buf, "%ld", (long)GDK_WINDOW_XWINDOW (ui_socket->window)); i = 0; argv[i++] = "sawfish-ui"; if (!no_flatten) argv[i++] = "--flatten"; else argv[i++] = "--single-level"; argv[i++] = "--socket-id"; argv[i++] = buf; if (group != 0) { argv[i++] = "--group"; argv[i++] = group; } argv[i++] = 0; execvp (argv[0], argv); exit (10); default: /* parent */ close (ui_stdin[0]); close (ui_stdout[1]); ui_handler_id = gdk_input_add (ui_stdout[0], GDK_INPUT_READ, (GdkInputFunction) ui_output_callback, 0); } } /* entry point */ int main (int argc, char **argv) { GnomeClient *client = NULL; GnomeClientFlags flags; gchar *session_args[3]; int token, init_results; static struct poptOption options[] = { { "sawmill-group", 0, POPT_ARG_STRING, &group, 0, "Sawfish customization group", "GROUP" }, { "sawfish-group", 0, POPT_ARG_STRING, &group, 0, "Sawfish customization group", "GROUP" }, { "sawfish-no-flatten", 0, POPT_ARG_NONE, &no_flatten, 0, "Don't flatten group trees", 0 }, { 0, 0, 0, 0, 0 } }; #if 0 bindtextdomain (PACKAGE, GNOMELOCALEDIR); textdomain (PACKAGE); #endif init_results = gnome_capplet_init("sawfish-properties", SAWFISH_VERSION, argc, argv, options, 0, NULL); if (init_results < 0) { g_warning ("an initialization error occurred while " "starting 'sawfish-properties-capplet'.\n" "aborting...\n"); exit (1); } client = gnome_master_client (); flags = gnome_client_get_flags(client); #if 0 /* XXX I copied this from mouse-properties.c, but the XXX GNOME_SAWFISH_PROPERTIES root property just grows XXX each time the capplet is started... */ if (flags & GNOME_CLIENT_IS_CONNECTED) { token = gnome_startup_acquire_token("GNOME_SAWFISH_PROPERTIES", gnome_client_get_id(client)); if (token) { session_args[0] = argv[0]; session_args[1] = "--init-session-settings"; session_args[2] = NULL; gnome_client_set_priority (client, 20); gnome_client_set_restart_style (client, GNOME_RESTART_ANYWAY); gnome_client_set_restart_command (client, 2, session_args); } else gnome_client_set_restart_style (client, GNOME_RESTART_NEVER); gnome_client_flush (client); } else token = 1; #endif if (init_results != 1) { sawmill_setup (); gtk_widget_show_all (capplet); capplet_gtk_main (); if (ui_pid != 0) waitpid (ui_pid, 0, 0); } return 0; }