[Xfce4-commits] <xfce4-panel:xfce-4.8> Panel: Wait until the wm is ready on all screens (bug #7161).

Nick Schermer noreply at xfce.org
Sat Jul 9 15:54:01 CEST 2011


Updating branch refs/heads/xfce-4.8
         to cabbdfd1c04caf20a71e0af773accf809135a03d (commit)
       from 8e5b6c8214413bdcd2e6dafb63ad86a57f329d83 (commit)

commit cabbdfd1c04caf20a71e0af773accf809135a03d
Author: Nick Schermer <nick at xfce.org>
Date:   Sat Jul 9 15:51:33 2011 +0200

    Panel: Wait until the wm is ready on all screens (bug #7161).
    
    (cherry picked from commit 4e14f278ea242dae6b7f4a3e0ebc1a98f79a1c55)
    (cherry picked from commit e3e6be1c591c8e9cce625722866a1c7b129ecdfd)
    (cherry picked from commit 9a2407b90828a8716d4972433d1fe2169cbff08c)

 panel/main.c              |    3 +
 panel/panel-application.c |  152 ++++++++++++++++++++++++++++++++++++++++++---
 panel/panel-application.h |    3 +
 3 files changed, 149 insertions(+), 9 deletions(-)

diff --git a/panel/main.c b/panel/main.c
index 76c851a..15600c8 100644
--- a/panel/main.c
+++ b/panel/main.c
@@ -58,6 +58,7 @@ static gchar     *opt_add = NULL;
 static gboolean   opt_restart = FALSE;
 static gboolean   opt_quit = FALSE;
 static gboolean   opt_version = FALSE;
+static gboolean   opt_disable_wm_check = FALSE;
 static gchar     *opt_plugin_event = NULL;
 static gchar    **opt_arguments = NULL;
 static gboolean   sm_client_saved_state = FALSE;
@@ -81,6 +82,7 @@ static GOptionEntry option_entries[] =
   { "add", '\0', 0, G_OPTION_ARG_STRING, &opt_add, N_("Add a new plugin to the panel"), N_("PLUGIN-NAME") },
   { "restart", 'r', 0, G_OPTION_ARG_NONE, &opt_restart, N_("Restart the running panel instance"), NULL },
   { "quit", 'q', 0, G_OPTION_ARG_NONE, &opt_quit, N_("Quit the running panel instance"), NULL },
+  { "disable-wm-check", 'd', 0, G_OPTION_ARG_NONE, &opt_disable_wm_check, N_("Do not wait for a window manager on startup"), NULL },
   { "version", 'V', 0, G_OPTION_ARG_NONE, &opt_version, N_("Print version information and exit"), NULL },
   { "plugin-event", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_plugin_event, NULL, NULL },
   { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &opt_arguments, NULL, NULL },
@@ -345,6 +347,7 @@ main (gint argc, gchar **argv)
     signal (signums[i], panel_signal_handler);
 
   application = panel_application_get ();
+  panel_application_load (application, opt_disable_wm_check);
 
   /* save the state before the quit signal if we can, this is a bit safer */
   g_signal_connect (G_OBJECT (sm_client), "save-state",
diff --git a/panel/panel-application.c b/panel/panel-application.c
index 03a6004..02a9cc6 100644
--- a/panel/panel-application.c
+++ b/panel/panel-application.c
@@ -30,6 +30,11 @@
 #include <libxfce4util/libxfce4util.h>
 #include <libxfce4ui/libxfce4ui.h>
 
+#ifdef GDK_WINDOWING_X11
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#endif
+
 #include <common/panel-private.h>
 #include <common/panel-xfconf.h>
 #include <common/panel-debug.h>
@@ -55,7 +60,6 @@
 
 
 static void      panel_application_finalize           (GObject                *object);
-static void      panel_application_load               (PanelApplication       *application);
 static void      panel_application_plugin_move        (GtkWidget              *item,
                                                        PanelApplication       *application);
 static gboolean  panel_application_plugin_insert      (PanelApplication       *application,
@@ -126,6 +130,10 @@ struct _PanelApplication
   /* autosave timeout */
   guint               autosave_timeout_id;
 
+#ifdef GDK_WINDOWING_X11
+  guint               wait_for_wm_timeout_id;
+#endif
+
   /* drag and drop data */
   guint               drop_data_ready : 1;
   guint               drop_occurred : 1;
@@ -133,6 +141,20 @@ struct _PanelApplication
   guint               drop_index;
 };
 
+#ifdef GDK_WINDOWING_X11
+typedef struct
+{
+  PanelApplication *application;
+
+  Display          *dpy;
+  Atom             *atoms;
+  guint             atom_count;
+  guint             have_wm : 1;
+  guint             counter;
+}
+WaitForWM;
+#endif
+
 enum
 {
   TARGET_PLUGIN_NAME,
@@ -204,18 +226,11 @@ panel_application_init (PanelApplication *application)
   /* get a factory reference so it never unloads */
   application->factory = panel_module_factory_get ();
 
-  /* load setup */
-  panel_application_load (application);
-
   /* start the autosave timeout */
   application->autosave_timeout_id =
       g_timeout_add_seconds (AUTOSAVE_INTERVAL,
                              panel_application_save_timeout,
                              application);
-
-  /* create empty window if everything else failed */
-  if (G_UNLIKELY (application->windows == NULL))
-    panel_application_new_window (application, NULL, TRUE);
 }
 
 
@@ -231,6 +246,12 @@ panel_application_finalize (GObject *object)
   /* stop the autosave timeout */
   g_source_remove (application->autosave_timeout_id);
 
+#ifdef GDK_WINDOWING_X11
+  /* stop autostart timeout */
+  if (application->wait_for_wm_timeout_id != 0)
+    g_source_remove (application->wait_for_wm_timeout_id);
+#endif
+
   /* free all windows */
   for (li = application->windows; li != NULL; li = li->next)
     {
@@ -298,7 +319,7 @@ panel_application_xfconf_window_bindings (PanelApplication *application,
 
 
 static void
-panel_application_load (PanelApplication *application)
+panel_application_load_real (PanelApplication *application)
 {
   PanelWindow  *window;
   guint         i, j, n_panels;
@@ -375,11 +396,75 @@ panel_application_load (PanelApplication *application)
 
       xfconf_array_free (array);
     }
+
+  /* create empty window if everything else failed */
+  if (G_UNLIKELY (application->windows == NULL))
+    panel_application_new_window (application, NULL, TRUE);
+}
+
+
+
+#ifdef GDK_WINDOWING_X11
+static gboolean
+panel_application_wait_for_window_manager (gpointer data)
+{
+  WaitForWM *wfwm = data;
+  guint      i;
+  gboolean   have_wm = TRUE;
+
+  for (i = 0; i < wfwm->atom_count; i++)
+    {
+      if (XGetSelectionOwner (wfwm->dpy, wfwm->atoms[i]) == None)
+        {
+          panel_debug (PANEL_DEBUG_APPLICATION, "window manager not ready on screen %d", i);
+
+          have_wm = FALSE;
+          break;
+        }
+    }
+
+  wfwm->have_wm = have_wm;
+
+  /* abort if a window manager is found or 5 seconds expired */
+  return wfwm->counter++ < 20 * 5 && !wfwm->have_wm;
 }
 
 
 
 static void
+panel_application_wait_for_window_manager_destroyed (gpointer data)
+{
+  WaitForWM        *wfwm = data;
+  PanelApplication *application = wfwm->application;
+
+  application->wait_for_wm_timeout_id = 0;
+
+  if (!wfwm->have_wm)
+    {
+      g_printerr (G_LOG_DOMAIN ": No window manager registered on screen 0. "
+                  "To start the panel without this check, run with --disable-wm-check.\n");
+    }
+  else
+    {
+      panel_debug (PANEL_DEBUG_APPLICATION, "found window manager after %d tries",
+                   wfwm->counter);
+    }
+
+  g_free (wfwm->atoms);
+  XCloseDisplay (wfwm->dpy);
+  g_slice_free (WaitForWM, wfwm);
+
+  /* start loading the panels, hopefully a window manager is found, but it
+   * probably also works fine without... */
+  GDK_THREADS_ENTER ();
+  panel_application_load_real (application);
+  GDK_THREADS_LEAVE ();
+}
+#endif
+
+
+
+static void
 panel_application_plugin_move_drag_data_get (GtkWidget        *item,
                                              GdkDragContext   *drag_context,
                                              GtkSelectionData *selection_data,
@@ -1092,6 +1177,55 @@ panel_application_get (void)
 
 
 void
+panel_application_load (PanelApplication  *application,
+                        gboolean           disable_wm_check)
+{
+#ifdef GDK_WINDOWING_X11
+  WaitForWM  *wfwm;
+  guint       i;
+  gchar     **atom_names;
+
+  if (!disable_wm_check)
+    {
+      /* setup data for wm checking */
+      wfwm = g_slice_new0 (WaitForWM);
+      wfwm->application = application;
+      wfwm->dpy = XOpenDisplay (NULL);
+      wfwm->have_wm = FALSE;
+      wfwm->counter = 0;
+
+      /* preload wm atoms for all screens */
+      wfwm->atom_count = XScreenCount (wfwm->dpy);
+      wfwm->atoms = g_new (Atom, wfwm->atom_count);
+      atom_names = g_new0 (gchar *, wfwm->atom_count + 1);
+
+      for (i = 0; i < wfwm->atom_count; i++)
+        atom_names[i] = g_strdup_printf ("WM_S%d", i);
+
+      if (!XInternAtoms (wfwm->dpy, atom_names, wfwm->atom_count, False, wfwm->atoms))
+        wfwm->atom_count = 0;
+
+      g_strfreev (atom_names);
+
+      /* setup timeout to check for a window manager */
+      application->wait_for_wm_timeout_id =
+          g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 50, panel_application_wait_for_window_manager,
+                              wfwm, panel_application_wait_for_window_manager_destroyed);
+    }
+  else
+    {
+      /* directly launch */
+      panel_application_load_real (application);
+    }
+#else
+  /* directly launch */
+  panel_application_load_real (application);
+#endif
+}
+
+
+
+void
 panel_application_save (PanelApplication *application,
                         gboolean          save_plugin_providers)
 {
diff --git a/panel/panel-application.h b/panel/panel-application.h
index 17238b1..5073821 100644
--- a/panel/panel-application.h
+++ b/panel/panel-application.h
@@ -38,6 +38,9 @@ GType             panel_application_get_type          (void) G_GNUC_CONST;
 
 PanelApplication *panel_application_get               (void);
 
+void              panel_application_load              (PanelApplication  *application,
+                                                       gboolean           disable_wm_check);
+
 void              panel_application_save              (PanelApplication  *application,
                                                        gboolean           save_plugin_providers);
 



More information about the Xfce4-commits mailing list