[gnome-panel] use dbus to register with session manager



commit 8d9956d04b42f1d5ab5b9ec76f4a48beb69c6aa5
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Fri Nov 7 03:40:56 2014 +0200

    use dbus to register with session manager
    
    autorestart in desktop file is set to false. It is needed to
    correctly handle --replace. It will be autorestarted in case of
    crash.

 gnome-panel/Makefile.am               |    2 -
 gnome-panel/gnome-panel.desktop.in.in |    3 +-
 gnome-panel/main.c                    |   28 ++--
 gnome-panel/panel-session.c           |  323 ++++++++++++++++++++++++++++-----
 gnome-panel/panel-session.h           |   67 +++++--
 gnome-panel/panel-shell.c             |  163 -----------------
 gnome-panel/panel-shell.h             |   35 ----
 7 files changed, 347 insertions(+), 274 deletions(-)
---
diff --git a/gnome-panel/Makefile.am b/gnome-panel/Makefile.am
index 095cf2d..efa777a 100644
--- a/gnome-panel/Makefile.am
+++ b/gnome-panel/Makefile.am
@@ -35,7 +35,6 @@ panel_sources =                       \
        launcher.c              \
        panel-applet-frame.c    \
        panel-applets-manager.c \
-       panel-shell.c           \
        panel-background.c      \
        panel-background-monitor.c      \
        panel-stock-icons.c     \
@@ -83,7 +82,6 @@ panel_headers =                       \
        launcher.h              \
        panel-applet-frame.h    \
        panel-applets-manager.h \
-       panel-shell.h           \
        panel-background.h      \
        panel-background-monitor.h      \
        panel-stock-icons.h     \
diff --git a/gnome-panel/gnome-panel.desktop.in.in b/gnome-panel/gnome-panel.desktop.in.in
index ef7913b..0877786 100644
--- a/gnome-panel/gnome-panel.desktop.in.in
+++ b/gnome-panel/gnome-panel.desktop.in.in
@@ -12,6 +12,7 @@ X-GNOME-Bugzilla-Version= VERSION@
 Categories=GNOME;GTK;System;Core;
 OnlyShowIn=GNOME-Flashback;
 NoDisplay=true
-X-GNOME-AutoRestart=true
+X-GNOME-AutoRestart=false
+X-GNOME-Autostart-Notify=true
 X-GNOME-Autostart-Phase=Panel
 X-GNOME-Provides=panel
diff --git a/gnome-panel/main.c b/gnome-panel/main.c
index 75ff387..ada0789 100644
--- a/gnome-panel/main.c
+++ b/gnome-panel/main.c
@@ -20,7 +20,7 @@
 #include <libpanel-util/panel-cleanup.h>
 #include <libpanel-util/panel-glib.h>
 
-#include "panel-shell.h"
+#include "panel-toplevel.h"
 #include "panel-multiscreen.h"
 #include "panel-session.h"
 #include "panel-stock-icons.h"
@@ -82,14 +82,14 @@ main (int argc, char **argv)
        GOptionContext *context;
        GError         *error;
        GtkSettings    *settings;
+       PanelSession   *session;
+       GSList         *toplevels_to_destroy;
+       GSList         *l;
 
        bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
        textdomain (GETTEXT_PACKAGE);
 
-       /* We will register explicitly when we're ready -- see panel-session.c */
-       egg_sm_client_set_mode (EGG_SM_CLIENT_MODE_DISABLED);
-
        g_set_prgname ("gnome-panel");
 
        desktopfile = panel_g_lookup_in_applications_dirs ("gnome-panel.desktop");
@@ -99,8 +99,6 @@ main (int argc, char **argv)
        }
 
        context = g_option_context_new ("");
-       g_option_context_add_group (context,
-                                   egg_sm_client_get_option_group ());
        g_option_context_add_group (context, gtk_get_option_group (TRUE));
        g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
 
@@ -117,16 +115,15 @@ main (int argc, char **argv)
 
        g_option_context_free (context);
 
+       session = panel_session_new (replace);
+       if (session == NULL)
+               return 1;
+
        if (!egg_get_desktop_file ()) {
                g_set_application_name (_("Panel"));
                gtk_window_set_default_icon_name (PANEL_ICON_PANEL);
        }
 
-       if (!panel_shell_register (replace)) {
-               panel_cleanup_do ();
-               return 1;
-       }
-
        panel_action_protocol_init ();
        panel_multiscreen_init ();
 
@@ -143,7 +140,7 @@ main (int argc, char **argv)
 
        /* Do this at the end, to be sure that we're really ready when
         * connecting to the session manager */
-       panel_session_init ();
+       panel_session_register_client (session);
 
        settings = gtk_settings_get_default ();
        g_signal_connect (settings, "notify::gtk-theme-name", G_CALLBACK (theme_changed), NULL);
@@ -151,6 +148,13 @@ main (int argc, char **argv)
 
        gtk_main ();
 
+       g_object_unref (session);
+
+       toplevels_to_destroy = g_slist_copy (panel_toplevel_list_toplevels ());
+       for (l = toplevels_to_destroy; l; l = l->next)
+       gtk_widget_destroy (l->data);
+       g_slist_free (toplevels_to_destroy);
+
        panel_cleanup_do ();
 
        return 0;
diff --git a/gnome-panel/panel-session.c b/gnome-panel/panel-session.c
index e9b4d37..7ee8bf2 100644
--- a/gnome-panel/panel-session.c
+++ b/gnome-panel/panel-session.c
@@ -1,78 +1,313 @@
 /*
- * panel-session.c: panel session management routines
- *
+ * Copyright (C) 2001 Ximian, Inc.
  * Copyright (C) 2003 Sun Microsystems, Inc.
+ * Copyright (C) 2008 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ * Copyright (C) 2010 Carlos Garcia Campos
+ * Copyright (C) 2014 Alberts Muktupāvels
  *
- * 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 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 3 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.
+ * 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, see <http://www.gnu.org/licenses/>.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  * Authors:
- *     Mark McLoughlin <mark skynet ie>
+ *    Alberts Muktupāvels <alberts muktupavels gmail com>
+ *    Carlos Garcia Campos <carlosgc gnome org>
+ *    Colin Walters <walters verbum org>
+ *    Jacob Berkman <jacob ximian com>
+ *    Mark McLoughlin <mark skynet ie>
+ *    Vincent Untz <vuntz gnome org>
  */
 
 #include <config.h>
+#include <dbus/dbus-glib.h>
+#include <gtk/gtk.h>
+
+#include "panel-session.h"
 
-#include <stdlib.h>
+#define PANEL_DBUS_SERVICE "org.gnome.Panel"
 
-#include <gdk/gdkx.h>
+#define SESSION_MANAGER_NAME      "org.gnome.SessionManager"
+#define SESSION_MANAGER_PATH      "/org/gnome/SessionManager"
+#define SESSION_MANAGER_INTERFACE "org.gnome.SessionManager"
 
-#include <libegg/eggsmclient.h>
+#define SESSION_MANAGER_CLIENT_PRIVATE_INTERFACE "org.gnome.SessionManager.ClientPrivate"
 
-#include "panel-shell.h"
+struct _PanelSessionPrivate {
+       GDBusConnection *connection;
+       guint            name_lost_id;
 
-#include "panel-session.h"
+       GDBusProxy      *session_manager_proxy;
+       GDBusProxy      *client_proxy;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (PanelSession, panel_session, G_TYPE_OBJECT)
+
+static void
+respond_to_end_session (GDBusProxy *proxy)
+{
+       g_dbus_proxy_call (proxy,
+                          "EndSessionResponse",
+                          g_variant_new ("(bs)", TRUE, ""),
+                          G_DBUS_CALL_FLAGS_NONE,
+                          -1,
+                          NULL,
+                          NULL,
+                          NULL);
+}
+
+static void
+panel_session_client_proxy_signal_cb (GDBusProxy  *proxy,
+                                      const gchar *sender_name,
+                                      const gchar *signal_name,
+                                      GVariant    *parameters,
+                                      gpointer     user_data)
+{
+       if (g_str_equal (signal_name, "QueryEndSession")) {
+               respond_to_end_session (proxy);
+       } else if (g_str_equal (signal_name, "EndSession")) {
+               respond_to_end_session (proxy);
+       } else if (g_str_equal (signal_name, "Stop")) {
+               gtk_main_quit ();
+       }
+}
+
+static gboolean
+panel_session_get_session_manager_proxy (PanelSession *session)
+{
+       PanelSessionPrivate *priv;
+       GError              *error;
+       GDBusProxyFlags      flags;
+
+       if (!session)
+               return FALSE;
+
+       priv = session->priv;
+       error = NULL;
+       flags = G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+               G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS;
+
+       priv->session_manager_proxy = g_dbus_proxy_new_sync (priv->connection,
+                                                            flags,
+                                                            NULL,
+                                                            SESSION_MANAGER_NAME,
+                                                            SESSION_MANAGER_PATH,
+                                                            SESSION_MANAGER_INTERFACE,
+                                                            NULL,
+                                                            &error);
+
+       if (error) {
+               g_warning ("Failed to get session manager proxy: %s", error->message);
+               g_error_free (error);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static void
+panel_session_name_lost (GDBusConnection *connection,
+                         const gchar     *sender_name,
+                         const gchar     *object_path,
+                         const gchar     *interface_name,
+                         const gchar     *signal_name,
+                         GVariant        *parameters,
+                         gpointer         user_data)
+{
+       gtk_main_quit ();
+}
+
+static gboolean
+panel_session_request_name (PanelSession *session,
+                            gboolean      replace)
+{
+       PanelSessionPrivate *priv;
+       GBusNameOwnerFlags   flags;
+       GError              *error;
+       GVariant            *result;
+       guint32              reply;
+
+       priv = session->priv;
+       flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT;
+       error = NULL;
+
+       priv->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
 
-static gboolean do_not_restart = FALSE;
+       if (error) {
+               g_warning ("Failed to get session bus: %s", error->message);
+               g_error_free (error);
+               return FALSE;
+       }
+
+       if (replace)
+               flags |= DBUS_NAME_FLAG_REPLACE_EXISTING;
+
+       result = g_dbus_connection_call_sync (priv->connection,
+                                             DBUS_SERVICE_DBUS,
+                                             DBUS_PATH_DBUS,
+                                             DBUS_INTERFACE_DBUS,
+                                             "RequestName",
+                                             g_variant_new ("(su)",
+                                                            PANEL_DBUS_SERVICE,
+                                                            flags),
+                                             G_VARIANT_TYPE ("(u)"),
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1,
+                                             NULL,
+                                             &error);
+
+       if (error) {
+               g_warning ("Failed to request name: %s", error->message);
+               g_error_free (error);
+               return FALSE;
+       }
+
+       g_variant_get (result, "(u)", &reply);
+       g_variant_unref (result);
+
+       switch (reply) {
+               case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
+               case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
+                       priv->name_lost_id = g_dbus_connection_signal_subscribe (priv->connection,
+                                                                                DBUS_SERVICE_DBUS,
+                                                                                DBUS_INTERFACE_DBUS,
+                                                                                "NameLost",
+                                                                                DBUS_PATH_DBUS,
+                                                                                PANEL_DBUS_SERVICE,
+                                                                                G_DBUS_SIGNAL_FLAGS_NONE,
+                                                                                (GDBusSignalCallback) 
panel_session_name_lost,
+                                                                                session,
+                                                                                NULL);
+                       break;
+               case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
+               case DBUS_REQUEST_NAME_REPLY_EXISTS:
+                       g_warning ("Failed to request name: the name already has an owner");
+                       return FALSE;
+               default:
+                       g_warning ("Failed to request name: unhandled reply %u from RequestName", reply);
+                       return FALSE;
+       }
+
+       return TRUE;
+}
 
 static void
-panel_session_handle_quit (EggSMClient *client,
-                          gpointer     data)
+panel_session_finalize (GObject *object)
 {
-       panel_shell_quit ();
+       PanelSession        *session;
+       PanelSessionPrivate *priv;
+
+       session = PANEL_SESSION (object);
+       priv = session->priv;
+
+       g_clear_object (&priv->client_proxy);
+       g_clear_object (&priv->session_manager_proxy);
+
+       if (priv->name_lost_id > 0) {
+               g_dbus_connection_signal_unsubscribe (priv->connection, priv->name_lost_id);
+               priv->name_lost_id = 0;
+       }
+
+       g_clear_object (&priv->connection);
+
+       G_OBJECT_CLASS (panel_session_parent_class)->finalize (object);
 }
 
-void
-panel_session_do_not_restart (void)
+static void
+panel_session_class_init (PanelSessionClass *session_class)
 {
-       do_not_restart = TRUE;
+       GObjectClass *object_class;
+
+       object_class = G_OBJECT_CLASS (session_class);
 
-       if (egg_sm_client_get_mode () != EGG_SM_CLIENT_MODE_DISABLED)
-               egg_sm_client_set_mode (EGG_SM_CLIENT_MODE_NO_RESTART);
+       object_class->finalize = panel_session_finalize;
 }
 
-void
-panel_session_init (void)
+static void
+panel_session_init (PanelSession *session)
 {
-       EggSMClientMode  mode;
-       EggSMClient     *client;
+       session->priv = panel_session_get_instance_private (session);
+}
+
+PanelSession *
+panel_session_new (gboolean replace)
+{
+       PanelSession *session;
+
+       session = g_object_new (PANEL_TYPE_SESSION, NULL);
+
+       if (!panel_session_request_name (session, replace))
+               g_clear_object (&session);
+
+       if (!panel_session_get_session_manager_proxy (session))
+               g_clear_object (&session);
+
+       return session;
+}
+
+gboolean
+panel_session_register_client (PanelSession *session)
+{
+       PanelSessionPrivate *priv;
+       GError              *error;
+       const gchar         *app_id;
+       const gchar         *client_startup_id;
+       GVariant            *parameters;
+       GVariant            *res;
+       gchar               *object_path;
+
+       priv = session->priv;
+       error = NULL;
+       app_id = "gnome-panel";
+       client_startup_id = g_getenv ("DESKTOP_AUTOSTART_ID");
+
+       parameters = g_variant_new ("(ss)", app_id, client_startup_id ? client_startup_id : "");
+
+       res = g_dbus_proxy_call_sync (priv->session_manager_proxy,
+                                     "RegisterClient",
+                                     parameters,
+                                     G_DBUS_CALL_FLAGS_NONE,
+                                     -1,
+                                     NULL,
+                                     &error);
+
+       if (error) {
+               g_warning ("Failed to register client: %s", error->message);
+               g_error_free (error);
+               return FALSE;
+       }
 
-       /* Explicitly tell the session manager we're ready -- we don't do it
-        * before. Note: this depends on setting the mode to DISABLED early
-        * during startup. */
+       g_variant_get (res, "(o)", &object_path);
+       g_variant_unref (res);
 
-        if (do_not_restart || getenv ("GNOME_PANEL_DEBUG"))
-               mode = EGG_SM_CLIENT_MODE_NO_RESTART;
-       else
-               mode = EGG_SM_CLIENT_MODE_NORMAL;
+       priv->client_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                           G_DBUS_PROXY_FLAGS_NONE,
+                                                           NULL,
+                                                           SESSION_MANAGER_NAME,
+                                                           object_path,
+                                                           SESSION_MANAGER_CLIENT_PRIVATE_INTERFACE,
+                                                           NULL,
+                                                           &error);
 
-       egg_sm_client_set_mode (mode);
+       g_free (object_path);
 
-       client = egg_sm_client_get ();
+       if (error) {
+               g_warning ("Failed to get a client proxy: %s", error->message);
+               g_error_free (error);
+               return FALSE;
+       }
 
-       g_signal_connect (client, "quit",
-                         G_CALLBACK (panel_session_handle_quit), NULL);
+       g_signal_connect (priv->client_proxy, "g-signal",
+                         G_CALLBACK (panel_session_client_proxy_signal_cb), session);
 
-       /* We don't want the WM to try and save/restore our
-        * window position */
-       gdk_x11_set_sm_client_id (NULL);
+       return TRUE;
 }
diff --git a/gnome-panel/panel-session.h b/gnome-panel/panel-session.h
index 7d35c9f..acbf50b 100644
--- a/gnome-panel/panel-session.h
+++ b/gnome-panel/panel-session.h
@@ -1,33 +1,66 @@
 /*
- * panel-session.h: panel session management routines
- *
+ * Copyright (C) 2001 Ximian, Inc.
  * Copyright (C) 2003 Sun Microsystems, Inc.
+ * Copyright (C) 2008 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ * Copyright (C) 2010 Carlos Garcia Campos
+ * Copyright (C) 2014 Alberts Muktupāvels
  *
- * 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 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 3 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.
+ * 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, see <http://www.gnu.org/licenses/>.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  * Authors:
- *     Mark McLoughlin <mark skynet ie>
+ *    Alberts Muktupāvels <alberts muktupavels gmail com>
+ *    Carlos Garcia Campos <carlosgc gnome org>
+ *    Colin Walters <walters verbum org>
+ *    Jacob Berkman <jacob ximian com>
+ *    Mark McLoughlin <mark skynet ie>
+ *    Vincent Untz <vuntz gnome org>
  */
 
-#ifndef __PANEL_SESSION_H__
-#define __PANEL_SESSION_H__
+#ifndef PANEL_SESSION_H
+#define PANEL_SESSION_H
+
+#include <glib-object.h>
 
 G_BEGIN_DECLS
 
-void panel_session_init           (void);
-void panel_session_do_not_restart (void);
+#define PANEL_TYPE_SESSION         (panel_session_get_type ())
+#define PANEL_SESSION(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), PANEL_TYPE_SESSION, PanelSession))
+#define PANEL_SESSION_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c),    PANEL_TYPE_SESSION, PanelSessionClass))
+#define PANEL_IS_SESSION(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), PANEL_TYPE_SESSION))
+#define PANEL_IS_SESSION_CLASS(c)  (G_TYPE_CHECK_CLASS_TYPE ((c),    PANEL_TYPE_SESSION))
+#define PANEL_SESSION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o),  PANEL_TYPE_SESSION, PanelSessionClass))
+
+typedef struct _PanelSession        PanelSession;
+typedef struct _PanelSessionClass   PanelSessionClass;
+typedef struct _PanelSessionPrivate PanelSessionPrivate;
+
+struct _PanelSession {
+       GObject              parent;
+       PanelSessionPrivate *priv;
+};
+
+struct _PanelSessionClass {
+       GObjectClass parent_class;
+};
+
+GType         panel_session_get_type        (void);
+
+PanelSession *panel_session_new             (gboolean      replace);
+
+gboolean      panel_session_register_client (PanelSession *session);
 
 G_END_DECLS
 
-#endif /* __PANEL_SESSION_H__ */
+#endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]