Merge lp:~mterry/indicator-application/gdbus into lp:indicator-application/0.4

Proposed by Michael Terry
Status: Merged
Merged at revision: 171
Proposed branch: lp:~mterry/indicator-application/gdbus
Merge into: lp:indicator-application/0.4
Diff against target: 2473 lines (+941/-842)
13 files modified
.bzrignore (+2/-5)
configure.ac (+3/-0)
data/indicator-application.service.in (+1/-1)
src/Makefile.am (+21/-9)
src/application-service-appstore.c (+645/-544)
src/application-service.c (+0/-1)
src/application-service.xml (+1/-1)
src/dbus-properties.xml (+0/-23)
src/dbus-shared.h (+3/-3)
src/indicator-application.c (+155/-177)
src/notification-item.xml (+0/-39)
tests/Makefile.am (+1/-0)
tests/test-approver.c (+109/-39)
To merge this branch: bzr merge lp:~mterry/indicator-application/gdbus
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Review via email: mp+46009@code.launchpad.net
To post a comment you must log in.
173. By Michael Terry

fix issue where icons never went away

174. By Michael Terry

watch for name change, instead of name owner change for approver connections

175. By Michael Terry

don't second guess service's new application, which caused our positions to get out of sync with the service if it was a bit confused

176. By Michael Terry

actually request properties from applications; using cached properties doesn't seem to work

177. By Michael Terry

don't use cached properties for new icons or new aicons either. Instead, just ask for all properties again

178. By Michael Terry

reduce debug spew

179. By Michael Terry

make sure to free pre-validated applications; add applications to the app list as soon as we create them, to avoid apps that spam us (like gnome-power-manager) from creating multiple apps in our list

180. By Michael Terry

merge ken's com.canonical branch

Revision history for this message
Ted Gould (ted) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2010-08-11 16:10:03 +0000
3+++ .bzrignore 2011-01-14 02:39:08 +0000
4@@ -4,8 +4,6 @@
5 src/indicator-application-service
6 src/libappindicator.la
7 src/libappindicator_la-indicator-application.lo
8-src/notification-item-client.h
9-src/notification-item-server.h
10 src/notification-watcher-client.h
11 src/notification-watcher-server.h
12 src/libappindicator.la
13@@ -23,13 +21,12 @@
14 tests/test-libappindicator-dbus-server
15 tests/libappindicator-tests
16 tests/test-libappindicator-dbus
17-src/application-service-client.h
18+src/gen-application-service.xml.c
19+src/gen-application-service.xml.h
20 src/application-service-server.h
21 src/application-service-marshal.c
22 src/application-service-marshal.h
23 src/stamp-marshal
24-src/dbus-properties-client.h
25-src/dbus-properties-server.h
26 tests/test-simple-app
27 example/.deps
28 example/.libs
29
30=== modified file 'configure.ac'
31--- configure.ac 2010-12-08 19:16:13 +0000
32+++ configure.ac 2011-01-14 02:39:08 +0000
33@@ -31,6 +31,7 @@
34
35 GTK_REQUIRED_VERSION=2.18
36 GTK3_REQUIRED_VERSION=2.91
37+GIO_REQUIRED_VERSION=2.26
38 INDICATOR_REQUIRED_VERSION=0.3.5
39 DBUSMENUGTK_REQUIRED_VERSION=0.2.2
40 JSON_GLIB_REQUIRED_VERSION=0.7.6
41@@ -43,6 +44,7 @@
42 [with_gtk=2])
43 AS_IF([test "x$with_gtk" = x3],
44 [PKG_CHECK_MODULES(INDICATOR, gtk+-3.0 >= $GTK3_REQUIRED_VERSION
45+ gio-2.0 >= $GIO_REQUIRED_VERSION
46 indicator3 >= $INDICATOR_REQUIRED_VERSION
47 json-glib-1.0 >= $JSON_GLIB_REQUIRED_VERSION
48 dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION
49@@ -53,6 +55,7 @@
50 ],
51 [test "x$with_gtk" = x2],
52 [PKG_CHECK_MODULES(INDICATOR, gtk+-2.0 >= $GTK_REQUIRED_VERSION
53+ gio-2.0 >= $GIO_REQUIRED_VERSION
54 indicator >= $INDICATOR_REQUIRED_VERSION
55 json-glib-1.0 >= $JSON_GLIB_REQUIRED_VERSION
56 dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION
57
58=== modified file 'data/indicator-application.service.in'
59--- data/indicator-application.service.in 2009-11-25 03:52:40 +0000
60+++ data/indicator-application.service.in 2011-01-14 02:39:08 +0000
61@@ -1,3 +1,3 @@
62 [D-BUS Service]
63-Name=org.ayatana.indicator.application
64+Name=com.canonical.indicator.application
65 Exec=@libexecdir@/indicator-application-service
66
67=== modified file 'src/Makefile.am'
68--- src/Makefile.am 2010-12-08 19:09:39 +0000
69+++ src/Makefile.am 2011-01-14 02:39:08 +0000
70@@ -39,11 +39,8 @@
71 libexec_PROGRAMS = indicator-application-service
72
73 BUILT_SOURCES += \
74- application-service-server.h \
75 application-service-marshal.h \
76 application-service-marshal.c \
77- dbus-properties-client.h \
78- notification-item-client.h \
79 notification-watcher-server.h
80
81 indicator_application_service_SOURCES = \
82@@ -53,6 +50,7 @@
83 application-service-marshal.c \
84 application-service-watcher.h \
85 application-service-watcher.c \
86+ gen-application-service.xml.c \
87 app-indicator-enum-types.c \
88 dbus-shared.h \
89 generate-id.h \
90@@ -81,11 +79,11 @@
91 # DBus Specs
92 ##################################
93
94+GDBUS_SPECS = \
95+ application-service.xml \
96+ notification-approver.xml
97+
98 DBUS_SPECS = \
99- dbus-properties.xml \
100- application-service.xml \
101- notification-approver.xml \
102- notification-item.xml \
103 notification-watcher.xml
104
105 %-client.h: %.xml
106@@ -102,10 +100,24 @@
107 --output=$@ \
108 $<
109
110+gen-%.xml.c: %.xml
111+ @echo "Building $@ from $<"
112+ @echo "const char * _$(subst -,_,$(subst .,_,$(basename $<))) = " > $@
113+ @sed -e "s:\":\\\\\":g" -e s:^:\": -e s:\$$:\\\\n\": $< >> $@
114+ @echo ";" >> $@
115+
116+gen-%.xml.h: %.xml
117+ @echo "Building $@ from $<"
118+ @echo "extern const char * _$(subst -,_,$(subst .,_,$(basename $<)));" > $@
119+
120 BUILT_SOURCES += \
121 $(DBUS_SPECS:.xml=-client.h) \
122- $(DBUS_SPECS:.xml=-server.h)
123+ $(DBUS_SPECS:.xml=-server.h) \
124+ gen-application-service.xml.c \
125+ gen-application-service.xml.h \
126+ gen-notification-approver.xml.c \
127+ gen-notification-approver.xml.h
128
129 CLEANFILES += $(BUILT_SOURCES)
130
131-EXTRA_DIST += $(DBUS_SPECS)
132+EXTRA_DIST += $(DBUS_SPECS) $(GDBUS_SPECS)
133
134=== modified file 'src/application-service-appstore.c'
135--- src/application-service-appstore.c 2010-12-02 22:49:42 +0000
136+++ src/application-service-appstore.c 2011-01-14 02:39:08 +0000
137@@ -24,20 +24,19 @@
138 #include "config.h"
139 #endif
140
141-#include <dbus/dbus-glib.h>
142 #include "libappindicator/app-indicator.h"
143 #include "app-indicator-enum-types.h"
144 #include "application-service-appstore.h"
145 #include "application-service-marshal.h"
146-#include "dbus-properties-client.h"
147 #include "dbus-shared.h"
148-#include "notification-approver-client.h"
149 #include "generate-id.h"
150
151 /* DBus Prototypes */
152-static gboolean _application_service_server_get_applications (ApplicationServiceAppstore * appstore, GPtrArray ** apps, GError ** error);
153+static GVariant * get_applications (ApplicationServiceAppstore * appstore);
154+static void bus_method_call (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * method, GVariant * params, GDBusMethodInvocation * invocation, gpointer user_data);
155+static void props_cb (GObject * object, GAsyncResult * res, gpointer user_data);
156
157-#include "application-service-server.h"
158+#include "gen-application-service.xml.h"
159
160 #define NOTIFICATION_ITEM_PROP_ID "Id"
161 #define NOTIFICATION_ITEM_PROP_CATEGORY "Category"
162@@ -61,7 +60,9 @@
163
164 /* Private Stuff */
165 struct _ApplicationServiceAppstorePrivate {
166- DBusGConnection * bus;
167+ GCancellable * bus_cancel;
168+ GDBusConnection * bus;
169+ guint dbus_registration;
170 GList * applications;
171 GList * approvers;
172 GHashTable * ordering_overrides;
173@@ -76,8 +77,10 @@
174
175 typedef struct _Approver Approver;
176 struct _Approver {
177- DBusGProxy * proxy;
178- gboolean destroy_by_proxy;
179+ ApplicationServiceAppstore * appstore; /* not ref'd */
180+ GCancellable * proxy_cancel;
181+ GDBusProxy * proxy;
182+ guint name_watcher;
183 };
184
185 typedef struct _Application Application;
186@@ -87,8 +90,11 @@
187 gchar * dbus_name;
188 gchar * dbus_object;
189 ApplicationServiceAppstore * appstore; /* not ref'd */
190- DBusGProxy * dbus_proxy;
191- DBusGProxy * prop_proxy;
192+ GCancellable * dbus_proxy_cancel;
193+ GDBusProxy * dbus_proxy;
194+ GCancellable * props_cancel;
195+ gboolean queued_props;
196+ GDBusProxy * props;
197 gboolean validated; /* Whether we've gotten all the parameters and they look good. */
198 AppIndicatorStatus status;
199 gchar * icon;
200@@ -101,23 +107,21 @@
201 guint ordering_index;
202 GList * approved_by;
203 visible_state_t visible_state;
204+ guint name_watcher;
205 };
206
207 #define APPLICATION_SERVICE_APPSTORE_GET_PRIVATE(o) \
208 (G_TYPE_INSTANCE_GET_PRIVATE ((o), APPLICATION_SERVICE_APPSTORE_TYPE, ApplicationServiceAppstorePrivate))
209
210-/* Signals Stuff */
211-enum {
212- APPLICATION_ADDED,
213- APPLICATION_REMOVED,
214- APPLICATION_ICON_CHANGED,
215- APPLICATION_LABEL_CHANGED,
216- APPLICATION_ICON_THEME_PATH_CHANGED,
217- LAST_SIGNAL
218+/* GDBus Stuff */
219+static GDBusNodeInfo * node_info = NULL;
220+static GDBusInterfaceInfo * interface_info = NULL;
221+static GDBusInterfaceVTable interface_table = {
222+ method_call: bus_method_call,
223+ get_property: NULL, /* No properties */
224+ set_property: NULL /* No properties */
225 };
226
227-static guint signals[LAST_SIGNAL] = { 0 };
228-
229 /* GObject stuff */
230 static void application_service_appstore_class_init (ApplicationServiceAppstoreClass *klass);
231 static void application_service_appstore_init (ApplicationServiceAppstore *self);
232@@ -132,6 +136,13 @@
233 static void check_with_new_approver (gpointer papp, gpointer papprove);
234 static void check_with_old_approver (gpointer papprove, gpointer papp);
235 static Application * find_application (ApplicationServiceAppstore * appstore, const gchar * address, const gchar * object);
236+static void bus_get_cb (GObject * object, GAsyncResult * res, gpointer user_data);
237+static void dbus_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data);
238+static void app_receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, GVariant * parameters, gpointer user_data);
239+static void approver_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data);
240+static void approver_receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, GVariant * parameters, gpointer user_data);
241+static void get_all_properties (Application * app);
242+static void application_free (Application * app);
243
244 G_DEFINE_TYPE (ApplicationServiceAppstore, application_service_appstore, G_TYPE_OBJECT);
245
246@@ -145,56 +156,24 @@
247 object_class->dispose = application_service_appstore_dispose;
248 object_class->finalize = application_service_appstore_finalize;
249
250- signals[APPLICATION_ADDED] = g_signal_new ("application-added",
251- G_TYPE_FROM_CLASS(klass),
252- G_SIGNAL_RUN_LAST,
253- G_STRUCT_OFFSET (ApplicationServiceAppstoreClass, application_added),
254- NULL, NULL,
255- _application_service_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING,
256- G_TYPE_NONE, 7, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_NONE);
257- signals[APPLICATION_REMOVED] = g_signal_new ("application-removed",
258- G_TYPE_FROM_CLASS(klass),
259- G_SIGNAL_RUN_LAST,
260- G_STRUCT_OFFSET (ApplicationServiceAppstoreClass, application_removed),
261- NULL, NULL,
262- g_cclosure_marshal_VOID__INT,
263- G_TYPE_NONE, 1, G_TYPE_INT, G_TYPE_NONE);
264- signals[APPLICATION_ICON_CHANGED] = g_signal_new ("application-icon-changed",
265- G_TYPE_FROM_CLASS(klass),
266- G_SIGNAL_RUN_LAST,
267- G_STRUCT_OFFSET (ApplicationServiceAppstoreClass, application_icon_changed),
268- NULL, NULL,
269- _application_service_marshal_VOID__INT_STRING,
270- G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING, G_TYPE_NONE);
271- signals[APPLICATION_ICON_THEME_PATH_CHANGED] = g_signal_new ("application-icon-theme-path-changed",
272- G_TYPE_FROM_CLASS(klass),
273- G_SIGNAL_RUN_LAST,
274- G_STRUCT_OFFSET (ApplicationServiceAppstoreClass, application_icon_theme_path_changed),
275- NULL, NULL,
276- _application_service_marshal_VOID__INT_STRING,
277- G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING, G_TYPE_NONE);
278- signals[APPLICATION_LABEL_CHANGED] = g_signal_new ("application-label-changed",
279- G_TYPE_FROM_CLASS(klass),
280- G_SIGNAL_RUN_LAST,
281- G_STRUCT_OFFSET (ApplicationServiceAppstoreClass, application_label_changed),
282- NULL, NULL,
283- _application_service_marshal_VOID__INT_STRING_STRING,
284- G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_NONE);
285-
286- dbus_g_object_register_marshaller(_application_service_marshal_VOID__STRING_STRING,
287- G_TYPE_NONE,
288- G_TYPE_STRING,
289- G_TYPE_STRING,
290- G_TYPE_INVALID);
291- dbus_g_object_register_marshaller(_application_service_marshal_VOID__BOOLEAN_STRING_OBJECT,
292- G_TYPE_NONE,
293- G_TYPE_BOOLEAN,
294- G_TYPE_STRING,
295- G_TYPE_OBJECT,
296- G_TYPE_INVALID);
297-
298- dbus_g_object_type_install_info(APPLICATION_SERVICE_APPSTORE_TYPE,
299- &dbus_glib__application_service_server_object_info);
300+ /* Setting up the DBus interfaces */
301+ if (node_info == NULL) {
302+ GError * error = NULL;
303+
304+ node_info = g_dbus_node_info_new_for_xml(_application_service, &error);
305+ if (error != NULL) {
306+ g_error("Unable to parse Application Service Interface description: %s", error->message);
307+ g_error_free(error);
308+ }
309+ }
310+
311+ if (interface_info == NULL) {
312+ interface_info = g_dbus_node_info_lookup_interface(node_info, INDICATOR_APPLICATION_DBUS_IFACE);
313+
314+ if (interface_info == NULL) {
315+ g_error("Unable to find interface '" INDICATOR_APPLICATION_DBUS_IFACE "'");
316+ }
317+ }
318
319 return;
320 }
321@@ -207,6 +186,8 @@
322
323 priv->applications = NULL;
324 priv->approvers = NULL;
325+ priv->bus_cancel = NULL;
326+ priv->dbus_registration = 0;
327
328 priv->ordering_overrides = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
329
330@@ -214,21 +195,76 @@
331 gchar * userfile = g_build_filename(g_get_user_data_dir(), "indicators", "application", OVERRIDE_FILE_NAME, NULL);
332 load_override_file(priv->ordering_overrides, userfile);
333 g_free(userfile);
334-
335+
336+ priv->bus_cancel = g_cancellable_new();
337+ g_bus_get(G_BUS_TYPE_SESSION,
338+ priv->bus_cancel,
339+ bus_get_cb,
340+ self);
341+
342+ self->priv = priv;
343+
344+ return;
345+}
346+
347+static void
348+bus_get_cb (GObject * object, GAsyncResult * res, gpointer user_data)
349+{
350 GError * error = NULL;
351- priv->bus = dbus_g_bus_get(DBUS_BUS_STARTER, &error);
352- if (error != NULL) {
353- g_error("Unable to get session bus: %s", error->message);
354- g_error_free(error);
355- return;
356- }
357-
358- dbus_g_connection_register_g_object(priv->bus,
359- INDICATOR_APPLICATION_DBUS_OBJ,
360- G_OBJECT(self));
361-
362- self->priv = priv;
363-
364+ GDBusConnection * connection = g_bus_get_finish(res, &error);
365+
366+ if (error != NULL) {
367+ g_error("OMG! Unable to get a connection to DBus: %s", error->message);
368+ g_error_free(error);
369+ return;
370+ }
371+
372+ ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE_GET_PRIVATE (user_data);
373+
374+ g_warn_if_fail(priv->bus == NULL);
375+ priv->bus = connection;
376+
377+ if (priv->bus_cancel != NULL) {
378+ g_object_unref(priv->bus_cancel);
379+ priv->bus_cancel = NULL;
380+ }
381+
382+ /* Now register our object on our new connection */
383+ priv->dbus_registration = g_dbus_connection_register_object(priv->bus,
384+ INDICATOR_APPLICATION_DBUS_OBJ,
385+ interface_info,
386+ &interface_table,
387+ user_data,
388+ NULL,
389+ &error);
390+
391+ if (error != NULL) {
392+ g_error("Unable to register the object to DBus: %s", error->message);
393+ g_error_free(error);
394+ return;
395+ }
396+
397+ return;
398+}
399+
400+/* A method has been called from our dbus inteface. Figure out what it
401+ is and dispatch it. */
402+static void
403+bus_method_call (GDBusConnection * connection, const gchar * sender,
404+ const gchar * path, const gchar * interface,
405+ const gchar * method, GVariant * params,
406+ GDBusMethodInvocation * invocation, gpointer user_data)
407+{
408+ ApplicationServiceAppstore * service = APPLICATION_SERVICE_APPSTORE(user_data);
409+ GVariant * retval = NULL;
410+
411+ if (g_strcmp0(method, "GetApplications") == 0) {
412+ retval = get_applications(service);
413+ } else {
414+ g_warning("Calling method '%s' on the indicator service and it's unknown", method);
415+ }
416+
417+ g_dbus_method_invocation_return_value(invocation, retval);
418 return;
419 }
420
421@@ -249,6 +285,23 @@
422 priv->approvers = NULL;
423 }
424
425+ if (priv->dbus_registration != 0) {
426+ g_dbus_connection_unregister_object(priv->bus, priv->dbus_registration);
427+ /* Don't care if it fails, there's nothing we can do */
428+ priv->dbus_registration = 0;
429+ }
430+
431+ if (priv->bus != NULL) {
432+ g_object_unref(priv->bus);
433+ priv->bus = NULL;
434+ }
435+
436+ if (priv->bus_cancel != NULL) {
437+ g_cancellable_cancel(priv->bus_cancel);
438+ g_object_unref(priv->bus_cancel);
439+ priv->bus_cancel = NULL;
440+ }
441+
442 G_OBJECT_CLASS (application_service_appstore_parent_class)->dispose (object);
443 return;
444 }
445@@ -323,94 +376,156 @@
446 }
447
448 /* Return from getting the properties from the item. We're looking at those
449- and making sure we have everythign that we need. If we do, then we'll
450+ and making sure we have everything that we need. If we do, then we'll
451 move on up to sending this onto the indicator. */
452 static void
453-get_all_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * error, gpointer data)
454+got_all_properties (GObject * source_object, GAsyncResult * res,
455+ gpointer user_data)
456 {
457+ Application * app = (Application *)user_data;
458+ g_return_if_fail(app != NULL);
459+
460+ GError * error = NULL;
461+ ApplicationServiceAppstorePrivate * priv = app->appstore->priv;
462+ GVariant * menu = NULL, * id = NULL, * category = NULL,
463+ * status = NULL, * icon_name = NULL, * aicon_name = NULL,
464+ * icon_theme_path = NULL, * index = NULL, * label = NULL,
465+ * guide = NULL;
466+
467+ GVariant * properties = g_dbus_proxy_call_finish(app->props, res, &error);
468+
469+ if (app->props_cancel != NULL) {
470+ g_object_unref(app->props_cancel);
471+ app->props_cancel = NULL;
472+ }
473+
474 if (error != NULL) {
475- g_warning("Unable to get properties: %s", error->message);
476- /* TODO: We need to free all the application data here */
477+ g_error("Could not grab DBus properties for %s: %s", app->dbus_name, error->message);
478+ g_error_free(error);
479+ if (!app->validated)
480+ application_free(app);
481 return;
482 }
483
484- Application * app = (Application *)data;
485+ /* Grab all properties from variant */
486+ GVariantIter * iter = NULL;
487+ const gchar * name = NULL;
488+ GVariant * value = NULL;
489+ g_variant_get(properties, "(a{sv})", &iter);
490+ while (g_variant_iter_loop (iter, "{&sv}", &name, &value)) {
491+ if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_MENU) == 0) {
492+ menu = g_variant_ref(value);
493+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_ID) == 0) {
494+ id = g_variant_ref(value);
495+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_CATEGORY) == 0) {
496+ category = g_variant_ref(value);
497+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_STATUS) == 0) {
498+ status = g_variant_ref(value);
499+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_ICON_NAME) == 0) {
500+ icon_name = g_variant_ref(value);
501+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_AICON_NAME) == 0) {
502+ aicon_name = g_variant_ref(value);
503+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_ICON_THEME_PATH) == 0) {
504+ icon_theme_path = g_variant_ref(value);
505+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_ORDERING_INDEX) == 0) {
506+ index = g_variant_ref(value);
507+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_LABEL) == 0) {
508+ label = g_variant_ref(value);
509+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_LABEL_GUIDE) == 0) {
510+ guide = g_variant_ref(value);
511+ } /* else ignore */
512+ }
513+ g_variant_iter_free (iter);
514
515- if (g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_MENU) == NULL ||
516- g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ID) == NULL ||
517- g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_CATEGORY) == NULL ||
518- g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_STATUS) == NULL ||
519- g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_NAME) == NULL) {
520+ if (menu == NULL || id == NULL || category == NULL || status == NULL ||
521+ icon_name == NULL) {
522 g_warning("Notification Item on object %s of %s doesn't have enough properties.", app->dbus_object, app->dbus_name);
523 g_free(app); // Need to do more than this, but it gives the idea of the flow we're going for.
524- return;
525- }
526-
527- app->validated = TRUE;
528-
529- app->id = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ID));
530- app->category = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_CATEGORY));
531- app->status = string_to_status(g_value_get_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_STATUS)));
532-
533- ApplicationServiceAppstorePrivate * priv = app->appstore->priv;
534-
535- app->icon = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_NAME));
536-
537- GValue * menuval = (GValue *)g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_MENU);
538- if (G_VALUE_TYPE(menuval) == G_TYPE_STRING) {
539- /* This is here to support an older version where we
540- were using strings instea of object paths. */
541- app->menu = g_value_dup_string(menuval);
542- } else {
543- app->menu = g_strdup((gchar *)g_value_get_boxed(menuval));
544- }
545-
546- if (g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_AICON_NAME) != NULL) {
547- app->aicon = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_AICON_NAME));
548- }
549-
550- gpointer icon_theme_path_data = g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_THEME_PATH);
551- if (icon_theme_path_data != NULL) {
552- app->icon_theme_path = g_value_dup_string((GValue *)icon_theme_path_data);
553- } else {
554- app->icon_theme_path = g_strdup("");
555- }
556-
557- gpointer ordering_index_over = g_hash_table_lookup(priv->ordering_overrides, app->id);
558- if (ordering_index_over == NULL) {
559- gpointer ordering_index_data = g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ORDERING_INDEX);
560- if (ordering_index_data == NULL || g_value_get_uint(ordering_index_data) == 0) {
561- app->ordering_index = generate_id(string_to_cat(app->category), app->id);
562- } else {
563- app->ordering_index = g_value_get_uint(ordering_index_data);
564- }
565- } else {
566- app->ordering_index = GPOINTER_TO_UINT(ordering_index_over);
567- }
568- g_debug("'%s' ordering index is '%X'", app->id, app->ordering_index);
569-
570- gpointer label_data = g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_LABEL);
571- if (label_data != NULL) {
572- app->label = g_value_dup_string((GValue *)label_data);
573- } else {
574- app->label = g_strdup("");
575- }
576-
577- gpointer guide_data = g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_LABEL_GUIDE);
578- if (guide_data != NULL) {
579- app->guide = g_value_dup_string((GValue *)guide_data);
580- } else {
581- app->guide = g_strdup("");
582- }
583-
584- priv->applications = g_list_insert_sorted_with_data (priv->applications, app, app_sort_func, NULL);
585- g_list_foreach(priv->approvers, check_with_old_approver, app);
586-
587- apply_status(app);
588+ }
589+ else {
590+ app->validated = TRUE;
591+
592+ app->id = g_variant_dup_string(id, NULL);
593+ app->category = g_variant_dup_string(category, NULL);
594+ app->status = string_to_status(g_variant_get_string(status, NULL));
595+ app->icon = g_variant_dup_string(icon_name, NULL);
596+ app->menu = g_variant_dup_string(menu, NULL);
597+
598+ /* Now the optional properties */
599+
600+ if (aicon_name != NULL) {
601+ app->aicon = g_variant_dup_string(aicon_name, NULL);
602+ }
603+
604+ if (icon_theme_path != NULL) {
605+ app->icon_theme_path = g_variant_dup_string(icon_theme_path, NULL);
606+ } else {
607+ app->icon_theme_path = g_strdup("");
608+ }
609+
610+ gpointer ordering_index_over = g_hash_table_lookup(priv->ordering_overrides, app->id);
611+ if (ordering_index_over == NULL) {
612+ if (index == NULL || g_variant_get_uint32(index) == 0) {
613+ app->ordering_index = generate_id(string_to_cat(app->category), app->id);
614+ } else {
615+ app->ordering_index = g_variant_get_uint32(index);
616+ }
617+ } else {
618+ app->ordering_index = GPOINTER_TO_UINT(ordering_index_over);
619+ }
620+ g_debug("'%s' ordering index is '%X'", app->id, app->ordering_index);
621+
622+ if (label != NULL) {
623+ app->label = g_variant_dup_string(label, NULL);
624+ } else {
625+ app->label = g_strdup("");
626+ }
627+
628+ if (guide != NULL) {
629+ app->guide = g_variant_dup_string(guide, NULL);
630+ } else {
631+ app->guide = g_strdup("");
632+ }
633+
634+ g_list_foreach(priv->approvers, check_with_old_approver, app);
635+
636+ apply_status(app);
637+
638+ if (app->queued_props) {
639+ get_all_properties(app);
640+ app->queued_props = FALSE;
641+ }
642+ }
643+
644+ if (menu) g_variant_unref (menu);
645+ if (id) g_variant_unref (id);
646+ if (category) g_variant_unref (category);
647+ if (status) g_variant_unref (status);
648+ if (icon_name) g_variant_unref (icon_name);
649+ if (aicon_name) g_variant_unref (aicon_name);
650+ if (icon_theme_path) g_variant_unref (icon_theme_path);
651+ if (index) g_variant_unref (index);
652+ if (label) g_variant_unref (label);
653+ if (guide) g_variant_unref (guide);
654
655 return;
656 }
657
658+static void
659+get_all_properties (Application * app)
660+{
661+ if (app->props != NULL && app->props_cancel == NULL) {
662+ g_dbus_proxy_call(app->props, "GetAll",
663+ g_variant_new("(s)", NOTIFICATION_ITEM_DBUS_IFACE),
664+ G_DBUS_CALL_FLAGS_NONE, -1, app->props_cancel,
665+ got_all_properties, app);
666+ }
667+ else {
668+ g_debug("Queuing a properties check");
669+ app->queued_props = TRUE;
670+ }
671+}
672+
673 /* Check the application against an approver */
674 static void
675 check_with_old_approver (gpointer papprove, gpointer papp)
676@@ -508,11 +623,32 @@
677 if (app->currently_free) return;
678 app->currently_free = TRUE;
679
680+ /* Remove from the application list */
681+ app->appstore->priv->applications = g_list_remove(app->appstore->priv->applications, app);
682+
683+ if (app->name_watcher != 0) {
684+ g_dbus_connection_signal_unsubscribe(g_dbus_proxy_get_connection(app->dbus_proxy), app->name_watcher);
685+ app->name_watcher = 0;
686+ }
687+
688+ if (app->props) {
689+ g_object_unref(app->props);
690+ }
691+
692+ if (app->props_cancel != NULL) {
693+ g_cancellable_cancel(app->props_cancel);
694+ g_object_unref(app->props_cancel);
695+ app->props_cancel = NULL;
696+ }
697+
698 if (app->dbus_proxy) {
699 g_object_unref(app->dbus_proxy);
700 }
701- if (app->prop_proxy) {
702- g_object_unref(app->prop_proxy);
703+
704+ if (app->dbus_proxy_cancel != NULL) {
705+ g_cancellable_cancel(app->dbus_proxy_cancel);
706+ g_object_unref(app->dbus_proxy_cancel);
707+ app->dbus_proxy_cancel = NULL;
708 }
709
710 if (app->id != NULL) {
711@@ -553,21 +689,18 @@
712 return;
713 }
714
715-/* Gets called when the proxy is destroyed, which is usually when it
716+/* Gets called when the proxy changes owners, which is usually when it
717 drops off of the bus. */
718 static void
719-application_removed_cb (DBusGProxy * proxy, gpointer userdata)
720+application_died (Application * app)
721 {
722- Application * app = (Application *)userdata;
723+ /* Application died */
724 g_debug("Application proxy destroyed '%s'", app->id);
725
726 /* Remove from the panel */
727 app->status = APP_INDICATOR_STATUS_PASSIVE;
728 apply_status(app);
729
730- /* Remove from the application list */
731- app->appstore->priv->applications = g_list_remove(app->appstore->priv->applications, app);
732-
733 /* Destroy the data */
734 application_free(app);
735 return;
736@@ -583,6 +716,30 @@
737 return (appb->ordering_index/2) - (appa->ordering_index/2);
738 }
739
740+static void
741+emit_signal (ApplicationServiceAppstore * appstore, const gchar * name,
742+ GVariant * variant)
743+{
744+ ApplicationServiceAppstorePrivate * priv = appstore->priv;
745+ GError * error = NULL;
746+
747+ g_dbus_connection_emit_signal (priv->bus,
748+ NULL,
749+ INDICATOR_APPLICATION_DBUS_OBJ,
750+ INDICATOR_APPLICATION_DBUS_IFACE,
751+ name,
752+ variant,
753+ &error);
754+
755+ if (error != NULL) {
756+ g_error("Unable to send %s signal: %s", name, error->message);
757+ g_error_free(error);
758+ return;
759+ }
760+
761+ return;
762+}
763+
764 /* Change the status of the application. If we're going passive
765 it removes it from the panel. If we're coming online, then
766 it add it to the panel. Otherwise it changes the icon. */
767@@ -613,16 +770,17 @@
768 return;
769 }
770
771- g_debug("Changing app '%s' state from %s to %s", app->id, STATE2STRING(app->visible_state), STATE2STRING(goal_state));
772+ if (app->visible_state != goal_state) {
773+ g_debug("Changing app '%s' state from %s to %s", app->id, STATE2STRING(app->visible_state), STATE2STRING(goal_state));
774+ }
775
776 /* This means we're going off line */
777 if (goal_state == VISIBLE_STATE_HIDDEN) {
778 gint position = get_position(app);
779 if (position == -1) return;
780
781- g_signal_emit(G_OBJECT(appstore),
782- signals[APPLICATION_REMOVED], 0,
783- position, TRUE);
784+ emit_signal (appstore, "ApplicationRemoved",
785+ g_variant_new ("(i)", position));
786 } else {
787 /* Figure out which icon we should be using */
788 gchar * newicon = app->icon;
789@@ -633,24 +791,19 @@
790 /* Determine whether we're already shown or not */
791 if (app->visible_state == VISIBLE_STATE_HIDDEN) {
792 /* Put on panel */
793- g_signal_emit(G_OBJECT(app->appstore),
794- signals[APPLICATION_ADDED], 0,
795- newicon,
796- get_position(app), /* Position */
797- app->dbus_name,
798- app->menu,
799- app->icon_theme_path,
800- app->label,
801- app->guide,
802- TRUE);
803+ emit_signal (appstore, "ApplicationAdded",
804+ g_variant_new ("(sisosss)", newicon,
805+ get_position(app),
806+ app->dbus_name, app->menu,
807+ app->icon_theme_path,
808+ app->label, app->guide));
809 } else {
810 /* Icon update */
811 gint position = get_position(app);
812 if (position == -1) return;
813
814- g_signal_emit(G_OBJECT(appstore),
815- signals[APPLICATION_ICON_CHANGED], 0,
816- position, newicon, TRUE);
817+ emit_signal (appstore, "ApplicationIconChanged",
818+ g_variant_new ("(is)", position, newicon));
819 }
820 }
821
822@@ -659,123 +812,11 @@
823 return;
824 }
825
826-/* Gets the data back on an updated icon signal. Hopefully
827- a new fun icon. */
828-static void
829-new_icon_cb (DBusGProxy * proxy, GValue value, GError * error, gpointer userdata)
830-{
831- /* Check for errors */
832- if (error != NULL) {
833- g_warning("Unable to get updated icon name: %s", error->message);
834- return;
835- }
836-
837- /* Grab the icon and make sure we have one */
838- const gchar * newicon = g_value_get_string(&value);
839- if (newicon == NULL) {
840- g_warning("Bad new icon :(");
841- return;
842- }
843-
844- Application * app = (Application *) userdata;
845-
846- if (g_strcmp0(newicon, app->icon)) {
847- /* If the new icon is actually a new icon */
848- if (app->icon != NULL) g_free(app->icon);
849- app->icon = g_strdup(newicon);
850-
851- if (app->visible_state == VISIBLE_STATE_SHOWN && app->status == APP_INDICATOR_STATUS_ACTIVE) {
852- gint position = get_position(app);
853- if (position == -1) return;
854-
855- g_signal_emit(G_OBJECT(app->appstore),
856- signals[APPLICATION_ICON_CHANGED], 0,
857- position, newicon, TRUE);
858- }
859- }
860-
861- return;
862-}
863-
864-/* Gets the data back on an updated aicon signal. Hopefully
865- a new fun icon. */
866-static void
867-new_aicon_cb (DBusGProxy * proxy, GValue value, GError * error, gpointer userdata)
868-{
869- /* Check for errors */
870- if (error != NULL) {
871- g_warning("Unable to get updated icon name: %s", error->message);
872- return;
873- }
874-
875- /* Grab the icon and make sure we have one */
876- const gchar * newicon = g_value_get_string(&value);
877- if (newicon == NULL) {
878- g_warning("Bad new icon :(");
879- return;
880- }
881-
882- Application * app = (Application *) userdata;
883-
884- if (g_strcmp0(newicon, app->aicon)) {
885- /* If the new icon is actually a new icon */
886- if (app->aicon != NULL) g_free(app->aicon);
887- app->aicon = g_strdup(newicon);
888-
889- if (app->visible_state == VISIBLE_STATE_SHOWN && app->status == APP_INDICATOR_STATUS_ATTENTION) {
890- gint position = get_position(app);
891- if (position == -1) return;
892-
893- g_signal_emit(G_OBJECT(app->appstore),
894- signals[APPLICATION_ICON_CHANGED], 0,
895- position, newicon, TRUE);
896- }
897- }
898-
899- return;
900-}
901-
902-/* Called when the Notification Item signals that it
903- has a new icon. */
904-static void
905-new_icon (DBusGProxy * proxy, gpointer data)
906-{
907- Application * app = (Application *)data;
908- if (!app->validated) return;
909-
910- org_freedesktop_DBus_Properties_get_async(app->prop_proxy,
911- NOTIFICATION_ITEM_DBUS_IFACE,
912- NOTIFICATION_ITEM_PROP_ICON_NAME,
913- new_icon_cb,
914- app);
915- return;
916-}
917-
918-/* Called when the Notification Item signals that it
919- has a new attention icon. */
920-static void
921-new_aicon (DBusGProxy * proxy, gpointer data)
922-{
923- Application * app = (Application *)data;
924- if (!app->validated) return;
925-
926- org_freedesktop_DBus_Properties_get_async(app->prop_proxy,
927- NOTIFICATION_ITEM_DBUS_IFACE,
928- NOTIFICATION_ITEM_PROP_AICON_NAME,
929- new_aicon_cb,
930- app);
931-
932- return;
933-}
934-
935 /* Called when the Notification Item signals that it
936 has a new status. */
937 static void
938-new_status (DBusGProxy * proxy, const gchar * status, gpointer data)
939+new_status (Application * app, const gchar * status)
940 {
941- Application * app = (Application *)data;
942- if (!app->validated) return;
943-
944 app->status = string_to_status(status);
945 apply_status(app);
946
947@@ -785,11 +826,8 @@
948 /* Called when the Notification Item signals that it
949 has a new icon theme path. */
950 static void
951-new_icon_theme_path (DBusGProxy * proxy, const gchar * icon_theme_path, gpointer data)
952+new_icon_theme_path (Application * app, const gchar * icon_theme_path)
953 {
954- Application * app = (Application *)data;
955- if (!app->validated) return;
956-
957 if (g_strcmp0(icon_theme_path, app->icon_theme_path)) {
958 /* If the new icon theme path is actually a new icon theme path */
959 if (app->icon_theme_path != NULL) g_free(app->icon_theme_path);
960@@ -799,9 +837,10 @@
961 gint position = get_position(app);
962 if (position == -1) return;
963
964- g_signal_emit(G_OBJECT(app->appstore),
965- signals[APPLICATION_ICON_THEME_PATH_CHANGED], 0,
966- position, app->icon_theme_path, TRUE);
967+ emit_signal (app->appstore,
968+ "ApplicationIconThemePathChanged",
969+ g_variant_new ("(is)", position,
970+ app->icon_theme_path));
971 }
972 }
973
974@@ -811,11 +850,8 @@
975 /* Called when the Notification Item signals that it
976 has a new label. */
977 static void
978-new_label (DBusGProxy * proxy, const gchar * label, const gchar * guide, gpointer data)
979+new_label (Application * app, const gchar * label, const gchar * guide)
980 {
981- Application * app = (Application *)data;
982- if (!app->validated) return;
983-
984 gboolean changed = FALSE;
985
986 if (g_strcmp0(app->label, label) != 0) {
987@@ -840,11 +876,10 @@
988 gint position = get_position(app);
989 if (position == -1) return;
990
991- g_signal_emit(app->appstore, signals[APPLICATION_LABEL_CHANGED], 0,
992- position,
993- app->label != NULL ? app->label : "",
994- app->guide != NULL ? app->guide : "",
995- TRUE);
996+ emit_signal (app->appstore, "ApplicationLabelChanged",
997+ g_variant_new ("(iss)", position,
998+ app->label != NULL ? app->label : "",
999+ app->guide != NULL ? app->guide : ""));
1000 }
1001
1002 return;
1003@@ -862,15 +897,11 @@
1004 g_return_if_fail(IS_APPLICATION_SERVICE_APPSTORE(appstore));
1005 g_return_if_fail(dbus_name != NULL && dbus_name[0] != '\0');
1006 g_return_if_fail(dbus_object != NULL && dbus_object[0] != '\0');
1007- ApplicationServiceAppstorePrivate * priv = appstore->priv;
1008 Application * app = find_application(appstore, dbus_name, dbus_object);
1009
1010 if (app != NULL) {
1011- g_warning("Application already exists! Rerequesting properties.");
1012- org_freedesktop_DBus_Properties_get_all_async(app->prop_proxy,
1013- NOTIFICATION_ITEM_DBUS_IFACE,
1014- get_all_properties_cb,
1015- app);
1016+ g_warning("Application already exists, re-requesting properties.");
1017+ get_all_properties(app);
1018 return;
1019 }
1020
1021@@ -893,98 +924,169 @@
1022 app->ordering_index = 0;
1023 app->approved_by = NULL;
1024 app->visible_state = VISIBLE_STATE_HIDDEN;
1025+ app->name_watcher = 0;
1026+ app->props_cancel = NULL;
1027+ app->props = NULL;
1028+ app->queued_props = FALSE;
1029
1030 /* Get the DBus proxy for the NotificationItem interface */
1031- GError * error = NULL;
1032- app->dbus_proxy = dbus_g_proxy_new_for_name_owner(priv->bus,
1033- app->dbus_name,
1034- app->dbus_object,
1035- NOTIFICATION_ITEM_DBUS_IFACE,
1036- &error);
1037-
1038- if (error != NULL) {
1039- g_warning("Unable to get notification item proxy for object '%s' on host '%s': %s", dbus_object, dbus_name, error->message);
1040- g_error_free(error);
1041- g_free(app);
1042- return;
1043- }
1044-
1045- /* We've got it, let's watch it for destruction */
1046- g_signal_connect(G_OBJECT(app->dbus_proxy), "destroy", G_CALLBACK(application_removed_cb), app);
1047-
1048- /* Grab the property proxy interface */
1049- app->prop_proxy = dbus_g_proxy_new_for_name_owner(priv->bus,
1050- app->dbus_name,
1051- app->dbus_object,
1052- DBUS_INTERFACE_PROPERTIES,
1053- &error);
1054-
1055- if (error != NULL) {
1056- g_warning("Unable to get property proxy for object '%s' on host '%s': %s", dbus_object, dbus_name, error->message);
1057- g_error_free(error);
1058- g_object_unref(app->dbus_proxy);
1059- g_free(app);
1060- return;
1061- }
1062-
1063- /* Connect to signals */
1064- dbus_g_proxy_add_signal(app->dbus_proxy,
1065- NOTIFICATION_ITEM_SIG_NEW_ICON,
1066- G_TYPE_INVALID);
1067- dbus_g_proxy_add_signal(app->dbus_proxy,
1068- NOTIFICATION_ITEM_SIG_NEW_AICON,
1069- G_TYPE_INVALID);
1070- dbus_g_proxy_add_signal(app->dbus_proxy,
1071- NOTIFICATION_ITEM_SIG_NEW_STATUS,
1072- G_TYPE_STRING,
1073- G_TYPE_INVALID);
1074- dbus_g_proxy_add_signal(app->dbus_proxy,
1075- NOTIFICATION_ITEM_SIG_NEW_ICON_THEME_PATH,
1076- G_TYPE_STRING,
1077- G_TYPE_INVALID);
1078- dbus_g_proxy_add_signal(app->dbus_proxy,
1079- NOTIFICATION_ITEM_SIG_NEW_LABEL,
1080- G_TYPE_STRING,
1081- G_TYPE_STRING,
1082- G_TYPE_INVALID);
1083-
1084- dbus_g_proxy_connect_signal(app->dbus_proxy,
1085- NOTIFICATION_ITEM_SIG_NEW_ICON,
1086- G_CALLBACK(new_icon),
1087- app,
1088- NULL);
1089- dbus_g_proxy_connect_signal(app->dbus_proxy,
1090- NOTIFICATION_ITEM_SIG_NEW_AICON,
1091- G_CALLBACK(new_aicon),
1092- app,
1093- NULL);
1094- dbus_g_proxy_connect_signal(app->dbus_proxy,
1095- NOTIFICATION_ITEM_SIG_NEW_STATUS,
1096- G_CALLBACK(new_status),
1097- app,
1098- NULL);
1099- dbus_g_proxy_connect_signal(app->dbus_proxy,
1100- NOTIFICATION_ITEM_SIG_NEW_ICON_THEME_PATH,
1101- G_CALLBACK(new_icon_theme_path),
1102- app,
1103- NULL);
1104- dbus_g_proxy_connect_signal(app->dbus_proxy,
1105- NOTIFICATION_ITEM_SIG_NEW_LABEL,
1106- G_CALLBACK(new_label),
1107- app,
1108- NULL);
1109-
1110- /* Get all the propertiees */
1111- org_freedesktop_DBus_Properties_get_all_async(app->prop_proxy,
1112- NOTIFICATION_ITEM_DBUS_IFACE,
1113- get_all_properties_cb,
1114- app);
1115+ app->dbus_proxy_cancel = g_cancellable_new();
1116+ g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION,
1117+ G_DBUS_PROXY_FLAGS_NONE,
1118+ NULL,
1119+ app->dbus_name,
1120+ app->dbus_object,
1121+ NOTIFICATION_ITEM_DBUS_IFACE,
1122+ app->dbus_proxy_cancel,
1123+ dbus_proxy_cb,
1124+ app);
1125+
1126+ appstore->priv->applications = g_list_insert_sorted_with_data (appstore->priv->applications, app, app_sort_func, NULL);
1127
1128 /* We're returning, nothing is yet added until the properties
1129 come back and give us more info. */
1130 return;
1131 }
1132
1133+static void
1134+name_changed (GDBusConnection * connection, const gchar * sender_name,
1135+ const gchar * object_path, const gchar * interface_name,
1136+ const gchar * signal_name, GVariant * parameters,
1137+ gpointer user_data)
1138+{
1139+ Application * app = (Application *)user_data;
1140+
1141+ const gchar * new_name;
1142+ g_variant_get(parameters, "(&s&s&s)", NULL, NULL, &new_name);
1143+
1144+ if (new_name == NULL || new_name[0] == 0)
1145+ application_died(app);
1146+}
1147+
1148+/* Callback from trying to create the proxy for the app. */
1149+static void
1150+dbus_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data)
1151+{
1152+ GError * error = NULL;
1153+
1154+ Application * app = (Application *)user_data;
1155+ g_return_if_fail(app != NULL);
1156+
1157+ GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
1158+
1159+ if (app->dbus_proxy_cancel != NULL) {
1160+ g_object_unref(app->dbus_proxy_cancel);
1161+ app->dbus_proxy_cancel = NULL;
1162+ }
1163+
1164+ if (error != NULL) {
1165+ g_error("Could not grab DBus proxy for %s: %s", app->dbus_name, error->message);
1166+ g_error_free(error);
1167+ application_free(app);
1168+ return;
1169+ }
1170+
1171+ /* Okay, we're good to grab the proxy at this point, we're
1172+ sure that it's ours. */
1173+ app->dbus_proxy = proxy;
1174+
1175+ /* We've got it, let's watch it for destruction */
1176+ app->name_watcher = g_dbus_connection_signal_subscribe(
1177+ g_dbus_proxy_get_connection(proxy),
1178+ "org.freedesktop.DBus",
1179+ "org.freedesktop.DBus",
1180+ "NameOwnerChanged",
1181+ "/org/freedesktop/DBus",
1182+ g_dbus_proxy_get_name(proxy),
1183+ G_DBUS_SIGNAL_FLAGS_NONE,
1184+ name_changed,
1185+ app,
1186+ NULL);
1187+
1188+ g_signal_connect(proxy, "g-signal", G_CALLBACK(app_receive_signal), app);
1189+
1190+ app->props_cancel = g_cancellable_new();
1191+ g_dbus_proxy_new(g_dbus_proxy_get_connection(proxy),
1192+ G_DBUS_PROXY_FLAGS_NONE,
1193+ NULL,
1194+ app->dbus_name,
1195+ app->dbus_object,
1196+ "org.freedesktop.DBus.Properties",
1197+ app->props_cancel,
1198+ props_cb,
1199+ app);
1200+
1201+ return;
1202+}
1203+
1204+/* Callback from trying to create the proxy for the app. */
1205+static void
1206+props_cb (GObject * object, GAsyncResult * res, gpointer user_data)
1207+{
1208+ GError * error = NULL;
1209+
1210+ Application * app = (Application *)user_data;
1211+ g_return_if_fail(app != NULL);
1212+
1213+ GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
1214+
1215+ if (app->props_cancel != NULL) {
1216+ g_object_unref(app->props_cancel);
1217+ app->props_cancel = NULL;
1218+ }
1219+
1220+ if (error != NULL) {
1221+ g_error("Could not grab Properties DBus proxy for %s: %s", app->dbus_name, error->message);
1222+ g_error_free(error);
1223+ application_free(app);
1224+ return;
1225+ }
1226+
1227+ /* Okay, we're good to grab the proxy at this point, we're
1228+ sure that it's ours. */
1229+ app->props = proxy;
1230+
1231+ get_all_properties(app);
1232+
1233+ return;
1234+}
1235+
1236+/* Receives all signals from the service, routed to the appropriate functions */
1237+static void
1238+app_receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name,
1239+ GVariant * parameters, gpointer user_data)
1240+{
1241+ Application * app = (Application *)user_data;
1242+
1243+ if (!app->validated) return;
1244+
1245+ if (g_strcmp0(signal_name, NOTIFICATION_ITEM_SIG_NEW_ICON) == 0) {
1246+ /* icon name isn't provided by signal, so look it up */
1247+ get_all_properties(app);
1248+ }
1249+ else if (g_strcmp0(signal_name, NOTIFICATION_ITEM_SIG_NEW_AICON) == 0) {
1250+ /* aicon name isn't provided by signal, so look it up */
1251+ get_all_properties(app);
1252+ }
1253+ else if (g_strcmp0(signal_name, NOTIFICATION_ITEM_SIG_NEW_STATUS) == 0) {
1254+ const gchar * status;
1255+ g_variant_get(parameters, "(&s)", &status);
1256+ new_status(app, status);
1257+ }
1258+ else if (g_strcmp0(signal_name, NOTIFICATION_ITEM_SIG_NEW_ICON_THEME_PATH) == 0) {
1259+ const gchar * icon_theme_path;
1260+ g_variant_get(parameters, "(&s)", &icon_theme_path);
1261+ new_icon_theme_path(app, icon_theme_path);
1262+ }
1263+ else if (g_strcmp0(signal_name, NOTIFICATION_ITEM_SIG_NEW_LABEL) == 0) {
1264+ const gchar * label, * guide;
1265+ g_variant_get(parameters, "(&s&s)", &label, &guide);
1266+ new_label(app, label, guide);
1267+ }
1268+
1269+ return;
1270+}
1271+
1272 /* Looks for an application in the list of applications */
1273 static Application *
1274 find_application (ApplicationServiceAppstore * appstore, const gchar * address, const gchar * object)
1275@@ -1014,7 +1116,7 @@
1276
1277 Application * app = find_application(appstore, dbus_name, dbus_object);
1278 if (app != NULL) {
1279- application_removed_cb(NULL, app);
1280+ application_died(app);
1281 } else {
1282 g_warning("Unable to find application %s:%s", dbus_name, dbus_object);
1283 }
1284@@ -1050,12 +1152,12 @@
1285 }
1286
1287 /* DBus Interface */
1288-static gboolean
1289-_application_service_server_get_applications (ApplicationServiceAppstore * appstore, GPtrArray ** apps, GError ** error)
1290+static GVariant *
1291+get_applications (ApplicationServiceAppstore * appstore)
1292 {
1293 ApplicationServiceAppstorePrivate * priv = appstore->priv;
1294
1295- *apps = g_ptr_array_new();
1296+ GVariantBuilder * builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
1297 GList * listpntr;
1298 gint position = 0;
1299
1300@@ -1065,56 +1167,13 @@
1301 continue;
1302 }
1303
1304- GValueArray * values = g_value_array_new(5);
1305-
1306- GValue value = {0};
1307-
1308- /* Icon name */
1309- g_value_init(&value, G_TYPE_STRING);
1310- g_value_set_string(&value, app->icon);
1311- g_value_array_append(values, &value);
1312- g_value_unset(&value);
1313-
1314- /* Position */
1315- g_value_init(&value, G_TYPE_INT);
1316- g_value_set_int(&value, position++);
1317- g_value_array_append(values, &value);
1318- g_value_unset(&value);
1319-
1320- /* DBus Address */
1321- g_value_init(&value, G_TYPE_STRING);
1322- g_value_set_string(&value, app->dbus_name);
1323- g_value_array_append(values, &value);
1324- g_value_unset(&value);
1325-
1326- /* DBus Object */
1327- g_value_init(&value, DBUS_TYPE_G_OBJECT_PATH);
1328- g_value_set_static_boxed(&value, app->menu);
1329- g_value_array_append(values, &value);
1330- g_value_unset(&value);
1331-
1332- /* Icon path */
1333- g_value_init(&value, G_TYPE_STRING);
1334- g_value_set_string(&value, app->icon_theme_path);
1335- g_value_array_append(values, &value);
1336- g_value_unset(&value);
1337-
1338- /* Label */
1339- g_value_init(&value, G_TYPE_STRING);
1340- g_value_set_string(&value, app->label);
1341- g_value_array_append(values, &value);
1342- g_value_unset(&value);
1343-
1344- /* Guide */
1345- g_value_init(&value, G_TYPE_STRING);
1346- g_value_set_string(&value, app->guide);
1347- g_value_array_append(values, &value);
1348- g_value_unset(&value);
1349-
1350- g_ptr_array_add(*apps, values);
1351+ g_variant_builder_add (builder, "(sisosss)", app->icon,
1352+ position++, app->dbus_name, app->menu,
1353+ app->icon_theme_path, app->label,
1354+ app->guide);
1355 }
1356
1357- return TRUE;
1358+ return g_variant_new("(a(sisosss))", builder);
1359 }
1360
1361 /* Removes and approver from our list of approvers and
1362@@ -1139,30 +1198,47 @@
1363 ApplicationServiceAppstore * appstore = APPLICATION_SERVICE_APPSTORE(user_data);
1364 g_list_foreach(appstore->priv->applications, remove_approver, approver->proxy);
1365
1366+ if (approver->name_watcher != 0) {
1367+ g_dbus_connection_signal_unsubscribe(g_dbus_proxy_get_connection(approver->proxy), approver->name_watcher);
1368+ approver->name_watcher = 0;
1369+ }
1370+
1371 if (approver->proxy != NULL) {
1372- if (!approver->destroy_by_proxy) {
1373- g_object_unref(approver->proxy);
1374- }
1375+ g_object_unref(approver->proxy);
1376 approver->proxy = NULL;
1377 }
1378
1379+ if (approver->proxy_cancel != NULL) {
1380+ g_cancellable_cancel(approver->proxy_cancel);
1381+ g_object_unref(approver->proxy_cancel);
1382+ approver->proxy_cancel = NULL;
1383+ }
1384+
1385 g_free(approver);
1386 return;
1387 }
1388
1389 /* What did the approver tell us? */
1390 static void
1391-approver_request_cb (DBusGProxy *proxy, gboolean OUT_approved, GError *error, gpointer userdata)
1392+approver_request_cb (GObject *object, GAsyncResult *res, gpointer user_data)
1393 {
1394+ GDBusProxy * proxy = G_DBUS_PROXY(object);
1395+ Application * app = (Application *)user_data;
1396+ GError * error = NULL;
1397+ gboolean approved = TRUE; /* default to approved */
1398+ GVariant * result;
1399+
1400+ result = g_dbus_proxy_call_finish(proxy, res, &error);
1401+
1402 if (error == NULL) {
1403- g_debug("Approver responded: %s", OUT_approved ? "approve" : "rejected");
1404- } else {
1405+ g_variant_get(result, "(b)", &approved);
1406+ g_debug("Approver responded: %s", approved ? "approve" : "rejected");
1407+ }
1408+ else {
1409 g_debug("Approver responded error: %s", error->message);
1410 }
1411
1412- Application * app = (Application *)userdata;
1413-
1414- if (OUT_approved || error != NULL) {
1415+ if (approved) {
1416 app->approved_by = g_list_prepend(app->approved_by, proxy);
1417 } else {
1418 app->approved_by = g_list_remove(app->approved_by, proxy);
1419@@ -1179,50 +1255,11 @@
1420 Application * app = (Application *)papp;
1421 Approver * approver = (Approver *)papprove;
1422
1423- org_ayatana_StatusNotifierApprover_approve_item_async(approver->proxy,
1424- app->id,
1425- app->category,
1426- 0,
1427- app->dbus_name,
1428- app->dbus_object,
1429- approver_request_cb,
1430- app);
1431-
1432- return;
1433-}
1434-
1435-/* Look through all the approvers and find the one with a given
1436- proxy. */
1437-static gint
1438-approver_find_by_proxy (gconstpointer papprover, gconstpointer pproxy)
1439-{
1440- Approver * approver = (Approver *)papprover;
1441-
1442- if (approver->proxy == pproxy) {
1443- return 0;
1444- }
1445-
1446- return -1;
1447-}
1448-
1449-/* Tracks when a proxy gets destroyed so that we know that the
1450- approver has dropped off the bus. */
1451-static void
1452-approver_destroyed (gpointer pproxy, gpointer pappstore)
1453-{
1454- ApplicationServiceAppstore * appstore = APPLICATION_SERVICE_APPSTORE(pappstore);
1455-
1456- GList * lapprover = g_list_find_custom(appstore->priv->approvers, pproxy, approver_find_by_proxy);
1457- if (lapprover == NULL) {
1458- g_warning("Approver proxy died, but we don't seem to have that approver.");
1459- return;
1460- }
1461-
1462- Approver * approver = (Approver *)lapprover->data;
1463- approver->destroy_by_proxy = TRUE;
1464-
1465- appstore->priv->approvers = g_list_remove(appstore->priv->approvers, approver);
1466- approver_free(approver, appstore);
1467+ g_dbus_proxy_call(approver->proxy, "ApproveItem",
1468+ g_variant_new("(ssuso)", app->id, app->category,
1469+ 0, app->dbus_name, app->dbus_object),
1470+ G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1471+ approver_request_cb, app);
1472
1473 return;
1474 }
1475@@ -1230,17 +1267,12 @@
1476 /* A signal when an approver changes the why that it thinks about
1477 a particular indicator. */
1478 void
1479-approver_revise_judgement (DBusGProxy * proxy, gboolean new_status, gchar * address, DBusGProxy * get_path, gpointer user_data)
1480+approver_revise_judgement (Approver * approver, gboolean new_status, const gchar * address, const gchar * path)
1481 {
1482- g_return_if_fail(IS_APPLICATION_SERVICE_APPSTORE(user_data));
1483 g_return_if_fail(address != NULL && address[0] != '\0');
1484- g_return_if_fail(get_path != NULL);
1485- const gchar * path = dbus_g_proxy_get_path(get_path);
1486 g_return_if_fail(path != NULL && path[0] != '\0');
1487
1488- ApplicationServiceAppstore * appstore = APPLICATION_SERVICE_APPSTORE(user_data);
1489-
1490- Application * app = find_application(appstore, address, path);
1491+ Application * app = find_application(approver->appstore, address, path);
1492
1493 if (app == NULL) {
1494 g_warning("Unable to update approver status of application (%s:%s) as it was not found", address, path);
1495@@ -1248,9 +1280,9 @@
1496 }
1497
1498 if (new_status) {
1499- app->approved_by = g_list_prepend(app->approved_by, proxy);
1500+ app->approved_by = g_list_prepend(app->approved_by, approver->proxy);
1501 } else {
1502- app->approved_by = g_list_remove(app->approved_by, proxy);
1503+ app->approved_by = g_list_remove(app->approved_by, approver->proxy);
1504 }
1505 apply_status(app);
1506
1507@@ -1267,39 +1299,108 @@
1508 ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE_GET_PRIVATE (appstore);
1509
1510 Approver * approver = g_new0(Approver, 1);
1511- approver->destroy_by_proxy = FALSE;
1512-
1513- GError * error = NULL;
1514- approver->proxy = dbus_g_proxy_new_for_name_owner(priv->bus,
1515- dbus_name,
1516- dbus_object,
1517- NOTIFICATION_APPROVER_DBUS_IFACE,
1518- &error);
1519- if (error != NULL) {
1520- g_warning("Unable to get approver interface on '%s:%s' : %s", dbus_name, dbus_object, error->message);
1521- g_error_free(error);
1522- g_free(approver);
1523- return;
1524- }
1525-
1526- g_signal_connect(G_OBJECT(approver->proxy), "destroy", G_CALLBACK(approver_destroyed), appstore);
1527-
1528- dbus_g_proxy_add_signal(approver->proxy,
1529- "ReviseJudgement",
1530- G_TYPE_BOOLEAN,
1531- G_TYPE_STRING,
1532- DBUS_TYPE_G_OBJECT_PATH,
1533- G_TYPE_INVALID);
1534- dbus_g_proxy_connect_signal(approver->proxy,
1535- "ReviseJudgement",
1536- G_CALLBACK(approver_revise_judgement),
1537- appstore,
1538- NULL);
1539+ approver->appstore = appstore;
1540+ approver->proxy_cancel = NULL;
1541+ approver->proxy = NULL;
1542+ approver->name_watcher = 0;
1543+
1544+ approver->proxy_cancel = g_cancellable_new();
1545+ g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION,
1546+ G_DBUS_PROXY_FLAGS_NONE,
1547+ NULL,
1548+ dbus_name,
1549+ dbus_object,
1550+ NOTIFICATION_APPROVER_DBUS_IFACE,
1551+ approver->proxy_cancel,
1552+ approver_proxy_cb,
1553+ approver);
1554
1555 priv->approvers = g_list_prepend(priv->approvers, approver);
1556
1557+ return;
1558+}
1559+
1560+static void
1561+approver_name_changed (GDBusConnection * connection, const gchar * sender_name,
1562+ const gchar * object_path, const gchar * interface_name,
1563+ const gchar * signal_name, GVariant * parameters,
1564+ gpointer user_data)
1565+{
1566+ Approver * approver = (Approver *)user_data;
1567+ ApplicationServiceAppstore * appstore = approver->appstore;
1568+
1569+ const gchar * new_name;
1570+ g_variant_get(parameters, "(&s&s&s)", NULL, NULL, &new_name);
1571+
1572+ if (new_name == NULL || new_name[0] == 0) {
1573+ appstore->priv->approvers = g_list_remove(appstore->priv->approvers, approver);
1574+ approver_free(approver, appstore);
1575+ }
1576+}
1577+
1578+/* Callback from trying to create the proxy for the approver. */
1579+static void
1580+approver_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data)
1581+{
1582+ GError * error = NULL;
1583+
1584+ Approver * approver = (Approver *)user_data;
1585+ g_return_if_fail(approver != NULL);
1586+
1587+ GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
1588+ ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE_GET_PRIVATE (approver->appstore);
1589+
1590+ if (approver->proxy_cancel != NULL) {
1591+ g_object_unref(approver->proxy_cancel);
1592+ approver->proxy_cancel = NULL;
1593+ }
1594+
1595+ if (error != NULL) {
1596+ g_error("Could not grab DBus proxy for approver: %s", error->message);
1597+ g_error_free(error);
1598+ return;
1599+ }
1600+
1601+ /* Okay, we're good to grab the proxy at this point, we're
1602+ sure that it's ours. */
1603+ approver->proxy = proxy;
1604+
1605+ /* We've got it, let's watch it for destruction */
1606+ approver->name_watcher = g_dbus_connection_signal_subscribe(
1607+ g_dbus_proxy_get_connection(proxy),
1608+ "org.freedesktop.DBus",
1609+ "org.freedesktop.DBus",
1610+ "NameOwnerChanged",
1611+ "/org/freedesktop/DBus",
1612+ g_dbus_proxy_get_name(proxy),
1613+ G_DBUS_SIGNAL_FLAGS_NONE,
1614+ approver_name_changed,
1615+ approver,
1616+ NULL);
1617+
1618+ g_signal_connect(proxy, "g-signal", G_CALLBACK(approver_receive_signal),
1619+ approver);
1620+
1621 g_list_foreach(priv->applications, check_with_new_approver, approver);
1622
1623 return;
1624 }
1625
1626+/* Receives all signals from the service, routed to the appropriate functions */
1627+static void
1628+approver_receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name,
1629+ GVariant * parameters, gpointer user_data)
1630+{
1631+ Approver * approver = (Approver *)user_data;
1632+
1633+ if (g_strcmp0(signal_name, "ReviseJudgement") == 0) {
1634+ gboolean approved;
1635+ const gchar * address;
1636+ const gchar * path;
1637+ g_variant_get(parameters, "(b&s&o)", &approved, &address, &path);
1638+ approver_revise_judgement(approver, approved, address, path);
1639+ }
1640+
1641+ return;
1642+}
1643+
1644
1645=== modified file 'src/application-service.c'
1646--- src/application-service.c 2010-08-10 19:47:23 +0000
1647+++ src/application-service.c 2011-01-14 02:39:08 +0000
1648@@ -22,7 +22,6 @@
1649
1650
1651 #include "libindicator/indicator-service.h"
1652-#include "notification-item-client.h"
1653 #include "application-service-appstore.h"
1654 #include "application-service-watcher.h"
1655 #include "dbus-shared.h"
1656
1657=== modified file 'src/application-service.xml'
1658--- src/application-service.xml 2010-08-05 21:54:12 +0000
1659+++ src/application-service.xml 2011-01-14 02:39:08 +0000
1660@@ -20,7 +20,7 @@
1661 with this program. If not, see <http://www.gnu.org/licenses/>.
1662 -->
1663 <node name="/">
1664- <interface name="org.ayatana.indicator.application.service">
1665+ <interface name="com.canonical.indicator.application.service">
1666 <!-- Properties -->
1667 <!-- None currently -->
1668
1669
1670=== removed file 'src/dbus-properties.xml'
1671--- src/dbus-properties.xml 2009-11-07 04:50:48 +0000
1672+++ src/dbus-properties.xml 1970-01-01 00:00:00 +0000
1673@@ -1,23 +0,0 @@
1674-<?xml version="1.0" encoding="UTF-8"?>
1675-<node name="/">
1676- <interface name="org.freedesktop.DBus.Properties">
1677-
1678- <method name="Get">
1679- <arg direction="in" type="s" name="Interface_Name"/>
1680- <arg direction="in" type="s" name="Property_Name"/>
1681- <arg direction="out" type="v" name="Value"/>
1682- </method>
1683-
1684- <method name="Set">
1685- <arg direction="in" type="s" name="Interface_Name"/>
1686- <arg direction="in" type="s" name="Property_Name"/>
1687- <arg direction="in" type="v" name="Value"/>
1688- </method>
1689-
1690- <method name="GetAll">
1691- <arg direction="in" type="s" name="Interface_Name"/>
1692- <arg direction="out" type="a{sv}" name="Properties"/>
1693- </method>
1694-
1695- </interface>
1696-</node>
1697
1698=== modified file 'src/dbus-shared.h'
1699--- src/dbus-shared.h 2010-07-09 21:06:37 +0000
1700+++ src/dbus-shared.h 2011-01-14 02:39:08 +0000
1701@@ -20,9 +20,9 @@
1702 */
1703
1704
1705-#define INDICATOR_APPLICATION_DBUS_ADDR "org.ayatana.indicator.application"
1706-#define INDICATOR_APPLICATION_DBUS_OBJ "/org/ayatana/indicator/application/service"
1707-#define INDICATOR_APPLICATION_DBUS_IFACE "org.ayatana.indicator.application.service"
1708+#define INDICATOR_APPLICATION_DBUS_ADDR "com.canonical.indicator.application"
1709+#define INDICATOR_APPLICATION_DBUS_OBJ "/com/canonical/indicator/application/service"
1710+#define INDICATOR_APPLICATION_DBUS_IFACE "com.canonical.indicator.application.service"
1711
1712 #define NOTIFICATION_WATCHER_DBUS_ADDR "org.kde.StatusNotifierWatcher"
1713 #define NOTIFICATION_WATCHER_DBUS_OBJ "/StatusNotifierWatcher"
1714
1715=== modified file 'src/indicator-application.c'
1716--- src/indicator-application.c 2010-12-04 03:21:06 +0000
1717+++ src/indicator-application.c 2011-01-14 02:39:08 +0000
1718@@ -28,10 +28,10 @@
1719 /* G Stuff */
1720 #include <glib.h>
1721 #include <glib-object.h>
1722+#include <gio/gio.h>
1723 #include <gtk/gtk.h>
1724
1725 /* DBus Stuff */
1726-#include <dbus/dbus-glib.h>
1727 #ifdef HAVE_GTK3
1728 #include <libdbusmenu-gtk3/menu.h>
1729 #else
1730@@ -46,7 +46,7 @@
1731
1732 /* Local Stuff */
1733 #include "dbus-shared.h"
1734-#include "application-service-client.h"
1735+#include "gen-application-service.xml.h"
1736 #include "application-service-marshal.h"
1737
1738 #define PANEL_ICON_SUFFIX "panel"
1739@@ -81,8 +81,8 @@
1740 typedef struct _IndicatorApplicationPrivate IndicatorApplicationPrivate;
1741 struct _IndicatorApplicationPrivate {
1742 IndicatorServiceManager * sm;
1743- DBusGConnection * bus;
1744- DBusGProxy * service_proxy;
1745+ GCancellable * service_proxy_cancel;
1746+ GDBusProxy * service_proxy;
1747 GList * applications;
1748 GHashTable * theme_dirs;
1749 guint disconnect_kill;
1750@@ -114,15 +114,17 @@
1751 static void disconnected_helper (gpointer data, gpointer user_data);
1752 static gboolean disconnected_kill (gpointer user_data);
1753 static void disconnected_kill_helper (gpointer data, gpointer user_data);
1754-static void application_added (DBusGProxy * proxy, const gchar * iconname, gint position, const gchar * dbusaddress, const gchar * dbusobject, const gchar * icon_theme_path, const gchar * label, const gchar * guide, IndicatorApplication * application);
1755-static void application_removed (DBusGProxy * proxy, gint position , IndicatorApplication * application);
1756-static void application_label_changed (DBusGProxy * proxy, gint position, const gchar * label, const gchar * guide, IndicatorApplication * application);
1757-static void application_icon_changed (DBusGProxy * proxy, gint position, const gchar * iconname, IndicatorApplication * application);
1758-static void application_icon_theme_path_changed (DBusGProxy * proxy, gint position, const gchar * icon_theme_path, IndicatorApplication * application);
1759-static void get_applications (DBusGProxy *proxy, GPtrArray *OUT_applications, GError *error, gpointer userdata);
1760-static void get_applications_helper (gpointer data, gpointer user_data);
1761+static void application_added (IndicatorApplication * application, const gchar * iconname, gint position, const gchar * dbusaddress, const gchar * dbusobject, const gchar * icon_theme_path, const gchar * label, const gchar * guide);
1762+static void application_removed (IndicatorApplication * application, gint position);
1763+static void application_label_changed (IndicatorApplication * application, gint position, const gchar * label, const gchar * guide);
1764+static void application_icon_changed (IndicatorApplication * application, gint position, const gchar * iconname);
1765+static void application_icon_theme_path_changed (IndicatorApplication * application, gint position, const gchar * icon_theme_path);
1766+static void get_applications (GObject * obj, GAsyncResult * res, gpointer user_data);
1767+static void get_applications_helper (IndicatorApplication * self, GVariant * variant);
1768 static void theme_dir_unref(IndicatorApplication * ia, const gchar * dir);
1769 static void theme_dir_ref(IndicatorApplication * ia, const gchar * dir);
1770+static void service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data);
1771+static void receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, GVariant * parameters, gpointer user_data);
1772
1773 G_DEFINE_TYPE (IndicatorApplication, indicator_application, INDICATOR_OBJECT_TYPE);
1774
1775@@ -141,28 +143,6 @@
1776 io_class->get_entries = get_entries;
1777 io_class->get_location = get_location;
1778
1779- dbus_g_object_register_marshaller(_application_service_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING,
1780- G_TYPE_NONE,
1781- G_TYPE_STRING,
1782- G_TYPE_INT,
1783- G_TYPE_STRING,
1784- G_TYPE_STRING,
1785- G_TYPE_STRING,
1786- G_TYPE_STRING,
1787- G_TYPE_STRING,
1788- G_TYPE_INVALID);
1789- dbus_g_object_register_marshaller(_application_service_marshal_VOID__INT_STRING,
1790- G_TYPE_NONE,
1791- G_TYPE_INT,
1792- G_TYPE_STRING,
1793- G_TYPE_INVALID);
1794- dbus_g_object_register_marshaller(_application_service_marshal_VOID__INT_STRING_STRING,
1795- G_TYPE_NONE,
1796- G_TYPE_INT,
1797- G_TYPE_STRING,
1798- G_TYPE_STRING,
1799- G_TYPE_INVALID);
1800-
1801 return;
1802 }
1803
1804@@ -172,7 +152,7 @@
1805 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(self);
1806
1807 /* These are built in the connection phase */
1808- priv->bus = NULL;
1809+ priv->service_proxy_cancel = NULL;
1810 priv->service_proxy = NULL;
1811 priv->theme_dirs = NULL;
1812 priv->disconnect_kill = 0;
1813@@ -197,9 +177,8 @@
1814 }
1815
1816 while (priv->applications != NULL) {
1817- application_removed(priv->service_proxy,
1818- 0,
1819- INDICATOR_APPLICATION(object));
1820+ application_removed(INDICATOR_APPLICATION(object),
1821+ 0);
1822 }
1823
1824 if (priv->sm != NULL) {
1825@@ -207,16 +186,17 @@
1826 priv->sm = NULL;
1827 }
1828
1829- if (priv->bus != NULL) {
1830- /* We're not incrementing the ref count on this one. */
1831- priv->bus = NULL;
1832- }
1833-
1834 if (priv->service_proxy != NULL) {
1835 g_object_unref(G_OBJECT(priv->service_proxy));
1836 priv->service_proxy = NULL;
1837 }
1838
1839+ if (priv->service_proxy_cancel != NULL) {
1840+ g_cancellable_cancel(priv->service_proxy_cancel);
1841+ g_object_unref(priv->service_proxy_cancel);
1842+ priv->service_proxy_cancel = NULL;
1843+ }
1844+
1845 if (priv->theme_dirs != NULL) {
1846 while (g_hash_table_size(priv->theme_dirs)) {
1847 GList * keys = g_hash_table_get_keys(priv->theme_dirs);
1848@@ -260,93 +240,59 @@
1849 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(application);
1850 g_debug("Connected to Application Indicator Service.");
1851
1852+ if (priv->service_proxy_cancel == NULL && priv->service_proxy == NULL) {
1853+ /* Build the service proxy */
1854+ priv->service_proxy_cancel = g_cancellable_new();
1855+
1856+ g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION,
1857+ G_DBUS_PROXY_FLAGS_NONE,
1858+ NULL,
1859+ INDICATOR_APPLICATION_DBUS_ADDR,
1860+ INDICATOR_APPLICATION_DBUS_OBJ,
1861+ INDICATOR_APPLICATION_DBUS_IFACE,
1862+ priv->service_proxy_cancel,
1863+ service_proxy_cb,
1864+ application);
1865+ }
1866+
1867+ return;
1868+}
1869+
1870+/* Callback from trying to create the proxy for the service, this
1871+ could include starting the service. */
1872+static void
1873+service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data)
1874+{
1875 GError * error = NULL;
1876
1877- /* Grab the session bus */
1878- if (priv->bus == NULL) {
1879- priv->bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
1880-
1881- if (error != NULL) {
1882- g_error("Unable to get session bus: %s", error->message);
1883- g_error_free(error);
1884- return;
1885- }
1886- }
1887-
1888- if (priv->service_proxy == NULL) {
1889- /* Build the service proxy */
1890- priv->service_proxy = dbus_g_proxy_new_for_name(priv->bus,
1891- INDICATOR_APPLICATION_DBUS_ADDR,
1892- INDICATOR_APPLICATION_DBUS_OBJ,
1893- INDICATOR_APPLICATION_DBUS_IFACE);
1894-
1895- /* Set up proxy signals */
1896- g_debug("Setup proxy signals");
1897- dbus_g_proxy_add_signal(priv->service_proxy,
1898- "ApplicationAdded",
1899- G_TYPE_STRING,
1900- G_TYPE_INT,
1901- G_TYPE_STRING,
1902- G_TYPE_STRING,
1903- G_TYPE_STRING,
1904- G_TYPE_STRING,
1905- G_TYPE_STRING,
1906- G_TYPE_INVALID);
1907- dbus_g_proxy_add_signal(priv->service_proxy,
1908- "ApplicationRemoved",
1909- G_TYPE_INT,
1910- G_TYPE_INVALID);
1911- dbus_g_proxy_add_signal(priv->service_proxy,
1912- "ApplicationIconChanged",
1913- G_TYPE_INT,
1914- G_TYPE_STRING,
1915- G_TYPE_INVALID);
1916- dbus_g_proxy_add_signal(priv->service_proxy,
1917- "ApplicationIconThemePathChanged",
1918- G_TYPE_INT,
1919- G_TYPE_STRING,
1920- G_TYPE_INVALID);
1921- dbus_g_proxy_add_signal(priv->service_proxy,
1922- "ApplicationLabelChanged",
1923- G_TYPE_INT,
1924- G_TYPE_STRING,
1925- G_TYPE_STRING,
1926- G_TYPE_INVALID);
1927-
1928- /* Connect to them */
1929- g_debug("Connect to them.");
1930- dbus_g_proxy_connect_signal(priv->service_proxy,
1931- "ApplicationAdded",
1932- G_CALLBACK(application_added),
1933- application,
1934- NULL /* Disconnection Signal */);
1935- dbus_g_proxy_connect_signal(priv->service_proxy,
1936- "ApplicationRemoved",
1937- G_CALLBACK(application_removed),
1938- application,
1939- NULL /* Disconnection Signal */);
1940- dbus_g_proxy_connect_signal(priv->service_proxy,
1941- "ApplicationIconChanged",
1942- G_CALLBACK(application_icon_changed),
1943- application,
1944- NULL /* Disconnection Signal */);
1945- dbus_g_proxy_connect_signal(priv->service_proxy,
1946- "ApplicationIconThemePathChanged",
1947- G_CALLBACK(application_icon_theme_path_changed),
1948- application,
1949- NULL /* Disconnection Signal */);
1950- dbus_g_proxy_connect_signal(priv->service_proxy,
1951- "ApplicationLabelChanged",
1952- G_CALLBACK(application_label_changed),
1953- application,
1954- NULL /* Disconnection Signal */);
1955- }
1956+ IndicatorApplication * self = INDICATOR_APPLICATION(user_data);
1957+ g_return_if_fail(self != NULL);
1958+
1959+ IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(self);
1960+ GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
1961+
1962+ if (priv->service_proxy_cancel != NULL) {
1963+ g_object_unref(priv->service_proxy_cancel);
1964+ priv->service_proxy_cancel = NULL;
1965+ }
1966+
1967+ if (error != NULL) {
1968+ g_error("Could not grab DBus proxy for %s: %s", INDICATOR_APPLICATION_DBUS_ADDR, error->message);
1969+ g_error_free(error);
1970+ return;
1971+ }
1972+
1973+ /* Okay, we're good to grab the proxy at this point, we're
1974+ sure that it's ours. */
1975+ priv->service_proxy = proxy;
1976+
1977+ g_signal_connect(proxy, "g-signal", G_CALLBACK(receive_signal), self);
1978
1979 /* Query it for existing applications */
1980 g_debug("Request current apps");
1981- org_ayatana_indicator_application_service_get_applications_async(priv->service_proxy,
1982- get_applications,
1983- application);
1984+ g_dbus_proxy_call(priv->service_proxy, "GetApplications", NULL,
1985+ G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1986+ get_applications, self);
1987
1988 return;
1989 }
1990@@ -397,7 +343,7 @@
1991 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(user_data);
1992 ApplicationEntry * entry = (ApplicationEntry *)data;
1993 if (entry->old_service) {
1994- application_removed(NULL, g_list_index(priv->applications, data), INDICATOR_APPLICATION(user_data));
1995+ application_removed(INDICATOR_APPLICATION(user_data), g_list_index(priv->applications, data));
1996 }
1997 return;
1998 }
1999@@ -435,22 +381,6 @@
2000 return g_list_index(priv->applications, entry);
2001 }
2002
2003-/* Searching for ApplicationEntries where the dbusobject and
2004- address are the same. */
2005-static gint
2006-application_added_search (gconstpointer a, gconstpointer b)
2007-{
2008- ApplicationEntry * appa = (ApplicationEntry *)a;
2009- ApplicationEntry * appb = (ApplicationEntry *)b;
2010-
2011- if (g_strcmp0(appa->dbusaddress, appb->dbusaddress) == 0 &&
2012- g_strcmp0(appa->dbusobject, appb->dbusobject) == 0) {
2013- return 0;
2014- }
2015-
2016- return -1;
2017-}
2018-
2019 /* Does a quick meausre of how big the string is in
2020 pixels with a Pango layout */
2021 static gint
2022@@ -495,25 +425,12 @@
2023 ApplicationEntry and signaling the indicator host that
2024 we've got a new indicator. */
2025 static void
2026-application_added (DBusGProxy * proxy, const gchar * iconname, gint position, const gchar * dbusaddress, const gchar * dbusobject, const gchar * icon_theme_path, const gchar * label, const gchar * guide, IndicatorApplication * application)
2027+application_added (IndicatorApplication * application, const gchar * iconname, gint position, const gchar * dbusaddress, const gchar * dbusobject, const gchar * icon_theme_path, const gchar * label, const gchar * guide)
2028 {
2029 g_return_if_fail(IS_INDICATOR_APPLICATION(application));
2030- g_debug("Building new application entry: %s with icon: %s", dbusaddress, iconname);
2031+ g_debug("Building new application entry: %s with icon: %s at position %i", dbusaddress, iconname, position);
2032 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(application);
2033
2034- /* First search to see if we already have this entry */
2035- ApplicationEntry searchapp;
2036- searchapp.dbusaddress = (gchar *)dbusaddress; /* Casting off const, but it's okay, we're not changing it */
2037- searchapp.dbusobject = (gchar *)dbusobject; /* Casting off const, but it's okay, we're not changing it */
2038-
2039- GList * searchpointer = g_list_find_custom(priv->applications, &searchapp, application_added_search);
2040- if (searchpointer != NULL) {
2041- g_debug("\t...Already have that one.");
2042- ApplicationEntry * app = (ApplicationEntry *)searchpointer->data;
2043- app->old_service = FALSE;
2044- return;
2045- }
2046-
2047 ApplicationEntry * app = g_new(ApplicationEntry, 1);
2048
2049 app->old_service = FALSE;
2050@@ -574,7 +491,7 @@
2051 /* This removes the application from the list and free's all
2052 of the memory associated with it. */
2053 static void
2054-application_removed (DBusGProxy * proxy, gint position, IndicatorApplication * application)
2055+application_removed (IndicatorApplication * application, gint position)
2056 {
2057 g_return_if_fail(IS_INDICATOR_APPLICATION(application));
2058 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(application);
2059@@ -621,7 +538,7 @@
2060 /* The callback for the signal that the label for an application
2061 has changed. */
2062 static void
2063-application_label_changed (DBusGProxy * proxy, gint position, const gchar * label, const gchar * guide, IndicatorApplication * application)
2064+application_label_changed (IndicatorApplication * application, gint position, const gchar * label, const gchar * guide)
2065 {
2066 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(application);
2067 ApplicationEntry * app = (ApplicationEntry *)g_list_nth_data(priv->applications, position);
2068@@ -702,7 +619,7 @@
2069 /* The callback for the signal that the icon for an application
2070 has changed. */
2071 static void
2072-application_icon_changed (DBusGProxy * proxy, gint position, const gchar * iconname, IndicatorApplication * application)
2073+application_icon_changed (IndicatorApplication * application, gint position, const gchar * iconname)
2074 {
2075 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(application);
2076 ApplicationEntry * app = (ApplicationEntry *)g_list_nth_data(priv->applications, position);
2077@@ -732,7 +649,7 @@
2078 /* The callback for the signal that the icon theme path for an application
2079 has changed. */
2080 static void
2081-application_icon_theme_path_changed (DBusGProxy * proxy, gint position, const gchar * icon_theme_path, IndicatorApplication * application)
2082+application_icon_theme_path_changed (IndicatorApplication * application, gint position, const gchar * icon_theme_path)
2083 {
2084 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(application);
2085 ApplicationEntry * app = (ApplicationEntry *)g_list_nth_data(priv->applications, position);
2086@@ -758,16 +675,78 @@
2087 return;
2088 }
2089
2090-/* This repsonds to the list of applications that the service
2091+/* Receives all signals from the service, routed to the appropriate functions */
2092+static void
2093+receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name,
2094+ GVariant * parameters, gpointer user_data)
2095+{
2096+ IndicatorApplication * self = INDICATOR_APPLICATION(user_data);
2097+
2098+ if (g_strcmp0(signal_name, "ApplicationAdded") == 0) {
2099+ const gchar * iconname;
2100+ gint position;
2101+ const gchar * dbusaddress;
2102+ const gchar * dbusobject;
2103+ const gchar * icon_theme_path;
2104+ const gchar * label;
2105+ const gchar * guide;
2106+ g_variant_get (parameters, "(&si&s&o&s&s&s)", &iconname,
2107+ &position, &dbusaddress, &dbusobject,
2108+ &icon_theme_path, &label, &guide);
2109+ application_added(self, iconname, position, dbusaddress,
2110+ dbusobject, icon_theme_path, label, guide);
2111+ }
2112+ else if (g_strcmp0(signal_name, "ApplicationRemoved") == 0) {
2113+ gint position;
2114+ g_variant_get (parameters, "(i)", &position);
2115+ application_removed(self, position);
2116+ }
2117+ else if (g_strcmp0(signal_name, "ApplicationIconChanged") == 0) {
2118+ gint position;
2119+ const gchar * iconname;
2120+ g_variant_get (parameters, "(i&s)", &position, &iconname);
2121+ application_icon_changed(self, position, iconname);
2122+ }
2123+ else if (g_strcmp0(signal_name, "ApplicationIconThemePathChanged") == 0) {
2124+ gint position;
2125+ const gchar * icon_theme_path;
2126+ g_variant_get (parameters, "(i&s)", &position, &icon_theme_path);
2127+ application_icon_theme_path_changed(self, position, icon_theme_path);
2128+ }
2129+ else if (g_strcmp0(signal_name, "ApplicationLabelChanged") == 0) {
2130+ gint position;
2131+ const gchar * label;
2132+ const gchar * guide;
2133+ g_variant_get (parameters, "(i&s&s)", &position, &label, &guide);
2134+ application_label_changed(self, position, label, guide);
2135+ }
2136+
2137+ return;
2138+}
2139+
2140+/* This responds to the list of applications that the service
2141 has and calls application_added on each one of them. */
2142 static void
2143-get_applications (DBusGProxy *proxy, GPtrArray *OUT_applications, GError *error, gpointer userdata)
2144+get_applications (GObject * obj, GAsyncResult * res, gpointer user_data)
2145 {
2146+ IndicatorApplication * self = INDICATOR_APPLICATION(user_data);
2147+ IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(self);
2148+ GError * error = NULL;
2149+ GVariant * result;
2150+ GVariant * child;
2151+ GVariantIter * iter;
2152+
2153+ result = g_dbus_proxy_call_finish(priv->service_proxy, res, &error);
2154+
2155 if (error != NULL) {
2156 g_warning("Unable to get application list: %s", error->message);
2157 return;
2158 }
2159- g_ptr_array_foreach(OUT_applications, get_applications_helper, userdata);
2160+
2161+ g_variant_get(result, "(a(sisosss))", &iter);
2162+ while ((child = g_variant_iter_next_value (iter)))
2163+ get_applications_helper(self, child);
2164+ g_variant_iter_free (iter);
2165
2166 return;
2167 }
2168@@ -775,21 +754,20 @@
2169 /* A little helper that takes apart the DBus structure and calls
2170 application_added on every entry in the list. */
2171 static void
2172-get_applications_helper (gpointer data, gpointer user_data)
2173+get_applications_helper (IndicatorApplication * self, GVariant * variant)
2174 {
2175- GValueArray * array = (GValueArray *)data;
2176-
2177- g_return_if_fail(array->n_values == 7);
2178-
2179- const gchar * icon_name = g_value_get_string(g_value_array_get_nth(array, 0));
2180- gint position = g_value_get_int(g_value_array_get_nth(array, 1));
2181- const gchar * dbus_address = g_value_get_string(g_value_array_get_nth(array, 2));
2182- const gchar * dbus_object = g_value_get_boxed(g_value_array_get_nth(array, 3));
2183- const gchar * icon_theme_path = g_value_get_string(g_value_array_get_nth(array, 4));
2184- const gchar * label = g_value_get_string(g_value_array_get_nth(array, 5));
2185- const gchar * guide = g_value_get_string(g_value_array_get_nth(array, 6));
2186-
2187- return application_added(NULL, icon_name, position, dbus_address, dbus_object, icon_theme_path, label, guide, user_data);
2188+ const gchar * icon_name;
2189+ gint position;
2190+ const gchar * dbus_address;
2191+ const gchar * dbus_object;
2192+ const gchar * icon_theme_path;
2193+ const gchar * label;
2194+ const gchar * guide;
2195+ g_variant_get(variant, "(sisosss)", &icon_name, &position,
2196+ &dbus_address, &dbus_object, &icon_theme_path, &label,
2197+ &guide);
2198+
2199+ return application_added(self, icon_name, position, dbus_address, dbus_object, icon_theme_path, label, guide);
2200 }
2201
2202 /* Unrefs a theme directory. This may involve removing it from
2203
2204=== removed file 'src/notification-item.xml'
2205--- src/notification-item.xml 2010-08-11 20:55:25 +0000
2206+++ src/notification-item.xml 1970-01-01 00:00:00 +0000
2207@@ -1,39 +0,0 @@
2208-<?xml version="1.0" encoding="UTF-8"?>
2209-<node name="/StatusNotifierItem">
2210- <interface name="org.kde.StatusNotifierItem">
2211-
2212-<!-- Properties -->
2213- <property name="Id" type="s" access="read" />
2214- <property name="Category" type="s" access="read" />
2215- <property name="Status" type="s" access="read" />
2216- <property name="IconName" type="s" access="read" />
2217- <property name="AttentionIconName" type="s" access="read" />
2218- <!-- An additional path to add to the theme search path
2219- to find the icons specified above. -->
2220- <property name="IconThemePath" type="s" access="read" />
2221- <property name="Menu" type="o" access="read" />
2222- <property name="XAyatanaLabel" type="s" access="read" />
2223- <property name="XAyatanaLabelGuide" type="s" access="read" />
2224- <property name="XAyatanaOrderingIndex" type="u" access="read" />
2225-
2226-<!-- Methods -->
2227- <!-- None currently -->
2228-
2229-<!-- Signals -->
2230- <signal name="NewIcon">
2231- </signal>
2232- <signal name="NewIconThemePath">
2233- <arg type="s" name="icon_theme_path" direction="out" />
2234- </signal>
2235- <signal name="NewAttentionIcon">
2236- </signal>
2237- <signal name="NewStatus">
2238- <arg type="s" name="status" direction="out" />
2239- </signal>
2240- <signal name="XAyatanaNewLabel">
2241- <arg type="s" name="label" direction="out" />
2242- <arg type="s" name="guide" direction="out" />
2243- </signal>
2244-
2245- </interface>
2246-</node>
2247
2248=== modified file 'tests/Makefile.am'
2249--- tests/Makefile.am 2010-12-02 22:56:23 +0000
2250+++ tests/Makefile.am 2011-01-14 02:39:08 +0000
2251@@ -14,6 +14,7 @@
2252 #########################################
2253
2254 test_approver_SOURCES = \
2255+ $(top_srcdir)/src/gen-notification-approver.xml.c \
2256 test-approver.c
2257
2258 test_approver_CFLAGS = \
2259
2260=== modified file 'tests/test-approver.c'
2261--- tests/test-approver.c 2010-12-02 22:56:23 +0000
2262+++ tests/test-approver.c 2011-01-14 02:39:08 +0000
2263@@ -1,11 +1,10 @@
2264 #include <glib.h>
2265 #include <glib-object.h>
2266-
2267-#include <dbus/dbus-glib-bindings.h>
2268-
2269-#include "notification-watcher-client.h"
2270+#include <gio/gio.h>
2271+
2272 #include "dbus-shared.h"
2273 #include "libappindicator/app-indicator.h"
2274+#include "gen-notification-approver.xml.h"
2275
2276 #define APPROVER_PATH "/my/approver"
2277
2278@@ -35,13 +34,22 @@
2279
2280 static void test_approver_class_init (TestApproverClass *klass);
2281 static void test_approver_init (TestApprover *self);
2282-static gboolean _notification_approver_server_approve_item (TestApprover * ta, const gchar * id, const gchar * category, guint pid, const gchar * address, const gchar * path, gboolean * approved, GError ** error);
2283+static GVariant * approve_item (TestApprover * ta, const gchar * id);
2284+static void bus_method_call (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * method, GVariant * params, GDBusMethodInvocation * invocation, gpointer user_data);
2285
2286-#include "../src/notification-approver-server.h"
2287+/* GDBus Stuff */
2288+static GDBusNodeInfo * node_info = NULL;
2289+static GDBusInterfaceInfo * interface_info = NULL;
2290+static GDBusInterfaceVTable interface_table = {
2291+ method_call: bus_method_call,
2292+ get_property: NULL, /* No properties */
2293+ set_property: NULL /* No properties */
2294+};
2295
2296 GMainLoop * main_loop = NULL;
2297-DBusGConnection * session_bus = NULL;
2298-DBusGProxy * bus_proxy = NULL;
2299+GDBusConnection * session_bus = NULL;
2300+GDBusProxy * bus_proxy = NULL;
2301+GDBusProxy * watcher_proxy = NULL;
2302 AppIndicator * app_indicator = NULL;
2303 gboolean passed = FALSE;
2304
2305@@ -50,8 +58,24 @@
2306 static void
2307 test_approver_class_init (TestApproverClass *klass)
2308 {
2309- dbus_g_object_type_install_info(TEST_APPROVER_TYPE,
2310- &dbus_glib__notification_approver_server_object_info);
2311+ /* Setting up the DBus interfaces */
2312+ if (node_info == NULL) {
2313+ GError * error = NULL;
2314+
2315+ node_info = g_dbus_node_info_new_for_xml(_notification_approver, &error);
2316+ if (error != NULL) {
2317+ g_error("Unable to parse Approver Service Interface description: %s", error->message);
2318+ g_error_free(error);
2319+ }
2320+ }
2321+
2322+ if (interface_info == NULL) {
2323+ interface_info = g_dbus_node_info_lookup_interface(node_info, NOTIFICATION_APPROVER_DBUS_IFACE);
2324+
2325+ if (interface_info == NULL) {
2326+ g_error("Unable to find interface '" NOTIFICATION_APPROVER_DBUS_IFACE "'");
2327+ }
2328+ }
2329
2330 return;
2331 }
2332@@ -59,17 +83,29 @@
2333 static void
2334 test_approver_init (TestApprover *self)
2335 {
2336- dbus_g_connection_register_g_object(session_bus,
2337- APPROVER_PATH,
2338- G_OBJECT(self));
2339+ GError * error = NULL;
2340+
2341+ /* Now register our object on our new connection */
2342+ g_dbus_connection_register_object(session_bus,
2343+ APPROVER_PATH,
2344+ interface_info,
2345+ &interface_table,
2346+ self,
2347+ NULL,
2348+ &error);
2349+
2350+ if (error != NULL) {
2351+ g_error("Unable to register the object to DBus: %s", error->message);
2352+ g_error_free(error);
2353+ return;
2354+ }
2355
2356 return;
2357 }
2358
2359-static gboolean
2360-_notification_approver_server_approve_item (TestApprover * ta, const gchar * id, const gchar * category, guint pid, const gchar * address, const gchar * path, gboolean * approved, GError ** error)
2361+static GVariant *
2362+approve_item (TestApprover * ta, const gchar * id)
2363 {
2364- *approved = TRUE;
2365 g_debug("Asked to approve indicator");
2366
2367 if (g_strcmp0(id, INDICATOR_ID) == 0) {
2368@@ -78,12 +114,41 @@
2369
2370 g_main_loop_quit(main_loop);
2371
2372- return TRUE;
2373-}
2374-
2375-static void
2376-register_cb (DBusGProxy * proxy, GError * error, gpointer user_data)
2377-{
2378+ return g_variant_new("(b)", TRUE);
2379+}
2380+
2381+/* A method has been called from our dbus inteface. Figure out what it
2382+ is and dispatch it. */
2383+static void
2384+bus_method_call (GDBusConnection * connection, const gchar * sender,
2385+ const gchar * path, const gchar * interface,
2386+ const gchar * method, GVariant * params,
2387+ GDBusMethodInvocation * invocation, gpointer user_data)
2388+{
2389+ TestApprover * ta = (TestApprover *)user_data;
2390+ GVariant * retval = NULL;
2391+
2392+ if (g_strcmp0(method, "ApproveItem") == 0) {
2393+ const gchar * id;
2394+ g_variant_get(params, "(&ssuso)", &id, NULL, NULL, NULL, NULL);
2395+ retval = approve_item(ta, id);
2396+ } else {
2397+ g_warning("Calling method '%s' on the indicator service and it's unknown", method);
2398+ }
2399+
2400+ g_dbus_method_invocation_return_value(invocation, retval);
2401+ return;
2402+}
2403+
2404+static void
2405+register_cb (GObject *object, GAsyncResult *res, gpointer user_data)
2406+{
2407+ GDBusProxy * proxy = G_DBUS_PROXY(object);
2408+ GError * error = NULL;
2409+ GVariant * result;
2410+
2411+ result = g_dbus_proxy_call_finish(proxy, res, &error);
2412+
2413 if (error != NULL) {
2414 g_warning("Unable to register approver: %s", error->message);
2415 g_error_free(error);
2416@@ -118,18 +183,17 @@
2417 owner_count++;
2418
2419 gboolean has_owner = FALSE;
2420- org_freedesktop_DBus_name_has_owner(bus_proxy, NOTIFICATION_WATCHER_DBUS_ADDR, &has_owner, NULL);
2421+ gchar * owner = g_dbus_proxy_get_name_owner(bus_proxy);
2422+ has_owner = (owner != NULL);
2423+ g_free (owner);
2424
2425 if (has_owner) {
2426- const char * cats = NULL;
2427- DBusGProxy * proxy = dbus_g_proxy_new_for_name(session_bus,
2428- NOTIFICATION_WATCHER_DBUS_ADDR,
2429- NOTIFICATION_WATCHER_DBUS_OBJ,
2430- NOTIFICATION_WATCHER_DBUS_IFACE);
2431-
2432 g_debug("Registering Approver");
2433- org_kde_StatusNotifierWatcher_x_ayatana_register_notification_approver_async (proxy, APPROVER_PATH, &cats, register_cb, NULL);
2434-
2435+ GVariantBuilder * builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2436+ g_dbus_proxy_call(bus_proxy, "XAyatanaRegisterNotificationApprover",
2437+ g_variant_new("(oas)", APPROVER_PATH, builder),
2438+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, register_cb,
2439+ NULL);
2440 return FALSE;
2441 }
2442
2443@@ -152,16 +216,22 @@
2444 gtk_init(&argc, &argv);
2445 g_debug("Initing");
2446
2447- session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
2448- if (error != NULL) {
2449- g_warning("Unable to get session bus: %s", error->message);
2450- g_error_free(error);
2451- return -1;
2452- }
2453-
2454+ session_bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
2455 TestApprover * approver = g_object_new(TEST_APPROVER_TYPE, NULL);
2456
2457- bus_proxy = dbus_g_proxy_new_for_name(session_bus, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
2458+ bus_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, NOTIFICATION_WATCHER_DBUS_ADDR, NOTIFICATION_WATCHER_DBUS_OBJ, NOTIFICATION_WATCHER_DBUS_IFACE, NULL, &error);
2459+ if (error != NULL) {
2460+ g_warning("Unable to get bus proxy: %s", error->message);
2461+ g_error_free(error);
2462+ return -1;
2463+ }
2464+
2465+ watcher_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, NOTIFICATION_WATCHER_DBUS_ADDR, NOTIFICATION_WATCHER_DBUS_OBJ, NOTIFICATION_WATCHER_DBUS_IFACE, NULL, &error);
2466+ if (error != NULL) {
2467+ g_warning("Unable to get watcher bus: %s", error->message);
2468+ g_error_free(error);
2469+ return -1;
2470+ }
2471
2472 g_timeout_add(100, check_for_service, NULL);
2473 g_timeout_add_seconds(2, fail_timeout, NULL);

Subscribers

People subscribed via source and target branches