Merge lp:~mterry/indicator-appmenu/gdbus into lp:indicator-appmenu/0.3

Proposed by Michael Terry
Status: Merged
Merged at revision: 86
Proposed branch: lp:~mterry/indicator-appmenu/gdbus
Merge into: lp:indicator-appmenu/0.3
Diff against target: 1428 lines (+597/-333)
8 files modified
configure.ac (+10/-4)
scripts/menu-pusher.c (+9/-8)
src/Makefile.am (+20/-18)
src/application-menu-renderer.xml (+1/-1)
src/clean-namespaces.xslt (+14/-0)
src/indicator-appmenu.c (+414/-228)
src/window-menus.c (+87/-43)
tools/mock-json-app.c (+42/-31)
To merge this branch: bzr merge lp:~mterry/indicator-appmenu/gdbus
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Review via email: mp+46045@code.launchpad.net
To post a comment you must log in.
lp:~mterry/indicator-appmenu/gdbus updated
87. By Michael Terry

add log domain; don't detach menus that aren't attached

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
=== modified file 'configure.ac'
--- configure.ac 2010-10-06 18:43:21 +0000
+++ configure.ac 2011-01-13 04:42:14 +0000
@@ -47,15 +47,15 @@
47###########################47###########################
4848
49GTK_REQUIRED_VERSION=2.1249GTK_REQUIRED_VERSION=2.12
50GIO_REQUIRED_VERSION=2.26
50INDICATOR_REQUIRED_VERSION=0.3.1451INDICATOR_REQUIRED_VERSION=0.3.14
51DBUSMENUGTK_REQUIRED_VERSION=0.3.352DBUSMENUGTK_REQUIRED_VERSION=0.3.3
52DBUS_GLIB_REQUIRED_VERSION=0.82
53BAMF_REQUIRED_VERSION=0.2.5353BAMF_REQUIRED_VERSION=0.2.53
5454
55PKG_CHECK_MODULES(INDICATOR, gtk+-2.0 >= $GTK_REQUIRED_VERSION55PKG_CHECK_MODULES(INDICATOR, gtk+-2.0 >= $GTK_REQUIRED_VERSION
56 gio-2.0 >= $GIO_REQUIRED_VERSION
56 indicator >= $INDICATOR_REQUIRED_VERSION57 indicator >= $INDICATOR_REQUIRED_VERSION
57 dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION58 dbusmenu-gtk-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION
58 dbusmenu-gtk >= $DBUSMENUGTK_REQUIRED_VERSION
59 libbamf >= $BAMF_REQUIRED_VERSION)59 libbamf >= $BAMF_REQUIRED_VERSION)
6060
61AC_SUBST(INDICATOR_CFLAGS)61AC_SUBST(INDICATOR_CFLAGS)
@@ -68,13 +68,19 @@
68DBUSMENU_JSONLOADER_REQUIRED_VERSION=0.3.368DBUSMENU_JSONLOADER_REQUIRED_VERSION=0.3.3
6969
70PKG_CHECK_MODULES(INDICATORTEST,70PKG_CHECK_MODULES(INDICATORTEST,
71 dbusmenu-jsonloader >= $DBUSMENU_JSONLOADER_REQUIRED_VERSION71 dbusmenu-jsonloader-0.4 >= $DBUSMENU_JSONLOADER_REQUIRED_VERSION
72 )72 )
7373
74AC_SUBST(INDICATORTEST_CFLAGS)74AC_SUBST(INDICATORTEST_CFLAGS)
75AC_SUBST(INDICATORTEST_LIBS)75AC_SUBST(INDICATORTEST_LIBS)
7676
77###########################77###########################
78# XSLT Processor
79###########################
80
81AC_PATH_PROG([XSLT_PROC], [xsltproc])
82
83###########################
78# Check to see if we're local84# Check to see if we're local
79###########################85###########################
8086
8187
=== modified file 'scripts/menu-pusher.c'
--- scripts/menu-pusher.c 2010-07-20 21:48:25 +0000
+++ scripts/menu-pusher.c 2011-01-13 04:42:14 +0000
@@ -20,12 +20,11 @@
20*/20*/
2121
22#include <gtk/gtk.h>22#include <gtk/gtk.h>
23#include <dbus/dbus-glib.h>23#include <gio/gio.h>
24#include <libdbusmenu-glib/menuitem.h>24#include <libdbusmenu-glib/menuitem.h>
25#include <libdbusmenu-glib/server.h>25#include <libdbusmenu-glib/server.h>
26#include <libdbusmenu-gtk/menuitem.h>26#include <libdbusmenu-gtk/menuitem.h>
27#include "../src/dbus-shared.h"27#include "../src/dbus-shared.h"
28#include "../src/application-menu-registrar-client.h"
2928
30int29int
31main (int argv, char ** argc)30main (int argv, char ** argc)
@@ -73,16 +72,18 @@
73 dbusmenu_server_set_root(server, root);72 dbusmenu_server_set_root(server, root);
7473
7574
76 DBusGConnection * session = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);75 GDBusProxy * proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SESSION,
77 g_return_val_if_fail(session != NULL, 1);76 G_DBUS_PROXY_FLAGS_NONE,
7877 NULL, DBUS_NAME,
79 DBusGProxy * proxy = dbus_g_proxy_new_for_name_owner(session, DBUS_NAME, REG_OBJECT, REG_IFACE, NULL);78 REG_OBJECT, REG_IFACE,
79 NULL, NULL);
80 g_return_val_if_fail(proxy != NULL, 1);80 g_return_val_if_fail(proxy != NULL, 1);
8181
82 org_ayatana_AppMenu_Registrar_register_window(proxy, 0, "/this/is/a/long/object/path", NULL);82 g_dbus_proxy_call_sync(proxy, "RegisterWindow",
83 g_variant_new("(uo)", 0, "/this/is/a/long/object/path"),
84 G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL);
8385
84 gtk_main();86 gtk_main();
8587
86
87 return 0;88 return 0;
88}89}
8990
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2010-09-03 16:30:59 +0000
+++ src/Makefile.am 2011-01-13 04:42:14 +0000
@@ -12,7 +12,6 @@
12appmenulibdir = $(INDICATORDIR)12appmenulibdir = $(INDICATORDIR)
13appmenulib_LTLIBRARIES = libappmenu.la13appmenulib_LTLIBRARIES = libappmenu.la
14libappmenu_la_SOURCES = \14libappmenu_la_SOURCES = \
15 application-menu-registrar-server.h \
16 dbus-shared.h \15 dbus-shared.h \
17 gdk-get-func.h \16 gdk-get-func.h \
18 gdk-get-func.c \17 gdk-get-func.c \
@@ -20,8 +19,12 @@
20 indicator-appmenu.c \19 indicator-appmenu.c \
21 indicator-appmenu-marshal.c \20 indicator-appmenu-marshal.c \
22 window-menus.c \21 window-menus.c \
23 window-menus.h22 window-menus.h \
24libappmenu_la_CFLAGS = $(INDICATOR_CFLAGS) -Wall -Wl,-Bsymbolic-functions -Wl,-z,defs -Wl,--as-needed -Werror23 gen-application-menu-renderer.xml.c \
24 gen-application-menu-renderer.xml.h \
25 gen-application-menu-registrar.xml.c \
26 gen-application-menu-registrar.xml.h
27libappmenu_la_CFLAGS = $(INDICATOR_CFLAGS) -Wall -Wl,-Bsymbolic-functions -Wl,-z,defs -Wl,--as-needed -Werror -DG_LOG_DOMAIN=\"Indicator-Appmenu\"
25libappmenu_la_LIBADD = $(INDICATOR_LIBS) -lX1128libappmenu_la_LIBADD = $(INDICATOR_LIBS) -lX11
26libappmenu_la_LDFLAGS = -module -avoid-version29libappmenu_la_LDFLAGS = -module -avoid-version
2730
@@ -40,24 +43,23 @@
40 application-menu-renderer.xml \43 application-menu-renderer.xml \
41 application-menu-registrar.xml44 application-menu-registrar.xml
4245
43%-client.h: %.xml46gen-%.xml.c: %.xml
44 dbus-binding-tool \47 @echo "Building $@ from $<"
45 --prefix=_$(notdir $(subst -,_,$(<:.xml=)))_client \48 @echo "const char * _$(subst -,_,$(subst .,_,$(basename $<))) = " > $@
46 --mode=glib-client \49 @$(XSLT_PROC) $(srcdir)/clean-namespaces.xslt $< | \
47 --output=$@ \50 sed -e "s:\":\\\\\":g" -e s:^:\": -e s:\$$:\\\\n\": >> $@
48 $<51 @echo ";" >> $@
4952
50%-server.h: %.xml53gen-%.xml.h: %.xml
51 dbus-binding-tool \54 @echo "Building $@ from $<"
52 --prefix=_$(notdir $(subst -,_,$(<:.xml=)))_server \55 @echo "extern const char * _$(subst -,_,$(subst .,_,$(basename $<)));" > $@
53 --mode=glib-server \
54 --output=$@ \
55 $<
5656
57BUILT_SOURCES += \57BUILT_SOURCES += \
58 $(DBUS_SPECS:.xml=-client.h) \58 gen-application-menu-renderer.xml.c \
59 $(DBUS_SPECS:.xml=-server.h)59 gen-application-menu-renderer.xml.h \
60 gen-application-menu-registrar.xml.c \
61 gen-application-menu-registrar.xml.h
6062
61CLEANFILES += $(BUILT_SOURCES)63CLEANFILES += $(BUILT_SOURCES)
6264
63EXTRA_DIST += $(DBUS_SPECS)65EXTRA_DIST += $(DBUS_SPECS) clean-namespaces.xslt
6466
=== modified file 'src/application-menu-renderer.xml'
--- src/application-menu-renderer.xml 2010-07-13 19:52:07 +0000
+++ src/application-menu-renderer.xml 2011-01-13 04:42:14 +0000
@@ -1,5 +1,5 @@
1<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">1<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
2<node name="/org/ayatana/AppMenu/Renderer">2<node name="/org/ayatana/AppMenu/Renderer" xmlns:dox="http://www.ayatana.org/dbus/dox.dtd">
3 <dox:d><![CDATA[3 <dox:d><![CDATA[
4 @mainpage4 @mainpage
5  5  
66
=== added file 'src/clean-namespaces.xslt'
--- src/clean-namespaces.xslt 1970-01-01 00:00:00 +0000
+++ src/clean-namespaces.xslt 2011-01-13 04:42:14 +0000
@@ -0,0 +1,14 @@
1<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dox="http://www.ayatana.org/dbus/dox.dtd">
2 <xsl:template match="*|@*">
3 <xsl:copy>
4 <xsl:apply-templates select="*|@*" />
5 </xsl:copy>
6 </xsl:template>
7 <xsl:template match="@dox:*|dox:*"/>
8 <xsl:template match="*">
9 <xsl:element name="{local-name()}">
10 <xsl:apply-templates select="@* | node()"/>
11 </xsl:element>
12 </xsl:template>
13</xsl:stylesheet>
14
015
=== modified file 'src/indicator-appmenu.c'
--- src/indicator-appmenu.c 2010-10-06 18:43:21 +0000
+++ src/indicator-appmenu.c 2011-01-13 04:42:14 +0000
@@ -25,11 +25,7 @@
2525
26#include <X11/Xlib.h>26#include <X11/Xlib.h>
27#include <gdk/gdkx.h>27#include <gdk/gdkx.h>
2828#include <gio/gio.h>
29#include <dbus/dbus-glib.h>
30#include <dbus/dbus-glib-bindings.h>
31#include <dbus/dbus-glib-lowlevel.h>
32#include <dbus/dbus-gtype-specialized.h>
3329
34#include <libindicator/indicator.h>30#include <libindicator/indicator.h>
35#include <libindicator/indicator-object.h>31#include <libindicator/indicator-object.h>
@@ -39,6 +35,8 @@
3935
40#include <libbamf/bamf-matcher.h>36#include <libbamf/bamf-matcher.h>
4137
38#include "gen-application-menu-registrar.xml.h"
39#include "gen-application-menu-renderer.xml.h"
42#include "indicator-appmenu-marshal.h"40#include "indicator-appmenu-marshal.h"
43#include "window-menus.h"41#include "window-menus.h"
44#include "dbus-shared.h"42#include "dbus-shared.h"
@@ -102,6 +100,10 @@
102 WindowMenus * desktop_menu;100 WindowMenus * desktop_menu;
103101
104 IndicatorAppmenuDebug * debug;102 IndicatorAppmenuDebug * debug;
103
104 GDBusConnection * bus;
105 guint owner_id;
106 guint dbus_registration;
105};107};
106108
107109
@@ -124,6 +126,9 @@
124struct _IndicatorAppmenuDebug {126struct _IndicatorAppmenuDebug {
125 GObject parent;127 GObject parent;
126 IndicatorAppmenu * appmenu;128 IndicatorAppmenu * appmenu;
129 GCancellable * bus_cancel;
130 GDBusConnection * bus;
131 guint dbus_registration;
127};132};
128133
129134
@@ -136,6 +141,7 @@
136static void indicator_appmenu_finalize (GObject *object);141static void indicator_appmenu_finalize (GObject *object);
137static void indicator_appmenu_debug_class_init (IndicatorAppmenuDebugClass *klass);142static void indicator_appmenu_debug_class_init (IndicatorAppmenuDebugClass *klass);
138static void indicator_appmenu_debug_init (IndicatorAppmenuDebug *self);143static void indicator_appmenu_debug_init (IndicatorAppmenuDebug *self);
144static void indicator_appmenu_debug_dispose (GObject *object);
139static void build_window_menus (IndicatorAppmenu * iapp);145static void build_window_menus (IndicatorAppmenu * iapp);
140static GList * get_entries (IndicatorObject * io);146static GList * get_entries (IndicatorObject * io);
141static guint get_location (IndicatorObject * io,147static guint get_location (IndicatorObject * io,
@@ -153,25 +159,6 @@
153static void old_window (BamfMatcher * matcher,159static void old_window (BamfMatcher * matcher,
154 BamfView * view,160 BamfView * view,
155 gpointer user_data);161 gpointer user_data);
156static gboolean _application_menu_registrar_server_register_window (IndicatorAppmenu * iapp,
157 guint windowid,
158 const gchar * objectpath,
159 DBusGMethodInvocation * method);
160static gboolean _application_menu_registrar_server_unregister_window (IndicatorAppmenu * iapp,
161 guint windowid,
162 GError ** error);
163static gboolean _application_menu_registrar_server_get_menu_for_window (IndicatorAppmenu * iapp,
164 guint windowid,
165 gchar ** objectpath,
166 gchar ** address,
167 GError ** error);
168static gboolean _application_menu_registrar_server_get_menus (IndicatorAppmenu * iapp,
169 GPtrArray ** entries,
170 GError ** error);
171static void request_name_cb (DBusGProxy *proxy,
172 guint result,
173 GError *error,
174 gpointer userdata);
175static void window_entry_added (WindowMenus * mw,162static void window_entry_added (WindowMenus * mw,
176 IndicatorObjectEntry * entry,163 IndicatorObjectEntry * entry,
177 gpointer user_data);164 gpointer user_data);
@@ -186,22 +173,36 @@
186 BamfView * oldview,173 BamfView * oldview,
187 BamfView * newview,174 BamfView * newview,
188 gpointer user_data);175 gpointer user_data);
189static gboolean _application_menu_renderer_server_get_current_menu (IndicatorAppmenuDebug * iappd,
190 gchar ** objectpath,
191 gchar ** address,
192 GError ** error);
193static gboolean _application_menu_renderer_server_activate_menu_item (IndicatorAppmenuDebug * iappd,
194 GArray * menulist,
195 GError ** error);
196static gboolean _application_menu_renderer_server_dump_current_menu (IndicatorAppmenuDebug * iappd,
197 gchar ** jsondata,
198 GError ** error);
199static gboolean _application_menu_renderer_server_dump_menu (IndicatorAppmenuDebug * iappd,
200 guint windowid,
201 gchar ** jsondata,
202 GError ** error);
203static GQuark error_quark (void);176static GQuark error_quark (void);
204static gboolean retry_registration (gpointer user_data);177static gboolean retry_registration (gpointer user_data);
178static void bus_method_call (GDBusConnection * connection,
179 const gchar * sender,
180 const gchar * path,
181 const gchar * interface,
182 const gchar * method,
183 GVariant * params,
184 GDBusMethodInvocation * invocation,
185 gpointer user_data);
186static void on_bus_acquired (GDBusConnection * connection,
187 const gchar * name,
188 gpointer user_data);
189static void on_name_acquired (GDBusConnection * connection,
190 const gchar * name,
191 gpointer user_data);
192static void on_name_lost (GDBusConnection * connection,
193 const gchar * name,
194 gpointer user_data);
195static void dbg_bus_method_call (GDBusConnection * connection,
196 const gchar * sender,
197 const gchar * path,
198 const gchar * interface,
199 const gchar * method,
200 GVariant * params,
201 GDBusMethodInvocation * invocation,
202 gpointer user_data);
203static void dbg_bus_get_cb (GObject * object,
204 GAsyncResult * res,
205 gpointer user_data);
205206
206/* Unique error codes for debug interface */207/* Unique error codes for debug interface */
207enum {208enum {
@@ -213,16 +214,21 @@
213/**********************214/**********************
214 DBus Interfaces215 DBus Interfaces
215 **********************/216 **********************/
216#include "application-menu-registrar-server.h"217static GDBusNodeInfo * node_info = NULL;
217#include "application-menu-renderer-server.h"218static GDBusInterfaceInfo * interface_info = NULL;
218219static GDBusInterfaceVTable interface_table = {
219enum {220 method_call: bus_method_call,
220 WINDOW_REGISTERED,221 get_property: NULL, /* No properties */
221 WINDOW_UNREGISTERED,222 set_property: NULL /* No properties */
222 LAST_SIGNAL223};
223};224
224225static GDBusNodeInfo * dbg_node_info = NULL;
225static guint signals[LAST_SIGNAL] = { 0 };226static GDBusInterfaceInfo * dbg_interface_info = NULL;
227static GDBusInterfaceVTable dbg_interface_table = {
228 method_call: dbg_bus_method_call,
229 get_property: NULL, /* No properties */
230 set_property: NULL /* No properties */
231};
226232
227G_DEFINE_TYPE (IndicatorAppmenu, indicator_appmenu, INDICATOR_OBJECT_TYPE);233G_DEFINE_TYPE (IndicatorAppmenu, indicator_appmenu, INDICATOR_OBJECT_TYPE);
228234
@@ -241,22 +247,24 @@
241 ioclass->get_location = get_location;247 ioclass->get_location = get_location;
242 ioclass->entry_activate = entry_activate;248 ioclass->entry_activate = entry_activate;
243249
244 signals[WINDOW_REGISTERED] = g_signal_new("window-registered",250 /* Setting up the DBus interfaces */
245 G_TYPE_FROM_CLASS(klass),251 if (node_info == NULL) {
246 G_SIGNAL_RUN_LAST,252 GError * error = NULL;
247 G_STRUCT_OFFSET (IndicatorAppmenuClass, window_registered),253
248 NULL, NULL,254 node_info = g_dbus_node_info_new_for_xml(_application_menu_registrar, &error);
249 _indicator_appmenu_marshal_VOID__UINT_STRING_BOXED,255 if (error != NULL) {
250 G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH);256 g_error("Unable to parse Application Menu Interface description: %s", error->message);
251 signals[WINDOW_UNREGISTERED] = g_signal_new("window-unregistered",257 g_error_free(error);
252 G_TYPE_FROM_CLASS(klass),258 }
253 G_SIGNAL_RUN_LAST,259 }
254 G_STRUCT_OFFSET (IndicatorAppmenuClass, window_unregistered),260
255 NULL, NULL,261 if (interface_info == NULL) {
256 _indicator_appmenu_marshal_VOID__UINT,262 interface_info = g_dbus_node_info_lookup_interface(node_info, REG_IFACE);
257 G_TYPE_NONE, 1, G_TYPE_UINT);263
258264 if (interface_info == NULL) {
259 dbus_g_object_type_install_info(INDICATOR_APPMENU_TYPE, &dbus_glib__application_menu_registrar_server_object_info);265 g_error("Unable to find interface '" REG_IFACE "'");
266 }
267 }
260268
261 return;269 return;
262}270}
@@ -273,6 +281,9 @@
273 self->active_stubs = STUBS_UNKNOWN;281 self->active_stubs = STUBS_UNKNOWN;
274 self->close_item = NULL;282 self->close_item = NULL;
275 self->retry_registration = 0;283 self->retry_registration = 0;
284 self->bus = NULL;
285 self->owner_id = 0;
286 self->dbus_registration = 0;
276287
277 /* Setup the entries for the fallbacks */288 /* Setup the entries for the fallbacks */
278 self->window_menus = g_array_sized_new(FALSE, FALSE, sizeof(IndicatorObjectEntry), 2);289 self->window_menus = g_array_sized_new(FALSE, FALSE, sizeof(IndicatorObjectEntry), 2);
@@ -299,38 +310,8 @@
299310
300 find_desktop_windows(self);311 find_desktop_windows(self);
301312
302 /* Register this object on DBus */313 /* Request a name so others can find us */
303 gboolean sent_registration = FALSE;314 retry_registration(self);
304 GError * error = NULL;
305 DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
306 if (connection != NULL && error == NULL) {
307 dbus_g_connection_register_g_object(connection,
308 REG_OBJECT,
309 G_OBJECT(self));
310
311 /* Request a name so others can find us */
312 DBusGProxy * dbus_proxy = dbus_g_proxy_new_for_name_owner(connection,
313 DBUS_SERVICE_DBUS,
314 DBUS_PATH_DBUS,
315 DBUS_INTERFACE_DBUS,
316 NULL);
317 if (dbus_proxy != NULL) {
318 org_freedesktop_DBus_request_name_async (dbus_proxy,
319 DBUS_NAME,
320 DBUS_NAME_FLAG_DO_NOT_QUEUE,
321 request_name_cb,
322 self);
323 sent_registration = TRUE;
324 } else {
325 g_warning("Unable to get proxy to DBus daemon");
326 }
327 } else {
328 g_warning("Unable to connect to session bus");
329 }
330
331 if (!sent_registration) {
332 self->retry_registration = g_timeout_add_seconds(1, retry_registration, self);
333 }
334315
335 /* Setup debug interface */316 /* Setup debug interface */
336 self->debug = g_object_new(INDICATOR_APPMENU_DEBUG_TYPE, NULL);317 self->debug = g_object_new(INDICATOR_APPMENU_DEBUG_TYPE, NULL);
@@ -339,6 +320,82 @@
339 return;320 return;
340}321}
341322
323/* If we weren't able to register on the bus, then we need
324 to try it all again. */
325static gboolean
326retry_registration (gpointer user_data)
327{
328 g_return_val_if_fail(IS_INDICATOR_APPMENU(user_data), FALSE);
329 IndicatorAppmenu * iapp = INDICATOR_APPMENU(user_data);
330
331 iapp->owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
332 DBUS_NAME,
333 G_BUS_NAME_OWNER_FLAGS_NONE,
334 iapp->dbus_registration == 0 ? on_bus_acquired : NULL,
335 on_name_acquired,
336 on_name_lost,
337 g_object_ref(iapp),
338 g_object_unref);
339
340 return TRUE;
341}
342
343static void
344on_bus_acquired (GDBusConnection * connection, const gchar * name,
345 gpointer user_data)
346{
347 IndicatorAppmenu * iapp = INDICATOR_APPMENU(user_data);
348 GError * error = NULL;
349
350 iapp->bus = connection;
351
352 /* Now register our object on our new connection */
353 iapp->dbus_registration = g_dbus_connection_register_object(connection,
354 REG_OBJECT,
355 interface_info,
356 &interface_table,
357 user_data,
358 NULL,
359 &error);
360
361 if (error != NULL) {
362 g_error("Unable to register the object to DBus: %s", error->message);
363 g_error_free(error);
364 g_bus_unown_name(iapp->owner_id);
365 iapp->owner_id = 0;
366 iapp->retry_registration = g_timeout_add_seconds(1, retry_registration, iapp);
367 return;
368 }
369
370 return;
371}
372
373static void
374on_name_acquired (GDBusConnection * connection, const gchar * name,
375 gpointer user_data)
376{
377}
378
379static void
380on_name_lost (GDBusConnection * connection, const gchar * name,
381 gpointer user_data)
382{
383 IndicatorAppmenu * iapp = INDICATOR_APPMENU(user_data);
384
385 if (connection == NULL) {
386 g_error("OMG! Unable to get a connection to DBus");
387 }
388 else {
389 g_error("Unable to claim the name %s", DBUS_NAME);
390 }
391
392 /* We can rest assured no one will register with us, but let's
393 just ensure we're not showing anything. */
394 switch_default_app(iapp, NULL, NULL);
395
396 iapp->owner_id = 0;
397}
398
342/* Object refs decrement */399/* Object refs decrement */
343static void400static void
344indicator_appmenu_dispose (GObject *object)401indicator_appmenu_dispose (GObject *object)
@@ -351,6 +408,22 @@
351 iapp->retry_registration = 0;408 iapp->retry_registration = 0;
352 }409 }
353410
411 if (iapp->dbus_registration != 0) {
412 g_dbus_connection_unregister_object(iapp->bus, iapp->dbus_registration);
413 /* Don't care if it fails, there's nothing we can do */
414 iapp->dbus_registration = 0;
415 }
416
417 if (iapp->bus != NULL) {
418 g_object_unref(iapp->bus);
419 iapp->bus = NULL;
420 }
421
422 if (iapp->owner_id != 0) {
423 g_bus_unown_name(iapp->owner_id);
424 iapp->owner_id = 0;
425 }
426
354 /* bring down the matcher before resetting to no menu so we don't427 /* bring down the matcher before resetting to no menu so we don't
355 get match signals */428 get match signals */
356 if (iapp->matcher != NULL) {429 if (iapp->matcher != NULL) {
@@ -411,7 +484,28 @@
411static void484static void
412indicator_appmenu_debug_class_init (IndicatorAppmenuDebugClass *klass)485indicator_appmenu_debug_class_init (IndicatorAppmenuDebugClass *klass)
413{486{
414 dbus_g_object_type_install_info(INDICATOR_APPMENU_DEBUG_TYPE, &dbus_glib__application_menu_renderer_server_object_info);487 GObjectClass *object_class = G_OBJECT_CLASS (klass);
488
489 object_class->dispose = indicator_appmenu_debug_dispose;
490
491 /* Setting up the DBus interfaces */
492 if (dbg_node_info == NULL) {
493 GError * error = NULL;
494
495 dbg_node_info = g_dbus_node_info_new_for_xml(_application_menu_renderer, &error);
496 if (error != NULL) {
497 g_error("Unable to parse Application Menu Renderer Interface description: %s", error->message);
498 g_error_free(error);
499 }
500 }
501
502 if (dbg_interface_info == NULL) {
503 dbg_interface_info = g_dbus_node_info_lookup_interface(dbg_node_info, DEBUG_IFACE);
504
505 if (dbg_interface_info == NULL) {
506 g_error("Unable to find interface '" DEBUG_IFACE "'");
507 }
508 }
415509
416 return;510 return;
417}511}
@@ -421,52 +515,107 @@
421indicator_appmenu_debug_init (IndicatorAppmenuDebug *self)515indicator_appmenu_debug_init (IndicatorAppmenuDebug *self)
422{516{
423 self->appmenu = NULL;517 self->appmenu = NULL;
518 self->bus_cancel = NULL;
519 self->bus = NULL;
520 self->dbus_registration = 0;
424521
425 /* Register this object on DBus */522 /* Register this object on DBus */
426 DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);523 self->bus_cancel = g_cancellable_new();
427 dbus_g_connection_register_g_object(connection,524 g_bus_get(G_BUS_TYPE_SESSION,
428 DEBUG_OBJECT,525 self->bus_cancel,
429 G_OBJECT(self));526 dbg_bus_get_cb,
430527 self);
431 return;528
432}529 return;
433530}
434/* If we weren't able to register on the bus, then we need531
435 to try it all again. */532static void
436static gboolean533dbg_bus_get_cb (GObject * object, GAsyncResult * res, gpointer user_data)
437retry_registration (gpointer user_data)534{
438{535 GError * error = NULL;
439 g_return_val_if_fail(IS_INDICATOR_APPMENU(user_data), FALSE);536 GDBusConnection * connection = g_bus_get_finish(res, &error);
440 IndicatorAppmenu * iapp = INDICATOR_APPMENU(user_data);537
441538 if (error != NULL) {
442 DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);539 g_error("OMG! Unable to get a connection to DBus: %s", error->message);
443 if (connection != NULL) {540 g_error_free(error);
444 dbus_g_connection_register_g_object(connection,541 return;
445 REG_OBJECT,542 }
446 G_OBJECT(iapp));543
447544 IndicatorAppmenuDebug * iappd = (IndicatorAppmenuDebug *)user_data;
448 /* Request a name so others can find us */545
449 DBusGProxy * dbus_proxy = dbus_g_proxy_new_for_name_owner(connection,546 g_warn_if_fail(iappd->bus == NULL);
450 DBUS_SERVICE_DBUS,547 iappd->bus = connection;
451 DBUS_PATH_DBUS,548
452 DBUS_INTERFACE_DBUS,549 if (iappd->bus_cancel != NULL) {
453 NULL);550 g_object_unref(iappd->bus_cancel);
454 if (dbus_proxy != NULL) {551 iappd->bus_cancel = NULL;
455 org_freedesktop_DBus_request_name_async (dbus_proxy,552 }
456 DBUS_NAME,553
457 DBUS_NAME_FLAG_DO_NOT_QUEUE,554 /* Now register our object on our new connection */
458 request_name_cb,555 iappd->dbus_registration = g_dbus_connection_register_object(iappd->bus,
459 iapp);556 DEBUG_OBJECT,
460 iapp->retry_registration = 0;557 dbg_interface_info,
461 return FALSE;558 &dbg_interface_table,
462 } else {559 user_data,
463 g_warning("Unable to get proxy to DBus daemon");560 NULL,
464 }561 &error);
465 } else {562
466 g_warning("Unable to connect to session bus");563 if (error != NULL) {
467 }564 g_error("Unable to register the object to DBus: %s", error->message);
468565 g_error_free(error);
469 return TRUE;566 return;
567 }
568
569 return;
570}
571
572/* Object refs decrement */
573static void
574indicator_appmenu_debug_dispose (GObject *object)
575{
576 IndicatorAppmenuDebug * iappd = INDICATOR_APPMENU_DEBUG(object);
577
578 if (iappd->dbus_registration != 0) {
579 g_dbus_connection_unregister_object(iappd->bus, iappd->dbus_registration);
580 /* Don't care if it fails, there's nothing we can do */
581 iappd->dbus_registration = 0;
582 }
583
584 if (iappd->bus != NULL) {
585 g_object_unref(iappd->bus);
586 iappd->bus = NULL;
587 }
588
589 if (iappd->bus_cancel != NULL) {
590 g_cancellable_cancel(iappd->bus_cancel);
591 g_object_unref(iappd->bus_cancel);
592 iappd->bus_cancel = NULL;
593 }
594
595 G_OBJECT_CLASS (indicator_appmenu_debug_parent_class)->dispose (object);
596 return;
597}
598
599static void
600emit_signal (IndicatorAppmenu * iapp, const gchar * name, GVariant * variant)
601{
602 GError * error = NULL;
603
604 g_dbus_connection_emit_signal (iapp->bus,
605 NULL,
606 REG_OBJECT,
607 REG_IFACE,
608 name,
609 variant,
610 &error);
611
612 if (error != NULL) {
613 g_error("Unable to send %s signal: %s", name, error->message);
614 g_error_free(error);
615 return;
616 }
617
618 return;
470}619}
471620
472/* Close the current application using magic */621/* Close the current application using magic */
@@ -895,7 +1044,7 @@
895 gtk_widget_hide(GTK_WIDGET(entry->label));1044 gtk_widget_hide(GTK_WIDGET(entry->label));
896 }1045 }
8971046
898 if (entry->menu != NULL) {1047 if (entry->menu != NULL && gtk_menu_get_attach_widget(entry->menu) != NULL) {
899 gtk_menu_detach(entry->menu);1048 gtk_menu_detach(entry->menu);
900 }1049 }
9011050
@@ -1064,10 +1213,10 @@
1064}1213}
10651214
1066/* A new window wishes to register it's windows with us */1215/* A new window wishes to register it's windows with us */
1067static gboolean1216static GVariant *
1068_application_menu_registrar_server_register_window (IndicatorAppmenu * iapp, guint windowid, const gchar * objectpath, DBusGMethodInvocation * method)1217register_window (IndicatorAppmenu * iapp, guint windowid, const gchar * objectpath,
1218 const gchar * sender)
1069{1219{
1070 const gchar * sender = dbus_g_method_get_sender(method);
1071 g_debug("Registering window ID %d with path %s from %s", windowid, objectpath, sender);1220 g_debug("Registering window ID %d with path %s from %s", windowid, objectpath, sender);
10721221
1073 if (g_hash_table_lookup(iapp->apps, GUINT_TO_POINTER(windowid)) == NULL && windowid != 0) {1222 if (g_hash_table_lookup(iapp->apps, GUINT_TO_POINTER(windowid)) == NULL && windowid != 0) {
@@ -1078,7 +1227,8 @@
10781227
1079 g_hash_table_insert(iapp->apps, GUINT_TO_POINTER(windowid), wm);1228 g_hash_table_insert(iapp->apps, GUINT_TO_POINTER(windowid), wm);
10801229
1081 g_signal_emit(G_OBJECT(iapp), signals[WINDOW_REGISTERED], 0, windowid, sender, objectpath, TRUE);1230 emit_signal(iapp, "WindowRegistered",
1231 g_variant_new("(uso)", windowid, sender, objectpath));
10821232
1083 gpointer pdesktop = g_hash_table_lookup(iapp->desktop_windows, GUINT_TO_POINTER(windowid));1233 gpointer pdesktop = g_hash_table_lookup(iapp->desktop_windows, GUINT_TO_POINTER(windowid));
1084 if (pdesktop != NULL) {1234 if (pdesktop != NULL) {
@@ -1097,22 +1247,21 @@
1097 }1247 }
1098 }1248 }
10991249
1100 dbus_g_method_return(method);1250 return g_variant_new("()");
1101 return TRUE;
1102}1251}
11031252
1104/* Kindly remove an entry from our DB */1253/* Kindly remove an entry from our DB */
1105static gboolean1254static GVariant *
1106_application_menu_registrar_server_unregister_window (IndicatorAppmenu * iapp, guint windowid, GError ** error)1255unregister_window (IndicatorAppmenu * iapp, guint windowid)
1107{1256{
1108 /* TODO: Do it */1257 /* TODO: Do it */
11091258
1110 return FALSE;1259 return g_variant_new("()");
1111}1260}
11121261
1113/* Grab the menu information for a specific window */1262/* Grab the menu information for a specific window */
1114static gboolean1263static GVariant *
1115_application_menu_registrar_server_get_menu_for_window (IndicatorAppmenu * iapp, guint windowid, gchar ** objectpath, gchar ** address, GError ** error)1264get_menu_for_window (IndicatorAppmenu * iapp, guint windowid, GError ** error)
1116{1265{
1117 WindowMenus * wm = NULL;1266 WindowMenus * wm = NULL;
11181267
@@ -1124,81 +1273,77 @@
11241273
1125 if (wm == NULL) {1274 if (wm == NULL) {
1126 g_set_error_literal(error, error_quark(), ERROR_WINDOW_NOT_FOUND, "Window not found");1275 g_set_error_literal(error, error_quark(), ERROR_WINDOW_NOT_FOUND, "Window not found");
1127 return FALSE;1276 return NULL;
1128 }1277 }
11291278
1130 *objectpath = window_menus_get_path(wm);1279 return g_variant_new("(so)", window_menus_get_address(wm),
1131 *address = window_menus_get_address(wm);1280 window_menus_get_path(wm));
1132
1133 return TRUE;
1134}1281}
11351282
1136/* Get all the menus we have */1283/* Get all the menus we have */
1137static gboolean1284static GVariant *
1138_application_menu_registrar_server_get_menus (IndicatorAppmenu * iapp, GPtrArray ** entries, GError ** error)1285get_menus (IndicatorAppmenu * iapp, GError ** error)
1139{1286{
1140 if (iapp->apps == NULL) {1287 if (iapp->apps == NULL) {
1141 g_set_error_literal(error, error_quark(), ERROR_NO_APPLICATIONS, "No applications are registered");1288 g_set_error_literal(error, error_quark(), ERROR_NO_APPLICATIONS, "No applications are registered");
1142 return FALSE;1289 return NULL;
1143 }1290 }
11441291
1145 *entries = g_ptr_array_new();1292 GVariantBuilder * builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
1146
1147 GList * appkeys = NULL;1293 GList * appkeys = NULL;
1148 for (appkeys = g_hash_table_get_keys(iapp->apps); appkeys != NULL; appkeys = g_list_next(appkeys)) {1294 for (appkeys = g_hash_table_get_keys(iapp->apps); appkeys != NULL; appkeys = g_list_next(appkeys)) {
1149 GValueArray * structval = g_value_array_new(3);
1150 gpointer hash_val = g_hash_table_lookup(iapp->apps, appkeys->data);1295 gpointer hash_val = g_hash_table_lookup(iapp->apps, appkeys->data);
11511296
1152 if (hash_val == NULL) { continue; }1297 if (hash_val == NULL) { continue; }
11531298
1154 GValue winid = {0};1299 g_variant_builder_add (builder, "(uso)",
1155 g_value_init(&winid, G_TYPE_UINT);1300 window_menus_get_xid(WINDOW_MENUS(hash_val)),
1156 g_value_set_uint(&winid, window_menus_get_xid(WINDOW_MENUS(hash_val)));1301 window_menus_get_path(WINDOW_MENUS(hash_val)),
1157 g_value_array_append(structval, &winid);1302 window_menus_get_address(WINDOW_MENUS(hash_val)));
1158 g_value_unset(&winid);
1159
1160 GValue path = {0};
1161 g_value_init(&path, DBUS_TYPE_G_OBJECT_PATH);
1162 g_value_take_boxed(&path, window_menus_get_path(WINDOW_MENUS(hash_val)));
1163 g_value_array_append(structval, &path);
1164 g_value_unset(&path);
1165
1166 GValue address = {0};
1167 g_value_init(&address, G_TYPE_STRING);
1168 g_value_take_string(&address, window_menus_get_address(WINDOW_MENUS(hash_val)));
1169 g_value_array_append(structval, &address);
1170 g_value_unset(&address);
1171
1172 g_ptr_array_add(*entries, structval);
1173 }1303 }
11741304
1175 return TRUE;1305 return g_variant_new("(a(uso))", builder);
1176}1306}
11771307
1178/* Response to whether we got our name or not */1308/* A method has been called from our dbus inteface. Figure out what it
1309 is and dispatch it. */
1179static void1310static void
1180request_name_cb (DBusGProxy *proxy, guint result, GError * inerror, gpointer userdata)1311bus_method_call (GDBusConnection * connection, const gchar * sender,
1312 const gchar * path, const gchar * interface,
1313 const gchar * method, GVariant * params,
1314 GDBusMethodInvocation * invocation, gpointer user_data)
1181{1315{
1182 gboolean error = FALSE;1316 IndicatorAppmenu * iapp = INDICATOR_APPMENU(user_data);
11831317 GVariant * retval = NULL;
1184 if (inerror != NULL) {1318 GError * error = NULL;
1185 g_warning("Unable to get name request: %s", inerror->message);1319
1186 error = TRUE;1320 if (g_strcmp0(method, "RegisterWindow") == 0) {
1187 }1321 guint32 xid;
11881322 const gchar * path;
1189 if (!error && result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER && result != DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER) {1323 g_variant_get(params, "(u&o)", &xid, &path);
1190 g_warning("The dbus name we want is already taken");1324 retval = register_window(iapp, xid, path, sender);
1191 error = TRUE;1325 } else if (g_strcmp0(method, "UnregisterWindow") == 0) {
1192 }1326 guint32 xid;
11931327 g_variant_get(params, "(u)", &xid);
1194 if (error) {1328 retval = unregister_window(iapp, xid);
1195 /* We can rest assured no one will register with us, but let's1329 } else if (g_strcmp0(method, "GetMenuForWindow") == 0) {
1196 just ensure we're not showing anything. */1330 guint32 xid;
1197 switch_default_app(INDICATOR_APPMENU(userdata), NULL, NULL);1331 g_variant_get(params, "(u)", &xid);
1198 }1332 retval = get_menu_for_window(iapp, xid, &error);
11991333 } else if (g_strcmp0(method, "GetMenus") == 0) {
1200 g_object_unref(proxy);1334 retval = get_menus(iapp, &error);
12011335 } else {
1336 g_warning("Calling method '%s' on the indicator service and it's unknown", method);
1337 }
1338
1339 if (error != NULL) {
1340 g_dbus_method_invocation_return_dbus_error(invocation,
1341 "org.ayatana.AppMenu.Error",
1342 error->message);
1343 g_error_free(error);
1344 } else {
1345 g_dbus_method_invocation_return_value(invocation, retval);
1346 }
1202 return;1347 return;
1203}1348}
12041349
@@ -1453,44 +1598,36 @@
1453}1598}
14541599
1455/* Grab the location of the dbusmenu of the current menu */1600/* Grab the location of the dbusmenu of the current menu */
1456static gboolean1601static GVariant *
1457_application_menu_renderer_server_get_current_menu (IndicatorAppmenuDebug * iappd, gchar ** objectpath, gchar ** address, GError ** error)1602get_current_menu (IndicatorAppmenuDebug * iappd, GError ** error)
1458{1603{
1459 IndicatorAppmenu * iapp = iappd->appmenu;1604 IndicatorAppmenu * iapp = iappd->appmenu;
14601605
1461 if (iapp->default_app == NULL) {1606 if (iapp->default_app == NULL) {
1462 g_set_error_literal(error, error_quark(), ERROR_NO_DEFAULT_APP, "Not currently showing an application");1607 g_set_error_literal(error, error_quark(), ERROR_NO_DEFAULT_APP, "Not currently showing an application");
1463 return FALSE;1608 return NULL;
1464 }1609 }
14651610
1466 *objectpath = window_menus_get_path(iapp->default_app);1611 return g_variant_new("(so)", window_menus_get_address(iapp->default_app),
1467 *address = window_menus_get_address(iapp->default_app);1612 window_menus_get_path(iapp->default_app));
1468
1469 return TRUE;
1470}1613}
14711614
1472/* Activate menu items through a script given as a parameter */1615/* Activate menu items through a script given as a parameter */
1473static gboolean1616static GVariant *
1474_application_menu_renderer_server_activate_menu_item (IndicatorAppmenuDebug * iappd, GArray * menulist, GError ** error)1617activate_menu_item (IndicatorAppmenuDebug * iappd, GVariantIter * iter, GError ** error)
1475{1618{
1476 /* TODO: Do it */1619 /* TODO: Do it */
14771620
1478 return FALSE;1621 return g_variant_new("()");
1479}
1480
1481/* Dump the current menu to a JSON file */
1482static gboolean
1483_application_menu_renderer_server_dump_current_menu (IndicatorAppmenuDebug * iappd, gchar ** jsondata, GError ** error)
1484{
1485 return _application_menu_renderer_server_dump_menu(iappd, 0, jsondata, error);
1486}1622}
14871623
1488/* Dump a specific window's menus to a JSON file */1624/* Dump a specific window's menus to a JSON file */
1489static gboolean1625static GVariant *
1490_application_menu_renderer_server_dump_menu (IndicatorAppmenuDebug * iappd, guint windowid, gchar ** jsondata, GError ** error)1626dump_menu (IndicatorAppmenuDebug * iappd, guint windowid, GError ** error)
1491{1627{
1492 IndicatorAppmenu * iapp = iappd->appmenu;1628 IndicatorAppmenu * iapp = iappd->appmenu;
1493 WindowMenus * wm = NULL;1629 WindowMenus * wm = NULL;
1630 gchar * jsondata = NULL;
14941631
1495 if (windowid == 0) {1632 if (windowid == 0) {
1496 wm = iapp->default_app;1633 wm = iapp->default_app;
@@ -1500,7 +1637,7 @@
15001637
1501 if (wm == NULL) {1638 if (wm == NULL) {
1502 g_set_error_literal(error, error_quark(), ERROR_WINDOW_NOT_FOUND, "Window not found");1639 g_set_error_literal(error, error_quark(), ERROR_WINDOW_NOT_FOUND, "Window not found");
1503 return FALSE;1640 return NULL;
1504 }1641 }
15051642
1506 GArray * strings = g_array_new(TRUE, FALSE, sizeof(gchar *));1643 GArray * strings = g_array_new(TRUE, FALSE, sizeof(gchar *));
@@ -1548,10 +1685,59 @@
1548 temp = g_strdup("}");1685 temp = g_strdup("}");
1549 g_array_append_val(strings, temp);1686 g_array_append_val(strings, temp);
15501687
1551 *jsondata = g_strjoinv(NULL, (gchar **)strings->data);1688 jsondata = g_strjoinv(NULL, (gchar **)strings->data);
1552 g_strfreev((gchar **)strings->data);1689 g_strfreev((gchar **)strings->data);
1553 g_array_free(strings, FALSE);1690 g_array_free(strings, FALSE);
15541691
1555 return TRUE;1692 GVariant * rv = g_variant_new("(s)", jsondata);
1693 g_free(jsondata);
1694 return rv;
1695}
1696
1697/* Dump the current menu to a JSON file */
1698static GVariant *
1699dump_current_menu (IndicatorAppmenuDebug * iappd, GError ** error)
1700{
1701 return dump_menu(iappd, 0, error);
1702}
1703
1704/* A method has been called from our dbus inteface. Figure out what it
1705 is and dispatch it. */
1706static void
1707dbg_bus_method_call (GDBusConnection * connection, const gchar * sender,
1708 const gchar * path, const gchar * interface,
1709 const gchar * method, GVariant * params,
1710 GDBusMethodInvocation * invocation, gpointer user_data)
1711{
1712 IndicatorAppmenuDebug * iappd = INDICATOR_APPMENU_DEBUG(user_data);
1713 GVariant * retval = NULL;
1714 GError * error = NULL;
1715
1716 if (g_strcmp0(method, "GetCurrentMenu") == 0) {
1717 retval = get_current_menu(iappd, &error);
1718 } else if (g_strcmp0(method, "ActivateMenuItem") == 0) {
1719 GVariantIter *iter;
1720 g_variant_get(params, "(ai)", &iter);
1721 retval = activate_menu_item(iappd, iter, &error);
1722 g_variant_iter_free(iter);
1723 } else if (g_strcmp0(method, "DumpCurrentMenu") == 0) {
1724 retval = dump_current_menu(iappd, &error);
1725 } else if (g_strcmp0(method, "DumpMenu") == 0) {
1726 guint32 xid;
1727 g_variant_get(params, "(u)", &xid);
1728 retval = dump_menu(iappd, xid, &error);
1729 } else {
1730 g_warning("Calling method '%s' on the indicator service and it's unknown", method);
1731 }
1732
1733 if (error != NULL) {
1734 g_dbus_method_invocation_return_dbus_error(invocation,
1735 "org.ayatana.AppMenu.Error",
1736 error->message);
1737 g_error_free(error);
1738 } else {
1739 g_dbus_method_invocation_return_value(invocation, retval);
1740 }
1741 return;
1556}1742}
15571743
15581744
=== modified file 'src/window-menus.c'
--- src/window-menus.c 2010-12-10 22:28:31 +0000
+++ src/window-menus.c 2011-01-13 04:42:14 +0000
@@ -24,8 +24,8 @@
24#endif24#endif
2525
26#include <libdbusmenu-gtk/menu.h>26#include <libdbusmenu-gtk/menu.h>
27#include <dbus/dbus-glib.h>
28#include <glib.h>27#include <glib.h>
28#include <gio/gio.h>
2929
30#include "window-menus.h"30#include "window-menus.h"
31#include "indicator-appmenu-marshal.h"31#include "indicator-appmenu-marshal.h"
@@ -37,13 +37,14 @@
37 guint windowid;37 guint windowid;
38 DbusmenuGtkClient * client;38 DbusmenuGtkClient * client;
39 DbusmenuMenuitem * root;39 DbusmenuMenuitem * root;
40 DBusGProxy * props;40 GCancellable * props_cancel;
41 GDBusProxy * props;
41 GArray * entries;42 GArray * entries;
42 gboolean error_state;43 gboolean error_state;
43 guint retry_timer;44 guint retry_timer;
44 gint retry_id;45 gint retry_id;
45 gchar * retry_name;46 gchar * retry_name;
46 GValue retry_data;47 GVariant * retry_data;
47 guint retry_timestamp;48 guint retry_timestamp;
48};49};
4950
@@ -77,12 +78,13 @@
77static void window_menus_init (WindowMenus *self);78static void window_menus_init (WindowMenus *self);
78static void window_menus_dispose (GObject *object);79static void window_menus_dispose (GObject *object);
79static void window_menus_finalize (GObject *object);80static void window_menus_finalize (GObject *object);
80static void properties_destroyed (GObject * object, gpointer user_data);81static void name_owner_changed (GObject * gobject, GParamSpec * pspec, gpointer user_data);
81static void root_changed (DbusmenuClient * client, DbusmenuMenuitem * new_root, gpointer user_data);82static void root_changed (DbusmenuClient * client, DbusmenuMenuitem * new_root, gpointer user_data);
82static void menu_entry_added (DbusmenuMenuitem * root, DbusmenuMenuitem * newentry, guint position, gpointer user_data);83static void menu_entry_added (DbusmenuMenuitem * root, DbusmenuMenuitem * newentry, guint position, gpointer user_data);
83static void menu_entry_removed (DbusmenuMenuitem * root, DbusmenuMenuitem * oldentry, gpointer user_data);84static void menu_entry_removed (DbusmenuMenuitem * root, DbusmenuMenuitem * oldentry, gpointer user_data);
84static void menu_entry_realized (DbusmenuMenuitem * newentry, gpointer user_data);85static void menu_entry_realized (DbusmenuMenuitem * newentry, gpointer user_data);
85static void menu_child_realized (DbusmenuMenuitem * child, gpointer user_data);86static void menu_child_realized (DbusmenuMenuitem * child, gpointer user_data);
87static void props_cb (GObject * object, GAsyncResult * res, gpointer user_data);
8688
87G_DEFINE_TYPE (WindowMenus, window_menus, G_TYPE_OBJECT);89G_DEFINE_TYPE (WindowMenus, window_menus, G_TYPE_OBJECT);
8890
@@ -144,6 +146,7 @@
144 WindowMenusPrivate * priv = WINDOW_MENUS_GET_PRIVATE(self);146 WindowMenusPrivate * priv = WINDOW_MENUS_GET_PRIVATE(self);
145147
146 priv->client = NULL;148 priv->client = NULL;
149 priv->props_cancel = NULL;
147 priv->props = NULL;150 priv->props = NULL;
148 priv->root = NULL;151 priv->root = NULL;
149 priv->error_state = FALSE;152 priv->error_state = FALSE;
@@ -176,11 +179,17 @@
176 priv->props = NULL;179 priv->props = NULL;
177 }180 }
178181
182 if (priv->props_cancel != NULL) {
183 g_cancellable_cancel(priv->props_cancel);
184 g_object_unref(priv->props_cancel);
185 priv->props_cancel = NULL;
186 }
187
179 if (priv->retry_timer != 0) {188 if (priv->retry_timer != 0) {
180 g_source_remove(priv->retry_timer);189 g_source_remove(priv->retry_timer);
181 priv->retry_timer = 0;190 priv->retry_timer = 0;
182 g_value_unset(&priv->retry_data);191 g_variant_unref(priv->retry_data);
183 g_value_reset(&priv->retry_data);192 priv->retry_data = NULL;
184 g_free(priv->retry_name);193 g_free(priv->retry_name);
185 priv->retry_name = NULL;194 priv->retry_name = NULL;
186 }195 }
@@ -227,11 +236,11 @@
227 g_return_val_if_fail(IS_WINDOW_MENUS(user_data), FALSE);236 g_return_val_if_fail(IS_WINDOW_MENUS(user_data), FALSE);
228 WindowMenusPrivate * priv = WINDOW_MENUS_GET_PRIVATE(user_data);237 WindowMenusPrivate * priv = WINDOW_MENUS_GET_PRIVATE(user_data);
229238
230 dbusmenu_client_send_event(DBUSMENU_CLIENT(priv->client), priv->retry_id, priv->retry_name, &priv->retry_data, priv->retry_timestamp);239 dbusmenu_client_send_event(DBUSMENU_CLIENT(priv->client), priv->retry_id, priv->retry_name, priv->retry_data, priv->retry_timestamp);
231240
232 priv->retry_timer = 0;241 priv->retry_timer = 0;
233 g_value_unset(&priv->retry_data);242 g_variant_unref(priv->retry_data);
234 g_value_reset(&priv->retry_data);243 priv->retry_data = NULL;
235 g_free(priv->retry_name);244 g_free(priv->retry_name);
236 priv->retry_name = NULL;245 priv->retry_name = NULL;
237246
@@ -240,7 +249,7 @@
240249
241/* Listen to whether our events are successfully sent */250/* Listen to whether our events are successfully sent */
242static void251static void
243event_status (DbusmenuClient * client, DbusmenuMenuitem * mi, gchar * event, GValue * evdata, guint timestamp, GError * error, gpointer user_data)252event_status (DbusmenuClient * client, DbusmenuMenuitem * mi, gchar * event, GVariant * evdata, guint timestamp, GError * error, gpointer user_data)
244{253{
245 g_return_if_fail(IS_WINDOW_MENUS(user_data));254 g_return_if_fail(IS_WINDOW_MENUS(user_data));
246 WindowMenusPrivate * priv = WINDOW_MENUS_GET_PRIVATE(user_data);255 WindowMenusPrivate * priv = WINDOW_MENUS_GET_PRIVATE(user_data);
@@ -266,8 +275,8 @@
266 if (priv->retry_timer != 0) {275 if (priv->retry_timer != 0) {
267 g_source_remove(priv->retry_timer);276 g_source_remove(priv->retry_timer);
268 priv->retry_timer = 0;277 priv->retry_timer = 0;
269 g_value_unset(&priv->retry_data);278 g_variant_unref(priv->retry_data);
270 g_value_reset(&priv->retry_data);279 priv->retry_data = NULL;
271 g_free(priv->retry_name);280 g_free(priv->retry_name);
272 priv->retry_name = NULL;281 priv->retry_name = NULL;
273 }282 }
@@ -297,8 +306,7 @@
297306
298 priv->retry_id = dbusmenu_menuitem_get_id(mi);307 priv->retry_id = dbusmenu_menuitem_get_id(mi);
299 priv->retry_name = g_strdup(event);308 priv->retry_name = g_strdup(event);
300 g_value_init(&priv->retry_data, G_VALUE_TYPE(evdata));309 priv->retry_data = g_variant_ref(evdata);
301 g_value_copy(evdata, &priv->retry_data);
302 priv->retry_timestamp = timestamp;310 priv->retry_timestamp = timestamp;
303 }311 }
304312
@@ -360,26 +368,22 @@
360 g_return_val_if_fail(dbus_addr != NULL, NULL);368 g_return_val_if_fail(dbus_addr != NULL, NULL);
361 g_return_val_if_fail(dbus_object != NULL, NULL);369 g_return_val_if_fail(dbus_object != NULL, NULL);
362370
363 DBusGConnection * session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
364 g_return_val_if_fail(session_bus != NULL, NULL);
365
366 WindowMenus * newmenu = WINDOW_MENUS(g_object_new(WINDOW_MENUS_TYPE, NULL));371 WindowMenus * newmenu = WINDOW_MENUS(g_object_new(WINDOW_MENUS_TYPE, NULL));
367 WindowMenusPrivate * priv = WINDOW_MENUS_GET_PRIVATE(newmenu);372 WindowMenusPrivate * priv = WINDOW_MENUS_GET_PRIVATE(newmenu);
368373
369 priv->windowid = windowid;374 priv->windowid = windowid;
370375
371 priv->props = dbus_g_proxy_new_for_name_owner(session_bus,376 /* Build the service proxy */
372 dbus_addr,377 priv->props_cancel = g_cancellable_new();
373 dbus_object,378 g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION,
374 DBUS_INTERFACE_PROPERTIES,379 G_DBUS_PROXY_FLAGS_NONE,
375 NULL);380 NULL,
376 if (priv->props == NULL) {381 dbus_addr,
377 g_warning("Unable to get property proxy on '%s' object '%s'", dbus_addr, dbus_object);382 dbus_object,
378 g_object_unref(newmenu);383 "org.freedesktop.DBus.Properties",
379 return NULL;384 priv->props_cancel,
380 }385 props_cb,
381386 newmenu);
382 g_signal_connect(G_OBJECT(priv->props), "destroy", G_CALLBACK(properties_destroyed), newmenu);
383387
384 priv->client = dbusmenu_gtkclient_new((gchar *)dbus_addr, (gchar *)dbus_object);388 priv->client = dbusmenu_gtkclient_new((gchar *)dbus_addr, (gchar *)dbus_object);
385 GtkAccelGroup * agroup = gtk_accel_group_new();389 GtkAccelGroup * agroup = gtk_accel_group_new();
@@ -397,17 +401,57 @@
397 return newmenu;401 return newmenu;
398}402}
399403
400/* Respond to the proxies getting destoryed. I means that we need404/* Callback from trying to create the proxy for the service, this
401 to kill ourselves. */405 could include starting the service. */
402static void406static void
403properties_destroyed (GObject * object, gpointer user_data)407props_cb (GObject * object, GAsyncResult * res, gpointer user_data)
408{
409 GError * error = NULL;
410
411 WindowMenus * self = WINDOW_MENUS(user_data);
412 g_return_if_fail(self != NULL);
413
414 WindowMenusPrivate * priv = WINDOW_MENUS_GET_PRIVATE(self);
415 GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
416
417 if (priv->props_cancel != NULL) {
418 g_object_unref(priv->props_cancel);
419 priv->props_cancel = NULL;
420 }
421
422 if (error != NULL) {
423 g_error("Could not grab DBus proxy for window %u: %s", priv->windowid, error->message);
424 g_error_free(error);
425 return;
426 }
427
428 /* Okay, we're good to grab the proxy at this point, we're
429 sure that it's ours. */
430 priv->props = proxy;
431
432 g_signal_connect(proxy, "notify::g-name-owner", G_CALLBACK(name_owner_changed), self);
433
434 return;
435}
436
437/* Gets called when the proxy changes owners, which is usually when it
438 drops off of the bus. */
439static void
440name_owner_changed (GObject * gobject, GParamSpec * pspec, gpointer user_data)
404{441{
405 WindowMenus * wm = WINDOW_MENUS(user_data);442 WindowMenus * wm = WINDOW_MENUS(user_data);
406 WindowMenusPrivate * priv = WINDOW_MENUS_GET_PRIVATE(wm);443 WindowMenusPrivate * priv = WINDOW_MENUS_GET_PRIVATE(wm);
407444 GDBusProxy * proxy = G_DBUS_PROXY(gobject);
408 priv->props = NULL;445
446 gchar * owner = g_dbus_proxy_get_name_owner(proxy);
447 if (owner != NULL) {
448 /* OK, carry on */
449 g_free (owner);
450 return;
451 }
452
453 /* We should die now */
409 g_debug("Properties destroyed for window: %d", priv->windowid);454 g_debug("Properties destroyed for window: %d", priv->windowid);
410
411 g_object_unref(G_OBJECT(wm));455 g_object_unref(G_OBJECT(wm));
412 return;456 return;
413}457}
@@ -554,13 +598,13 @@
554/* Respond to properties changing on the menu item so that we can598/* Respond to properties changing on the menu item so that we can
555 properly hide and show them. */599 properly hide and show them. */
556static void600static void
557menu_prop_changed (DbusmenuMenuitem * item, const gchar * property, const GValue * value, gpointer user_data)601menu_prop_changed (DbusmenuMenuitem * item, const gchar * property, GVariant * value, gpointer user_data)
558{602{
559 IndicatorObjectEntry * entry = (IndicatorObjectEntry *)user_data;603 IndicatorObjectEntry * entry = (IndicatorObjectEntry *)user_data;
560 WMEntry * wmentry = (WMEntry *)user_data;604 WMEntry * wmentry = (WMEntry *)user_data;
561605
562 if (!g_strcmp0(property, DBUSMENU_MENUITEM_PROP_VISIBLE)) {606 if (!g_strcmp0(property, DBUSMENU_MENUITEM_PROP_VISIBLE)) {
563 if (g_value_get_boolean(value)) {607 if (g_variant_get_boolean(value)) {
564 gtk_widget_show(GTK_WIDGET(entry->label));608 gtk_widget_show(GTK_WIDGET(entry->label));
565 wmentry->hidden = FALSE;609 wmentry->hidden = FALSE;
566 } else {610 } else {
@@ -568,10 +612,10 @@
568 wmentry->hidden = TRUE;612 wmentry->hidden = TRUE;
569 }613 }
570 } else if (!g_strcmp0(property, DBUSMENU_MENUITEM_PROP_ENABLED)) {614 } else if (!g_strcmp0(property, DBUSMENU_MENUITEM_PROP_ENABLED)) {
571 gtk_widget_set_sensitive(GTK_WIDGET(entry->label), g_value_get_boolean(value));615 gtk_widget_set_sensitive(GTK_WIDGET(entry->label), g_variant_get_boolean(value));
572 wmentry->disabled = !g_value_get_boolean(value);616 wmentry->disabled = !g_variant_get_boolean(value);
573 } else if (!g_strcmp0(property, DBUSMENU_MENUITEM_PROP_LABEL)) {617 } else if (!g_strcmp0(property, DBUSMENU_MENUITEM_PROP_LABEL)) {
574 gtk_label_set_text_with_mnemonic(entry->label, g_value_get_string(value));618 gtk_label_set_text_with_mnemonic(entry->label, g_variant_get_string(value, NULL));
575 }619 }
576620
577 return;621 return;
@@ -609,7 +653,7 @@
609653
610 g_signal_connect(G_OBJECT(newentry), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menu_prop_changed), entry);654 g_signal_connect(G_OBJECT(newentry), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menu_prop_changed), entry);
611655
612 if (dbusmenu_menuitem_property_get_value(newentry, DBUSMENU_MENUITEM_PROP_VISIBLE) != NULL656 if (dbusmenu_menuitem_property_get_variant(newentry, DBUSMENU_MENUITEM_PROP_VISIBLE) != NULL
613 && dbusmenu_menuitem_property_get_bool(newentry, DBUSMENU_MENUITEM_PROP_VISIBLE) == FALSE) {657 && dbusmenu_menuitem_property_get_bool(newentry, DBUSMENU_MENUITEM_PROP_VISIBLE) == FALSE) {
614 gtk_widget_hide(GTK_WIDGET(entry->label));658 gtk_widget_hide(GTK_WIDGET(entry->label));
615 wmentry->hidden = TRUE;659 wmentry->hidden = TRUE;
@@ -618,7 +662,7 @@
618 wmentry->hidden = FALSE;662 wmentry->hidden = FALSE;
619 }663 }
620664
621 if (dbusmenu_menuitem_property_get_value (newentry, DBUSMENU_MENUITEM_PROP_ENABLED) != NULL) {665 if (dbusmenu_menuitem_property_get_variant (newentry, DBUSMENU_MENUITEM_PROP_ENABLED) != NULL) {
622 gboolean sensitive = dbusmenu_menuitem_property_get_bool(newentry, DBUSMENU_MENUITEM_PROP_ENABLED);666 gboolean sensitive = dbusmenu_menuitem_property_get_bool(newentry, DBUSMENU_MENUITEM_PROP_ENABLED);
623 gtk_widget_set_sensitive(GTK_WIDGET(entry->label), sensitive);667 gtk_widget_set_sensitive(GTK_WIDGET(entry->label), sensitive);
624 wmentry->disabled = !sensitive;668 wmentry->disabled = !sensitive;
625669
=== modified file 'tools/mock-json-app.c'
--- tools/mock-json-app.c 2010-07-20 21:48:25 +0000
+++ tools/mock-json-app.c 2011-01-13 04:42:14 +0000
@@ -22,43 +22,49 @@
2222
23#include <gtk/gtk.h>23#include <gtk/gtk.h>
24#include <gdk/gdkx.h>24#include <gdk/gdkx.h>
25#include <dbus/dbus-glib.h>25#include <gio/gio.h>
26#include <libdbusmenu-glib/server.h>26#include <libdbusmenu-glib/server.h>
27#include <libdbusmenu-jsonloader/json-loader.h>27#include <libdbusmenu-jsonloader/json-loader.h>
2828
29#include "../src/dbus-shared.h"29#include "../src/dbus-shared.h"
30#include "../src/application-menu-registrar-client.h"
3130
32#define MENU_PATH "/mock/json/app/menu"31#define MENU_PATH "/mock/json/app/menu"
3332
34GtkWidget * window = NULL;33GtkWidget * window = NULL;
35DbusmenuServer * server = NULL;34DbusmenuServer * server = NULL;
36DBusGProxy * registrar = NULL;35GDBusProxy * registrar = NULL;
3736
38static void37static void
39register_cb (DBusGProxy *proxy, GError *error, gpointer userdata)38dbus_owner_change (GObject *gobject, GParamSpec *pspec, gpointer user_data)
40{39{
41 if (error != NULL) {40 GDBusProxy * proxy = G_DBUS_PROXY(gobject);
42 g_warning("Unable to register: %s", error->message);41
43 }42 gchar * owner = g_dbus_proxy_get_name_owner(proxy);
44 return;43
45}44 if (owner == NULL || owner[0] == '\0') {
46
47static void
48dbus_owner_change (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, gpointer data)
49{
50 if (new == NULL || new[0] == '\0') {
51 /* We only care about folks coming on the bus. Exit quickly otherwise. */45 /* We only care about folks coming on the bus. Exit quickly otherwise. */
46 g_free(owner);
52 return;47 return;
53 }48 }
5449
55 if (g_strcmp0(name, DBUS_NAME)) {50 if (g_strcmp0(owner, DBUS_NAME)) {
56 /* We only care about this address, reject all others. */51 /* We only care about this address, reject all others. */
52 g_free(owner);
57 return;53 return;
58 }54 }
5955
60 org_ayatana_AppMenu_Registrar_register_window_async(registrar, GDK_WINDOW_XID (gtk_widget_get_window (window)), MENU_PATH, register_cb, NULL);56 GError * error = NULL;
57 g_dbus_proxy_call_sync(registrar, "RegisterWindow",
58 g_variant_new("(uo)",
59 GDK_WINDOW_XID (gtk_widget_get_window (window)),
60 MENU_PATH),
61 G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL);
62 if (error != NULL) {
63 g_warning("Unable to register: %s", error->message);
64 g_error_free(error);
65 }
6166
67 g_free(owner);
62 return;68 return;
63}69}
6470
@@ -71,21 +77,26 @@
71 DbusmenuServer * server = dbusmenu_server_new(MENU_PATH);77 DbusmenuServer * server = dbusmenu_server_new(MENU_PATH);
72 dbusmenu_server_set_root(server, root);78 dbusmenu_server_set_root(server, root);
7379
74 DBusGConnection * session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);80 registrar = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SESSION,
75 registrar = dbus_g_proxy_new_for_name(session_bus, DBUS_NAME, REG_OBJECT, REG_IFACE);81 G_DBUS_PROXY_FLAGS_NONE,
82 NULL, DBUS_NAME,
83 REG_OBJECT, REG_IFACE,
84 NULL, NULL);
76 g_return_val_if_fail(registrar != NULL, FALSE);85 g_return_val_if_fail(registrar != NULL, FALSE);
7786
78 org_ayatana_AppMenu_Registrar_register_window_async(registrar, GDK_WINDOW_XID (gtk_widget_get_window (window)), MENU_PATH, register_cb, NULL);87 GError * error = NULL;
88 g_dbus_proxy_call_sync(registrar, "RegisterWindow",
89 g_variant_new("(uo)",
90 GDK_WINDOW_XID (gtk_widget_get_window (window)),
91 MENU_PATH),
92 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
93 if (error != NULL) {
94 g_warning("Unable to register: %s", error->message);
95 g_error_free(error);
96 }
7997
80 DBusGProxy * dbus_proxy = dbus_g_proxy_new_for_name(session_bus,98 g_signal_connect(registrar, "notify::g-name-owner",
81 DBUS_SERVICE_DBUS,99 G_CALLBACK(dbus_owner_change), NULL);
82 DBUS_PATH_DBUS,
83 DBUS_INTERFACE_DBUS);
84 dbus_g_proxy_add_signal(dbus_proxy, "NameOwnerChanged",
85 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
86 G_TYPE_INVALID);
87 dbus_g_proxy_connect_signal(dbus_proxy, "NameOwnerChanged",
88 G_CALLBACK(dbus_owner_change), NULL, NULL);
89100
90 return FALSE;101 return FALSE;
91}102}

Subscribers

People subscribed via source and target branches