From 04b92f38a2ebce2479670580857f722e9b3b3be4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 25 Nov 2014 17:45:05 -0600 Subject: [PATCH 1/2] Revert "applet: don't check for gnome shell (bgo #707953)" This reverts commit 4473e6a48fcfda1d87d4a4bc9f5c0589235dcfe0. --- src/applet.c | 47 +++++++++- src/applet.h | 4 + src/shell-watcher.c | 241 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/shell-watcher.h | 56 ++++++++++++ 4 files changed, 347 insertions(+), 1 deletion(-) create mode 100644 src/shell-watcher.c create mode 100644 src/shell-watcher.h diff --git a/src/applet.c b/src/applet.c index f0536f8..f3f4344 100644 --- a/src/applet.c +++ b/src/applet.c @@ -87,6 +87,7 @@ #include "nm-wifi-dialog.h" #include "applet-vpn-request.h" #include "utils.h" +#include "shell-watcher.h" #include "nm-ui-utils.h" #include "nm-glib-compat.h" @@ -3542,6 +3543,39 @@ register_agent (NMApplet *applet) G_CALLBACK (applet_agent_cancel_secrets_cb), applet); } +static void +shell_version_changed_cb (NMShellWatcher *watcher, GParamSpec *pspec, gpointer user_data) +{ + NMApplet *applet = user_data; + + if (nm_shell_watcher_version_at_least (watcher, 3, 0)) { + g_debug ("gnome-shell is running"); + + if (applet->agent) { + g_debug ("destroying secret agent"); + + g_signal_handlers_disconnect_by_func (applet->agent, + G_CALLBACK (applet_agent_get_secrets_cb), + applet); + g_signal_handlers_disconnect_by_func (applet->agent, + G_CALLBACK (applet_agent_cancel_secrets_cb), + applet); + nm_secret_agent_unregister (NM_SECRET_AGENT (applet->agent)); + g_clear_object (&applet->agent); + } + + /* We don't need the watcher any more */ + g_signal_handlers_disconnect_by_func (applet->shell_watcher, + G_CALLBACK (shell_version_changed_cb), + applet); + g_clear_object (&applet->shell_watcher); + } else if (!applet->agent) { + /* No shell */ + g_debug ("gnome-shell is not running, registering secret agent"); + register_agent (applet); + } +} + static gboolean dbus_setup (NMApplet *applet, GError **error) { @@ -3694,7 +3728,15 @@ initable_init (GInitable *initable, GCancellable *cancellable, GError **error) G_CALLBACK (applet_embedded_cb), NULL); applet_embedded_cb (G_OBJECT (applet->status_icon), NULL, NULL); - register_agent (applet); + /* Watch GNOME Shell so we can unregister our applet agent if it appears */ + if (!shell_debug) { + applet->shell_watcher = nm_shell_watcher_new (); + g_signal_connect (applet->shell_watcher, + "notify::shell-version", + G_CALLBACK (shell_version_changed_cb), + applet); + } else + register_agent (applet); return TRUE; } @@ -3764,6 +3806,9 @@ static void finalize (GObject *object) if (applet->session_bus) dbus_g_connection_unref (applet->session_bus); + if (applet->shell_watcher) + g_object_unref (applet->shell_watcher); + G_OBJECT_CLASS (nma_parent_class)->finalize (object); } diff --git a/src/applet.h b/src/applet.h index 23632f7..cd5ac97 100644 --- a/src/applet.h +++ b/src/applet.h @@ -44,6 +44,7 @@ #include #include #include "applet-agent.h" +#include "shell-watcher.h" #if WITH_MODEM_MANAGER_1 #include @@ -86,6 +87,9 @@ typedef struct GMainLoop *loop; DBusGConnection *session_bus; + NMShellWatcher *shell_watcher; + guint agent_start_id; + NMClient *nm_client; NMRemoteSettings *settings; AppletAgent *agent; diff --git a/src/shell-watcher.c b/src/shell-watcher.c new file mode 100644 index 0000000..da62121 --- /dev/null +++ b/src/shell-watcher.c @@ -0,0 +1,241 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager Applet -- allow user control over networking + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "shell-watcher.h" + +G_DEFINE_TYPE (NMShellWatcher, nm_shell_watcher, G_TYPE_OBJECT) + +struct NMShellWatcherPrivate { + GDBusProxy *shell_proxy; + guint signal_id; + + guint retry_timeout; + guint retries; + + guint shell_version; + gboolean shell_version_set; +}; + +enum { + PROP_0, + PROP_SHELL_VERSION, + LAST_PROP +}; + +static void create_gnome_shell_proxy (NMShellWatcher *watcher); + +static gboolean +retry_create_shell_proxy (gpointer user_data) +{ + NMShellWatcher *watcher = user_data; + NMShellWatcherPrivate *priv = watcher->priv; + + priv->retry_timeout = 0; + create_gnome_shell_proxy (watcher); + return FALSE; +} + +static void +try_update_version (NMShellWatcher *watcher) +{ + NMShellWatcherPrivate *priv = watcher->priv; + GVariant *v; + char *version, *p; + + v = g_dbus_proxy_get_cached_property (priv->shell_proxy, "ShellVersion"); + if (!v) { + /* The shell has claimed the name, but not yet registered its interfaces... + * (https://bugzilla.gnome.org/show_bug.cgi?id=673182). There's no way + * to make GDBusProxy re-read the properties at this point, so we + * have to destroy this proxy and try again. + */ + if (priv->signal_id) { + g_signal_handler_disconnect (priv->shell_proxy, priv->signal_id); + priv->signal_id = 0; + } + g_object_unref (priv->shell_proxy); + priv->shell_proxy = NULL; + + priv->retry_timeout = g_timeout_add_seconds (2, retry_create_shell_proxy, watcher); + return; + } + + g_warn_if_fail (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING)); + version = g_variant_dup_string (v, NULL); + if (version) { + guint major, minor; + + major = strtoul (version, &p, 10); + if (*p == '.') + minor = strtoul (p + 1, NULL, 10); + else + minor = 0; + + g_warn_if_fail (major < 256); + g_warn_if_fail (minor < 256); + + priv->shell_version = (major << 8) | minor; + priv->shell_version_set = TRUE; + g_object_notify (G_OBJECT (watcher), "shell-version"); + } + + g_variant_unref (v); +} + +static void +name_owner_changed_cb (GDBusProxy *proxy, GParamSpec *pspec, gpointer user_data) +{ + NMShellWatcher *watcher = user_data; + NMShellWatcherPrivate *priv = watcher->priv; + char *owner; + + owner = g_dbus_proxy_get_name_owner (proxy); + if (owner) { + try_update_version (watcher); + g_free (owner); + } else if (priv->shell_version || !priv->shell_version_set) { + priv->shell_version = 0; + priv->shell_version_set = TRUE; + g_object_notify (G_OBJECT (watcher), "shell-version"); + } +} + +static void +got_shell_proxy (GObject *source, GAsyncResult *result, gpointer user_data) +{ + NMShellWatcher *watcher = user_data; + NMShellWatcherPrivate *priv = watcher->priv; + GError *error = NULL; + + priv->shell_proxy = g_dbus_proxy_new_for_bus_finish (result, &error); + if (!priv->shell_proxy) { + g_warning ("Could not create GDBusProxy for org.gnome.Shell: %s", error->message); + g_error_free (error); + return; + } + + priv->signal_id = g_signal_connect (priv->shell_proxy, + "notify::g-name-owner", + G_CALLBACK (name_owner_changed_cb), + watcher); + + name_owner_changed_cb (priv->shell_proxy, NULL, watcher); + g_object_unref (watcher); +} + +static void +create_gnome_shell_proxy (NMShellWatcher *watcher) +{ + NMShellWatcherPrivate *priv = watcher->priv; + + if (priv->retries++ == 5) { + g_warning ("Could not find ShellVersion property on org.gnome.Shell after 5 tries"); + return; + } + + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + "org.gnome.Shell", + "/org/gnome/Shell", + "org.gnome.Shell", + NULL, + got_shell_proxy, + g_object_ref (watcher)); +} + +static void +nm_shell_watcher_init (NMShellWatcher *watcher) +{ + watcher->priv = G_TYPE_INSTANCE_GET_PRIVATE (watcher, NM_TYPE_SHELL_WATCHER, + NMShellWatcherPrivate); + create_gnome_shell_proxy (watcher); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMShellWatcher *watcher = NM_SHELL_WATCHER (object); + + switch (prop_id) { + case PROP_SHELL_VERSION: + g_value_set_uint (value, watcher->priv->shell_version); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +finalize (GObject *object) +{ + NMShellWatcher *watcher = NM_SHELL_WATCHER (object); + NMShellWatcherPrivate *priv = watcher->priv; + + if (priv->retry_timeout) + g_source_remove (priv->retry_timeout); + if (priv->signal_id) + g_signal_handler_disconnect (priv->shell_proxy, priv->signal_id); + if (priv->shell_proxy) + g_object_unref (priv->shell_proxy); + + G_OBJECT_CLASS (nm_shell_watcher_parent_class)->finalize (object); +} + +static void +nm_shell_watcher_class_init (NMShellWatcherClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMShellWatcherPrivate)); + + oclass->get_property = get_property; + oclass->finalize = finalize; + + g_object_class_install_property (oclass, PROP_SHELL_VERSION, + g_param_spec_uint ("shell-version", + "Shell version", + "Running GNOME Shell version, eg, 0x0304", + 0, 0xFFFF, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} + +NMShellWatcher * +nm_shell_watcher_new (void) +{ + return g_object_new (NM_TYPE_SHELL_WATCHER, NULL); +} + +gboolean +nm_shell_watcher_version_at_least (NMShellWatcher *watcher, guint major, guint minor) +{ + guint version = (major << 8) | minor; + + return watcher->priv->shell_version >= version; +} diff --git a/src/shell-watcher.h b/src/shell-watcher.h new file mode 100644 index 0000000..a6065f8 --- /dev/null +++ b/src/shell-watcher.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager Applet -- allow user control over networking + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Red Hat, Inc. + */ + +#ifndef SHELL_WATCHER_H +#define SHELL_WATCHER_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#define NM_TYPE_SHELL_WATCHER (nm_shell_watcher_get_type()) +#define NM_SHELL_WATCHER(object) (G_TYPE_CHECK_INSTANCE_CAST((object), NM_TYPE_SHELL_WATCHER, NMShellWatcher)) +#define NM_SHELL_WATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SHELL_WATCHER, NMShellWatcherClass)) +#define NM_IS_SHELL_WATCHER(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), NM_TYPE_SHELL_WATCHER)) +#define NM_IS_SHELL_WATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SHELL_WATCHER)) +#define NM_SHELL_WATCHER_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), NM_TYPE_SHELL_WATCHER, NMShellWatcherClass)) + +typedef struct NMShellWatcherPrivate NMShellWatcherPrivate; + +typedef struct { + GObject parent_instance; + + NMShellWatcherPrivate *priv; +} NMShellWatcher; + +typedef struct { + GObjectClass parent_class; +} NMShellWatcherClass; + +GType nm_shell_watcher_get_type (void); + +NMShellWatcher *nm_shell_watcher_new (void); + +gboolean nm_shell_watcher_version_at_least (NMShellWatcher *watcher, + guint major, guint minor); + +#endif -- 1.9.3 From bfc24e17555126bb1a9783c2d3c2771bb886ed58 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 25 Nov 2014 17:45:11 -0600 Subject: [PATCH 2/2] Revert "build: fix build after "applet: don't check for gnome shell (bgo #707953)"" This reverts commit 2014927869cb92be2c9e360f1a6a4b118b866403. --- src/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 0e85dd5..d8c1238 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -69,7 +69,9 @@ nm_applet_SOURCES = \ applet-device-bridge.c \ applet-device-infiniband.h \ applet-device-infiniband.c \ - fallback-icon.h + fallback-icon.h \ + shell-watcher.h \ + shell-watcher.c nm_applet_LDADD = \ -lm \ -- 1.9.3