[gnome-panel] use dbus to register with session manager
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-panel] use dbus to register with session manager
- Date: Fri, 7 Nov 2014 02:20:44 +0000 (UTC)
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]