[Xfce4-commits] <xfce4-settings:master> Fix double spawning of the helper.

Nick Schermer noreply at xfce.org
Tue Jul 27 20:58:01 CEST 2010


Updating branch refs/heads/master
         to 0bd600f5d3d26aa48e482ecd9a75f961b86a5ace (commit)
       from 2ddb597ed86f235e7cb3b4233a716d03b00a84d8 (commit)

commit 0bd600f5d3d26aa48e482ecd9a75f961b86a5ace
Author: Nick Schermer <nick at xfce.org>
Date:   Tue Jul 27 20:53:54 2010 +0200

    Fix double spawning of the helper.
    
    The old code was crapy, use dbus to check for running instances
    so never 2 processes are running.

 xfce4-settings-helper/Makefile.am         |    2 -
 xfce4-settings-helper/clipboard-manager.c |   82 +++++++++++++++++++++-
 xfce4-settings-helper/main.c              |   83 ++++++++--------------
 xfce4-settings-helper/utils.c             |  110 -----------------------------
 xfce4-settings-helper/utils.h             |   28 -------
 xfce4-settings-helper/workspaces.c        |    1 -
 6 files changed, 110 insertions(+), 196 deletions(-)

diff --git a/xfce4-settings-helper/Makefile.am b/xfce4-settings-helper/Makefile.am
index 7036699..e4ca94f 100644
--- a/xfce4-settings-helper/Makefile.am
+++ b/xfce4-settings-helper/Makefile.am
@@ -28,8 +28,6 @@ xfce4_settings_helper_SOURCES = \
 	keyboard-layout.h \
 	pointers.c \
 	pointers.h \
-	utils.c \
-	utils.h \
 	workspaces.c \
 	workspaces.h
 
diff --git a/xfce4-settings-helper/clipboard-manager.c b/xfce4-settings-helper/clipboard-manager.c
index d214dbe..a67b4b3 100644
--- a/xfce4-settings-helper/clipboard-manager.c
+++ b/xfce4-settings-helper/clipboard-manager.c
@@ -305,6 +305,86 @@ xfce_clipboard_manager_primary_owner_change (XfceClipboardManager *manager,
 
 
 
+static gboolean
+xfce_clipboard_manager_selection_owner (const gchar   *selection_name,
+                                        gboolean       force,
+                                        GdkFilterFunc  filter_func)
+{
+#ifdef GDK_WINDOWING_X11
+    GdkDisplay *gdpy = gdk_display_get_default ();
+    GtkWidget *invisible;
+    Display *dpy = GDK_DISPLAY_XDISPLAY (gdpy);
+    GdkWindow *rootwin = gdk_screen_get_root_window (gdk_display_get_screen (gdpy, 0));
+    GdkWindow *invisible_window;
+    Window xroot = GDK_WINDOW_XID (rootwin);
+    GdkAtom selection_atom;
+    Atom selection_atom_x11;
+    XClientMessageEvent xev;
+    gboolean has_owner;
+
+    g_return_val_if_fail (selection_name != NULL, FALSE);
+
+    selection_atom = gdk_atom_intern (selection_name, FALSE);
+    selection_atom_x11 = gdk_x11_atom_to_xatom_for_display (gdpy, selection_atom);
+
+    /* can't use gdk for the selection owner here because it returns NULL
+     * if the selection owner is in another process */
+    if (!force)
+    {
+        gdk_error_trap_push ();
+        has_owner = XGetSelectionOwner (dpy, selection_atom_x11) != None;
+        gdk_flush ();
+        gdk_error_trap_pop ();
+        if (has_owner)
+            return FALSE;
+    }
+
+    invisible = gtk_invisible_new ();
+    gtk_widget_realize (invisible);
+    gtk_widget_add_events (invisible, GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK);
+
+    invisible_window = gtk_widget_get_window (invisible);
+
+    if (!gdk_selection_owner_set_for_display (gdpy, invisible_window,
+                                              selection_atom, GDK_CURRENT_TIME,
+                                              TRUE))
+    {
+        g_critical ("Unable to get selection %s", selection_name);
+        gtk_widget_destroy (invisible);
+        return FALSE;
+    }
+
+    /* but we can use gdk here since we only care if it's our window */
+    if (gdk_selection_owner_get_for_display (gdpy, selection_atom) != invisible_window)
+    {
+        gtk_widget_destroy (invisible);
+        return FALSE;
+    }
+
+    xev.type = ClientMessage;
+    xev.window = xroot;
+    xev.message_type = gdk_x11_get_xatom_by_name_for_display (gdpy, "MANAGER");
+    xev.format = 32;
+    xev.data.l[0] = CurrentTime;
+    xev.data.l[1] = selection_atom_x11;
+    xev.data.l[2] = GDK_WINDOW_XID (invisible_window);
+    xev.data.l[3] = xev.data.l[4] = 0;
+
+    gdk_error_trap_push ();
+    XSendEvent (dpy, xroot, False, StructureNotifyMask, (XEvent *)&xev);
+    gdk_flush ();
+    if (gdk_error_trap_pop ())
+      g_critical ("Failed to send client event");
+
+    if (filter_func != NULL)
+        gdk_window_add_filter (invisible_window, filter_func, invisible);
+#endif
+
+    return TRUE;
+}
+
+
+
 XfceClipboardManager *
 xfce_clipboard_manager_new (void)
 {
@@ -325,7 +405,7 @@ xfce_clipboard_manager_start (XfceClipboardManager *manager)
         return FALSE;
     }
 
-    if (!xfce_utils_selection_owner ("CLIPBOARD_MANAGER", FALSE, NULL))
+    if (!xfce_clipboard_manager_selection_owner ("CLIPBOARD_MANAGER", FALSE, NULL))
     {
         g_warning ("Unable to get the clipboard manager selection.");
         return FALSE;
diff --git a/xfce4-settings-helper/main.c b/xfce4-settings-helper/main.c
index 4d2b9e0..d6d994f 100644
--- a/xfce4-settings-helper/main.c
+++ b/xfce4-settings-helper/main.c
@@ -38,6 +38,7 @@
 
 #include <glib.h>
 #include <gtk/gtk.h>
+#include <dbus/dbus.h>
 
 #ifdef GDK_WINDOWING_X11
 #include <gdk/gdkx.h>
@@ -56,17 +57,12 @@
 #include "keyboard-shortcuts.h"
 #include "workspaces.h"
 #include "clipboard-manager.h"
-#include "utils.h"
 
 #ifdef HAVE_XRANDR
 #include "displays.h"
 #endif
 
-#define SELECTION_NAME  "_XFCE_SETTINGS_HELPER"
-
-static GdkFilterReturn xfce_settings_helper_selection_watcher (GdkXEvent *xevt,
-                                                               GdkEvent *evt,
-                                                               gpointer user_data);
+#define HELPER_DBUS_NAME "org.xfce.SettingsHelper"
 
 
 static XfceSMClient *sm_client = NULL;
@@ -126,28 +122,6 @@ xfce_settings_helper_set_autostart_enabled (gboolean enabled)
 
 
 
-static GdkFilterReturn
-xfce_settings_helper_selection_watcher (GdkXEvent *xevt,
-                                        GdkEvent *evt,
-                                        gpointer user_data)
-{
-#ifdef GDK_WINDOWING_X11
-    GtkWidget *invisible = GTK_WIDGET (user_data);
-    Window xwin = GDK_WINDOW_XID (invisible->window);
-    XEvent *xe = (XEvent *)xevt;
-
-    if (xe->type == SelectionClear && xe->xclient.window == xwin)
-    {
-        if (sm_client)
-            xfce_sm_client_set_restart_style (sm_client, XFCE_SM_CLIENT_RESTART_NORMAL);
-        gtk_main_quit ();
-    }
-#endif
-    return GDK_FILTER_CONTINUE;
-}
-
-
-
 gint
 main (gint argc, gchar **argv)
 {
@@ -166,36 +140,32 @@ main (gint argc, gchar **argv)
     GObject              *workspaces_helper;
     pid_t                 pid;
     guint                 i;
-    const gint            signums[] = { SIGHUP, SIGINT, SIGQUIT, SIGTERM };
+    const gint            signums[] = { SIGQUIT, SIGTERM };
+    DBusConnection       *dbus_connection;
+    gint                  result;
 
-    /* setup translation domain */
     xfce_textdomain (GETTEXT_PACKAGE, LOCALEDIR, "UTF-8");
 
-    /* create option context */
     context = g_option_context_new (NULL);
     g_option_context_add_main_entries (context, option_entries, GETTEXT_PACKAGE);
     g_option_context_add_group (context, gtk_get_option_group (FALSE));
     g_option_context_add_group (context, xfce_sm_client_get_option_group (argc, argv));
 
-    /* initialize gtk */
     gtk_init (&argc, &argv);
 
     /* parse options */
     if (!g_option_context_parse (context, &argc, &argv, &error))
     {
-        /* print error */
         g_print ("%s: %s.\n", G_LOG_DOMAIN, error->message);
         g_print (_("Type '%s --help' for usage."), G_LOG_DOMAIN);
         g_print ("\n");
 
-        /* cleanup */
         g_error_free (error);
         g_option_context_free (context);
 
         return EXIT_FAILURE;
     }
 
-    /* cleanup */
     g_option_context_free (context);
 
     /* check if we should print version information */
@@ -210,10 +180,24 @@ main (gint argc, gchar **argv)
         return EXIT_SUCCESS;
     }
 
-    /* initialize xfconf */
+    dbus_connection = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+    if (G_LIKELY (dbus_connection != NULL))
+    {
+        result = dbus_bus_request_name (dbus_connection, HELPER_DBUS_NAME, DBUS_NAME_FLAG_DO_NOT_QUEUE, NULL);
+        if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+          {
+              g_printerr (G_LOG_DOMAIN ": %s\n", "Another instance is already running. Leaving...");
+              return EXIT_SUCCESS;
+          }
+    }
+    else
+    {
+        g_error ("Failed to connect to the dbus session bus.");
+        return EXIT_FAILURE;
+    }
+
     if (!xfconf_init (&error))
     {
-        /* print error and exit */
         g_error ("Failed to connect to xfconf daemon: %s.", error->message);
         g_error_free (error);
 
@@ -231,17 +215,10 @@ main (gint argc, gchar **argv)
         g_error_free (error);
     }
 
+    /* if this instance is started from a saved session, disable autostart so
+     * the helper is not spawned twice */
     in_session = xfce_sm_client_is_resumed (sm_client);
-    if (!xfce_utils_selection_owner (SELECTION_NAME, in_session,
-                                     xfce_settings_helper_selection_watcher))
-    {
-        g_printerr ("%s is already running\n", G_LOG_DOMAIN);
-        g_object_unref (G_OBJECT (sm_client));
-        return EXIT_FAILURE;
-    }
-
-    /* if we were restarted as part of the session, remove us from autostart */
-    xfce_settings_helper_set_autostart_enabled (!in_session);
+    xfce_settings_helper_set_autostart_enabled (in_session);
 
     /* daemonize the process when not running in debug mode */
     if (!opt_debug)
@@ -256,7 +233,7 @@ main (gint argc, gchar **argv)
         }
         else if (pid > 0)
         {
-            /* succesfully created a fork, leave this instance */
+            /* succesfully created a fork */
             _exit (EXIT_SUCCESS);
         }
     }
@@ -272,7 +249,6 @@ main (gint argc, gchar **argv)
 #endif
     workspaces_helper = g_object_new (XFCE_TYPE_WORKSPACES_HELPER, NULL);
 
-    /* Try to start the clipboard daemon */
     clipboard_daemon = xfce_clipboard_manager_new ();
     if (!xfce_clipboard_manager_start (clipboard_daemon))
     {
@@ -287,9 +263,12 @@ main (gint argc, gchar **argv)
             xfce_posix_signal_handler_set_handler (signums[i], signal_handler, NULL, NULL);
     }
 
-    /* enter the main loop */
     gtk_main();
 
+    /* release the dbus name */
+    if (dbus_connection != NULL)
+        dbus_bus_release_name (dbus_connection, HELPER_DBUS_NAME, NULL);
+
     /* release the sub daemons */
     g_object_unref (G_OBJECT (pointer_helper));
     g_object_unref (G_OBJECT (keyboards_helper));
@@ -301,17 +280,13 @@ main (gint argc, gchar **argv)
 #endif
     g_object_unref (G_OBJECT (workspaces_helper));
 
-    /* Stop the clipboard daemon */
     if (G_LIKELY (clipboard_daemon != NULL))
     {
         xfce_clipboard_manager_stop (clipboard_daemon);
         g_object_unref (G_OBJECT (clipboard_daemon));
     }
 
-    /* shutdown xfconf */
     xfconf_shutdown ();
-
-    /* release sm client */
     g_object_unref (G_OBJECT (sm_client));
 
     return EXIT_SUCCESS;
diff --git a/xfce4-settings-helper/utils.c b/xfce4-settings-helper/utils.c
deleted file mode 100644
index 2d8692a..0000000
--- a/xfce4-settings-helper/utils.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2009 Nick Schermer <nick at xfce.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gtk/gtk.h>
-
-#ifdef GDK_WINDOWING_X11
-#include <gdk/gdkx.h>
-#include <X11/X.h>
-#include <X11/Xlib.h>
-#endif
-
-#include "utils.h"
-
-gboolean
-xfce_utils_selection_owner (const gchar   *selection_name,
-                            gboolean       force,
-                            GdkFilterFunc  filter_func)
-{
-#ifdef GDK_WINDOWING_X11
-    GdkDisplay *gdpy = gdk_display_get_default ();
-    GtkWidget *invisible;
-    Display *dpy = GDK_DISPLAY_XDISPLAY (gdpy);
-    GdkWindow *rootwin = gdk_screen_get_root_window (gdk_display_get_screen (gdpy, 0));
-    GdkWindow *invisible_window;
-    Window xroot = GDK_WINDOW_XID (rootwin);
-    GdkAtom selection_atom;
-    Atom selection_atom_x11;
-    XClientMessageEvent xev;
-    gboolean has_owner;
-
-    g_return_val_if_fail (selection_name != NULL, FALSE);
-
-    selection_atom = gdk_atom_intern (selection_name, FALSE);
-    selection_atom_x11 = gdk_x11_atom_to_xatom_for_display (gdpy, selection_atom);
-
-    /* can't use gdk for the selection owner here because it returns NULL
-     * if the selection owner is in another process */
-    if (!force)
-    {
-        gdk_error_trap_push ();
-        has_owner = XGetSelectionOwner (dpy, selection_atom_x11) != None;
-        gdk_flush ();
-        gdk_error_trap_pop ();
-        if (has_owner)
-            return FALSE;
-    }
-
-    invisible = gtk_invisible_new ();
-    gtk_widget_realize (invisible);
-    gtk_widget_add_events (invisible, GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK);
-
-    invisible_window = gtk_widget_get_window (invisible);
-
-    if (!gdk_selection_owner_set_for_display (gdpy, invisible_window,
-                                              selection_atom, GDK_CURRENT_TIME,
-                                              TRUE))
-    {
-        g_critical ("Unable to get selection %s", selection_name);
-        gtk_widget_destroy (invisible);
-        return FALSE;
-    }
-
-    /* but we can use gdk here since we only care if it's our window */
-    if (gdk_selection_owner_get_for_display (gdpy, selection_atom) != invisible_window)
-    {
-        gtk_widget_destroy (invisible);
-        return FALSE;
-    }
-
-    xev.type = ClientMessage;
-    xev.window = xroot;
-    xev.message_type = gdk_x11_get_xatom_by_name_for_display (gdpy, "MANAGER");
-    xev.format = 32;
-    xev.data.l[0] = CurrentTime;
-    xev.data.l[1] = selection_atom_x11;
-    xev.data.l[2] = GDK_WINDOW_XID (invisible_window);
-    xev.data.l[3] = xev.data.l[4] = 0;
-
-    gdk_error_trap_push ();
-    XSendEvent (dpy, xroot, False, StructureNotifyMask, (XEvent *)&xev);
-    gdk_flush ();
-    if (gdk_error_trap_pop ())
-      g_critical ("Failed to send client event");
-
-    if (filter_func != NULL)
-        gdk_window_add_filter (invisible_window, filter_func, invisible);
-#endif
-
-    return TRUE;
-}
-
diff --git a/xfce4-settings-helper/utils.h b/xfce4-settings-helper/utils.h
deleted file mode 100644
index 8f5843f..0000000
--- a/xfce4-settings-helper/utils.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2009 Nick Schermer <nick at xfce.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-
-#ifndef __XFCE_UTILS_H__
-#define __XFCE_UTILS_H__
-
-gboolean
-xfce_utils_selection_owner (const gchar   *selection_name,
-                            gboolean       force,
-                            GdkFilterFunc  filter_func);
-
-#endif
diff --git a/xfce4-settings-helper/workspaces.c b/xfce4-settings-helper/workspaces.c
index a6840cc..1a45cb7 100644
--- a/xfce4-settings-helper/workspaces.c
+++ b/xfce4-settings-helper/workspaces.c
@@ -223,7 +223,6 @@ xfce_workspaces_helper_prop_changed(XfconfChannel *channel,
         return;
 
     display = gdk_display_get_default();
-
     for(s = 0; helper->screens[s]; ++s) {
         wnck_screen_force_update(helper->screens[s]);
         n_workspaces = wnck_screen_get_workspace_count(helper->screens[s]);



More information about the Xfce4-commits mailing list