Author: kelnos Date: 2008-11-07 01:53:25 +0000 (Fri, 07 Nov 2008) New Revision: 28637
Modified: xfce4-settings/trunk/NEWS xfce4-settings/trunk/xfce4-settings-helper/main.c Log: implement session management for xfce4-settings helper and use SmRestartImmediately to ensure it doesn't disappear. also acquire a manager selection to ensure uniqueness. Modified: xfce4-settings/trunk/NEWS =================================================================== --- xfce4-settings/trunk/NEWS 2008-11-06 23:49:52 UTC (rev 28636) +++ xfce4-settings/trunk/NEWS 2008-11-07 01:53:25 UTC (rev 28637) @@ -2,6 +2,14 @@ * Add an option to disable keyboard settings. * Default to "Rodent" icon theme instead of "hicolor" (Bug #4545) + * Use XfcePosixSignalHandler in xfce4-settings-helper to handle + signals, since calling gtk_main_quit() from a signal handler may + not be safe. + * Make xfce4-settings-helper connect to the session manager and use + the SmRestartImmediately facility to make sure it keeps running. + Disable the autostart .desktop file if we were restored from a + saved session. Attempt to acquire an X selection on startup to + ensure multiple copies of the helper aren't running (bug 4577). 4.5.91 (Xfce 4.6 beta1) Modified: xfce4-settings/trunk/xfce4-settings-helper/main.c =================================================================== --- xfce4-settings/trunk/xfce4-settings-helper/main.c 2008-11-06 23:49:52 UTC (rev 28636) +++ xfce4-settings/trunk/xfce4-settings-helper/main.c 2008-11-07 01:53:25 UTC (rev 28637) @@ -39,8 +39,15 @@ #include <glib.h> #include <gtk/gtk.h> +#ifdef GDK_WINDOWING_X11 +#include <gdk/gdkx.h> +#include <X11/X.h> +#include <X11/Xlib.h> +#endif + #include <xfconf/xfconf.h> #include <libxfce4util/libxfce4util.h> +#include <libxfcegui4/libxfcegui4.h> #include "accessibility.h" #include "displays.h" @@ -54,10 +61,12 @@ static gboolean opt_version = FALSE; static gboolean opt_debug = FALSE; +static gchar *opt_sm_client_id = NULL; static GOptionEntry option_entries[] = { - { "version", 'v', 0, G_OPTION_ARG_NONE, &opt_version, N_("Version information"), NULL }, + { "version", 'V', 0, G_OPTION_ARG_NONE, &opt_version, N_("Version information"), NULL }, { "debug", 'd', 0, G_OPTION_ARG_NONE, &opt_debug, N_("Start in debug mode (don't fork to the background)"), NULL }, + { "sm-client-id", 0, 0, G_OPTION_ARG_STRING, &opt_sm_client_id, N_("Client id used when resuming session"), NULL }, { NULL } }; @@ -72,7 +81,137 @@ } +static void +sm_client_die (gpointer client_data) +{ + signal_handler (SIGTERM, client_data); +} + +static gboolean +xfce_settings_helper_set_autostart_enabled (gboolean enabled) +{ + gboolean ret = TRUE; + XfceRc *rcfile = xfce_rc_config_open (XFCE_RESOURCE_CONFIG, + "autostart/" AUTOSTART_FILENAME, + FALSE); + + if (G_UNLIKELY (rcfile == NULL)) + { + g_warning ("Failed to create per-user autostart directory"); + return FALSE; + } + + xfce_rc_set_group (rcfile, "Desktop Entry"); + if (xfce_rc_read_bool_entry (rcfile, "Hidden", enabled) == enabled) + { + xfce_rc_write_bool_entry (rcfile, "Hidden", !enabled); + xfce_rc_flush (rcfile); + } + + if (xfce_rc_is_dirty (rcfile)) + { + g_warning ("Failed to write autostart file"); + ret = FALSE; + } + + xfce_rc_close (rcfile); + + return ret; +} + + +/* returns TRUE if we're now connected to the SM, FALSE otherwise */ +static gboolean +xfce_settings_helper_connect_session (int argc, + char **argv, + const gchar *sm_client_id) +{ + SessionClient *sm_client; + + /* we can't be sure that the SM will save the session later, so we only + * disable the autostart item if we're launching because we got *resumed* + * from a previous session. */ + + sm_client = client_session_new (argc, argv, NULL, + SESSION_RESTART_IMMEDIATELY, 40); + sm_client->die = sm_client_die; + if (sm_client_id) + client_session_set_client_id (sm_client, sm_client_id); + if (!session_init (sm_client)) + { + g_warning ("Failed to connect to session manager"); + client_session_free (sm_client); + xfce_settings_helper_set_autostart_enabled (TRUE); + return FALSE; + } + + if (sm_client_id && !g_ascii_strcasecmp (sm_client_id, sm_client->given_client_id)) + { + /* we passed a client id, and got the same one back, which means + * we were definitely restarted as a part of the session. so + * it's safe to disable the autostart item. */ + xfce_settings_helper_set_autostart_enabled (FALSE); + return TRUE; + } + + /* otherwise, let's just ensure the autostart item is enabled. */ + xfce_settings_helper_set_autostart_enabled (TRUE); + + return TRUE; +} + + +static gboolean +xfce_settings_helper_acquire_selection () +{ +#ifdef GDK_WINDOWING_X11 + GdkDisplay *gdpy = gdk_display_get_default (); + Display *dpy = GDK_DISPLAY_XDISPLAY (gdpy); + GdkWindow *rootwin = gdk_screen_get_root_window (gdk_display_get_screen (gdpy, 0)); + Window xroot = GDK_WINDOW_XID (rootwin); + Window xwin; + gchar selection_name[128]; + Atom selection_atom, manager_atom; + XClientMessageEvent xev; + + xwin = XCreateSimpleWindow (dpy, xroot, -100, -100, 1, 1, 0, 0, + XBlackPixel (GDK_DISPLAY (), 0)); + XSelectInput (dpy, xwin, PropertyChangeMask | StructureNotifyMask); + + selection_atom = XInternAtom (dpy, "_XFCE_SETTINGS_HELPER", False); + manager_atom = XInternAtom (dpy, "MANAGER", False); + + if (XGetSelectionOwner (dpy, selection_atom) != None) + { + XDestroyWindow (dpy, xwin); + return FALSE; + } + + XSetSelectionOwner (dpy, selection_atom, xwin, CurrentTime); + + if (XGetSelectionOwner (dpy, selection_atom) != xwin) + { + XDestroyWindow (dpy, xwin); + return FALSE; + } + + xev.type = ClientMessage; + xev.window = xroot; + xev.message_type = manager_atom; + xev.format = 32; + xev.data.l[0] = CurrentTime; + xev.data.l[1] = selection_atom; + xev.data.l[2] = xwin; + xev.data.l[3] = xev.data.l[4] = 0; + + XSendEvent (dpy, xroot, False, StructureNotifyMask, (XEvent *)&xev); +#endif + + return TRUE; +} + + gint main (gint argc, gchar **argv) { @@ -138,6 +277,12 @@ return EXIT_FAILURE; } + if (!xfce_settings_helper_acquire_selection ()) + { + g_printerr ("%s is already running\n", G_LOG_DOMAIN); + return EXIT_FAILURE; + } + /* daemonize the process when not running in debug mode */ if (!opt_debug) { @@ -156,6 +301,8 @@ } } + xfce_settings_helper_connect_session (argc, argv, opt_sm_client_id); + /* create the sub daemons */ pointer_helper = g_object_new (XFCE_TYPE_POINTERS_HELPER, NULL); keyboards_helper = g_object_new (XFCE_TYPE_KEYBOARDS_HELPER, NULL); _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org http://foo-projects.org/mailman/listinfo/xfce4-commits