From a3f33d2f9b5de45ff3a964755ddc78df8d936019 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Wed, 24 Feb 1999 22:59:12 +0000 Subject: [PATCH] Added window manager switching capplet. Please test. (a lot). 1999-02-24 Owen Taylor * capplets/wm-properties: Added window manager switching capplet. Please test. (a lot). --- ChangeLog | 5 + capplets/Makefile.am | 2 +- capplets/wm-properties/Makefile.am | 26 + .../wm-properties/wm-desktops/Makefile.am | 9 + capplets/wm-properties/wm-exec.c | 332 ++++++ capplets/wm-properties/wm-list.c | 361 ++++++ .../wm-properties/wm-properties-capplet.c | 1041 +++++++++++++++++ capplets/wm-properties/wm-properties.h | 56 + configure.in | 2 + 9 files changed, 1833 insertions(+), 1 deletion(-) create mode 100644 capplets/wm-properties/Makefile.am create mode 100644 capplets/wm-properties/wm-desktops/Makefile.am create mode 100644 capplets/wm-properties/wm-exec.c create mode 100644 capplets/wm-properties/wm-list.c create mode 100644 capplets/wm-properties/wm-properties-capplet.c create mode 100644 capplets/wm-properties/wm-properties.h diff --git a/ChangeLog b/ChangeLog index 78dd58abf..0fe124ac1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +1999-02-24 Owen Taylor + + * capplets/wm-properties: Added window manager + switching capplet. Please test. (a lot). + 1999-02-23 Jonathan Blandford * diff --git a/capplets/Makefile.am b/capplets/Makefile.am index 65480de83..ddd215c9f 100644 --- a/capplets/Makefile.am +++ b/capplets/Makefile.am @@ -2,7 +2,7 @@ always_built_SUBDIRS = mouse-properties keyboard-properties \ desktop-links screensaver-properties background-properties \ theme-switcher sound-properties bell-properties \ ui-properties url-properties gnome-edit-properties \ - session-properties + session-properties wm-properties SUBDIRS = $(always_built_SUBDIRS) diff --git a/capplets/wm-properties/Makefile.am b/capplets/wm-properties/Makefile.am new file mode 100644 index 000000000..19dbaaf16 --- /dev/null +++ b/capplets/wm-properties/Makefile.am @@ -0,0 +1,26 @@ +INCLUDES = -I. -I$(srcdir) \ + -I$(top_srcdir)/intl -I$(top_builddir)/intl \ + -I$(srcdir)/../../control-center \ + -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ + -I$(includedir) $(GNOME_INCLUDEDIR) $(IMLIB_CFLAGS) + +bin_PROGRAMS = wm-properties-capplet + + +wm_properties_capplet_SOURCES = \ + wm-properties.h \ + wm-properties-capplet.c \ + wm-list.c \ + wm-exec.c + +wm_properties_capplet_LDADD = \ +../../control-center/libcapplet.la \ +$(GNOME_LIBDIR) $(ORB_LIBS) $(GNOMEUI_LIBS) $(INTLLIBS) \ +-lgnorba $(IMLIB_LIBS) + +EXTRA_DIST = wm-properties.desktop + +SUBDIRS=wm-desktops + +sysdir = $(datadir)/control-center/Desktop +sys_DATA = wm-properties.desktop diff --git a/capplets/wm-properties/wm-desktops/Makefile.am b/capplets/wm-properties/wm-desktops/Makefile.am new file mode 100644 index 000000000..a97881ce0 --- /dev/null +++ b/capplets/wm-properties/wm-desktops/Makefile.am @@ -0,0 +1,9 @@ +wmdatadir = $(datadir)/gnome/wm-properties + +wmdata_DATA=\ + Enlightenment.desktop \ + IceWM.desktop \ + WindowMaker.desktop + +EXTRA_DIST= $(wmdata_DATA) + diff --git a/capplets/wm-properties/wm-exec.c b/capplets/wm-properties/wm-exec.c new file mode 100644 index 000000000..241f50860 --- /dev/null +++ b/capplets/wm-properties/wm-exec.c @@ -0,0 +1,332 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/* Copyright (C) 1998 Redhat Software Inc. + * Code available under the Gnu GPL. + * Authors: Owen Taylor + */ + +#include +#include +#include +#include "wm-properties.h" + +typedef struct _RestartInfo RestartInfo; + +struct _RestartInfo { + GnomeDesktopEntry *dentry; + gint retries; + WMResultFunc callback; + gpointer data; +}; + +gboolean +wm_is_running (void) +{ + gboolean result; + gboolean old_warnings = gdk_error_warnings; + guint old_mask; + XWindowAttributes attrs; + + gdk_error_warnings = FALSE; + gdk_error_code = 0; + + XGetWindowAttributes (GDK_DISPLAY(), GDK_ROOT_WINDOW(), &attrs); + + XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), + SubstructureRedirectMask); + XSync (GDK_DISPLAY(), False); + if (gdk_error_code == 0) { + result = FALSE; + XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), + attrs.your_event_mask); + } else + result = TRUE; + + gdk_error_warnings = old_warnings; + return result; +} + +/* Cut and paste from gnome-libs/gnome_win_hints_wm_exists, except that we + * return the xid instead of a window + */ +static Window +find_gnome_wm_window(void) +{ + Atom r_type; + int r_format; + unsigned long count; + unsigned long bytes_remain; + unsigned char *prop, *prop2; + gint prev_error; + GdkAtom cardinal_atom = gdk_atom_intern ("CARDINAL", FALSE); + + prev_error = gdk_error_warnings; + gdk_error_warnings = 0; + if (XGetWindowProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), + gdk_atom_intern ("_WIN_SUPPORTING_WM_CHECK", FALSE), + 0, 1, False, cardinal_atom, + &r_type, &r_format, + &count, &bytes_remain, &prop) == Success && prop) + { + if (r_type == cardinal_atom && r_format == 32 && count == 1) + { + Window n = *(long *)prop; + if (XGetWindowProperty(GDK_DISPLAY(), n, + gdk_atom_intern ("_WIN_SUPPORTING_WM_CHECK", FALSE), + 0, 1, False, cardinal_atom, + &r_type, &r_format, &count, &bytes_remain, + &prop2) == Success && prop) + { + if (r_type == cardinal_atom && r_format == 32 && count == 1) + { + XFree(prop); + XFree(prop2); + gdk_error_warnings = prev_error; + return n; + } + XFree(prop2); + } + } + XFree(prop); + } + gdk_error_warnings = prev_error; + return None; +} + +static Window +find_wm_window_from_client (GdkWindow *client) +{ + Window window, frame, parent, root; + Window *children; + unsigned int nchildren; + gboolean old_warnings; + + if (!client) + return None; + + frame = None; + window = GDK_WINDOW_XWINDOW (client); + + old_warnings = gdk_error_warnings; + gdk_error_warnings = FALSE; + gdk_error_code = 0; + + while (XQueryTree (GDK_DISPLAY(), window, + &root, &parent, &children, &nchildren) && + (gdk_error_code == 0)) { + + if (children) + XFree(children); + + if (window == root) + break; + + if (root == parent) { + frame = window; + break; + } + window = parent; + } + + gdk_error_warnings = old_warnings; + + return frame; +} + +static gboolean +window_has_wm_state (Window window) +{ + Atom r_type; + int r_format; + unsigned long count; + unsigned long bytes_remain; + unsigned char *prop; + + if (XGetWindowProperty(GDK_DISPLAY(), window, + gdk_atom_intern ("WM_STATE", FALSE), + 0, 0, False, AnyPropertyType, + &r_type, &r_format, + &count, &bytes_remain, &prop) == Success) { + + if (r_type != None) { + XFree(prop); + return TRUE; + } + } + return FALSE; +} + +static gboolean +descendent_has_wm_state (Window window) +{ + gboolean result = FALSE; + Window parent, root; + Window *children; + unsigned int nchildren; + gint i; + + if (!XQueryTree (GDK_DISPLAY(), window, + &root, &parent, &children, &nchildren)) + return FALSE; + + for (i=0; icallback(WM_SUCCESS, info->data); + gnome_desktop_entry_free (info->dentry); + g_free (info); + return FALSE; + } else { + info->retries--; + if (info->retries > 0) + return TRUE; + else { + info->callback(WM_CANT_START, info->data); + gnome_desktop_entry_free (info->dentry); + g_free (info); + return FALSE; + } + } +} + +static void +start_do (RestartInfo *info) +{ + gnome_desktop_entry_launch (info->dentry); + + info->retries = 20; + gtk_timeout_add (1000, start_timeout, info); +} + +static gboolean +kill_timeout (gpointer data) +{ + RestartInfo *info = data; + if (!wm_is_running ()) { + start_do (info); + return FALSE; + } else { + info->retries--; + if (info->retries > 0) + return TRUE; + else { + info->callback(WM_ALREADY_RUNNING, info->data); + gnome_desktop_entry_free (info->dentry); + g_free (info); + return FALSE; + } + } +} + +void +wm_restart (WindowManager *new, + GdkWindow *client, + WMResultFunc callback, + gpointer data) +{ + Window wm_window; + RestartInfo *info; + + g_return_if_fail (new->is_present); + + info = g_new (RestartInfo, 1); + info->dentry = gnome_desktop_entry_copy (new->dentry); + info->callback = callback; + info->data = data; + info->retries = 10; + + if (wm_is_running ()) { + wm_window = find_wm_window (client); + if (!wm_window) { + (*callback) (WM_ALREADY_RUNNING, data); + gnome_desktop_entry_free (info->dentry); + g_free (info); + } else { + XKillClient (GDK_DISPLAY(), wm_window); + gtk_timeout_add (1000, kill_timeout, info); + } + } else { + start_do (info); + } +} + +WindowManager * +wm_guess_current (void) +{ + return NULL; +} diff --git a/capplets/wm-properties/wm-list.c b/capplets/wm-properties/wm-list.c new file mode 100644 index 000000000..5f5c4716e --- /dev/null +++ b/capplets/wm-properties/wm-list.c @@ -0,0 +1,361 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/* Copyright (C) 1998 Redhat Software Inc. + * Code available under the Gnu GPL. + * Authors: Owen Taylor + */ + +#include +#include +#include +#include +#include "wm-properties.h" + +/* Current list of window managers */ +GList *window_managers = NULL; + +/* List on startup */ +static GList *window_managers_save = NULL; + +/* Current window manager */ +static WindowManager *current_wm; + +/* Window manager on startup */ +static WindowManager *current_wm_save; + +gboolean +is_blank (gchar *str) +{ + while (*str) { + if (!isspace(*str)) + return FALSE; + str++; + } + return TRUE; +} + +static gint +wm_compare (gconstpointer a, gconstpointer b) +{ + const WindowManager *wm_a = (const WindowManager *)a; + const WindowManager *wm_b = (const WindowManager *)b; + + return g_strcasecmp (wm_a->dentry->name, wm_b->dentry->name); +} + +static void +wm_free (WindowManager *wm) +{ + gnome_desktop_entry_free (wm->dentry); + g_free (wm->config_exec); + g_free (wm->config_tryexec);; + g_free (wm); +} + +void +wm_check_present (WindowManager *wm) +{ + gchar *path; + + if (wm->dentry->exec) { + if (wm->dentry->tryexec) { + path = gnome_is_program_in_path (wm->dentry->tryexec); + wm->is_present = (path != NULL); + if (path) + g_free (path); + } else + wm->is_present = TRUE; + } else + wm->is_present = FALSE; + + if (wm->config_exec) { + if (wm->config_tryexec) { + path = gnome_is_program_in_path (wm->config_tryexec); + wm->is_config_present = (path != NULL); + if (path) + g_free (path); + } else + wm->is_config_present = TRUE; + } else + wm->is_config_present = FALSE; + +} + +static WindowManager * +wm_copy (WindowManager *wm) +{ + WindowManager *result = g_new (WindowManager, 1); + + result->dentry = gnome_desktop_entry_copy (wm->dentry); + result->config_exec = g_strdup (wm->config_exec); + result->config_tryexec = g_strdup (wm->config_tryexec); + + result->session_managed = wm->session_managed; + result->is_user = wm->is_user; + result->is_present = wm->is_present; + result->is_config_present = wm->is_config_present; + + return result; +} + + +static WindowManager * +wm_list_find (GList *list, gchar *name) +{ + GList *tmp_list = list; + while (tmp_list) { + WindowManager *wm = tmp_list->data; + if (strcmp (wm->dentry->name, name) == 0) + return wm; + + tmp_list = tmp_list->next; + } + + return NULL; +} + +static GList * +wm_list_find_files (gchar *directory) +{ + DIR *dir; + struct dirent *child; + GList *result = NULL; + gchar *suffix; + + dir = opendir (directory); + if (dir == NULL) + return NULL; + + while ((child = readdir (dir)) != NULL) { + /* Ignore files without .desktop suffix, and ignore + * .desktop files with no prefix + */ + suffix = child->d_name + strlen (child->d_name) - 8; + /* strlen(".desktop") == 8 */ + + if (suffix <= child->d_name || + strcmp (suffix, ".desktop") != 0) + continue; + + result = g_list_prepend (result, + g_concat_dir_and_file (directory, + child->d_name)); + } + closedir (dir); + + return result; +} + +static void +wm_list_read_dir (gchar *directory, gboolean is_user) +{ + WindowManager *wm; + GList *tmp_list; + GList *files; + gchar *prefix; + + files = wm_list_find_files (directory); + + tmp_list = files; + while (tmp_list) { + wm = g_new (WindowManager, 1); + + wm->dentry = gnome_desktop_entry_load_unconditional (tmp_list->data); + if (!wm->dentry) { + g_free (wm); + tmp_list = tmp_list->next; + continue; + } + + prefix = g_strconcat ("=", wm->dentry->location, "=/Window Manager/", NULL); + gnome_config_push_prefix (prefix); + g_free (prefix); + + wm->config_exec = gnome_config_get_string ("ConfigExec"); + wm->config_tryexec = gnome_config_get_string ("ConfigTryExec"); + wm->session_managed = gnome_config_get_bool ("SessionManaged=0"); + wm->is_user = is_user; + + if (wm->config_exec && is_blank (wm->config_exec)) { + g_free (wm->config_exec); + wm->config_exec = NULL; + } + + gnome_config_pop_prefix (); + + wm_check_present (wm); + + if (wm->dentry->name && wm->dentry->exec && + (wm->is_user || wm->is_present)) { + window_managers = + g_list_insert_sorted (window_managers, + wm, + wm_compare); + window_managers_save = + g_list_insert_sorted (window_managers_save, + wm_copy (wm), + wm_compare); + } else { + wm_free (wm); + } + + + tmp_list = tmp_list->next; + } + g_list_free (files); +} + +void +wm_list_init (void) +{ + gchar *tempdir; + gchar *name; + + tempdir = gnome_unconditional_datadir_file ("gnome/wm-properties/"); + wm_list_read_dir (tempdir, FALSE); + g_free (tempdir); + + tempdir = gnome_util_home_file("wm-properties/"); + wm_list_read_dir (tempdir, TRUE); + g_free (tempdir); + + name = gnome_config_get_string ("wm-properties/Config/Config/Current"); + if (name) { + current_wm = wm_list_find (window_managers, name); + g_free (name); + } + + if (!current_wm && window_managers) + current_wm = window_managers->data; + + if (!current_wm) + g_error ("No window manager desktops found!"); + + current_wm_save = wm_list_find (window_managers_save, current_wm->dentry->name); +} + +void +wm_list_save (void) +{ + GList *old_files; + GList *tmp_list; + gchar *tempdir; + gchar *filename; + gchar *prefix; + WindowManager *wm; + + /* Clean out the current contents of .gnome/wm-desktops + */ + + tempdir = gnome_util_home_file("wm-properties/"); + old_files = wm_list_find_files (tempdir); + g_free (tempdir); + + tmp_list = old_files; + while (tmp_list) { + prefix = g_strconcat ("=", tmp_list->data, "=", NULL); + gnome_config_clean_file (prefix); + gnome_config_sync_file (prefix); + g_free (prefix); + + tmp_list = tmp_list->next; + } + g_list_free (old_files); + + + /* Save the user's desktops + */ + + tmp_list = window_managers; + while (tmp_list) { + wm = tmp_list->data; + + if (wm->is_user) { + gnome_desktop_entry_save (wm->dentry); + + prefix = g_strconcat ("=", wm->dentry->location, "=/Window Manager/", NULL); + gnome_config_push_prefix (prefix); + g_free (prefix); + + if (wm->config_exec) + gnome_config_set_string ("ConfigExec", wm->config_exec); + if (wm->config_tryexec) + gnome_config_set_string ("ConfigTryExec", wm->config_tryexec); + gnome_config_set_bool ("SessionManaged=0", wm->session_managed); + gnome_config_pop_prefix (); + + } + tmp_list = tmp_list->next; + } + + /* Save the current window manager + */ + + gnome_config_set_string ("wm-properties/Config/Config/Current", + current_wm->dentry->name); + gnome_config_sync (); +} + +void +wm_list_revert (void) +{ + GList *tmp_list; + gchar *old_name = g_strdup (current_wm->dentry->name); + + g_list_foreach (window_managers, (GFunc)wm_free, NULL); + g_list_free (window_managers); + window_managers = NULL; + + tmp_list = window_managers_save; + while (tmp_list) { + window_managers = g_list_prepend (window_managers, + wm_copy (tmp_list->data)); + tmp_list = tmp_list->next; + } + window_managers = g_list_reverse (window_managers); + current_wm = wm_list_find (window_managers, old_name); + g_free (old_name); +} + +void +wm_list_add (WindowManager *wm) +{ + g_return_if_fail (wm != NULL); + + window_managers = g_list_insert_sorted (window_managers, wm, + wm_compare); +} + +void +wm_list_delete (WindowManager *wm) +{ + GList *node; + + g_return_if_fail (wm != NULL); + g_return_if_fail (wm != current_wm); + + node = g_list_find (window_managers, wm); + g_return_if_fail (node != NULL); + + window_managers = g_list_remove_link (window_managers, node); + g_list_free_1 (node); + wm_free (wm); +} + +void +wm_list_set_current (WindowManager *wm) +{ + current_wm = wm; +} + +WindowManager * +wm_list_get_current (void) +{ + return current_wm; +} + +WindowManager * +wm_list_get_revert (void) +{ + return wm_list_find (window_managers, current_wm_save->dentry->name); +} + diff --git a/capplets/wm-properties/wm-properties-capplet.c b/capplets/wm-properties/wm-properties-capplet.c new file mode 100644 index 000000000..a7caeb3c3 --- /dev/null +++ b/capplets/wm-properties/wm-properties-capplet.c @@ -0,0 +1,1041 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/* Copyright (C) 1998-1999 Redhat Software Inc. + * Code available under the Gnu GPL. + * Authors: Jonathan Blandford + * Owen Taylor + */ +#include +#include +#include "wm-properties.h" +#include "capplet-widget.h" +#include "gnome.h" + +/* prototypes */ +static void restart (gboolean force); +static void try_callback (void); +static void ok_callback (void); +static void revert_callback (void); +static void cancel_callback (void); + +/* structures */ + +typedef struct { + GtkWidget *dialog; + GtkWidget *name_entry; + GtkWidget *exec_entry; + GtkWidget *config_entry; + GtkWidget *sm_toggle; +} WMDialog; + +/* vars. */ +static GtkWidget *capplet; +static GtkWidget *delete_button; +static GtkWidget *config_button; +static GtkWidget *clist; + +static WindowManager *selected_wm; + +static GtkWidget *restart_dialog = NULL; +static GtkWidget *restart_label = NULL; +guint restart_dialog_timeout; + +GnomeClient *client = NULL; +gchar *argv0; + +/* Enumeration describing the current state of the capplet. + * in any other state than idle, all controls are !sensitive. + */ +typedef enum { + STATE_IDLE, + STATE_TRY, + STATE_REVERT, + STATE_OK, + STATE_CANCEL, + STATE_TRY_REVERT, /* Currently trying, revert afterwards */ + STATE_TRY_CANCEL /* Currently trying, cancel afterwards */ +} StateType; + +/* The possible transitions between states are described below. + * + + * operation | try revert ok cancel finish + * ===========+================================================= + * IDLE | TRY REVERT OK CANCEL + * TRY | TRY_REVERT OK TRY_CANCEL IDLE + * REVERT | CANCEL CANCEL IDLE + * OK | (quit) + * CANCEL | (quit) + * TRY_REVERT | TRY_CANCEL TRY_CANCEL REVERT + * TRY_CANCEL | CANCEL + * + * When a restart fails, there are three cases + * + * (1) The failure was because the current window manager didn't + * die. We inform the user of the situation, and then + * abort the operation. + * + * (2) The window manager didn't start, and we don't have a + * a fallback. We pop up a error dialog, tell the user + * to start a new window manager, and abort the operation. + * + * (3) The window manager didn't start, and we previously had a + * window manager runnning. We pop up a warning dialog, + * then try to go back to the old window manager. + * + * operation | (1) (2) (3) + * ===========+================================================= + * IDLE | + * TRY | IDLE IDLE TRY + * REVERT | IDLE IDLE REVERT + * OK | (quit) (quit) OK + * CANCEL | (quit) (quit) CANCEL + * TRY_REVERT | REVERT REVERT REVERT + * TRY_CANCEL | CANCEL CANCEL CANCEL + */ + + + +/* Current state + */ +StateType state = STATE_IDLE; + +/* Set TRUE when we've exited the main loop, but state != IDLE + */ +gboolean quit_pending = FALSE; + +/* Set TRUE while we are filling in the list + */ +gboolean in_fill = FALSE; + + +static gboolean +restart_dialog_raise (gpointer data) +{ + if (restart_dialog && GTK_WIDGET_REALIZED (restart_dialog)) { + gdk_window_raise (restart_dialog->window); + } + return TRUE; +} + +static void +restart_dialog_destroyed (GtkWidget *widget) +{ + if (restart_dialog_timeout) { + gtk_timeout_remove (restart_dialog_timeout); + restart_dialog_timeout = 0; + } + + restart_dialog = NULL; +} + +static void +show_restart_dialog (gchar *name) +{ + GtkWidget *hbox; + GtkWidget *frame; + GtkWidget *pixmap; + gchar *tmp; + + if (!restart_dialog) { + restart_dialog = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_position (GTK_WINDOW (restart_dialog), + GTK_WIN_POS_CENTER); + + gtk_signal_connect (GTK_OBJECT (restart_dialog), "destroy", + GTK_SIGNAL_FUNC (restart_dialog_destroyed), + &restart_dialog); + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); + gtk_container_add (GTK_CONTAINER (restart_dialog), frame); + + hbox = gtk_hbox_new (FALSE, GNOME_PAD); + gtk_container_set_border_width (GTK_CONTAINER (hbox), GNOME_PAD); + gtk_container_add (GTK_CONTAINER (frame), hbox); + + tmp = gnome_unconditional_pixmap_file("gnome-info.png"); + if (tmp) { + pixmap = gnome_pixmap_new_from_file(tmp); + g_free(tmp); + gtk_box_pack_start (GTK_BOX (hbox), pixmap, FALSE, FALSE, 0); + } + + restart_label = gtk_label_new (""); + gtk_box_pack_start (GTK_BOX (hbox), restart_label, FALSE, FALSE, GNOME_PAD); + } + + if (!restart_dialog_timeout) { + gtk_timeout_add (250, restart_dialog_raise, NULL); + + } + + tmp = g_strdup_printf ("Starting %s", name); + gtk_label_set_text (GTK_LABEL (restart_label), tmp); + g_free (tmp); + + gtk_widget_show_all (restart_dialog); +} + +static void +hide_restart_dialog (void) +{ + if (restart_dialog) + gtk_widget_destroy (restart_dialog); +} + +static void +update_session (void) +{ + WindowManager *current_wm = wm_list_get_current(); + gchar *session_args[3]; + + if (!current_wm) + return; + + if (current_wm->session_managed) { + gnome_client_set_restart_style (client, + GNOME_RESTART_NEVER); + + } else { + session_args[0] = argv0; + session_args[1] = "--init-session-settings"; + session_args[2] = NULL; + /* We use a priority of 15 so that we start after + * session-managed WM's (priority 10), for safety. + */ + gnome_client_set_priority (client, 15); + gnome_client_set_restart_style (client, + GNOME_RESTART_ANYWAY); + gnome_client_set_restart_command (client, 2, + session_args); + } + + gnome_client_flush (client); +} + +static void +init_session (void) +{ + GnomeClientFlags flags; + gint token; + + client = gnome_master_client (); + flags = gnome_client_get_flags (client); + + if (flags & GNOME_CLIENT_IS_CONNECTED) { + token = gnome_startup_acquire_token("GNOME_WM_PROPERTIES", + gnome_client_get_id(client)); + + if (token) + update_session(); + else { + gnome_client_set_restart_style (client, + GNOME_RESTART_NEVER); + gnome_client_flush (client); + } + } +} + +static void +update_gui (void) +{ + GList *tmp_list; + WindowManager *current_wm = wm_list_get_current(); + gint new_row; + gchar *tmpstr; + + gtk_clist_clear (GTK_CLIST (clist)); + + in_fill = TRUE; + + tmp_list = window_managers; + while (tmp_list) { + gchar *row_text; + WindowManager *wm; + + wm = tmp_list->data; + + if (wm == current_wm) { + row_text = g_strconcat (wm->dentry->name, " (Current)", NULL); + + tmpstr = g_strconcat ("Run Configuration Tool for ", + wm->dentry->name, + NULL); + + gtk_label_set_text (GTK_LABEL (GTK_BIN (config_button)->child), + tmpstr); + gtk_widget_set_sensitive (config_button, + wm->is_config_present); + + g_free (tmpstr); + } else if (wm->is_user && !wm->is_present) { + row_text = g_strconcat (wm->dentry->name, " (Not found)", NULL); + } else { + row_text = g_strdup (wm->dentry->name); + } + + new_row = gtk_clist_append (GTK_CLIST (clist), &row_text); + gtk_clist_set_row_data (GTK_CLIST (clist), new_row, wm); + + if (wm == selected_wm) + gtk_clist_select_row (GTK_CLIST (clist), new_row, 0); + + g_free (row_text); + + tmp_list = tmp_list->next; + } + + in_fill = FALSE; + + gtk_widget_set_sensitive (delete_button, selected_wm->is_user); +} + +static void +init_callback (WMResult result, gpointer data) +{ + switch (result) { + case WM_SUCCESS: + break; + case WM_ALREADY_RUNNING: + g_warning ("wm-properties-capplet: Unable to initialize window manager.\n" + "\tAnother window manager is already running and could not be killed\n"); + break; + case WM_CANT_START: + g_warning ("wm-properties-capplet: Unable to initialize window manager.\n" + "\t'%s' didn't start\n", (gchar *)data); + break; + } + + g_free (data); + gtk_main_quit (); +} + +static void +restart_finalize () +{ + wm_list_set_current (selected_wm); + hide_restart_dialog(); + + switch (state) { + case STATE_TRY: + case STATE_REVERT: + gtk_widget_set_sensitive (capplet, TRUE); + update_gui(); + state = STATE_IDLE; + break; + + case STATE_OK: + case STATE_CANCEL: + if (quit_pending) + gtk_main_quit(); + break; + default: + g_warning ("Finalize in state %d!!!\n", state); + return; + } + +} + +static void +restart_failure (WMResult reason) +{ + GtkWidget *msgbox; + WindowManager *current_wm; + gchar *msg = NULL; + gboolean modal = FALSE; + + current_wm = wm_list_get_current (); + + /* Did the previous window manager not die? + */ + if (reason == WM_ALREADY_RUNNING) { + msg = g_strdup ("Previous window manager did not die\n"); + + switch (state) { + case STATE_TRY: + case STATE_REVERT: + case STATE_OK: + case STATE_CANCEL: + selected_wm = current_wm; + restart_finalize (); + break; + + case STATE_TRY_REVERT: + revert_callback (); + break; + + case STATE_TRY_CANCEL: + cancel_callback (); + break; + + default: + g_warning ("Failure in state %d!!!\n", state); + return; + } + } + /* Is there something reasonable to try to fall back to? + */ + else if (current_wm != selected_wm) { + + switch (state) { + case STATE_TRY: + case STATE_REVERT: + case STATE_OK: + case STATE_CANCEL: + msg = g_strdup_printf ("Could not start '%s'.\n" + "Falling back to previous window manager '%s'\n", + selected_wm->dentry->name, + current_wm->dentry->name); + selected_wm = current_wm; + restart(TRUE); + break; + + case STATE_TRY_REVERT: + revert_callback (); + break; + + case STATE_TRY_CANCEL: + cancel_callback (); + break; + + default: + g_warning ("Failure in state %d!!!\n", state); + return; + } + + /* Give up */ + } else { + + switch (state) { + case STATE_OK: + case STATE_CANCEL: + modal = TRUE; /* prevent an immediate exit */ + /* Fall through */ + case STATE_TRY: + case STATE_REVERT: + msg = g_strdup ( + "Could not start fallback window manager.\n" + "Please run a window manager manually. You can\n" + "do this by selecting \"Run Program\" in the\n" + "foot menu\n"); + + restart_finalize(); + break; + + case STATE_TRY_REVERT: + revert_callback (); + break; + + case STATE_TRY_CANCEL: + cancel_callback (); + break; + + default: + g_warning ("Failure in state %d!!!\n", state); + return; + } + } + + if (msg) { + msgbox = gnome_message_box_new (msg, + GNOME_MESSAGE_BOX_ERROR, + "OK", NULL); + if (modal) + gnome_dialog_run (GNOME_DIALOG (msgbox)); + else + gtk_widget_show (msgbox); + g_free (msg); + } +} + +static void +restart_finish (void) +{ + switch (state) { + case STATE_TRY: + case STATE_REVERT: + case STATE_OK: + case STATE_CANCEL: + restart_finalize(); + break; + + case STATE_TRY_REVERT: + revert_callback (); + break; + + case STATE_TRY_CANCEL: + cancel_callback (); + break; + + default: + g_warning ("Finished in state %d!!!\n", state); + return; + } +} + +static void +restart_callback (WMResult result, gpointer data) +{ + if (result == WM_SUCCESS) + restart_finish (); + else + restart_failure (result); +} + +static void +destroy_callback (GtkWidget *widget, void *data) +{ +} + +static void +restart (gboolean force) +{ + WindowManager *current_wm = wm_list_get_current(); + + if (force || current_wm != selected_wm) { + show_restart_dialog (selected_wm->dentry->name); + if (state != STATE_OK && state != STATE_CANCEL) + gtk_widget_set_sensitive (capplet, FALSE); + wm_restart (selected_wm, + capplet->window, + restart_callback, + NULL); + } else { + restart_finalize (); + } +} + +static void +try_callback (void) +{ + if (state != STATE_IDLE) { + g_warning ("try_callback in state %d!!!\n", state); + return; + } + + state = STATE_TRY; + restart(FALSE); +} + +static void +ok_callback (void) +{ + switch (state) { + case STATE_IDLE: + state = STATE_OK; + restart(FALSE); + return; + + case STATE_TRY: + state = STATE_OK; + break; + + case STATE_REVERT: + state = STATE_CANCEL; + break; + + case STATE_TRY_REVERT: + state = STATE_TRY_CANCEL; + break; + + default: + g_warning ("ok callback in state %d!!!\n", state); + return; + } +} + +static void +do_revert (void) +{ + wm_list_revert(); + selected_wm = wm_list_get_revert(); + if (state != STATE_CANCEL) + update_gui(); + restart(FALSE); +} + +static void +revert_callback (void) +{ + StateType old_state = state; + + switch (state) { + case STATE_IDLE: + case STATE_TRY_REVERT: + wm_list_revert(); + selected_wm = wm_list_get_revert(); + state = STATE_REVERT; + + restart (old_state == STATE_TRY_REVERT); + update_gui(); + + break; + + case STATE_TRY: + state = STATE_TRY_REVERT; + break; + + default: + g_warning ("revert callback in state %d!!!\n", state); + return; + } +} + +static void +cancel_callback (void) +{ + StateType old_state = state; + + switch (state) { + case STATE_IDLE: + case STATE_TRY_CANCEL: + wm_list_revert(); + selected_wm = wm_list_get_revert(); + state = STATE_CANCEL; + + restart (old_state == STATE_TRY_CANCEL); + + break; + + case STATE_TRY: + state = STATE_TRY_CANCEL; + break; + + case STATE_REVERT: + state = STATE_CANCEL; + break; + + case STATE_TRY_REVERT: + state = STATE_TRY_CANCEL; + break; + + default: + g_warning ("ok callback in state %d!!!\n", state); + return; + } +} + +static WMDialog * +create_dialog (gchar *title) +{ + GtkWidget *label; + GtkWidget *alignment; + GtkWidget *table; + WMDialog *dialog; + + dialog = g_new (WMDialog, 1); + + dialog->dialog = gnome_dialog_new ("Add New Window Manager", + "OK", "Cancel", NULL); + + gnome_dialog_set_default (GNOME_DIALOG (dialog->dialog), 0); + gnome_dialog_close_hides (GNOME_DIALOG (dialog->dialog), TRUE); + + table = gtk_table_new (4, 2, FALSE); + gtk_table_set_row_spacings (GTK_TABLE (table), GNOME_PAD_SMALL); + gtk_table_set_col_spacings (GTK_TABLE (table), GNOME_PAD_SMALL); + gtk_container_add (GTK_CONTAINER (GNOME_DIALOG (dialog->dialog)->vbox), + table); + + label = gtk_label_new ("Name:"); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); + gtk_table_attach (GTK_TABLE (table), label, + 0, 1, 0, 1, + GTK_FILL, 0, + 0, 0); + + dialog->name_entry = gtk_entry_new (); + gtk_table_attach (GTK_TABLE (table), dialog->name_entry, + 1, 2, 0, 1, + GTK_FILL | GTK_EXPAND, 0, + 0, 0); + + label = gtk_label_new ("Command:"); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); + gtk_table_attach (GTK_TABLE (table), label, + 0, 1, 1, 2, + GTK_FILL, 0, + 0, 0); + + dialog->exec_entry = gtk_entry_new (); + gtk_table_attach (GTK_TABLE (table), dialog->exec_entry, + 1, 2, 1, 2, + GTK_FILL | GTK_EXPAND, 0, + 0, 0); + + label = gtk_label_new ("Configuration Command:"); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); + gtk_table_attach (GTK_TABLE (table), label, + 0, 1, 2, 3, + GTK_FILL, 0, + 0, 0); + + dialog->config_entry = gtk_entry_new (); + gtk_table_attach (GTK_TABLE (table), dialog->config_entry, + 1, 2, 2, 3, + GTK_FILL | GTK_EXPAND, 0, + 0, 0); + + alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0); + gtk_table_attach (GTK_TABLE (table), alignment, + 0, 2, 3, 4, + GTK_FILL | GTK_EXPAND, 0, + 0, 0); + + dialog->sm_toggle = gtk_check_button_new_with_label ("Window manager is session managed"); + gtk_container_add (GTK_CONTAINER (alignment), dialog->sm_toggle); + + gtk_window_set_default_size (GTK_WINDOW (dialog->dialog), 400, -1); + gtk_window_set_policy (GTK_WINDOW (dialog->dialog), FALSE, TRUE, FALSE); + gtk_widget_show_all (dialog->dialog); + + return dialog; +} + +static gchar * +extract_entry (GtkWidget *widget) +{ + gchar *tmp; + + g_return_val_if_fail (GTK_IS_ENTRY (widget), NULL); + + tmp = gtk_entry_get_text (GTK_ENTRY (widget)); + if (is_blank (tmp)) + return NULL; + else + return g_strdup (tmp); +} + +static gchar * +make_filename (gchar *name) +{ + gchar *tempname = g_strconcat (name, ".desktop", NULL); + gchar *tempdir = gnome_util_home_file("wm-properties/"); + gchar *tmp = tempname; + gchar *result; + + while (*tmp) { + if (isspace (*tmp) || (*tmp == '/')) + *tmp = '_'; + tmp++; + } + result = g_concat_dir_and_file (tempdir, tempname); + g_free (tempname); + g_free (tempdir); + + return result; +} + +static gboolean +check_dialog (WMDialog *dialog) +{ + GtkWidget *msgbox; + + if (is_blank (gtk_entry_get_text (GTK_ENTRY (dialog->name_entry)))) { + msgbox = gnome_message_box_new ("Name cannot be empty", + GNOME_MESSAGE_BOX_ERROR, + "OK", NULL); + gnome_dialog_run (GNOME_DIALOG (msgbox)); + return FALSE; + } + if (is_blank (gtk_entry_get_text (GTK_ENTRY (dialog->exec_entry)))) { + msgbox = gnome_message_box_new ("Command cannot be empty", + GNOME_MESSAGE_BOX_ERROR, + "OK", NULL); + gnome_dialog_run (GNOME_DIALOG (msgbox)); + return FALSE; + } + + return TRUE; +} + +static void +get_dialog_contents (WMDialog *dialog, WindowManager *wm) +{ + gchar *tmp; + + if (wm->dentry->name) + g_free (wm->dentry->name); + wm->dentry->name = extract_entry (dialog->name_entry); + + if (wm->dentry->exec) + g_strfreev (wm->dentry->exec); + tmp = extract_entry (dialog->exec_entry); + gnome_config_make_vector (tmp, &wm->dentry->exec_length, + &wm->dentry->exec); + g_free (tmp); + + if (wm->config_exec) + g_free (wm->config_exec); + wm->config_exec = extract_entry (dialog->config_entry); + + if (wm->dentry->location) + g_free (wm->dentry->location); + wm->dentry->location = make_filename (wm->dentry->name); + + wm->session_managed = !!GTK_TOGGLE_BUTTON (dialog->sm_toggle)->active; + + wm_check_present (wm); +} + +static void +edit_dialog (void) +{ + WMDialog *dialog = create_dialog ("Add New Window Manager"); + gchar *tmp; + gint result; + + if (selected_wm->dentry->name) + gtk_entry_set_text (GTK_ENTRY (dialog->name_entry), selected_wm->dentry->name); + + if (selected_wm->dentry->exec) { + tmp = gnome_config_assemble_vector (selected_wm->dentry->exec_length, + (const char **)selected_wm->dentry->exec); + gtk_entry_set_text (GTK_ENTRY (dialog->exec_entry), tmp); + g_free (tmp); + } + + if (selected_wm->config_exec) + gtk_entry_set_text (GTK_ENTRY (dialog->config_entry), selected_wm->config_exec); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->sm_toggle), + selected_wm->session_managed); + + if (!selected_wm->is_user) { + gtk_widget_set_sensitive (dialog->name_entry, FALSE); + gtk_widget_set_sensitive (dialog->exec_entry, FALSE); + gtk_widget_set_sensitive (dialog->config_entry, FALSE); + gtk_widget_set_sensitive (dialog->sm_toggle, FALSE); + } + + do { + gtk_widget_show (dialog->dialog); + result = gnome_dialog_run (GNOME_DIALOG (dialog->dialog)); + } while (result == 0 && !check_dialog (dialog)); + + if (selected_wm->is_user && (result == 0)) { + get_dialog_contents (dialog, selected_wm); + update_gui(); + capplet_widget_state_changed (CAPPLET_WIDGET (capplet), TRUE); + } + + gtk_widget_destroy (dialog->dialog); + g_free (dialog); +} + +static void +add_dialog (void) +{ + WMDialog *dialog = create_dialog ("Edit Window Manager"); + WindowManager *wm; + gint result; + + do { + result = gnome_dialog_run (GNOME_DIALOG (dialog->dialog)); + } while (result == 0 && !check_dialog (dialog)); + + if (result == 0) { + wm = g_new0 (WindowManager, 1); + wm->dentry = g_new0 (GnomeDesktopEntry, 1); + get_dialog_contents (dialog, wm); + + wm->is_user = TRUE; + + wm_list_add (wm); + + update_gui(); + capplet_widget_state_changed (CAPPLET_WIDGET (capplet), TRUE); + } + + gtk_widget_destroy (dialog->dialog); + g_free (dialog); +} + +static void +select_row (GtkCList *the_clist, + gint row, + gint column, + GdkEvent *event, + gpointer data) +{ + WindowManager *wm; + + if (!in_fill) { + wm = gtk_clist_get_row_data (GTK_CLIST (clist), row); + gtk_widget_set_sensitive (delete_button, wm->is_user); + + if (wm != selected_wm) { + selected_wm = wm; + capplet_widget_state_changed (CAPPLET_WIDGET (capplet), TRUE); + } + } +} + +static void +delete (void) +{ + WindowManager *current_wm = wm_list_get_current(); + GtkWidget *msgbox; + + if (current_wm == selected_wm) { + msgbox = gnome_message_box_new ( + "You cannot delete the current Window Manager", + GNOME_MESSAGE_BOX_ERROR, "OK", NULL); + + gnome_dialog_run (GNOME_DIALOG (msgbox)); + return; + } + + wm_list_delete (selected_wm); + update_gui(); + capplet_widget_state_changed (CAPPLET_WIDGET (capplet), TRUE); +} + + +static void +run_config (void) +{ + WindowManager *current_wm = wm_list_get_current(); + if (current_wm->is_config_present && + current_wm->config_exec != NULL) { + gchar *argv[4]; + + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = current_wm->config_exec; + argv[3] = NULL; + + gnome_execute_async (NULL, 4, argv); + } +} + +static void +wm_setup (void) +{ + GtkWidget *hbox, *vbox, *bottom; + GtkWidget *util_vbox; + GtkWidget *add_button; + GtkWidget *edit_button; + GtkWidget *scrolled_window; + + capplet = capplet_widget_new (); + vbox = gtk_vbox_new (FALSE, 0); + hbox = gtk_hbox_new (FALSE, GNOME_PAD); + + gtk_container_set_border_width (GTK_CONTAINER (hbox), GNOME_PAD_SMALL); + bottom = gtk_hbox_new (FALSE, GNOME_PAD_SMALL); + gtk_container_set_border_width (GTK_CONTAINER (bottom), GNOME_PAD_SMALL); + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + clist = gtk_clist_new (1); + gtk_clist_column_titles_hide (GTK_CLIST (clist)); + gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, TRUE); + gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_BROWSE); + + gtk_signal_connect (GTK_OBJECT (clist), "select_row", + GTK_SIGNAL_FUNC (select_row), NULL); + + gtk_container_add (GTK_CONTAINER (scrolled_window), clist); + + gtk_box_pack_start (GTK_BOX (hbox), scrolled_window, TRUE, TRUE, 0); + + util_vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL); + gtk_box_pack_start (GTK_BOX (hbox), util_vbox, FALSE, FALSE, 0); + + add_button = gtk_button_new_with_label ("Add"); + gtk_signal_connect (GTK_OBJECT (add_button), "clicked", + GTK_SIGNAL_FUNC (add_dialog), NULL); + gtk_box_pack_start (GTK_BOX (util_vbox), add_button, FALSE, FALSE, 0); + + edit_button = gtk_button_new_with_label ("Edit"); + gtk_signal_connect (GTK_OBJECT (edit_button), "clicked", + GTK_SIGNAL_FUNC (edit_dialog), NULL); + gtk_box_pack_start (GTK_BOX (util_vbox), edit_button, FALSE, FALSE, 0); + + delete_button = gtk_button_new_with_label ("Delete"); + gtk_signal_connect (GTK_OBJECT (delete_button), "clicked", + GTK_SIGNAL_FUNC (delete), NULL); + gtk_box_pack_start (GTK_BOX (util_vbox), delete_button, FALSE, FALSE, 0); + config_button = gtk_button_new_with_label (""); + gtk_signal_connect (GTK_OBJECT (config_button), "clicked", + GTK_SIGNAL_FUNC (run_config), NULL); + gtk_box_pack_start (GTK_BOX (bottom), config_button, FALSE, FALSE, 0); + + gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); + gtk_box_pack_end (GTK_BOX (vbox), bottom, FALSE, FALSE, 0); + + gtk_container_add (GTK_CONTAINER (capplet), vbox); + + update_gui(); + + gtk_widget_show_all (capplet); +} + +int +main (int argc, char **argv) +{ + gint init_results; + + bindtextdomain (PACKAGE, GNOMELOCALEDIR); + textdomain (PACKAGE); + + argv0 = g_strdup (argv[0]); + init_results = gnome_capplet_init("wm-properties", VERSION, + argc, argv, NULL, 0, NULL); + + if (init_results < 0) { + g_warning ("an initialization error occurred while " + "starting 'wm-properties-capplet'.\n" + "aborting...\n"); + exit (1); + } + + /* Read in the list of window managers, and the current + * window manager + */ + wm_list_init(); + selected_wm = wm_list_get_current(); + + if (init_results == 0) { + init_session(); + wm_setup(); + gtk_signal_connect(GTK_OBJECT(capplet), "destroy", + GTK_SIGNAL_FUNC(destroy_callback), NULL); + gtk_signal_connect (GTK_OBJECT (capplet), "try", + GTK_SIGNAL_FUNC (try_callback), NULL); + gtk_signal_connect (GTK_OBJECT (capplet), "revert", + GTK_SIGNAL_FUNC (revert_callback), NULL); + gtk_signal_connect (GTK_OBJECT (capplet), "cancel", + GTK_SIGNAL_FUNC (cancel_callback), NULL); + gtk_signal_connect (GTK_OBJECT (capplet), "ok", + GTK_SIGNAL_FUNC (ok_callback), NULL); + + capplet_gtk_main (); + + if (state != STATE_IDLE) { + quit_pending = TRUE; + gtk_main(); + } + + if (state == STATE_OK) { + wm_list_save (); + update_session (); + } + + } else { + if (selected_wm && + !selected_wm->session_managed && + !wm_is_running()) { + + wm_restart (selected_wm, NULL, init_callback, + g_strdup (selected_wm->dentry->name)); + gtk_main (); + } + + init_session(); + } + + return 0; +} + diff --git a/capplets/wm-properties/wm-properties.h b/capplets/wm-properties/wm-properties.h new file mode 100644 index 000000000..c194c12ef --- /dev/null +++ b/capplets/wm-properties/wm-properties.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/* Copyright (C) 1998 Redhat Software Inc. + * Code available under the Gnu GPL. + * Authors: Owen Taylor + */ + +#include +#include + +typedef struct _WindowManager WindowManager; + +struct _WindowManager { + GnomeDesktopEntry *dentry; + gchar *config_exec; + gchar *config_tryexec; + gboolean session_managed : 1; + gboolean is_user : 1; + gboolean is_present : 1; + gboolean is_config_present : 1; +}; + +/* Utility functions */ +gboolean is_blank (gchar *str); + +/* Fill in the is_present and is_config_present fields */ +void wm_check_present (WindowManager *wm); + +/* Management of window manager list */ + +void wm_list_init (void); +void wm_list_save (void); +void wm_list_revert (void); +void wm_list_add (WindowManager *window_manager); +void wm_list_delete (WindowManager *window_manager); +void wm_list_set_current (WindowManager *window_manager); +WindowManager *wm_list_get_current (void); +WindowManager *wm_list_get_revert (void); + +extern GList *window_managers; + +/* Management of current window manager */ + +typedef enum { + WM_SUCCESS, + WM_ALREADY_RUNNING, + WM_CANT_START +} WMResult; + +typedef void (*WMResultFunc) (WMResult result, gpointer data); + +void wm_restart (WindowManager *new, + GdkWindow *client, + WMResultFunc callback, + gpointer data); +gboolean wm_is_running (void); +WindowManager *wm_guess_current (void); diff --git a/configure.in b/configure.in index aeeec3859..93ecd4060 100644 --- a/configure.in +++ b/configure.in @@ -106,6 +106,8 @@ capplets/theme-switcher/Makefile capplets/ui-properties/Makefile capplets/url-properties/Makefile capplets/gnome-edit-properties/Makefile +capplets/wm-properties/Makefile +capplets/wm-properties/wm-desktops/Makefile idl/Makefile intl/Makefile])