← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~ted/libindicate/discovery-and-love into lp:libindicate

 

Ted Gould has proposed merging lp:~ted/libindicate/discovery-and-love into lp:libindicate.

    Requested reviews:
    Indicator Applet Developers (indicator-applet-developers)


This merge removes all of the introspection of people coming on the bus.
Instead it sets up a signal when new listeners come on the bus and has
all servers respond with a show signal when they hear it.  Much, much
cleaner.

-- 
https://code.launchpad.net/~ted/libindicate/discovery-and-love/+merge/18503
Your team ayatana-commits is subscribed to branch lp:libindicate.
=== modified file 'configure.ac'
--- configure.ac	2010-02-02 08:15:17 +0000
+++ configure.ac	2010-02-03 05:46:11 +0000
@@ -52,14 +52,21 @@
 DBUS_REQUIRED_VERSION=0.76
 GLIB_REQUIRED_VERSION=2.18
 GIO_REQUIRED_VERSION=2.18
+<<<<<<< TREE
 XML_REQUIRED_VERSION=2.6
 DBUSMENU_REQUIRED_VERSION=0.2.0
+=======
+>>>>>>> MERGE-SOURCE
 
 PKG_CHECK_MODULES(LIBINDICATE, glib-2.0 >= $GLIB_REQUIRED_VERSION
                                gio-2.0 >= $GIO_REQUIRED_VERSION
+<<<<<<< TREE
                                dbus-glib-1 >= $DBUS_REQUIRED_VERSION
                                dbusmenu-glib >= $DBUSMENU_REQUIRED_VERSION
                                libxml-2.0 >= $XML_REQUIRED_VERSION)
+=======
+                               dbus-glib-1 >= $DBUS_REQUIRED_VERSION)
+>>>>>>> MERGE-SOURCE
 AC_SUBST(LIBINDICATE_CFLAGS)
 AC_SUBST(LIBINDICATE_LIBS)
 

=== modified file 'libindicate/indicate-listener.xml'
--- libindicate/indicate-listener.xml	2009-02-23 04:59:44 +0000
+++ libindicate/indicate-listener.xml	2010-02-03 05:46:11 +0000
@@ -35,6 +35,10 @@
 			<arg type="as" name="server_ids" direction="out" />
 		</method>
 
+<!-- Signals -->
+		<signal name="IndicatorServersReport">
+		</signal>
+
 <!-- End of interesting stuff -->
 
 	</interface>

=== modified file 'libindicate/listener-private.h'
--- libindicate/listener-private.h	2009-08-28 21:59:26 +0000
+++ libindicate/listener-private.h	2010-02-03 05:46:11 +0000
@@ -48,11 +48,7 @@
 	DBusGConnection * session_bus;
 	DBusGConnection * system_bus;
 
-	DBusGProxy * dbus_proxy_session;
-	DBusGProxy * dbus_proxy_system;
-
-	GList * proxies_working;
-	GList * proxies_possible;
+	GList * proxies;
 
 	GArray * proxy_todo;
 	guint todo_idle;

=== modified file 'libindicate/listener.c'
--- libindicate/listener.c	2010-02-01 06:13:31 +0000
+++ libindicate/listener.c	2010-02-03 05:46:11 +0000
@@ -27,12 +27,11 @@
 <http://www.gnu.org/licenses/>
 */
 
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-
+#include <stdlib.h>
 #include "listener.h"
 #include "listener-marshal.h"
 #include <dbus/dbus-glib-bindings.h>
+#include <dbus/dbus-glib-lowlevel.h>
 #include "dbus-indicate-client.h"
 #include "dbus-listener-client.h"
 #include "interests-priv.h"
@@ -50,6 +49,7 @@
 	SERVER_ADDED,
 	SERVER_REMOVED,
 	SERVER_COUNT_CHANGED,
+	INDICATOR_SERVERS_REPORT,
 	LAST_SIGNAL
 };
 
@@ -62,10 +62,12 @@
 	DBusGProxy * property_proxy;
 	DBusGConnection * connection;
 	gchar * name;
+	gchar * path;
 	gchar * type;
 	IndicateListener * listener;
 	GHashTable * indicators;
 	guint introspect_level;
+	gboolean hidden;
 
 	IndicateListenerServer server;
 } proxy_t;
@@ -86,28 +88,27 @@
 typedef struct {
 	DBusGConnection * bus;
 	gchar * name;
-	gboolean startup;
+	gchar * path;
 } proxy_todo_t;
 
 G_DEFINE_TYPE (IndicateListener, indicate_listener, G_TYPE_OBJECT);
 
 /* Prototypes */
 static void indicate_listener_finalize (GObject * obj);
-static void dbus_owner_change (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, IndicateListener * listener);
+static DBusHandlerResult dbus_filter_show_server (DBusConnection * connection, DBusMessage * message, void * user_data);
 static void proxy_struct_destroy (gpointer data);
-static void build_todo_list_cb (DBusGProxy * proxy, char ** names, GError * error, void * data);
-static void todo_list_add (const gchar * name, DBusGProxy * proxy, IndicateListener * listener, gboolean startup);
+static void todo_list_add (const gchar * name, const gchar * path, IndicateListener * listener);
 static gboolean todo_idle (gpointer data);
+void set_max_indicators_cb (DBusGProxy * proxy, GError * error, gpointer userdata);
+static void get_type_initial_cb (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data);
 static void get_type_cb (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data);
 static void proxy_indicator_added_legacy (DBusGProxy * proxy, guint id, gchar * type, proxy_t * proxyt);
-static void proxy_server_added (DBusGProxy * proxy, const gchar * type, proxy_t * proxyt);
 static void proxy_indicator_added (DBusGProxy * proxy, guint id, proxy_t * proxyt);
 static void proxy_indicator_removed_legacy (DBusGProxy * proxy, guint id, gchar * type, proxy_t * proxyt);
 static void proxy_indicator_removed (DBusGProxy * proxy, guint id, proxy_t * proxyt);
 static void proxy_indicator_modified (DBusGProxy * proxy, guint id, const gchar * property, proxy_t * proxyt);
 static void proxy_server_count_changed (DBusGProxy * proxy, guint count, proxy_t * proxyt);
 static void proxy_get_indicator_list (DBusGProxy * proxy, GArray * indicators, GError * error, gpointer data);
-static void introspect_this (DBusGProxy * proxy, char * OUT_data, GError * error, gpointer data);
 
 /* DBus interface */
 gboolean _indicate_listener_get_indicator_servers (IndicateListener * listener, GList * servers);
@@ -169,6 +170,13 @@
 	                                        NULL, NULL,
 	                                        _indicate_listener_marshal_VOID__POINTER_UINT,
 	                                        G_TYPE_NONE, 2, INDICATE_TYPE_LISTENER_SERVER, G_TYPE_UINT);
+	signals[INDICATOR_SERVERS_REPORT] = g_signal_new("indicator-servers-report",
+	                                        G_TYPE_FROM_CLASS (class),
+	                                        G_SIGNAL_RUN_LAST,
+	                                        G_STRUCT_OFFSET (IndicateListenerClass, indicator_servers_report),
+	                                        NULL, NULL,
+	                                        g_cclosure_marshal_VOID__VOID,
+	                                        G_TYPE_NONE, 0, G_TYPE_NONE);
 
 	dbus_g_object_register_marshaller(_indicate_listener_marshal_VOID__UINT_STRING,
 	                                  G_TYPE_NONE,
@@ -176,6 +184,9 @@
 	                                  G_TYPE_STRING,
 	                                  G_TYPE_INVALID);
 
+	dbus_g_object_type_install_info(INDICATE_TYPE_LISTENER,
+	                                &dbus_glib__indicate_listener_object_info);
+
 	return;
 }
 
@@ -194,28 +205,8 @@
 		return;
 	}
 
-	/* Set up the DBUS service proxies */
-	priv->dbus_proxy_session = dbus_g_proxy_new_for_name_owner (priv->session_bus,
-	                                                                DBUS_SERVICE_DBUS,
-	                                                                DBUS_PATH_DBUS,
-	                                                                DBUS_INTERFACE_DBUS,
-	                                                                &error);
-	if (error != NULL) {
-		g_error("Unable to get dbus proxy on session bus: %s", error->message);
-		g_error_free(error);
-		return;
-	}
-
-	/* Set up name change signals */
-	dbus_g_proxy_add_signal(priv->dbus_proxy_session, "NameOwnerChanged",
-	                        G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-	                        G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal(priv->dbus_proxy_session, "NameOwnerChanged",
-	                            G_CALLBACK(dbus_owner_change), listener, NULL);
-
 	/* Initialize Data structures */
-	priv->proxies_working = NULL;
-	priv->proxies_possible = NULL;
+	priv->proxies = NULL;
 
 	/* TODO: Look at some common scenarios and find out how to make this sized */
 	priv->proxy_todo = g_array_new(FALSE, TRUE, sizeof(proxy_todo_t));
@@ -227,8 +218,15 @@
 	/* Starting massive asynchronisity */
 	/*                                 */
 
-	/* Build todo list */
-	org_freedesktop_DBus_list_names_async (priv->dbus_proxy_session, build_todo_list_cb, listener);
+	dbus_connection_add_filter(dbus_g_connection_get_connection(priv->session_bus), dbus_filter_show_server, listener, NULL);
+	dbus_bus_add_match(dbus_g_connection_get_connection(priv->session_bus), "type='signal',interface='org.freedesktop.indicator',member='ServerShow'", NULL);
+
+	dbus_g_connection_register_g_object(priv->session_bus,
+	                                    "/org/freedesktop/indicator/listener",
+//	                                    dbus_bus_get_unique_name(dbus_g_connection_get_connection(priv->session_bus)),
+	                                    G_OBJECT(listener));
+
+	g_signal_emit(G_OBJECT(listener), signals[INDICATOR_SERVERS_REPORT], 0, TRUE);
 
 	return;
 }
@@ -239,32 +237,27 @@
 	IndicateListener * listener = INDICATE_LISTENER(obj);
 	IndicateListenerPrivate * priv = INDICATE_LISTENER_GET_PRIVATE(listener);
 
-	dbus_g_proxy_disconnect_signal(priv->dbus_proxy_session, "NameOwnerChanged",
-	                               G_CALLBACK(dbus_owner_change), listener);
-	dbus_g_proxy_disconnect_signal(priv->dbus_proxy_system, "NameOwnerChanged",
-	                               G_CALLBACK(dbus_owner_change), listener);
-	
 	if (priv->todo_idle != 0) {
 		g_idle_remove_by_data(obj);
 	}
 	/* Hack: proxy_struct_destroy() lacks a user_data parameter, but since the
 	 * caller is responsible for handling params on the stack, it works
 	 */
-	g_list_foreach(priv->proxies_possible, (GFunc)proxy_struct_destroy, NULL);
-	g_list_free(priv->proxies_possible);
-	g_list_foreach(priv->proxies_working, (GFunc)proxy_struct_destroy, NULL);
-	g_list_free(priv->proxies_working);
-
-	g_object_unref(priv->dbus_proxy_session);
-	g_object_unref(priv->dbus_proxy_system);
-
-	dbus_g_connection_unref(priv->session_bus);
-	dbus_g_connection_unref(priv->system_bus);
+	g_list_foreach(priv->proxies, (GFunc)proxy_struct_destroy, NULL);
+	g_list_free(priv->proxies);
 
 	G_OBJECT_CLASS (indicate_listener_parent_class)->finalize (obj);
 	return;
 }
 
+/**
+	indicate_listener_new:
+
+	Creates a new Listener object.  Does not set this to the default
+	listener object.
+
+	Return value: A new listener object.
+*/
 IndicateListener *
 indicate_listener_new (void)
 {
@@ -273,8 +266,22 @@
 	return listener;
 }
 
+/* The pointer to the default listener object */
 static IndicateListener * default_indicate_listener = NULL;
 
+/**
+	indcate_listener_ref_default:
+
+	Looks for the default listener, and if it doesn't exist it'll
+	allocate a new one and mark it the default.  This is what most
+	programs should use rather than #indicate_listener_new because
+	it is rare that anyone would need more than a single listener.
+	This function does increase the ref count on the object so anyone
+	calling it should unref thier instance of the default listener.
+
+	Return value: The default instance of #IndicateListener for the
+		program.
+*/
 IndicateListener *
 indicate_listener_ref_default (void)
 {
@@ -289,43 +296,26 @@
 	return default_indicate_listener;
 }
 
-/* Function to track when people get on and off the bus. */
-static void
-dbus_owner_change (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, IndicateListener * listener)
+/* A small filter function that notices when someone sends
+   a ServerShow signal and creates an entry for us to investigate
+   them more in an idle loop lookup. */
+static DBusHandlerResult
+dbus_filter_show_server (DBusConnection * connection, DBusMessage * message, void * user_data)
 {
-	g_return_if_fail(INDICATE_IS_LISTENER(listener));
-	IndicateListenerPrivate * priv = INDICATE_LISTENER_GET_PRIVATE(listener);
-
-	/* If someone is getting on the bus we add them to the
-	   todo list to see if they come up with something interesting */
-	if (prev != NULL && prev[0] == '\0') {
-		todo_list_add(name, proxy, listener, FALSE);
-	}
-
-	/* If they're leaving the bus we need to figure out if we
-	   were tracking them or not, and remove them from the
-	   appropriate lists. */
-	if (new != NULL && new[0] == '\0') {
-		proxy_t searchitem;
-		searchitem.connection = priv->session_bus;
-		searchitem.name = (gchar *)name; /* Droping const, not that it isn't, but to remove the warning */
-
-		GList * proxyt_item;
-		proxyt_item = g_list_find_custom(priv->proxies_working, &searchitem, proxy_t_equal);
-		if (proxyt_item != NULL) {
-			proxy_struct_destroy((proxy_t *)proxyt_item->data);
-			priv->proxies_working = g_list_remove(priv->proxies_working, proxyt_item->data);
-		}
-		proxyt_item = g_list_find_custom(priv->proxies_possible, &searchitem, proxy_t_equal);
-		if (proxyt_item != NULL) {
-			proxy_struct_destroy((proxy_t *)proxyt_item->data);
-			priv->proxies_possible = g_list_remove(priv->proxies_possible, proxyt_item->data);
-		}
-	}
-
-	return;
+	if (!dbus_message_is_signal(message, "org.freedesktop.indicator", "ServerShow")) {
+		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+	}
+
+	const char * sender = dbus_message_get_sender(message);
+	const char * path = dbus_message_get_path(message);
+
+	todo_list_add(sender, path, INDICATE_LISTENER(user_data));
+
+	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
+/* A hashtable for each function to look at all of the indicators
+   on a proxy_t object and signal their destruction */
 static void
 proxy_struct_destroy_indicators (gpointer key, gpointer value, gpointer data)
 {
@@ -337,12 +327,13 @@
 	return;
 }
 
+/* Cleans up a proxy_t struct after allocation.  It signals that
+   all of the indicators are going away and the server itself. */
 static void
 proxy_struct_destroy (gpointer data)
 {
 	proxy_t * proxy_data = data;
 
-	/* TODO: Clear the indicators by signaling */
 	if (proxy_data->indicators != NULL) {
 		g_hash_table_foreach(proxy_data->indicators,
 							 proxy_struct_destroy_indicators,
@@ -361,7 +352,14 @@
 		g_object_unref(G_OBJECT(proxy_data->proxy));
 	}
 
-	g_free(proxy_data->name);
+	if (proxy_data->name != NULL) {
+		g_free(proxy_data->name);
+	}
+
+	if (proxy_data->path != NULL) {
+		g_free(proxy_data->path);
+	}
+
 	if (proxy_data->type != NULL) {
 		g_free(proxy_data->type);
 	}
@@ -370,26 +368,11 @@
 	return;
 }
 
-static void
-build_todo_list_cb (DBusGProxy * proxy, char ** names, GError * error, void * data)
-{
-	IndicateListener * listener = INDICATE_LISTENER(data);
-
-	if (error != NULL) {
-		g_warning("Unable to get names: %s", error->message);
-		return;
-	}
-
-	guint i = 0;
-	for (i = 0; names[i] != NULL; i++) {
-		todo_list_add(names[i], proxy, listener, TRUE);
-	}
-
-	return;
-}
-
-static void
-todo_list_add (const gchar * name, DBusGProxy * proxy, IndicateListener * listener, gboolean startup)
+/* Creates a todo list item for the particular server and
+   path as they've signaled that they're on DBus and like
+   talking about indicators. */
+static void
+todo_list_add (const gchar * name, const gchar * path, IndicateListener * listener)
 {
 	if (name == NULL || name[0] != ':') {
 		return;
@@ -399,8 +382,8 @@
 
 	proxy_todo_t todo;
 	todo.name = g_strdup(name);
+	todo.path = g_strdup(path);
 	todo.bus  = priv->session_bus;
-	todo.startup = startup;
 
 	g_array_append_val(priv->proxy_todo, todo);
 
@@ -431,44 +414,131 @@
 	}
 
 	proxy_todo_t * todo = &g_array_index(priv->proxy_todo, proxy_todo_t, priv->proxy_todo->len - 1);
+	/* Remove the todo list */
+	priv->proxy_todo = g_array_remove_index(priv->proxy_todo, priv->proxy_todo->len - 1);
+
+	/* Check to see if we already have this item, if so,
+	   we assume that it's signal handler will handle the
+	   ServerShow signal.  We're just going to exit this 
+	   function. */
+	if (TRUE) {
+		proxy_t searchitem;
+		searchitem.name = todo->name;
+		searchitem.connection = todo->bus;
+
+		GList * proxyitem = g_list_find_custom(priv->proxies, &searchitem, proxy_t_equal);
+		if (proxyitem != NULL) {
+			g_free(todo->name);
+			g_free(todo->path);
+			g_free(todo);
+			return TRUE;
+		}
+	}
 
 	proxy_t * proxyt = g_new0(proxy_t, 1);
 	proxyt->name = todo->name;
+	proxyt->path = todo->path;
 	proxyt->type = NULL;
-	proxyt->proxy = dbus_g_proxy_new_for_name(todo->bus,
-	                                          proxyt->name,
-	                                          "/org/freedesktop/indicate",
-	                                          "org.freedesktop.indicator");
 	proxyt->property_proxy = NULL;
+	proxyt->proxy = NULL;
 	proxyt->listener = listener;
 	proxyt->indicators = NULL;
+	proxyt->hidden = FALSE;
 	proxyt->connection = todo->bus;
 	proxyt->server.name = todo->name;
-	proxyt->server.proxy = proxyt->proxy;
+	proxyt->server.proxy = NULL;
 	proxyt->server.connection = proxyt->connection;
 	proxyt->server.max_indicators = priv->max_indicators;
 
-	priv->proxy_todo = g_array_remove_index(priv->proxy_todo, priv->proxy_todo->len - 1);
-
-	if (proxyt->proxy == NULL) {
+	/* Build the indicators hash */
+	proxyt->indicators = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+	/* Build the proxy and ensure that it gets created.  If
+	   it gets created we're all happy. */
+	GError * error = NULL;
+	proxyt->proxy = dbus_g_proxy_new_for_name_owner(todo->bus,
+	                                                proxyt->name,
+	                                                todo->path,
+	                                                "org.freedesktop.indicator",
+	                                                &error);
+
+	g_free(todo);
+
+	if (error != NULL) {
 		g_warning("Unable to create proxy for %s", proxyt->name);
+		g_error_free(error);
 		return TRUE;
 	}
 
-	dbus_g_proxy_add_signal(proxyt->proxy, "ServerShow",
-	                        G_TYPE_STRING, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal(proxyt->proxy, "ServerShow",
-	                            G_CALLBACK(proxy_server_added), proxyt, NULL);
-
-	priv->proxies_possible = g_list_prepend(priv->proxies_possible, proxyt);
-
-	/* Look through the introspection data to see if this
-	   is already a server */
-	introspect_this (NULL, NULL, NULL, proxyt);
+	/* Making sure the server has the proxy as well */
+	proxyt->server.proxy = proxyt->proxy;
+
+	/* Adding into the list of proxies */
+	priv->proxies = g_list_prepend(priv->proxies, proxyt);
+
+	/* Setup all the signals that we need off of this
+	   proxy.  Lot's of fun signals. */
+	dbus_g_proxy_add_signal(proxyt->proxy, "IndicatorAdded",
+	                            G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal(proxyt->proxy, "IndicatorAdded",
+	                            G_CALLBACK(proxy_indicator_added_legacy), proxyt, NULL);
+	dbus_g_proxy_add_signal(proxyt->proxy, "IndicatorNew",
+	                            G_TYPE_UINT, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal(proxyt->proxy, "IndicatorNew",
+	                            G_CALLBACK(proxy_indicator_added), proxyt, NULL);
+	dbus_g_proxy_add_signal(proxyt->proxy, "IndicatorRemoved",
+	                            G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal(proxyt->proxy, "IndicatorRemoved",
+	                            G_CALLBACK(proxy_indicator_removed_legacy), proxyt, NULL);
+	dbus_g_proxy_add_signal(proxyt->proxy, "IndicatorDelete",
+	                            G_TYPE_UINT, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal(proxyt->proxy, "IndicatorDelete",
+	                            G_CALLBACK(proxy_indicator_removed), proxyt, NULL);
+	dbus_g_proxy_add_signal(proxyt->proxy, "IndicatorModified",
+	                            G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal(proxyt->proxy, "IndicatorModified",
+	                            G_CALLBACK(proxy_indicator_modified), proxyt, NULL);
+	dbus_g_proxy_add_signal(proxyt->proxy, "ServerCountChanged",
+	                            G_TYPE_UINT, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal(proxyt->proxy, "ServerCountChanged",
+	                            G_CALLBACK(proxy_server_count_changed), proxyt, NULL);
+
+	/* We're setting the max number of indicators from the default
+	   when we detect it.  This should give a reasonable amount of
+	   time for listeners to set the default if they want something
+	   different from infinite.  Otherwise it'd be easy to miss the
+	   first couple. */
+	proxyt->server.max_indicators = priv->max_indicators;
+	if (proxyt->server.max_indicators != -1) {
+		org_freedesktop_indicator_set_max_indicators_async(proxyt->proxy, proxyt->server.max_indicators, set_max_indicators_cb, proxyt->name);
+	}
+
+	indicate_listener_server_get_type(proxyt->listener, &proxyt->server, get_type_initial_cb, proxyt);
+	org_freedesktop_indicator_get_indicator_list_async(proxyt->proxy, proxy_get_indicator_list, proxyt);
 
 	return TRUE;
 }
 
+/* A callback function for the getting the type when it is looked
+   at initially.  So that we'll send a signal that the server has
+   been added so that everyone knows. */
+static void
+get_type_initial_cb (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data)
+{
+	get_type_cb(listener, server, type, data);
+
+	proxy_t * proxyt = (proxy_t *)data;
+
+	if (!proxyt->hidden && proxyt->type != NULL) {
+		g_signal_emit(proxyt->listener, signals[SERVER_ADDED], 0, &proxyt->server, proxyt->type, TRUE);
+	}
+
+	return;
+}
+
+/* Callback from getting the type of the server.  We're not using
+   this directly now, only through get_type_initial_cb right now
+   though we might use it more directly later. */
 static void
 get_type_cb (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data)
 {
@@ -480,8 +550,11 @@
 
 	proxy_t * proxyt = (proxy_t *)data;
 
-	proxy_server_added (proxyt->proxy, type, proxyt);
-	org_freedesktop_indicator_get_indicator_list_async(proxyt->proxy, proxy_get_indicator_list, proxyt);
+	if (proxyt->type != NULL) {
+		g_free(proxyt->type);
+		proxyt->type = NULL;
+	}
+	proxyt->type = g_strdup(type);
 
 	return;
 }
@@ -519,85 +592,6 @@
 	return;
 }
 
-/* Function called on the ServerShow signal from the bus, which is
-   usually when a DBus client says that they have some indicators
-   that we could be interested in.  Also, this function is called
-   in the discovery phase of starting up a new listener if we find
-   some indicators on the client. */
-static void
-proxy_server_added (DBusGProxy * proxy, const gchar * type, proxy_t * proxyt)
-{
-	g_debug("Proxy Server Added");
-	/* Check to see if we have an indicators table.  If we
-	   do this function's probably already been run.  If not
-	   we need to trick this server out. */
-	if (proxyt->indicators == NULL) {
-		proxyt->indicators = g_hash_table_new(g_direct_hash, g_direct_equal);
-
-		IndicateListenerPrivate * priv = INDICATE_LISTENER_GET_PRIVATE(proxyt->listener);
-
-		/* Move the proxy from 'possible' to 'working'. */
-		GList * proxyt_item;
-		proxyt_item = g_list_find_custom(priv->proxies_possible, proxyt, proxy_t_equal);
-		if (proxyt_item != NULL) {
-			priv->proxies_possible = g_list_remove(priv->proxies_possible, proxyt_item->data);
-		}
-		priv->proxies_working = g_list_prepend(priv->proxies_working, proxyt);
-
-		/* Connect to all the indicator based signals
-		   that are coming from this server */
-		dbus_g_proxy_add_signal(proxyt->proxy, "IndicatorAdded",
-								G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
-		dbus_g_proxy_connect_signal(proxyt->proxy, "IndicatorAdded",
-									G_CALLBACK(proxy_indicator_added_legacy), proxyt, NULL);
-		dbus_g_proxy_add_signal(proxyt->proxy, "IndicatorNew",
-								G_TYPE_UINT, G_TYPE_INVALID);
-		dbus_g_proxy_connect_signal(proxyt->proxy, "IndicatorNew",
-									G_CALLBACK(proxy_indicator_added), proxyt, NULL);
-		dbus_g_proxy_add_signal(proxyt->proxy, "IndicatorRemoved",
-								G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
-		dbus_g_proxy_connect_signal(proxyt->proxy, "IndicatorRemoved",
-									G_CALLBACK(proxy_indicator_removed_legacy), proxyt, NULL);
-		dbus_g_proxy_add_signal(proxyt->proxy, "IndicatorDelete",
-								G_TYPE_UINT, G_TYPE_INVALID);
-		dbus_g_proxy_connect_signal(proxyt->proxy, "IndicatorDelete",
-									G_CALLBACK(proxy_indicator_removed), proxyt, NULL);
-		dbus_g_proxy_add_signal(proxyt->proxy, "IndicatorModified",
-								G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
-		dbus_g_proxy_connect_signal(proxyt->proxy, "IndicatorModified",
-									G_CALLBACK(proxy_indicator_modified), proxyt, NULL);
-		dbus_g_proxy_add_signal(proxyt->proxy, "ServerCountChanged",
-								G_TYPE_UINT, G_TYPE_INVALID);
-		dbus_g_proxy_connect_signal(proxyt->proxy, "ServerCountChanged",
-									G_CALLBACK(proxy_server_count_changed), proxyt, NULL);
-
-		/* If we've got a type let it override the type
-		   we had here before */
-		if (type != NULL) {
-			if (proxyt->type != NULL) {
-				g_free(proxyt->type);
-			}
-			proxyt->type = g_strdup(type);
-		}
-
-		/* We're setting the max number of indicators from the default
-		   when we detect it.  This should give a reasonable amount of
-		   time for listeners to set the default if they want something
-		   different from infinite.  Otherwise it'd be easy to miss the
-		   first couple. */
-		proxyt->server.max_indicators = priv->max_indicators;
-		if (proxyt->server.max_indicators != -1) {
-			org_freedesktop_indicator_set_max_indicators_async(proxyt->proxy, proxyt->server.max_indicators, set_max_indicators_cb, proxyt->name);
-		}
-
-		/* Signal to clients of the listener that there's a new
-		   server.  Note the server parameter here is the pointer
-		   to the server struct in the proxy data structure. */
-		g_signal_emit(proxyt->listener, signals[SERVER_ADDED], 0, &proxyt->server, proxyt->type, TRUE);
-	}
-
-	return;
-}
 
 /* A fun little wrapper so that we can support the
    signals on the indicator v1 interface.  It just drops
@@ -619,10 +613,6 @@
 	g_debug("Proxy Indicator Added");
 	g_return_if_fail(proxyt != NULL);
 
-	if (proxyt->indicators == NULL) {
-		proxy_server_added (proxy, NULL, proxyt);
-	}
-
 	if (!g_hash_table_lookup(proxyt->indicators, GUINT_TO_POINTER(id))) {
 		g_hash_table_insert(proxyt->indicators, GUINT_TO_POINTER(id), GUINT_TO_POINTER(TRUE));
 		g_signal_emit(proxyt->listener, signals[INDICATOR_ADDED], 0, &proxyt->server, GUINT_TO_POINTER(id), TRUE);
@@ -1038,11 +1028,7 @@
 	searchitem.name = server->name;
 	searchitem.connection = server->connection;
 
-	GList * proxyitem = g_list_find_custom(priv->proxies_possible, &searchitem, proxy_t_equal);
-	if (proxyitem == NULL) {
-		proxyitem = g_list_find_custom(priv->proxies_working, &searchitem, proxy_t_equal);
-	}
-
+	GList * proxyitem = g_list_find_custom(priv->proxies, &searchitem, proxy_t_equal);
 	if (proxyitem == NULL) {
 		g_warning("Can not find a proxy for the server at all.");
 		return;
@@ -1053,7 +1039,7 @@
 	if (proxyt->property_proxy == NULL) {
 		proxyt->property_proxy = dbus_g_proxy_new_for_name(proxyt->connection,
 		                                                   proxyt->name,
-		                                                   "/org/freedesktop/indicate",
+		                                                   proxyt->path,
 		                                                   DBUS_INTERFACE_PROPERTIES);
 	}
 
@@ -1195,101 +1181,6 @@
   return our_type;
 }
 
-static const gchar * _introspector_path[] = {"", "org", "freedesktop", "indicate", NULL};
-static const gchar * _introspector_fullpath[] = {"/", "/org", "/org/freedesktop", "/org/freedesktop/indicate", NULL};
-static const gchar * _introspector_interface = "org.freedesktop.indicator";
-
-static void
-introspect_this (DBusGProxy * proxy, char * OUT_data, GError * error, gpointer data)
-{
-	/* g_debug("Introspect this:\n%s", OUT_data); */
-	proxy_t * server = (proxy_t *)data;
-	if (proxy != NULL) {
-		g_object_unref(proxy);
-	}
-	if (error != NULL) {
-		/* We probably couldn't introspect that far up.  That's
-		   life, it happens. Or there's a timeout, that happens
-		   too, I guess some apps are too busy for us. */
-		/* g_debug("Introspection error on %s object %s: %s", server->name, _introspector_fullpath[server->introspect_level], error->message); */
-		return;
-	}
-
-	if (OUT_data != NULL) {
-		xmlDocPtr xmldoc;
-		/* Parse the XML */
-		xmldoc = xmlReadMemory(OUT_data, g_utf8_strlen(OUT_data, 16*1024), "introspection.xml", NULL, 0);
-
-		/* Check for root being "node" */
-		xmlNodePtr root = xmlDocGetRootElement(xmldoc);
-		if (g_strcmp0((gchar *)root->name, "node") != 0) {
-			xmlFreeDoc(xmldoc);
-			g_warning("Introspection data from %s is not valid: %s", server->name, OUT_data);
-			return;
-		}
-
-		server->introspect_level += 1;
-		const gchar * nodename = NULL;
-		const gchar * nameval = NULL;
-		if (_introspector_path[server->introspect_level] == NULL) {
-			/* We're looking for our interface */
-			nodename = "interface";
-			nameval = _introspector_interface;
-		} else {
-			/* We're looking for our next node */
-			nodename = "node";
-			nameval = _introspector_path[server->introspect_level];
-		}
-
-		gboolean found = FALSE;
-		xmlNodePtr children;
-		for (children = root->children; children != NULL; children = children->next) {
-			gchar * xmlnameval = NULL;
-			if (g_strcmp0((gchar *)children->name, nodename) == 0) {
-				xmlAttrPtr attrib;
-				for (attrib = children->properties; attrib != NULL; attrib = attrib->next) {
-					if (g_strcmp0((gchar *)attrib->name, "name") == 0) {
-						if (attrib->children != NULL) {
-							xmlnameval = (gchar *)attrib->children->content;
-						}
-						break;
-					}
-				}
-
-				if (!g_strcmp0(nameval, xmlnameval)) {
-					found = TRUE;
-					break;
-				}
-			}
-		}
-
-		xmlFreeDoc(xmldoc);
-
-		if (!found) {
-			/* Ah, nothing we're interested in */
-			return;
-		}
-
-		if (_introspector_path[server->introspect_level] == NULL) {
-			/* If we've found the interface at the end of the tree, whoo! hoo! */
-			/* Now we know it's safe to get the type on it */
-			indicate_listener_server_get_type(server->listener, &server->server, get_type_cb, server);
-			return;
-		}
-	} else {
-		server->introspect_level = 0;
-	}
-
-	DBusGProxy * newproxy = dbus_g_proxy_new_for_name(server->connection,
-	                                                  server->name,
-	                                                  _introspector_fullpath[server->introspect_level],
-	                                                  DBUS_INTERFACE_INTROSPECTABLE);
-
-	org_freedesktop_DBus_Introspectable_introspect_async(newproxy, introspect_this, server);
-
-	return;
-}
-
 /**
 	indicate_listener_set_default_max_indicators:
 	@listener: Instance of #IndicateListener to set on.

=== modified file 'libindicate/listener.h'
--- libindicate/listener.h	2010-02-01 02:31:17 +0000
+++ libindicate/listener.h	2010-02-03 05:46:11 +0000
@@ -79,10 +79,10 @@
 	@server_added: Slot for IndicateListener::server-added.
 	@server_removed: Slot for IndicateListener::server-removed.
 	@server_count_changed: Slot for IndicateListener::server-count-changed.
+	@indicator_servers_report: Slot for IndicateListener::indicator-servers-report.
 	@indicate_listener_reserved1: Reserved for future use
 	@indicate_listener_reserved2: Reserved for future use
 	@indicate_listener_reserved3: Reserved for future use
-	@indicate_listener_reserved4: Reserved for future use
 
 	The class has all of the signals that are supplied by
 	the listener about what is happening on the server.
@@ -101,11 +101,12 @@
 	void (* server_removed) (IndicateListenerServer * server, gchar * type);
 	void (* server_count_changed) (IndicateListenerServer * server, guint count);
 
+	void (* indicator_servers_report) (void);
+
 	/* Future Use */
 	void (*indicate_listener_reserved1)(void);
 	void (*indicate_listener_reserved2)(void);
 	void (*indicate_listener_reserved3)(void);
-	void (*indicate_listener_reserved4)(void);
 };
 
 GType indicate_listener_get_type (void) G_GNUC_CONST;

=== modified file 'libindicate/server.c'
--- libindicate/server.c	2010-02-01 05:59:25 +0000
+++ libindicate/server.c	2010-02-03 05:46:11 +0000
@@ -129,7 +129,11 @@
 G_DEFINE_TYPE (IndicateServer, indicate_server, G_TYPE_OBJECT);
 
 /* Prototypes */
+<<<<<<< TREE
 static void indicate_server_dispose (GObject * obj);
+=======
+static DBusHandlerResult dbus_filter_new_listener (DBusConnection * connection, DBusMessage * message, void * user_data);
+>>>>>>> MERGE-SOURCE
 static void indicate_server_finalize (GObject * obj);
 static gboolean get_indicator_count (IndicateServer * server, guint * count, GError **error);
 static gboolean get_indicator_list (IndicateServer * server, GArray ** indicators, GError ** error);
@@ -408,6 +412,11 @@
 	priv->interestedfolks = NULL;
 	priv->max_indicators = MAX_INDICATORS_UNSET;
 
+	priv->connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+
+	dbus_connection_add_filter(dbus_g_connection_get_connection(priv->connection), dbus_filter_new_listener, server, NULL);
+	dbus_bus_add_match(dbus_g_connection_get_connection(priv->connection), "type='signal',interface='org.freedesktop.indicator.listener',member='IndicatorServersReport'", NULL);
+
 	return;
 }
 
@@ -526,6 +535,27 @@
 	return;
 }
 
+/* A small dbus filter that waits on the IndicatorServersReport
+   signal and sends the Show signal if this server is not hidden. */
+static DBusHandlerResult
+dbus_filter_new_listener (DBusConnection * connection, DBusMessage * message, void * user_data)
+{
+	if (!dbus_message_is_signal(message, "org.freedesktop.indicator.listener", "IndicatorServersReport")) {
+		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+	}
+
+	IndicateServer * server = INDICATE_SERVER(user_data);
+
+	if (server != NULL) {
+		IndicateServerPrivate * priv = INDICATE_SERVER_GET_PRIVATE(server);
+		if (priv->visible) {
+			g_signal_emit(server, signals[SERVER_SHOW], 0, priv->type ? priv->type : "", TRUE);
+		}
+	}
+
+	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
 /* Small little function to get an error quark for usage
    with the GError errors back across DBus */
 static GQuark


Follow ups