Rui Matos cf205c9
From f4402b64fd34b886a9d7e8c1e0833e4c3f7dcfe3 Mon Sep 17 00:00:00 2001
Rui Matos cf205c9
From: Rui Matos <tiagomatos@gmail.com>
Rui Matos cf205c9
Date: Tue, 26 Nov 2013 00:55:23 +0100
Rui Matos cf205c9
Subject: [PATCH] idle-monitor: Check if a monitor exists before creating a
Rui Matos cf205c9
 proxy for it
Rui Matos cf205c9
Rui Matos cf205c9
The fact that we know about a given device doesn't mean that mutter
Rui Matos cf205c9
also knows about it nor that it has created an idle monitor object on
Rui Matos cf205c9
the bus for it.
Rui Matos cf205c9
Rui Matos cf205c9
To fix this race, instead of immediately trying to create a proxy for
Rui Matos cf205c9
the bus object, we instantiate an object manager and ask it whether
Rui Matos cf205c9
the object we want already exists and if it doesn't we wait
Rui Matos cf205c9
(indefinitely) until it shows up.
Rui Matos cf205c9
Rui Matos cf205c9
https://bugzilla.gnome.org/show_bug.cgi?id=706229
Rui Matos cf205c9
---
Rui Matos cf205c9
 libgnome-desktop/gnome-idle-monitor.c | 109 +++++++++++++++++++++++-----------
Rui Matos cf205c9
 1 file changed, 73 insertions(+), 36 deletions(-)
Rui Matos cf205c9
Rui Matos cf205c9
diff --git a/libgnome-desktop/gnome-idle-monitor.c b/libgnome-desktop/gnome-idle-monitor.c
Rui Matos cf205c9
index 6af1343..539c99b 100644
Rui Matos cf205c9
--- a/libgnome-desktop/gnome-idle-monitor.c
Rui Matos cf205c9
+++ b/libgnome-desktop/gnome-idle-monitor.c
Rui Matos cf205c9
@@ -40,10 +40,12 @@ struct _GnomeIdleMonitorPrivate
Rui Matos cf205c9
 {
Rui Matos cf205c9
 	GCancellable        *cancellable;
Rui Matos cf205c9
 	MetaDBusIdleMonitor *proxy;
Rui Matos cf205c9
+	MetaDBusObjectManagerClient *om;
Rui Matos cf205c9
 	int                  name_watch_id;
Rui Matos cf205c9
 	GHashTable          *watches;
Rui Matos cf205c9
 	GHashTable          *watches_by_upstream_id;
Rui Matos cf205c9
 	GdkDevice           *device;
Rui Matos cf205c9
+	gchar               *path;
Rui Matos cf205c9
 };
Rui Matos cf205c9
 
Rui Matos cf205c9
 typedef struct
Rui Matos cf205c9
@@ -163,8 +165,10 @@ gnome_idle_monitor_dispose (GObject *object)
Rui Matos cf205c9
 	}
Rui Matos cf205c9
 
Rui Matos cf205c9
 	g_clear_object (&monitor->priv->proxy);
Rui Matos cf205c9
+	g_clear_object (&monitor->priv->om);
Rui Matos cf205c9
 	g_clear_pointer (&monitor->priv->watches, g_hash_table_destroy);
Rui Matos cf205c9
 	g_clear_object (&monitor->priv->device);
Rui Matos cf205c9
+	g_clear_pointer (&monitor->priv->path, g_free);
Rui Matos cf205c9
 
Rui Matos cf205c9
 	G_OBJECT_CLASS (gnome_idle_monitor_parent_class)->dispose (object);
Rui Matos cf205c9
 }
Rui Matos cf205c9
@@ -198,6 +202,15 @@ gnome_idle_monitor_set_property (GObject      *object,
Rui Matos cf205c9
 	{
Rui Matos cf205c9
 	case PROP_DEVICE:
Rui Matos cf205c9
 		monitor->priv->device = g_value_dup_object (value);
Rui Matos cf205c9
+
Rui Matos cf205c9
+		g_free (monitor->priv->path);
Rui Matos cf205c9
+		if (monitor->priv->device) {
Rui Matos cf205c9
+			monitor->priv->path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d",
Rui Matos cf205c9
+							       gdk_x11_device_get_id (monitor->priv->device));
Rui Matos cf205c9
+		} else {
Rui Matos cf205c9
+			monitor->priv->path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core");
Rui Matos cf205c9
+		}
Rui Matos cf205c9
+
Rui Matos cf205c9
 		break;
Rui Matos cf205c9
 	default:
Rui Matos cf205c9
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Rui Matos cf205c9
@@ -220,57 +233,74 @@ add_known_watch (gpointer key,
Rui Matos cf205c9
 }
Rui Matos cf205c9
 
Rui Matos cf205c9
 static void
Rui Matos cf205c9
-on_proxy_acquired (GObject      *object,
Rui Matos cf205c9
-		   GAsyncResult *result,
Rui Matos cf205c9
-		   gpointer      user_data)
Rui Matos cf205c9
+connect_proxy (GDBusObject	*object,
Rui Matos cf205c9
+	       GnomeIdleMonitor	*monitor)
Rui Matos cf205c9
 {
Rui Matos cf205c9
-	GnomeIdleMonitor *monitor = user_data;
Rui Matos cf205c9
-	GError *error;
Rui Matos cf205c9
 	MetaDBusIdleMonitor *proxy;
Rui Matos cf205c9
 
Rui Matos cf205c9
-	error = NULL;
Rui Matos cf205c9
-	proxy = meta_dbus_idle_monitor_proxy_new_finish (result, &error);
Rui Matos cf205c9
+	proxy = meta_dbus_object_get_idle_monitor (META_DBUS_OBJECT (object));
Rui Matos cf205c9
 	if (!proxy) {
Rui Matos cf205c9
-		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
Rui Matos cf205c9
-			g_error_free (error);
Rui Matos cf205c9
-			return;
Rui Matos cf205c9
-		}
Rui Matos cf205c9
-
Rui Matos cf205c9
-		g_warning ("Failed to acquire idle monitor proxy: %s", error->message);
Rui Matos cf205c9
-		g_error_free (error);
Rui Matos cf205c9
+		g_critical ("Unable to get idle monitor from object at %s",
Rui Matos cf205c9
+			    g_dbus_object_get_object_path (object));
Rui Matos cf205c9
 		return;
Rui Matos cf205c9
 	}
Rui Matos cf205c9
 
Rui Matos cf205c9
 	monitor->priv->proxy = proxy;
Rui Matos cf205c9
-
Rui Matos cf205c9
 	g_signal_connect_object (proxy, "watch-fired", G_CALLBACK (on_watch_fired), monitor, 0);
Rui Matos cf205c9
 	g_hash_table_foreach (monitor->priv->watches, add_known_watch, monitor);
Rui Matos cf205c9
 }
Rui Matos cf205c9
 
Rui Matos cf205c9
 static void
Rui Matos cf205c9
-connect_proxy (GnomeIdleMonitor *monitor,
Rui Matos cf205c9
-	       GDBusConnection  *connection,
Rui Matos cf205c9
-	       const char       *unique_name)
Rui Matos cf205c9
-{
Rui Matos cf205c9
-	char *path;
Rui Matos cf205c9
-	int device_id;
Rui Matos cf205c9
-
Rui Matos cf205c9
-	if (monitor->priv->device) {
Rui Matos cf205c9
-		/* FIXME! Gdk! WTF? */
Rui Matos cf205c9
-		device_id = gdk_x11_device_get_id (monitor->priv->device);
Rui Matos cf205c9
-	path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
Rui Matos cf205c9
-	} else {
Rui Matos cf205c9
-		path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core");
Rui Matos cf205c9
+on_object_added (GDBusObjectManager	*manager,
Rui Matos cf205c9
+		 GDBusObject		*object,
Rui Matos cf205c9
+		 gpointer		 user_data)
Rui Matos cf205c9
+{
Rui Matos cf205c9
+	GnomeIdleMonitor *monitor = user_data;
Rui Matos cf205c9
+
Rui Matos cf205c9
+	if (!g_str_equal (monitor->priv->path, g_dbus_object_get_object_path (object)))
Rui Matos cf205c9
+		return;
Rui Matos cf205c9
+
Rui Matos cf205c9
+	connect_proxy (object, monitor);
Rui Matos cf205c9
+
Rui Matos cf205c9
+	g_signal_handlers_disconnect_by_func (manager, on_object_added, user_data);
Rui Matos cf205c9
+}
Rui Matos cf205c9
+
Rui Matos cf205c9
+static void
Rui Matos cf205c9
+get_proxy (GnomeIdleMonitor *monitor)
Rui Matos cf205c9
+{
Rui Matos cf205c9
+	GDBusObject *object;
Rui Matos cf205c9
+
Rui Matos cf205c9
+	object = g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (monitor->priv->om),
Rui Matos cf205c9
+						   monitor->priv->path);
Rui Matos cf205c9
+	if (object) {
Rui Matos cf205c9
+		connect_proxy (object, monitor);
Rui Matos cf205c9
+		g_object_unref (object);
Rui Matos cf205c9
+		return;
Rui Matos cf205c9
 	}
Rui Matos cf205c9
 
Rui Matos cf205c9
-	meta_dbus_idle_monitor_proxy_new (connection,
Rui Matos cf205c9
-					  G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
Rui Matos cf205c9
-					  unique_name, path,
Rui Matos cf205c9
-					  monitor->priv->cancellable,
Rui Matos cf205c9
-					  on_proxy_acquired,
Rui Matos cf205c9
-					  monitor);
Rui Matos cf205c9
+	g_signal_connect_object (monitor->priv->om, "object-added",
Rui Matos cf205c9
+				 G_CALLBACK (on_object_added), monitor, 0);
Rui Matos cf205c9
+}
Rui Matos cf205c9
+
Rui Matos cf205c9
+static void
Rui Matos cf205c9
+on_object_manager_ready (GObject	*source,
Rui Matos cf205c9
+			 GAsyncResult	*res,
Rui Matos cf205c9
+			 gpointer	 user_data)
Rui Matos cf205c9
+{
Rui Matos cf205c9
+	GnomeIdleMonitor *monitor = user_data;
Rui Matos cf205c9
+	GDBusObjectManager *om;
Rui Matos cf205c9
+	GError *error = NULL;
Rui Matos cf205c9
+
Rui Matos cf205c9
+	om = meta_dbus_object_manager_client_new_finish (res, &error);
Rui Matos cf205c9
+	if (!om) {
Rui Matos cf205c9
+		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
Rui Matos cf205c9
+			g_warning ("Failed to acquire idle monitor object manager: %s", error->message);
Rui Matos cf205c9
+		g_error_free (error);
Rui Matos cf205c9
+		return;
Rui Matos cf205c9
+	}
Rui Matos cf205c9
 
Rui Matos cf205c9
-	g_free (path);
Rui Matos cf205c9
+	monitor->priv->om = META_DBUS_OBJECT_MANAGER_CLIENT (om);
Rui Matos cf205c9
+	get_proxy (monitor);
Rui Matos cf205c9
 }
Rui Matos cf205c9
 
Rui Matos cf205c9
 static void
Rui Matos cf205c9
@@ -281,7 +311,13 @@ on_name_appeared (GDBusConnection *connection,
Rui Matos cf205c9
 {
Rui Matos cf205c9
 	GnomeIdleMonitor *monitor = user_data;
Rui Matos cf205c9
 
Rui Matos cf205c9
-	connect_proxy (monitor, connection, name_owner);
Rui Matos cf205c9
+	meta_dbus_object_manager_client_new (connection,
Rui Matos cf205c9
+					     G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
Rui Matos cf205c9
+					     name_owner,
Rui Matos cf205c9
+					     "/org/gnome/Mutter/IdleMonitor",
Rui Matos cf205c9
+					     monitor->priv->cancellable,
Rui Matos cf205c9
+					     on_object_manager_ready,
Rui Matos cf205c9
+					     monitor);
Rui Matos cf205c9
 }
Rui Matos cf205c9
 
Rui Matos cf205c9
 static void
Rui Matos cf205c9
@@ -305,6 +341,7 @@ on_name_vanished (GDBusConnection *connection,
Rui Matos cf205c9
 
Rui Matos cf205c9
 	g_hash_table_foreach (monitor->priv->watches, clear_watch, monitor);
Rui Matos cf205c9
 	g_clear_object (&monitor->priv->proxy);
Rui Matos cf205c9
+	g_clear_object (&monitor->priv->om);
Rui Matos cf205c9
 }
Rui Matos cf205c9
 
Rui Matos cf205c9
 static gboolean
Rui Matos cf205c9
-- 
Rui Matos cf205c9
1.8.3.1
Rui Matos cf205c9