summaryrefslogtreecommitdiff
path: root/libwindow-settings
diff options
context:
space:
mode:
authorSeth Nickell <snickell@stanford.edu>2002-06-03 00:33:59 +0000
committerSeth Nickell <seth@src.gnome.org>2002-06-03 00:33:59 +0000
commitaa217d6cd714a6e2b1f6a86868218397befe0d61 (patch)
tree06f9df755868e14bdc825652d760dc1a6f4faa79 /libwindow-settings
parent0a5695f294b30d5aa7c70f5d2f745a8a740145b1 (diff)
downloadgnome-control-center-aa217d6cd714a6e2b1f6a86868218397befe0d61.tar.gz
Update to deal with the .pc file that gets generated.
2002-06-02 Seth Nickell <snickell@stanford.edu> * .cvsignore: Update to deal with the .pc file that gets generated. * Makefile.am: Build a real library, not just a non-installed. This is to get around problems dealing with GObject inheritance and static memory problems. We have a run time loaded object deriving from the library, so it has to link it in. But then the problem that occurs is that both the run-time loaded library and the program that calls it statically link the .la in. Then they have different memory spaces, and type registration goes to pot. Open to suggestions if there's a way of doing this without making an installed library. * gnome-window-manager.c: (gnome_window_manager_new), (gnome_window_manager_get_name), (gnome_window_manager_set_theme), (gnome_window_manager_get_theme_list), (gnome_window_manager_set_font), (gnome_window_manager_get_focus_follows_mouse), (gnome_window_manager_set_focus_follows_mouse), (gnome_window_manager_init), (gnome_window_manager_finalize), (gnome_window_manager_class_init), (gnome_window_manager_get_type): * gnome-window-manager.h: Lots of formatting fixes, change some of the boilerplate. * gnome-window-settings-2.0.pc.in: Since we're installing a library, go the whole way. Its good to make this easy to depend on for external window managers anyway, now that I think of it. * gnome-wm-manager.c: (gnome_wm_manager_init), (gnome_wm_manager_get_list), (gnome_wm_manager_set_current), (gnome_wm_manager_get_current), (gnome_wm_manager_change_wm_to_settings), (restart_label_update), (restart_dialog_raise), (restart_dialog_destroyed), (show_restart_dialog), (hide_restart_dialog), (init_session), (update_session), (init_callback), (restart_finalize), (restart_failure), (show_restart_info), (restart_finish), (restart_callback), (restart), (revert_callback), (cancel_callback): * gnome-wm-manager.h: Add code for doing the window manager switch to the library, snitched out of wm-properties. Its probably a little broken right now. * wm-exec.c: (wm_is_running), (find_gnome_wm_window), (find_wm_window_from_client), (window_has_wm_state), (descendent_has_wm_state), (find_wm_window_from_hunt), (find_wm_window), (start_timeout), (start_do), (kill_timeout), (wm_restart), (wm_guess_current): * wm-list.c: (is_blank), (wm_compare), (wm_free), (wm_check_present), (wm_copy), (wm_list_find), (wm_list_find_exec), (wm_list_find_files), (wm_list_read_dir), (wm_list_init), (wm_list_save), (wm_list_revert), (wm_list_add), (wm_list_delete), (wm_list_set_current), (wm_list_get_current), (wm_list_get_revert), (wm_read_from_xml), (wm_list_read_from_xml), (wm_write_to_xml), (wm_list_write_to_xml), (xml_read_bool), (xml_write_bool): * wm-properties.h: Take wm-switching code out of the capplet, move it here. (Jacob, I did a make dist and build the resulting tarball, hope things don't break for you this time ... )
Diffstat (limited to 'libwindow-settings')
-rw-r--r--libwindow-settings/.cvsignore3
-rw-r--r--libwindow-settings/ChangeLog68
-rw-r--r--libwindow-settings/Makefile.am32
-rw-r--r--libwindow-settings/gnome-window-manager.c130
-rw-r--r--libwindow-settings/gnome-window-manager.h47
-rw-r--r--libwindow-settings/gnome-window-settings-2.0.pc.in11
-rw-r--r--libwindow-settings/gnome-wm-manager.c608
-rw-r--r--libwindow-settings/gnome-wm-manager.h22
-rw-r--r--libwindow-settings/wm-exec.c331
-rw-r--r--libwindow-settings/wm-list.c577
-rw-r--r--libwindow-settings/wm-properties.h63
11 files changed, 1860 insertions, 32 deletions
diff --git a/libwindow-settings/.cvsignore b/libwindow-settings/.cvsignore
index 885705814..a397b2d1a 100644
--- a/libwindow-settings/.cvsignore
+++ b/libwindow-settings/.cvsignore
@@ -8,4 +8,5 @@ Makefile.in
gnome-window-properties
window-properties.desktop
*.oaf
-*.gladep \ No newline at end of file
+*.gladep
+gnome-window-settings-2.0.pc \ No newline at end of file
diff --git a/libwindow-settings/ChangeLog b/libwindow-settings/ChangeLog
index 7d8e7958e..a2d998940 100644
--- a/libwindow-settings/ChangeLog
+++ b/libwindow-settings/ChangeLog
@@ -1,3 +1,71 @@
+2002-06-02 Seth Nickell <snickell@stanford.edu>
+
+ * .cvsignore:
+
+ Update to deal with the .pc file that gets generated.
+
+ * Makefile.am:
+
+ Build a real library, not just a non-installed. This is to get around
+ problems dealing with GObject inheritance and static memory problems. We
+ have a run time loaded object deriving from the library, so it has to link it in. But then
+ the problem that occurs is that both the run-time loaded library and the
+ program that calls it statically link the .la in. Then they have different
+ memory spaces, and type registration goes to pot. Open to suggestions if there's
+ a way of doing this without making an installed library.
+
+ * gnome-window-manager.c: (gnome_window_manager_new),
+ (gnome_window_manager_get_name), (gnome_window_manager_set_theme),
+ (gnome_window_manager_get_theme_list),
+ (gnome_window_manager_set_font),
+ (gnome_window_manager_get_focus_follows_mouse),
+ (gnome_window_manager_set_focus_follows_mouse),
+ (gnome_window_manager_init), (gnome_window_manager_finalize),
+ (gnome_window_manager_class_init), (gnome_window_manager_get_type):
+ * gnome-window-manager.h:
+
+ Lots of formatting fixes, change some of the boilerplate.
+
+ * gnome-window-settings-2.0.pc.in:
+
+ Since we're installing a library, go the whole way. Its good to make this
+ easy to depend on for external window managers anyway, now that I think
+ of it.
+
+ * gnome-wm-manager.c: (gnome_wm_manager_init),
+ (gnome_wm_manager_get_list), (gnome_wm_manager_set_current),
+ (gnome_wm_manager_get_current),
+ (gnome_wm_manager_change_wm_to_settings), (restart_label_update),
+ (restart_dialog_raise), (restart_dialog_destroyed),
+ (show_restart_dialog), (hide_restart_dialog), (init_session),
+ (update_session), (init_callback), (restart_finalize),
+ (restart_failure), (show_restart_info), (restart_finish),
+ (restart_callback), (restart), (revert_callback),
+ (cancel_callback):
+ * gnome-wm-manager.h:
+
+ Add code for doing the window manager switch to the library,
+ snitched out of wm-properties. Its probably a little broken right now.
+
+ * wm-exec.c: (wm_is_running), (find_gnome_wm_window),
+ (find_wm_window_from_client), (window_has_wm_state),
+ (descendent_has_wm_state), (find_wm_window_from_hunt),
+ (find_wm_window), (start_timeout), (start_do), (kill_timeout),
+ (wm_restart), (wm_guess_current):
+ * wm-list.c: (is_blank), (wm_compare), (wm_free),
+ (wm_check_present), (wm_copy), (wm_list_find), (wm_list_find_exec),
+ (wm_list_find_files), (wm_list_read_dir), (wm_list_init),
+ (wm_list_save), (wm_list_revert), (wm_list_add), (wm_list_delete),
+ (wm_list_set_current), (wm_list_get_current), (wm_list_get_revert),
+ (wm_read_from_xml), (wm_list_read_from_xml), (wm_write_to_xml),
+ (wm_list_write_to_xml), (xml_read_bool), (xml_write_bool):
+ * wm-properties.h:
+
+ Take wm-switching code out of the capplet, move it here.
+
+ (Jacob, I did a make dist and build the resulting tarball, hope things
+ don't break for you this time ... )
+
2002-05-15 jacob berkman <jacob@ximian.com>
* Makefile.am: don't link against libs, like libbackground does
diff --git a/libwindow-settings/Makefile.am b/libwindow-settings/Makefile.am
index 79baf3335..8fe70a222 100644
--- a/libwindow-settings/Makefile.am
+++ b/libwindow-settings/Makefile.am
@@ -1,6 +1,4 @@
-EXTRA_DIST = ChangeLog
-
-INCLUDES = \
+INCLUDES = \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-DGNOME_ICONDIR=\""${prefix}/share/pixmaps"\" \
-DG_LOG_DOMAIN=\"capplet-common\" \
@@ -8,8 +6,30 @@ INCLUDES = \
-I$(top_srcdir)/ \
@CAPPLET_CFLAGS@
-noinst_LTLIBRARIES = libwindow-settings.la
+lib_LTLIBRARIES = libgnome-window-settings.la
+
+libgnome_window_settings_la_LDFLAGS = \
+ -export_dynamic \
+ -version-info 1:0:0
-libwindow_settings_la_SOURCES = \
+libgnome_window_settings_la_SOURCES = \
gnome-window-manager.c \
- gnome-window-manager.h
+ gnome-window-manager.h \
+ gnome-wm-manager.c \
+ gnome-wm-manager.h \
+ wm-exec.c \
+ wm-list.c \
+ wm-properties.h
+
+libgnome_window_settingsincludedir = $(includedir)/gnome-window-settings-2.0
+
+libgnome_window_settingsinclude_HEADERS = \
+ gnome-window-manager.h \
+ gnome-wm-manager.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = gnome-window-settings-2.0.pc
+
+EXTRA_DIST = \
+ gnome-window-settings-2.0.pc.in \
+ ChangeLog \ No newline at end of file
diff --git a/libwindow-settings/gnome-window-manager.c b/libwindow-settings/gnome-window-manager.c
index 08e9edcd2..716843d65 100644
--- a/libwindow-settings/gnome-window-manager.c
+++ b/libwindow-settings/gnome-window-manager.c
@@ -2,6 +2,13 @@
#include <gmodule.h>
+static GObjectClass *parent_class;
+
+struct _GnomeWindowManagerPrivate {
+ char *window_manager_name;
+ GnomeDesktopItem *ditem;
+};
+
GObject *
gnome_window_manager_new (GnomeDesktopItem *item)
{
@@ -23,7 +30,7 @@ gnome_window_manager_new (GnomeDesktopItem *item)
return NULL;
}
- success = g_module_symbol (module, "window_manager_new",
+ success = g_module_symbol (module, "metacity_window_manager_get_type",
(gpointer *) &wm_new_func);
if ((!success) || wm_new_func == NULL) {
@@ -31,7 +38,126 @@ gnome_window_manager_new (GnomeDesktopItem *item)
return NULL;
}
- wm = (wm_new_func) ();
+ wm = g_object_new ((wm_new_func) (), NULL);
+
+ (GNOME_WINDOW_MANAGER (wm))->p->window_manager_name = g_strdup (gnome_desktop_item_get_string (item, GNOME_DESKTOP_ITEM_NAME));
+ (GNOME_WINDOW_MANAGER (wm))->p->ditem = gnome_desktop_item_ref (item);
return (wm);
}
+
+const char *
+gnome_window_manager_get_name (GnomeWindowManager *wm)
+{
+ return wm->p->window_manager_name;
+}
+void
+gnome_window_manager_set_theme (GnomeWindowManager *wm, const char *theme_name)
+{
+ GnomeWindowManagerClass *klass = GNOME_WINDOW_MANAGER_GET_CLASS (wm);
+ klass->set_theme (theme_name);
+}
+
+GList *
+gnome_window_manager_get_theme_list (GnomeWindowManager *wm)
+{
+ GnomeWindowManagerClass *klass = GNOME_WINDOW_MANAGER_GET_CLASS (wm);
+ return klass->get_theme_list ();
+}
+
+void
+gnome_window_manager_set_font (GnomeWindowManager *wm, const char *font)
+{
+ GnomeWindowManagerClass *klass = GNOME_WINDOW_MANAGER_GET_CLASS (wm);
+ klass->set_font (font);
+}
+
+gboolean
+gnome_window_manager_get_focus_follows_mouse (GnomeWindowManager *wm)
+{
+ GnomeWindowManagerClass *klass = GNOME_WINDOW_MANAGER_GET_CLASS (wm);
+ return klass->get_focus_follows_mouse ();
+}
+
+void
+gnome_window_manager_set_focus_follows_mouse (GnomeWindowManager *wm, gboolean focus_follows_mouse)
+{
+ GnomeWindowManagerClass *klass = GNOME_WINDOW_MANAGER_GET_CLASS (wm);
+ klass->set_focus_follows_mouse (focus_follows_mouse);
+}
+
+static void
+gnome_window_manager_init (GnomeWindowManager *gnome_window_manager, GnomeWindowManagerClass *class)
+{
+ gnome_window_manager->p = g_new0 (GnomeWindowManagerPrivate, 1);
+}
+
+static void
+gnome_window_manager_finalize (GObject *object)
+{
+ GnomeWindowManager *gnome_window_manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (IS_GNOME_WINDOW_MANAGER (object));
+
+ gnome_window_manager = GNOME_WINDOW_MANAGER (object);
+
+ g_free (gnome_window_manager->p);
+
+ parent_class->finalize (object);
+}
+
+
+static void
+gnome_window_manager_class_init (GnomeWindowManagerClass *class)
+{
+ GObjectClass *object_class;
+ GnomeWindowManagerClass *wm_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ wm_class = GNOME_WINDOW_MANAGER_CLASS (class);
+
+ object_class->finalize = gnome_window_manager_finalize;
+
+ wm_class->set_theme = NULL;
+ wm_class->get_theme_list = NULL;
+ wm_class->set_font = NULL;
+ wm_class->get_focus_follows_mouse = NULL;
+ wm_class->set_focus_follows_mouse = NULL;
+
+ parent_class = g_type_class_peek_parent (class);
+}
+
+GType
+gnome_window_manager_get_type (void)
+{
+ static GType gnome_window_manager_type = 0;
+
+ printf ("getting called...\n");
+
+ if (!gnome_window_manager_type) {
+ static GTypeInfo gnome_window_manager_info = {
+ sizeof (GnomeWindowManagerClass),
+ NULL, /* GBaseInitFunc */
+ NULL, /* GBaseFinalizeFunc */
+ (GClassInitFunc) gnome_window_manager_class_init,
+ NULL, /* GClassFinalizeFunc */
+ NULL, /* user-supplied data */
+ sizeof (GnomeWindowManager),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gnome_window_manager_init,
+ NULL
+ };
+
+ gnome_window_manager_type =
+ g_type_register_static (G_TYPE_OBJECT,
+ "GWindowManager",
+ &gnome_window_manager_info, 0);
+ }
+
+ printf ("done\n");
+
+ return gnome_window_manager_type;
+}
+
+
diff --git a/libwindow-settings/gnome-window-manager.h b/libwindow-settings/gnome-window-manager.h
index 3da3efb16..9188602ae 100644
--- a/libwindow-settings/gnome-window-manager.h
+++ b/libwindow-settings/gnome-window-manager.h
@@ -1,7 +1,6 @@
#ifndef GNOME_WINDOW_MANAGER_H
#define GNOME_WINDOW_MANAGER_H
-#include <glib/gerror.h>
#include <glib-object.h>
#include <libgnome/gnome-desktop-item.h>
@@ -10,43 +9,45 @@ typedef GObject * (* GnomeWindowManagerNewFunc) (void);
G_BEGIN_DECLS
-#define GNOME_WINDOW_MANAGER_TYPE (gnome_window_manager_get_type ())
-#define GNOME_WINDOW_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_WINDOW_MANAGER_TYPE, GnomeWindowManager))
-#define GNOME_WINDOW_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_WINDOW_MANAGER_TYPE, GnomeWindowManagerClass))
-#define IS_GNOME_WINDOW_MANAGER(obj) (GTK_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_WINDOW_MANAGER_TYPE))
-#define IS_GNOME_WINDOW_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_WINDOW_MANAGER_TYPE))
-#define GNOME_WINDOW_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_WINDOW_MANAGER_TYPE, GnomeWindowManagerClass))
-
-#define GNOME_WINDOW_MANAGER_ERROR gnome_window_manager_error_quark ()
+#define GNOME_WINDOW_MANAGER(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, gnome_window_manager_get_type (), GnomeWindowManager)
+#define GNOME_WINDOW_MANAGER_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, gnome_window_manager_get_type (), GnomeWindowManagerClass)
+#define IS_GNOME_WINDOW_MANAGER(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, gnome_window_manager_get_type ())
+#define GNOME_WINDOW_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), gnome_window_manager_get_type, GnomeWindowManagerClass))
typedef struct _GnomeWindowManager GnomeWindowManager;
typedef struct _GnomeWindowManagerClass GnomeWindowManagerClass;
+
typedef struct _GnomeWindowManagerPrivate GnomeWindowManagerPrivate;
struct _GnomeWindowManager
{
- GObject parent_instance;
+ GObject parent;
+
+ GnomeWindowManagerPrivate *p;
};
struct _GnomeWindowManagerClass
{
- GObjectClass parent_class;
+ GObjectClass klass;
+
+ void (*set_theme) (const char *theme_name);
+ GList * (*get_theme_list) (void);
+ void (*set_font) (const char *font);
+ gboolean (*get_focus_follows_mouse) (void);
+ void (*set_focus_follows_mouse) (gboolean focus_follows_mouse);
- void (*set_theme) (const char *theme_name);
- GList * (*get_theme_list) (void);
- void (*set_font) (const char *font);
- gboolean (*get_focus_follows_mouse) (void);
- void (*set_focus_follows_mouse) (gboolean focus_follows_mouse);
};
-GObject *gnome_window_manager_new (GnomeDesktopItem *item);
-GType gnome_window_manager_get_type (void);
-void gnome_window_manager_set_theme (const char *theme_name);
-GList * gnome_window_manager_get_theme_list (void);
-void gnome_window_manager_set_font (const char *font);
-gboolean gnome_window_manager_get_focus_follows_mouse (void);
-void gnome_window_manager_set_focus_follows_mouse (gboolean focus_follows_mouse);
+GObject * gnome_window_manager_new (GnomeDesktopItem *item);
+GType gnome_window_manager_get_type (void);
+
+const char * gnome_window_manager_get_name (GnomeWindowManager *wm);
+void gnome_window_manager_set_theme (GnomeWindowManager *wm, const char *theme_name);
+GList * gnome_window_manager_get_theme_list (GnomeWindowManager *wm);
+void gnome_window_manager_set_font (GnomeWindowManager *wm, const char *font);
+gboolean gnome_window_manager_get_focus_follows_mouse (GnomeWindowManager *wm);
+void gnome_window_manager_set_focus_follows_mouse (GnomeWindowManager *wm, gboolean focus_follows_mouse);
G_END_DECLS
diff --git a/libwindow-settings/gnome-window-settings-2.0.pc.in b/libwindow-settings/gnome-window-settings-2.0.pc.in
new file mode 100644
index 000000000..0baab2a3e
--- /dev/null
+++ b/libwindow-settings/gnome-window-settings-2.0.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: gnome-window-settings-2.0
+Description: Utility library for getting window manager settings
+Requires: gtk+-2.0 libgnomeui-2.0
+Version: @VERSION@
+Libs: -L${libdir} -lwindow-settings
+Cflags: -I${includedir}/gnome-window-settings-2.0
diff --git a/libwindow-settings/gnome-wm-manager.c b/libwindow-settings/gnome-wm-manager.c
new file mode 100644
index 000000000..3e73bb066
--- /dev/null
+++ b/libwindow-settings/gnome-wm-manager.c
@@ -0,0 +1,608 @@
+#include "gnome-wm-manager.h"
+#include "wm-properties.h"
+
+#include <gtk/gtk.h>
+#include <libgnomeui/gnome-client.h>
+#include <gnome.h>
+
+/* prototypes */
+static void restart (gboolean force);
+static void revert_callback (void);
+static void cancel_callback (void);
+static void update_session (void);
+
+static WindowManager *selected_wm = NULL;
+
+/* 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;
+
+/* Current state
+ */
+static StateType state = STATE_IDLE;
+
+/* Set TRUE when we've exited the main loop, but restart_pending
+ */
+static gboolean quit_pending = FALSE;
+
+/* Set TRUE when we're waiting for the WM to restart
+ */
+static gboolean restart_pending = FALSE;
+
+static GtkWidget *capplet;
+
+void
+gnome_wm_manager_init (GtkWidget *some_window)
+{
+ wm_list_init();
+ selected_wm = wm_list_get_current();
+}
+
+GList *
+gnome_wm_manager_get_list (void)
+{
+ GList *wm_ditem;
+ GList *wms = NULL;
+ GnomeDesktopItem *ditem;
+
+ printf ("Total number of wms is %d\n", g_list_length (window_managers));
+
+ for (wm_ditem = window_managers; wm_ditem != NULL; wm_ditem = wm_ditem->next) {
+ ditem = ((WindowManager *)wm_ditem->data)->dentry;
+ wms = g_list_prepend (wms, gnome_window_manager_new (ditem));
+ }
+
+ return wms;
+}
+
+void
+gnome_wm_manager_set_current (GnomeWindowManager *wm)
+{
+ /*selected_wm = wm->ditem;*/
+}
+
+GnomeWindowManager *
+gnome_wm_manager_get_current (void)
+{
+ return gnome_window_manager_new (wm_list_get_current()->dentry);
+}
+
+void gnome_wm_manager_change_wm_to_settings (void)
+{
+ state = STATE_TRY;
+ restart(FALSE);
+ wm_list_set_current (selected_wm);
+ wm_list_save ();
+ update_session ();
+}
+
+
+static GtkWidget *restart_dialog = NULL;
+static GtkWidget *restart_label = NULL;
+static guint restart_dialog_timeout;
+static gchar *restart_name = NULL;
+
+/* Time until dialog times out */
+static gdouble restart_remaining_time;
+static gint restart_displayed_time;
+
+static GnomeClient *client = NULL;
+
+/* 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
+ */
+
+
+
+static void
+restart_label_update (void)
+{
+ gchar *tmp;
+
+ if ((gint)restart_remaining_time != restart_displayed_time) {
+ restart_displayed_time = restart_remaining_time;
+
+ tmp = g_strdup_printf (_("Starting %s\n"
+ "(%d seconds left before operation times out)"),
+ restart_name,
+ restart_displayed_time);
+ gtk_label_set_text (GTK_LABEL (restart_label), tmp);
+ g_free (tmp);
+ }
+}
+
+static gboolean
+restart_dialog_raise (gpointer data)
+{
+ if (restart_dialog && GTK_WIDGET_REALIZED (restart_dialog)) {
+ restart_remaining_time -= 0.25;
+ restart_label_update();
+ 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) {
+ restart_dialog_timeout = gtk_timeout_add (250, restart_dialog_raise, NULL);
+ }
+
+ restart_remaining_time = 10.0;
+ restart_displayed_time = -1;
+ if (restart_name)
+ g_free (restart_name);
+
+ restart_name = g_strdup (name);
+ restart_label_update ();
+
+ gtk_widget_show_all (restart_dialog);
+}
+
+static void
+hide_restart_dialog (void)
+{
+ if (restart_dialog)
+ gtk_widget_destroy (restart_dialog);
+}
+
+static void
+init_session (void)
+{
+ GnomeClientFlags flags;
+ gint token;
+
+ return;
+
+ 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)
+ printf ("broken\n");
+ /*update_session();*/
+ else {
+ gnome_client_set_restart_style (client,
+ GNOME_RESTART_NEVER);
+ gnome_client_flush (client);
+ }
+ }
+}
+
+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 {
+ g_warning ("We don't properly handle non-session managed Window Managers right now");
+ }
+ //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_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;
+ }
+
+ restart_pending = FALSE;
+}
+
+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?gnome_desktop_item_get_string (selected_wm->dentry, GNOME_DESKTOP_ITEM_NAME):"Unknown",
+ current_wm?gnome_desktop_item_get_string (current_wm->dentry, GNOME_DESKTOP_ITEM_NAME):"Unknown");
+ 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
+show_restart_info (void)
+{
+ gchar *save_session;
+
+ save_session = gnome_is_program_in_path ("save-session");
+
+ if (save_session != NULL) {
+ system (save_session);
+ }
+
+ g_free (save_session);
+}
+
+static void
+restart_finish (void)
+{
+ switch (state) {
+ case STATE_TRY:
+ case STATE_REVERT:
+ case STATE_OK:
+ case STATE_CANCEL:
+ hide_restart_dialog();
+ show_restart_info ();
+ 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
+restart (gboolean force)
+{
+ WindowManager *current_wm = wm_list_get_current(), *mywm;
+ static gboolean last_try_was_twm = FALSE;
+ GnomeDesktopItem *twm_dentry = gnome_desktop_item_new ();
+ WindowManager twm_fallback = {twm_dentry, "twm", "twm", 0, 0, 1, 0};
+
+ gnome_desktop_item_set_entry_type (twm_dentry, GNOME_DESKTOP_ITEM_TYPE_APPLICATION);
+ gnome_desktop_item_set_string (twm_dentry,
+ GNOME_DESKTOP_ITEM_NAME, "twm");
+ gnome_desktop_item_set_string (twm_dentry,
+ GNOME_DESKTOP_ITEM_COMMENT, "twm");
+ gnome_desktop_item_set_string (twm_dentry,
+ GNOME_DESKTOP_ITEM_EXEC, "twm");
+
+ if(selected_wm) {
+ last_try_was_twm = FALSE;
+ mywm = selected_wm;
+ } else if(!last_try_was_twm) {
+ last_try_was_twm = TRUE;
+ mywm = (WindowManager*)&twm_fallback;
+ } else {
+ restart_finalize();
+ gnome_desktop_item_unref (twm_dentry);
+ return;
+ }
+
+ if (force || current_wm != mywm) {
+ show_restart_dialog (g_strdup (gnome_desktop_item_get_string (mywm->dentry, GNOME_DESKTOP_ITEM_NAME)));
+ if (state != STATE_OK && state != STATE_CANCEL)
+ gtk_widget_set_sensitive (capplet, FALSE);
+ restart_pending = TRUE;
+ wm_restart (mywm,
+ capplet->window,
+ restart_callback,
+ NULL);
+ } else {
+ restart_finalize ();
+ }
+
+ gnome_desktop_item_unref (twm_dentry);
+}
+
+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;
+ }
+}
+
+
diff --git a/libwindow-settings/gnome-wm-manager.h b/libwindow-settings/gnome-wm-manager.h
new file mode 100644
index 000000000..e34af595a
--- /dev/null
+++ b/libwindow-settings/gnome-wm-manager.h
@@ -0,0 +1,22 @@
+#ifndef GNOME_WINDOW_MANAGER_LIST_H
+#define GNOME_WINDOW_MANAGER_LIST_H
+
+#include <gtk/gtk.h>
+
+#include "gnome-window-manager.h"
+
+void gnome_wm_manager_init (GtkWidget *some_window);
+
+/* returns a GList of available window managers */
+GList * gnome_wm_manager_get_list (void);
+
+/* sets the currently active window manager in GConf */
+void gnome_wm_manager_set_current (GnomeWindowManager *wm);
+
+/* gets the currently active window manager from GConf */
+GnomeWindowManager *gnome_wm_manager_get_current (void);
+
+/* change to the wm specified in GConf */
+void gnome_wm_manager_change_wm_to_settings (void);
+
+#endif
diff --git a/libwindow-settings/wm-exec.c b/libwindow-settings/wm-exec.c
new file mode 100644
index 000000000..f8d9356bf
--- /dev/null
+++ b/libwindow-settings/wm-exec.c
@@ -0,0 +1,331 @@
+/* -*- 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 <otaylor@redhat.com>
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <libgnome/libgnome.h>
+#include "wm-properties.h"
+
+typedef struct _RestartInfo RestartInfo;
+
+struct _RestartInfo {
+ GnomeDesktopItem *dentry;
+ gint retries;
+ WMResultFunc callback;
+ gpointer data;
+};
+
+gboolean
+wm_is_running (void)
+{
+ gboolean result;
+ guint old_mask;
+ XWindowAttributes attrs;
+
+ gdk_error_trap_push ();
+
+ XGetWindowAttributes (GDK_DISPLAY(), GDK_ROOT_WINDOW(), &attrs);
+
+ XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
+ SubstructureRedirectMask);
+ XSync (GDK_DISPLAY(), False);
+ if (gdk_error_trap_pop () == 0) {
+ result = FALSE;
+ XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
+ attrs.your_event_mask);
+ } else
+ result = TRUE;
+
+
+ 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;
+ GdkAtom cardinal_atom = gdk_atom_intern ("CARDINAL", FALSE);
+
+ gdk_error_trap_push ();
+ if (XGetWindowProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
+ gdk_x11_atom_to_xatom (gdk_atom_intern ("_WIN_SUPPORTING_WM_CHECK", FALSE)),
+ 0, 1, False, gdk_x11_atom_to_xatom (cardinal_atom),
+ &r_type, &r_format,
+ &count, &bytes_remain, &prop) == Success && prop)
+ {
+ if (r_type == gdk_x11_atom_to_xatom (cardinal_atom) && r_format == 32 && count == 1)
+ {
+ Window n = *(long *)prop;
+ if (XGetWindowProperty(GDK_DISPLAY(), n,
+ gdk_x11_atom_to_xatom (gdk_atom_intern ("_WIN_SUPPORTING_WM_CHECK", FALSE)),
+ 0, 1, False, gdk_x11_atom_to_xatom (cardinal_atom),
+ &r_type, &r_format, &count, &bytes_remain,
+ &prop2) == Success && prop)
+ {
+ if (r_type == gdk_x11_atom_to_xatom (cardinal_atom) && r_format == 32 && count == 1)
+ {
+ XFree(prop);
+ XFree(prop2);
+ gdk_error_trap_pop ();
+ return n;
+ }
+ XFree(prop2);
+ }
+ }
+ XFree(prop);
+ }
+ gdk_error_trap_pop ();
+ return None;
+}
+
+static Window
+find_wm_window_from_client (GdkWindow *client)
+{
+ Window window, frame, parent, root;
+ Window *children;
+ unsigned int nchildren;
+ gboolean needs_pop = TRUE;
+
+ if (!client)
+ return None;
+
+ frame = None;
+ window = GDK_WINDOW_XWINDOW (client);
+
+ gdk_error_trap_push ();
+
+ while (XQueryTree (GDK_DISPLAY(), window,
+ &root, &parent, &children, &nchildren))
+ {
+ if (gdk_error_trap_pop != 0)
+ {
+ needs_pop = FALSE;
+ break;
+ }
+
+ gdk_error_trap_push ();
+
+ if (children)
+ XFree(children);
+
+ if (window == root)
+ break;
+
+ if (root == parent) {
+ frame = window;
+ break;
+ }
+ window = parent;
+ }
+
+ if (needs_pop)
+ gdk_error_trap_pop ();
+
+ 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_x11_atom_to_xatom (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; i<nchildren; i++) {
+ if (window_has_wm_state (children[i]) ||
+ descendent_has_wm_state (children[i])) {
+ result = TRUE;
+ break;
+ }
+ }
+
+ if (children)
+ XFree (children);
+
+ return result;
+}
+
+/* This function tries to find a window manager frame by
+ * hunting all the children of the root window
+ */
+static Window
+find_wm_window_from_hunt (void)
+{
+ Window parent, root, frame;
+ Window *children;
+ unsigned int nchildren;
+ gint i;
+
+ frame = None;
+
+ gdk_error_trap_push ();
+
+ XQueryTree (GDK_DISPLAY(), GDK_ROOT_WINDOW (),
+ &root, &parent, &children, &nchildren);
+
+ /* We are looking for a window that doesn't have WIN_STATE
+ * set on it, but does have a child with WIN_STATE set
+ */
+ for (i=0; i<nchildren; i++) {
+ if (!window_has_wm_state (children[i]) &&
+ descendent_has_wm_state (children[i])) {
+ frame = children[i];
+ break;
+ }
+ }
+
+ if (children)
+ XFree (children);
+
+ gdk_error_trap_pop ();
+
+ return frame;
+}
+
+static Window
+find_wm_window (GdkWindow *client)
+{
+ Window wm_window = None;
+
+ /* First, try to find a GNOME compliant WM */
+
+ wm_window = find_gnome_wm_window();
+
+ if (!wm_window) {
+ wm_window = find_wm_window_from_client (client);
+ }
+
+ if (!wm_window) {
+ wm_window = find_wm_window_from_hunt ();
+ }
+
+ return wm_window;
+}
+
+static gboolean
+start_timeout (gpointer data)
+{
+ RestartInfo *info = data;
+ if (wm_is_running ()) {
+ info->callback(WM_SUCCESS, info->data);
+ gnome_desktop_item_unref (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_item_unref (info->dentry);
+ g_free (info);
+ return FALSE;
+ }
+ }
+}
+
+static void
+start_do (RestartInfo *info)
+{
+ gnome_desktop_item_launch (info->dentry, 0, 0, NULL);
+
+ info->retries = 10;
+ 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_item_unref (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_item_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_item_unref (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/libwindow-settings/wm-list.c b/libwindow-settings/wm-list.c
new file mode 100644
index 000000000..68fff2acd
--- /dev/null
+++ b/libwindow-settings/wm-list.c
@@ -0,0 +1,577 @@
+/* -*- 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 <otaylor@redhat.com>,
+ * Bradford Hovinen <hovinen@helixcode.com>
+ */
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <libgnome/libgnome.h>
+#include <gconf/gconf-client.h>
+#include <string.h>
+
+#include "wm-properties.h"
+
+
+#define CONFIG_PREFIX "/desktop/gnome/applications/window_manager"
+
+/* 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 = NULL;
+
+/* Window manager on startup */
+static WindowManager *current_wm_save = NULL;
+
+static gboolean xml_read_bool (xmlNodePtr node);
+static xmlNodePtr xml_write_bool (gchar *name,
+ gboolean value);
+
+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 (gnome_desktop_item_get_string (wm_a->dentry, GNOME_DESKTOP_ITEM_NAME), gnome_desktop_item_get_string (wm_b->dentry, GNOME_DESKTOP_ITEM_NAME));
+}
+
+static void
+wm_free (WindowManager *wm)
+{
+ gnome_desktop_item_unref (wm->dentry);
+ g_free (wm->config_exec);
+ g_free (wm->config_tryexec);;
+ g_free (wm);
+}
+
+void
+wm_check_present (WindowManager *wm)
+{
+ gchar *path;
+
+ if (gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_EXEC)) {
+ if (gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_TRY_EXEC)) {
+ path = gnome_is_program_in_path (gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_TRY_EXEC));
+ 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 {
+ path = gnome_is_program_in_path (wm->config_exec);
+ wm->is_config_present = (path != NULL);
+ if (path)
+ g_free (path);
+ }
+ } else
+ wm->is_config_present = FALSE;
+
+}
+
+static WindowManager *
+wm_copy (WindowManager *wm)
+{
+ WindowManager *result = g_new (WindowManager, 1);
+
+ result->dentry = gnome_desktop_item_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, const char *name)
+{
+ GList *tmp_list = list;
+ while (tmp_list) {
+ WindowManager *wm = tmp_list->data;
+ if (strcmp (gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_EXEC), name) == 0)
+ return wm;
+
+ tmp_list = tmp_list->next;
+ }
+
+ return NULL;
+}
+
+static WindowManager *
+wm_list_find_exec (GList *list, const char *name)
+{
+ GList *tmp_list = list;
+ while (tmp_list) {
+ WindowManager *wm = tmp_list->data;
+ if (!gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_EXEC))
+ continue;
+ if (strcmp (gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_EXEC), 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_item_new_from_file (tmp_list->data, GNOME_DESKTOP_ITEM_TYPE_APPLICATION, NULL);
+ gnome_desktop_item_set_entry_type (wm->dentry, GNOME_DESKTOP_ITEM_TYPE_APPLICATION);
+
+ if (!wm->dentry) {
+ g_free (wm);
+ tmp_list = tmp_list->next;
+ continue;
+ }
+
+ prefix = g_strconcat ("=", gnome_desktop_item_get_location (wm->dentry), "=/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;
+ }
+
+ if (wm->config_tryexec && is_blank (wm->config_tryexec)) {
+ g_free (wm->config_tryexec);
+ wm->config_tryexec = NULL;
+ }
+
+ gnome_config_pop_prefix ();
+
+ wm_check_present (wm);
+
+ if (gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_NAME) && gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_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;
+ GConfClient *client;
+
+ 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);
+
+ client = gconf_client_get_default ();
+ name = gconf_client_get_string (client, CONFIG_PREFIX "/current", NULL);
+ if (name) {
+ current_wm = wm_list_find (window_managers, name);
+ g_free (name);
+ }
+
+ if (!current_wm) {
+ name = gconf_client_get_string (client, CONFIG_PREFIX "/default", NULL);
+
+ if (name) {
+ current_wm = wm_list_find_exec (window_managers, name);
+ g_free (name);
+ }
+ }
+
+ if (!current_wm) {
+ gchar *wmfile, *prefix;
+
+ wmfile = gnome_unconditional_datadir_file ("default.wm");
+ prefix = g_strconcat ("=", wmfile, "=/Default/WM", NULL);
+ name = gnome_config_get_string (prefix);
+
+ g_free (wmfile);
+ g_free (prefix);
+
+ if (name) {
+ current_wm = wm_list_find_exec (window_managers, name);
+ g_free (name);
+ }
+ }
+
+ if (!current_wm && window_managers)
+ current_wm = window_managers->data;
+
+ if(current_wm)
+ current_wm_save = wm_list_find (window_managers_save, gnome_desktop_item_get_string (current_wm->dentry, GNOME_DESKTOP_ITEM_NAME));
+
+ g_object_unref (G_OBJECT (client));
+}
+
+void
+wm_list_save (void)
+{
+ GList *old_files;
+ GList *tmp_list;
+ gchar *tempdir;
+ 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_item_save (wm->dentry, NULL, TRUE, NULL);
+
+ prefix = g_strconcat ("=", gnome_desktop_item_get_location (wm->dentry), "=/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
+ */
+ if(current_wm)
+ {
+ GConfClient *client = gconf_client_get_default ();
+ gconf_client_set_string (client, CONFIG_PREFIX "/current",
+ gnome_desktop_item_get_string (current_wm->dentry, GNOME_DESKTOP_ITEM_EXEC),
+ NULL);
+ g_object_unref (G_OBJECT (client));
+ }
+
+ gnome_config_sync ();
+}
+
+void
+wm_list_revert (void)
+{
+ GList *tmp_list;
+ gchar *old_name = NULL;
+
+ if(current_wm)
+ old_name = g_strdup (gnome_desktop_item_get_string (current_wm->dentry, GNOME_DESKTOP_ITEM_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)
+{
+ if(current_wm_save)
+ return wm_list_find (window_managers, gnome_desktop_item_get_string (current_wm_save->dentry, GNOME_DESKTOP_ITEM_NAME));
+ else
+ return NULL;
+}
+
+static WindowManager *
+wm_read_from_xml (xmlNodePtr wm_node)
+{
+ xmlNodePtr node;
+ WindowManager *wm;
+ gboolean is_current = FALSE;
+
+ if (strcmp (wm_node->name, "window-manager")) return NULL;
+
+ wm = g_new0 (WindowManager, 1);
+
+ wm->dentry = gnome_desktop_item_new_from_file
+ (xmlGetProp (wm_node, "desktop-entry"),
+ GNOME_DESKTOP_ITEM_TYPE_APPLICATION, NULL);
+ gnome_desktop_item_set_entry_type (wm->dentry, GNOME_DESKTOP_ITEM_TYPE_APPLICATION);
+
+ for (node = wm_node->children; node; node = node->next) {
+ if (!strcmp (node->name, "config-exec"))
+ wm->config_exec = xmlNodeGetContent (node);
+ else if (!strcmp (node->name, "config-tryexec"))
+ wm->config_tryexec = xmlNodeGetContent (node);
+ else if (!strcmp (node->name, "session-managed"))
+ wm->session_managed = xml_read_bool (node);
+ else if (!strcmp (node->name, "is-user"))
+ wm->is_user = xml_read_bool (node);
+ else if (!strcmp (node->name, "is-current"))
+ is_current = xml_read_bool (node); /* FIXME: sanity check */
+ }
+
+ wm_check_present (wm);
+
+ if (wm->dentry == NULL ||
+ (wm->config_exec != NULL && is_blank (wm->config_exec)) ||
+ gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_NAME) == NULL || gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_EXEC) == NULL ||
+ !(wm->is_user || wm->is_present))
+ {
+ g_free (wm);
+ return NULL;
+ }
+
+ if (is_current) current_wm = wm;
+
+ return wm;
+}
+
+void
+wm_list_read_from_xml (xmlDocPtr doc)
+{
+ xmlNodePtr root_node, node;
+ WindowManager *wm;
+
+ root_node = xmlDocGetRootElement (doc);
+ if (strcmp (root_node->name, "wm-prefs")) return;
+
+ for (node = root_node; node; node = node->next) {
+ if (!strcmp (node->name, "window-manager")) {
+ wm = wm_read_from_xml (node);
+ if (wm) window_managers =
+ g_list_insert_sorted
+ (window_managers, wm, wm_compare);
+ }
+ }
+}
+
+static xmlNodePtr
+wm_write_to_xml (WindowManager *wm)
+{
+ xmlNodePtr node;
+
+ node = xmlNewNode (NULL, "window-manager");
+
+ xmlNewProp (node, "desktop-entry", gnome_desktop_item_get_location (wm->dentry));
+
+ if (wm->config_exec != NULL)
+ xmlNewChild (node, NULL, "config-exec", wm->config_exec);
+
+ xmlAddChild (node, xml_write_bool ("session-managed",
+ wm->session_managed));
+
+ xmlAddChild (node, xml_write_bool ("is-user", wm->is_user));
+ xmlAddChild (node, xml_write_bool ("is-current", wm == current_wm));
+
+ return node;
+}
+
+xmlDocPtr
+wm_list_write_to_xml (void)
+{
+ xmlDocPtr doc;
+ xmlNodePtr root_node, node;
+ GList *wm_node;
+
+ doc = xmlNewDoc ("1.0");
+ root_node = xmlNewDocNode (doc, NULL, "wm-prefs", NULL);
+
+ for (wm_node = window_managers; wm_node; wm_node = wm_node->next) {
+ node = wm_write_to_xml ((WindowManager *) wm_node->data);
+ if (node) xmlAddChild (root_node, node);
+ }
+
+ xmlDocSetRootElement (doc, root_node);
+
+ return doc;
+}
+
+/* Read a boolean value from a node */
+
+static gboolean
+xml_read_bool (xmlNodePtr node)
+{
+ char *text;
+
+ text = xmlNodeGetContent (node);
+
+ if (!g_strcasecmp (text, "true"))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Write out a boolean value in a node */
+
+static xmlNodePtr
+xml_write_bool (gchar *name, gboolean value)
+{
+ xmlNodePtr node;
+
+ g_return_val_if_fail (name != NULL, NULL);
+
+ node = xmlNewNode (NULL, name);
+
+ if (value)
+ xmlNodeSetContent (node, "true");
+ else
+ xmlNodeSetContent (node, "false");
+
+ return node;
+}
diff --git a/libwindow-settings/wm-properties.h b/libwindow-settings/wm-properties.h
new file mode 100644
index 000000000..f14dc4ea5
--- /dev/null
+++ b/libwindow-settings/wm-properties.h
@@ -0,0 +1,63 @@
+/* -*- 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 <otaylor@redhat.com>,
+ * Bradford Hovinen <hovinen@helixcode.com>
+ */
+
+#include <gdk/gdk.h>
+#include <libgnome/libgnome.h>
+#include <libgnome/gnome-desktop-item.h>
+
+#include <libxml/tree.h>
+
+typedef struct _WindowManager WindowManager;
+
+struct _WindowManager {
+ GnomeDesktopItem *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);
+
+void wm_list_read_from_xml (xmlDocPtr doc);
+xmlDocPtr wm_list_write_to_xml (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);