Merge lp:~dbusmenu-team/libdbusmenu/ubuntu into lp:~ubuntu-desktop/libdbusmenu/ubuntu

Proposed by Ted Gould
Status: Merged
Merged at revision: not available
Proposed branch: lp:~dbusmenu-team/libdbusmenu/ubuntu
Merge into: lp:~ubuntu-desktop/libdbusmenu/ubuntu
Diff against target: 1407 lines (+1182/-8)
15 files modified
.bzrignore (+5/-0)
Makefile.am (+1/-1)
configure.ac (+3/-3)
debian/changelog (+9/-0)
debian/rules (+2/-2)
libdbusmenu-glib/Makefile.am (+3/-0)
libdbusmenu-glib/client.c (+130/-1)
libdbusmenu-glib/menuitem-proxy.c (+362/-0)
libdbusmenu-glib/menuitem-proxy.h (+74/-0)
libdbusmenu-glib/server.c (+20/-1)
tests/Makefile.am (+54/-0)
tests/test-glib-proxy-client.c (+171/-0)
tests/test-glib-proxy-proxy.c (+80/-0)
tests/test-glib-proxy-server.c (+126/-0)
tests/test-glib-proxy.h (+142/-0)
To merge this branch: bzr merge lp:~dbusmenu-team/libdbusmenu/ubuntu
Reviewer Review Type Date Requested Status
Sebastien Bacher Pending
Review via email: mp+19633@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Ted Gould (ted) wrote :

0.2.5

lp:~dbusmenu-team/libdbusmenu/ubuntu updated
67. By Sebastien Bacher

releasing version 0.2.5-0ubuntu1

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2010-02-05 07:30:25 +0000
3+++ .bzrignore 2010-02-18 17:06:16 +0000
4@@ -60,3 +60,8 @@
5 tests/test-glib-objects.xml
6 tools/testapp/dbusmenu-testapp
7 libdbusmenu-glib/libdbusmenu_glib_la-client-menuitem.lo
8+libdbusmenu-glib/libdbusmenu_glib_la-menuitem-proxy.lo
9+tests/test-glib-proxy-client
10+tests/test-glib-proxy-server
11+tests/test-glib-proxy-proxy
12+tests/test-glib-proxy
13
14=== modified file 'Makefile.am'
15--- Makefile.am 2010-01-07 17:13:09 +0000
16+++ Makefile.am 2010-02-18 17:06:16 +0000
17@@ -1,3 +1,3 @@
18-
19+EXTRA_DIST = COPYING.2.1 COPYING-GPL3
20 SUBDIRS = libdbusmenu-glib libdbusmenu-gtk tools tests po
21
22
23=== modified file 'configure.ac'
24--- configure.ac 2010-02-11 16:09:27 +0000
25+++ configure.ac 2010-02-18 17:06:16 +0000
26@@ -1,11 +1,11 @@
27
28-AC_INIT(libdbusmenu, 0.2.4, ted@canonical.com)
29+AC_INIT(libdbusmenu, 0.2.5, ted@canonical.com)
30 AC_COPYRIGHT([Copyright 2009,2010 Canonical])
31
32 AC_PREREQ(2.53)
33
34 AM_CONFIG_HEADER(config.h)
35-AM_INIT_AUTOMAKE(libdbusmenu, 0.2.4)
36+AM_INIT_AUTOMAKE(libdbusmenu, 0.2.5)
37
38 AM_MAINTAINER_MODE
39
40@@ -66,7 +66,7 @@
41 ###########################
42
43 LIBDBUSMENU_CURRENT=1
44-LIBDBUSMENU_REVISION=2
45+LIBDBUSMENU_REVISION=3
46 LIBDBUSMENU_AGE=0
47
48 AC_SUBST(LIBDBUSMENU_CURRENT)
49
50=== modified file 'debian/changelog'
51--- debian/changelog 2010-02-11 16:13:58 +0000
52+++ debian/changelog 2010-02-18 17:06:16 +0000
53@@ -1,3 +1,12 @@
54+libdbusmenu (0.2.5-0ubuntu1~ppa1) lucid; urgency=low
55+
56+ * Upstream release 0.2.5
57+ * Adding in menuitem proxy object.
58+ * Adding ID to default <menu> item.
59+ * debian/rules: Updating shlibs
60+
61+ -- Ted Gould <ted@ubuntu.com> Thu, 18 Feb 2010 11:00:24 -0600
62+
63 libdbusmenu (0.2.4-0ubuntu1) lucid; urgency=low
64
65 * Upstream release 0.2.4
66
67=== modified file 'debian/rules'
68--- debian/rules 2010-02-04 22:09:19 +0000
69+++ debian/rules 2010-02-18 17:06:16 +0000
70@@ -6,6 +6,6 @@
71 DEB_CONFIGURE_EXTRA_FLAGS += --disable-scrollkeeper
72 LDFLAGS += -Wl,-z,defs -Wl,--as-needed
73
74-DEB_DH_MAKESHLIBS_ARGS_libdbusmenu-gtk1 += -V 'libdbusmenu-gtk1 (>= 0.2.2)'
75-DEB_DH_MAKESHLIBS_ARGS_libdbusmenu-glib1 += -V 'libdbusmenu-glib1 (>= 0.2.2)'
76+DEB_DH_MAKESHLIBS_ARGS_libdbusmenu-gtk1 += -V 'libdbusmenu-gtk1 (>= 0.2.5)'
77+DEB_DH_MAKESHLIBS_ARGS_libdbusmenu-glib1 += -V 'libdbusmenu-glib1 (>= 0.2.5)'
78
79
80=== modified file 'libdbusmenu-glib/Makefile.am'
81--- libdbusmenu-glib/Makefile.am 2010-02-04 02:00:36 +0000
82+++ libdbusmenu-glib/Makefile.am 2010-02-18 17:06:16 +0000
83@@ -12,6 +12,7 @@
84
85 libdbusmenu_glibinclude_HEADERS = \
86 menuitem.h \
87+ menuitem-proxy.h \
88 server.h \
89 client.h
90
91@@ -23,6 +24,8 @@
92 menuitem-marshal.h \
93 menuitem-marshal.c \
94 menuitem-private.h \
95+ menuitem-proxy.h \
96+ menuitem-proxy.c \
97 server.h \
98 server.c \
99 server-marshal.h \
100
101=== modified file 'libdbusmenu-glib/client.c'
102--- libdbusmenu-glib/client.c 2010-02-09 17:13:51 +0000
103+++ libdbusmenu-glib/client.c 2010-02-18 17:06:16 +0000
104@@ -75,6 +75,8 @@
105 DBusGProxy * dbusproxy;
106
107 GHashTable * type_handlers;
108+
109+ GArray * delayed_properties;
110 };
111
112 typedef struct _newItemPropData newItemPropData;
113@@ -85,6 +87,21 @@
114 DbusmenuMenuitem * parent;
115 };
116
117+typedef struct _propertyDelay propertyDelay;
118+struct _propertyDelay
119+{
120+ guint revision;
121+ GArray * entries;
122+};
123+
124+typedef struct _propertyDelayValue propertyDelayValue;
125+struct _propertyDelayValue
126+{
127+ gint id;
128+ gchar * name;
129+ GValue value;
130+};
131+
132 #define DBUSMENU_CLIENT_GET_PRIVATE(o) \
133 (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUSMENU_TYPE_CLIENT, DbusmenuClientPrivate))
134
135@@ -208,6 +225,8 @@
136 priv->type_handlers = g_hash_table_new_full(g_str_hash, g_str_equal,
137 g_free, NULL);
138
139+ priv->delayed_properties = g_array_new(FALSE, TRUE, sizeof(propertyDelay));
140+
141 return;
142 }
143
144@@ -255,6 +274,23 @@
145 g_hash_table_destroy(priv->type_handlers);
146 }
147
148+ if (priv->delayed_properties) {
149+ gint i;
150+ for (i = 0; i < priv->delayed_properties->len; i++) {
151+ propertyDelay * delay = &g_array_index(priv->delayed_properties, propertyDelay, i);
152+ gint j;
153+ for (j = 0; j < delay->entries->len; j++) {
154+ propertyDelayValue * value = &g_array_index(delay->entries, propertyDelayValue, j);
155+ g_free(value->name);
156+ g_value_unset(&value->value);
157+ }
158+ g_array_free(delay->entries, TRUE);
159+ delay->entries = NULL;
160+ }
161+ g_array_free(priv->delayed_properties, TRUE);
162+ priv->delayed_properties = NULL;
163+ }
164+
165 G_OBJECT_CLASS (dbusmenu_client_parent_class)->finalize (object);
166 return;
167 }
168@@ -319,6 +355,49 @@
169 return;
170 }
171
172+/* Add an entry to the set of entries that are delayed until the
173+ layout has been updated to this revision */
174+static void
175+delay_prop_update (guint revision, GArray * delayarray, gint id, gchar * prop, GValue * value)
176+{
177+ propertyDelay * delay = NULL;
178+ gint i;
179+
180+ /* First look for something with this revision number. This
181+ array should be really short, probably not more than an entry or
182+ two so there is no reason to optimize this. */
183+ for (i = 0; i < delayarray->len; i++) {
184+ propertyDelay * localdelay = &g_array_index(delayarray, propertyDelay, i);
185+ if (localdelay->revision == revision) {
186+ delay = localdelay;
187+ break;
188+ }
189+ }
190+
191+ /* If we don't have any entires for this revision number then we
192+ need to create a new one with it's own array of entires. */
193+ if (delay == NULL) {
194+ propertyDelay localdelay = {0};
195+ localdelay.revision = revision;
196+ localdelay.entries = g_array_new(FALSE, TRUE, sizeof(propertyDelayValue));
197+
198+ g_array_append_val(delayarray, localdelay);
199+ delay = &g_array_index(delayarray, propertyDelay, delayarray->len - 1);
200+ }
201+
202+ /* Build the actual entry and tack it on the end of the array
203+ of entries */
204+ propertyDelayValue delayvalue = {0};
205+ delayvalue.id = id;
206+ delayvalue.name = g_strdup(prop);
207+
208+ g_value_init(&delayvalue.value, G_VALUE_TYPE(value));
209+ g_value_copy(value, &delayvalue.value);
210+
211+ g_array_append_val(delay->entries, delayvalue);
212+ return;
213+}
214+
215 /* Signal from the server that a property has changed
216 on one of our menuitems */
217 static void
218@@ -333,7 +412,16 @@
219 #endif
220
221 DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
222- g_return_if_fail(priv->root != NULL);
223+
224+ /* If we're not on the right revision, we need to cache the property
225+ changes as it could be that the menuitems don't exist yet. */
226+ if (priv->root == NULL || priv->my_revision != priv->current_revision) {
227+ #ifdef MASSIVEDEBUGGING
228+ g_debug("Delaying prop update until rev %d for id %d property %s", priv->current_revision, id, property);
229+ #endif
230+ delay_prop_update(priv->current_revision, priv->delayed_properties, id, property, value);
231+ return;
232+ }
233
234 DbusmenuMenuitem * menuitem = dbusmenu_menuitem_find_id(priv->root, id);
235 g_return_if_fail(menuitem != NULL);
236@@ -810,16 +898,19 @@
237 DbusmenuClient * client = DBUSMENU_CLIENT(data);
238 DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
239
240+ /* Check to make sure this isn't an issue */
241 if (error != NULL) {
242 g_warning("Getting layout failed on client %s object %s: %s", priv->dbus_name, priv->dbus_object, error->message);
243 return;
244 }
245
246+ /* Try to take in the layout that we got */
247 if (!parse_layout(client, xml)) {
248 g_warning("Unable to parse layout!");
249 return;
250 }
251
252+ /* Success, so we need to update our local variables */
253 priv->my_revision = rev;
254 /* g_debug("Root is now: 0x%X", (unsigned int)priv->root); */
255 priv->layoutcall = NULL;
256@@ -828,6 +919,44 @@
257 #endif
258 g_signal_emit(G_OBJECT(client), signals[LAYOUT_UPDATED], 0, TRUE);
259
260+ /* Apply the delayed properties that were queued up while
261+ we were waiting on this layout update. */
262+ if (G_LIKELY(priv->delayed_properties != NULL)) {
263+ gint i;
264+ for (i = 0; i < priv->delayed_properties->len; i++) {
265+ propertyDelay * delay = &g_array_index(priv->delayed_properties, propertyDelay, i);
266+ if (delay->revision > priv->my_revision) {
267+ /* Check to see if this is for future revisions, which
268+ is possible if there is a ton of updates. */
269+ break;
270+ }
271+
272+ gint j;
273+ for (j = 0; j < delay->entries->len; j++) {
274+ propertyDelayValue * value = &g_array_index(delay->entries, propertyDelayValue, j);
275+ DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, value->id);
276+ if (mi != NULL) {
277+ #ifdef MASSIVEDEBUGGING
278+ g_debug("Applying delayed property id %d property %s", value->id, value->name);
279+ #endif
280+ dbusmenu_menuitem_property_set_value(mi, value->name, &value->value);
281+ }
282+ g_free(value->name);
283+ g_value_unset(&value->value);
284+ }
285+ g_array_free(delay->entries, TRUE);
286+
287+ /* We're removing the entry and moving the index down one
288+ to ensure that we adjust for the shift in the array. The
289+ reality is that i is always 0. You understood this loop
290+ until you got here, didn't you :) */
291+ g_array_remove_index(priv->delayed_properties, i);
292+ i--;
293+ }
294+ }
295+
296+ /* Check to see if we got another update in the time this
297+ one was issued. */
298 if (priv->my_revision < priv->current_revision) {
299 update_layout(client);
300 }
301
302=== added file 'libdbusmenu-glib/menuitem-proxy.c'
303--- libdbusmenu-glib/menuitem-proxy.c 1970-01-01 00:00:00 +0000
304+++ libdbusmenu-glib/menuitem-proxy.c 2010-02-18 17:06:16 +0000
305@@ -0,0 +1,362 @@
306+/*
307+An object to ferry over properties and signals between two different
308+dbusmenu instances. Useful for services.
309+
310+Copyright 2010 Canonical Ltd.
311+
312+Authors:
313+ Ted Gould <ted@canonical.com>
314+
315+This program is free software: you can redistribute it and/or modify it
316+under the terms of either or both of the following licenses:
317+
318+1) the GNU Lesser General Public License version 3, as published by the
319+Free Software Foundation; and/or
320+2) the GNU Lesser General Public License version 2.1, as published by
321+the Free Software Foundation.
322+
323+This program is distributed in the hope that it will be useful, but
324+WITHOUT ANY WARRANTY; without even the implied warranties of
325+MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
326+PURPOSE. See the applicable version of the GNU Lesser General Public
327+License for more details.
328+
329+You should have received a copy of both the GNU Lesser General Public
330+License version 3 and version 2.1 along with this program. If not, see
331+<http://www.gnu.org/licenses/>
332+*/
333+
334+#ifdef HAVE_CONFIG_H
335+#include "config.h"
336+#endif
337+
338+#include "menuitem-proxy.h"
339+
340+typedef struct _DbusmenuMenuitemProxyPrivate DbusmenuMenuitemProxyPrivate;
341+struct _DbusmenuMenuitemProxyPrivate {
342+ DbusmenuMenuitem * mi;
343+ gulong sig_property_changed;
344+ gulong sig_child_added;
345+ gulong sig_child_removed;
346+ gulong sig_child_moved;
347+};
348+
349+/* Properties */
350+enum {
351+ PROP_0,
352+ PROP_MENU_ITEM
353+};
354+
355+#define PROP_MENU_ITEM_S "menu-item"
356+
357+#define DBUSMENU_MENUITEM_PROXY_GET_PRIVATE(o) \
358+(G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUSMENU_TYPE_MENUITEM_PROXY, DbusmenuMenuitemProxyPrivate))
359+
360+static void dbusmenu_menuitem_proxy_class_init (DbusmenuMenuitemProxyClass *klass);
361+static void dbusmenu_menuitem_proxy_init (DbusmenuMenuitemProxy *self);
362+static void dbusmenu_menuitem_proxy_dispose (GObject *object);
363+static void dbusmenu_menuitem_proxy_finalize (GObject *object);
364+static void set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec);
365+static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec);
366+static void handle_event (DbusmenuMenuitem * mi, const gchar * name, const GValue * value, guint timestamp);
367+static void add_menuitem (DbusmenuMenuitemProxy * pmi, DbusmenuMenuitem * mi);
368+static void remove_menuitem (DbusmenuMenuitemProxy * pmi);
369+
370+G_DEFINE_TYPE (DbusmenuMenuitemProxy, dbusmenu_menuitem_proxy, DBUSMENU_TYPE_MENUITEM);
371+
372+static void
373+dbusmenu_menuitem_proxy_class_init (DbusmenuMenuitemProxyClass *klass)
374+{
375+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
376+
377+ g_type_class_add_private (klass, sizeof (DbusmenuMenuitemProxyPrivate));
378+
379+ object_class->dispose = dbusmenu_menuitem_proxy_dispose;
380+ object_class->finalize = dbusmenu_menuitem_proxy_finalize;
381+ object_class->set_property = set_property;
382+ object_class->get_property = get_property;
383+
384+ DbusmenuMenuitemClass * miclass = DBUSMENU_MENUITEM_CLASS(klass);
385+
386+ miclass->handle_event = handle_event;
387+
388+ g_object_class_install_property (object_class, PROP_MENU_ITEM,
389+ g_param_spec_object(PROP_MENU_ITEM_S, "The Menuitem we're proxying",
390+ "An instance of the DbusmenuMenuitem class that this menuitem will mimic.",
391+ DBUSMENU_TYPE_MENUITEM,
392+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
393+
394+ return;
395+}
396+
397+static void
398+dbusmenu_menuitem_proxy_init (DbusmenuMenuitemProxy *self)
399+{
400+ DbusmenuMenuitemProxyPrivate * priv = DBUSMENU_MENUITEM_PROXY_GET_PRIVATE(self);
401+
402+ priv->mi = NULL;
403+
404+ priv->sig_property_changed = 0;
405+ priv->sig_child_added = 0;
406+ priv->sig_child_removed = 0;
407+ priv->sig_child_moved = 0;
408+
409+ return;
410+}
411+
412+/* Remove references to objects */
413+static void
414+dbusmenu_menuitem_proxy_dispose (GObject *object)
415+{
416+ remove_menuitem(DBUSMENU_MENUITEM_PROXY(object));
417+
418+ G_OBJECT_CLASS (dbusmenu_menuitem_proxy_parent_class)->dispose (object);
419+ return;
420+}
421+
422+/* Free any memory that we've allocated */
423+static void
424+dbusmenu_menuitem_proxy_finalize (GObject *object)
425+{
426+
427+ G_OBJECT_CLASS (dbusmenu_menuitem_proxy_parent_class)->finalize (object);
428+ return;
429+}
430+
431+/* Set a property using the generic GObject interface */
432+static void
433+set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec)
434+{
435+ switch (id) {
436+ case PROP_MENU_ITEM: {
437+ GObject * lobj = g_value_get_object(value);
438+ add_menuitem(DBUSMENU_MENUITEM_PROXY(obj), DBUSMENU_MENUITEM(lobj));
439+ break;
440+ }
441+ default:
442+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, id, pspec);
443+ break;
444+ }
445+
446+ return;
447+}
448+
449+/* Get a property using the generic GObject interface */
450+static void
451+get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec)
452+{
453+ DbusmenuMenuitemProxyPrivate * priv = DBUSMENU_MENUITEM_PROXY_GET_PRIVATE(obj);
454+
455+ switch (id) {
456+ case PROP_MENU_ITEM:
457+ g_value_set_object(value, priv->mi);
458+ break;
459+ default:
460+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, id, pspec);
461+ break;
462+ }
463+
464+ return;
465+}
466+
467+/* Takes the event and passes it along to the item that we're
468+ playing proxy for. */
469+static void
470+handle_event (DbusmenuMenuitem * mi, const gchar * name, const GValue * value, guint timestamp)
471+{
472+ g_return_if_fail(DBUSMENU_IS_MENUITEM_PROXY(mi));
473+ DbusmenuMenuitemProxyPrivate * priv = DBUSMENU_MENUITEM_PROXY_GET_PRIVATE(mi);
474+ g_return_if_fail(priv->mi != NULL);
475+ return dbusmenu_menuitem_handle_event(priv->mi, name, value, timestamp);
476+}
477+
478+/* Watches a property change and makes sure to put that value
479+ into our property list. */
480+static void
481+proxy_item_property_changed (DbusmenuMenuitem * mi, gchar * property, GValue * value, gpointer user_data)
482+{
483+ DbusmenuMenuitemProxy * pmi = DBUSMENU_MENUITEM_PROXY(user_data);
484+ dbusmenu_menuitem_property_set_value(DBUSMENU_MENUITEM(pmi), property, value);
485+ return;
486+}
487+
488+/* Looks for a child getting added and wraps it and places it
489+ in our list of children. */
490+static void
491+proxy_item_child_added (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, guint position, gpointer user_data)
492+{
493+ DbusmenuMenuitemProxy * pmi = DBUSMENU_MENUITEM_PROXY(user_data);
494+ DbusmenuMenuitemProxy * child_pmi = dbusmenu_menuitem_proxy_new(child);
495+ dbusmenu_menuitem_child_add_position(DBUSMENU_MENUITEM(pmi), DBUSMENU_MENUITEM(child_pmi), position);
496+ return;
497+}
498+
499+/* Find the wrapper for this child and remove it as well. */
500+static void
501+proxy_item_child_removed (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, gpointer user_data)
502+{
503+ DbusmenuMenuitemProxy * pmi = DBUSMENU_MENUITEM_PROXY(user_data);
504+ GList * children = dbusmenu_menuitem_get_children(DBUSMENU_MENUITEM(pmi));
505+ DbusmenuMenuitemProxy * finalpmi = NULL;
506+ GList * childitem;
507+
508+ for (childitem = children; childitem != NULL; childitem = g_list_next(childitem)) {
509+ DbusmenuMenuitemProxy * childpmi = (DbusmenuMenuitemProxy *)childitem->data;
510+ DbusmenuMenuitem * childmi = dbusmenu_menuitem_proxy_get_wrapped(childpmi);
511+ if (childmi == child) {
512+ finalpmi = childpmi;
513+ break;
514+ }
515+ }
516+
517+ if (finalpmi != NULL) {
518+ dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(pmi), DBUSMENU_MENUITEM(finalpmi));
519+ }
520+
521+ return;
522+}
523+
524+/* Find the wrapper for the item and move it in our child list */
525+static void
526+proxy_item_child_moved (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, guint newpos, guint oldpos, gpointer user_data)
527+{
528+ DbusmenuMenuitemProxy * pmi = DBUSMENU_MENUITEM_PROXY(user_data);
529+ GList * children = dbusmenu_menuitem_get_children(DBUSMENU_MENUITEM(pmi));
530+ DbusmenuMenuitemProxy * finalpmi = NULL;
531+ GList * childitem;
532+
533+ for (childitem = children; childitem != NULL; childitem = g_list_next(childitem)) {
534+ DbusmenuMenuitemProxy * childpmi = (DbusmenuMenuitemProxy *)childitem->data;
535+ DbusmenuMenuitem * childmi = dbusmenu_menuitem_proxy_get_wrapped(childpmi);
536+ if (childmi == child) {
537+ finalpmi = childpmi;
538+ break;
539+ }
540+ }
541+
542+ if (finalpmi != NULL) {
543+ dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(pmi), DBUSMENU_MENUITEM(finalpmi), newpos);
544+ }
545+
546+ return;
547+}
548+
549+/* Making g_object_unref into a GFunc */
550+static void
551+func_g_object_unref (gpointer data, gpointer user_data)
552+{
553+ return g_object_unref(G_OBJECT(data));
554+}
555+
556+/* References all of the things we need for talking to this menuitem
557+ including signals and other data. If the menuitem already has
558+ properties we need to signal that they've changed for us. */
559+static void
560+add_menuitem (DbusmenuMenuitemProxy * pmi, DbusmenuMenuitem * mi)
561+{
562+ /* Put it in private */
563+ DbusmenuMenuitemProxyPrivate * priv = DBUSMENU_MENUITEM_PROXY_GET_PRIVATE(pmi);
564+ if (priv->mi != NULL) {
565+ remove_menuitem(pmi);
566+ }
567+ priv->mi = mi;
568+ g_object_ref(G_OBJECT(priv->mi));
569+
570+ /* Attach signals */
571+ priv->sig_property_changed = g_signal_connect(G_OBJECT(priv->mi), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(proxy_item_property_changed), pmi);
572+ priv->sig_child_added = g_signal_connect(G_OBJECT(priv->mi), DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED, G_CALLBACK(proxy_item_child_added), pmi);
573+ priv->sig_child_removed = g_signal_connect(G_OBJECT(priv->mi), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(proxy_item_child_removed), pmi);
574+ priv->sig_child_moved = g_signal_connect(G_OBJECT(priv->mi), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(proxy_item_child_moved), pmi);
575+
576+ /* Grab (cache) Properties */
577+ GList * props = dbusmenu_menuitem_properties_list(priv->mi);
578+ GList * prop;
579+ for (prop = props; prop != NULL; prop = g_list_next(prop)) {
580+ gchar * prop_name = (gchar *)prop->data;
581+ dbusmenu_menuitem_property_set_value(DBUSMENU_MENUITEM(pmi), prop_name, dbusmenu_menuitem_property_get_value(priv->mi, prop_name));
582+ }
583+ g_list_free(props);
584+
585+ /* Go through children and wrap them */
586+ GList * children = dbusmenu_menuitem_get_children(priv->mi);
587+ GList * child;
588+ for (child = children; child != NULL; child = g_list_next(child)) {
589+ DbusmenuMenuitemProxy * child_pmi = dbusmenu_menuitem_proxy_new(DBUSMENU_MENUITEM(child->data));
590+ dbusmenu_menuitem_child_append(DBUSMENU_MENUITEM(pmi), DBUSMENU_MENUITEM(child_pmi));
591+ }
592+
593+ return;
594+}
595+
596+/* Removes the menuitem from being our proxy. Typically this isn't
597+ done until this object is destroyed, but who knows?!? */
598+static void
599+remove_menuitem (DbusmenuMenuitemProxy * pmi)
600+{
601+ DbusmenuMenuitemProxyPrivate * priv = DBUSMENU_MENUITEM_PROXY_GET_PRIVATE(pmi);
602+ if (priv->mi == NULL) {
603+ return;
604+ }
605+
606+ /* Remove signals */
607+ if (priv->sig_property_changed != 0) {
608+ g_signal_handler_disconnect(G_OBJECT(priv->mi), priv->sig_property_changed);
609+ }
610+ if (priv->sig_child_added != 0) {
611+ g_signal_handler_disconnect(G_OBJECT(priv->mi), priv->sig_child_added);
612+ }
613+ if (priv->sig_child_removed != 0) {
614+ g_signal_handler_disconnect(G_OBJECT(priv->mi), priv->sig_child_removed);
615+ }
616+ if (priv->sig_child_moved != 0) {
617+ g_signal_handler_disconnect(G_OBJECT(priv->mi), priv->sig_child_moved);
618+ }
619+
620+ /* Unref */
621+ g_object_unref(G_OBJECT(priv->mi));
622+ priv->mi = NULL;
623+
624+ /* Remove our own children */
625+ GList * children = dbusmenu_menuitem_take_children(DBUSMENU_MENUITEM(pmi));
626+ g_list_foreach(children, func_g_object_unref, NULL);
627+ g_list_free(children);
628+
629+ return;
630+}
631+
632+/**
633+ dbusmenu_menuitem_proxy_new:
634+ @mi: The #DbusmenuMenuitem to proxy
635+
636+ Builds a new #DbusmenuMenuitemProxy object that proxies
637+ all of the values for @mi.
638+
639+ Return value: A new #DbusmenuMenuitemProxy object.
640+*/
641+DbusmenuMenuitemProxy *
642+dbusmenu_menuitem_proxy_new (DbusmenuMenuitem * mi)
643+{
644+ DbusmenuMenuitemProxy * pmi = g_object_new(DBUSMENU_TYPE_MENUITEM_PROXY,
645+ PROP_MENU_ITEM_S, mi,
646+ NULL);
647+
648+ return pmi;
649+}
650+
651+/**
652+ dbusmenu_menuitem_proxy_get_wrapped:
653+ @pmi: #DbusmenuMenuitemProxy to look into
654+
655+ Accesses the private variable of which #DbusmenuMenuitem
656+ we are doing the proxying for.
657+
658+ Return value: A #DbusmenuMenuitem object or a #NULL if we
659+ don't have one or there is an error.
660+*/
661+DbusmenuMenuitem *
662+dbusmenu_menuitem_proxy_get_wrapped (DbusmenuMenuitemProxy * pmi)
663+{
664+ g_return_val_if_fail(DBUSMENU_MENUITEM_PROXY(pmi), NULL);
665+ DbusmenuMenuitemProxyPrivate * priv = DBUSMENU_MENUITEM_PROXY_GET_PRIVATE(pmi);
666+ return priv->mi;
667+}
668
669=== added file 'libdbusmenu-glib/menuitem-proxy.h'
670--- libdbusmenu-glib/menuitem-proxy.h 1970-01-01 00:00:00 +0000
671+++ libdbusmenu-glib/menuitem-proxy.h 2010-02-18 17:06:16 +0000
672@@ -0,0 +1,74 @@
673+/*
674+An object to ferry over properties and signals between two different
675+dbusmenu instances. Useful for services.
676+
677+Copyright 2010 Canonical Ltd.
678+
679+Authors:
680+ Ted Gould <ted@canonical.com>
681+
682+This program is free software: you can redistribute it and/or modify it
683+under the terms of either or both of the following licenses:
684+
685+1) the GNU Lesser General Public License version 3, as published by the
686+Free Software Foundation; and/or
687+2) the GNU Lesser General Public License version 2.1, as published by
688+the Free Software Foundation.
689+
690+This program is distributed in the hope that it will be useful, but
691+WITHOUT ANY WARRANTY; without even the implied warranties of
692+MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
693+PURPOSE. See the applicable version of the GNU Lesser General Public
694+License for more details.
695+
696+You should have received a copy of both the GNU Lesser General Public
697+License version 3 and version 2.1 along with this program. If not, see
698+<http://www.gnu.org/licenses/>
699+*/
700+
701+#ifndef __DBUSMENU_MENUITEM_PROXY_H__
702+#define __DBUSMENU_MENUITEM_PROXY_H__
703+
704+#include <glib.h>
705+#include <glib-object.h>
706+#include "menuitem.h"
707+
708+G_BEGIN_DECLS
709+
710+#define DBUSMENU_TYPE_MENUITEM_PROXY (dbusmenu_menuitem_proxy_get_type ())
711+#define DBUSMENU_MENUITEM_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DBUSMENU_TYPE_MENUITEM_PROXY, DbusmenuMenuitemProxy))
712+#define DBUSMENU_MENUITEM_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DBUSMENU_TYPE_MENUITEM_PROXY, DbusmenuMenuitemProxyClass))
713+#define DBUSMENU_IS_MENUITEM_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DBUSMENU_TYPE_MENUITEM_PROXY))
714+#define DBUSMENU_IS_MENUITEM_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUSMENU_TYPE_MENUITEM_PROXY))
715+#define DBUSMENU_MENUITEM_PROXY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUSMENU_TYPE_MENUITEM_PROXY, DbusmenuMenuitemProxyClass))
716+
717+typedef struct _DbusmenuMenuitemProxy DbusmenuMenuitemProxy;
718+typedef struct _DbusmenuMenuitemProxyClass DbusmenuMenuitemProxyClass;
719+
720+/**
721+ DbusmenuMenuitemProxyClass:
722+ @parent_class: The Class of #DbusmeneMenuitem
723+
724+ Functions and signal slots for #DbusmenuMenuitemProxy.
725+*/
726+struct _DbusmenuMenuitemProxyClass {
727+ DbusmenuMenuitemClass parent_class;
728+};
729+
730+/**
731+ DbusmeneMenuitemProxy:
732+ @parent: The instance of #DbusmenuMenuitem
733+
734+ Public instance data for a #DbusmenuMenuitemProxy.
735+*/
736+struct _DbusmenuMenuitemProxy {
737+ DbusmenuMenuitem parent;
738+};
739+
740+GType dbusmenu_menuitem_proxy_get_type (void);
741+DbusmenuMenuitemProxy * dbusmenu_menuitem_proxy_new (DbusmenuMenuitem * mi);
742+DbusmenuMenuitem * dbusmenu_menuitem_proxy_get_wrapped (DbusmenuMenuitemProxy * pmi);
743+
744+G_END_DECLS
745+
746+#endif
747
748=== modified file 'libdbusmenu-glib/server.c'
749--- libdbusmenu-glib/server.c 2010-02-09 16:52:21 +0000
750+++ libdbusmenu-glib/server.c 2010-02-18 17:06:16 +0000
751@@ -301,10 +301,29 @@
752 return;
753 }
754
755+/* Adds the signals for this entry to the list and looks at
756+ the children of this entry to add the signals we need
757+ as well. We like signals. */
758+static void
759+added_check_children (gpointer data, gpointer user_data)
760+{
761+ DbusmenuMenuitem * mi = (DbusmenuMenuitem *)data;
762+ DbusmenuServer * server = (DbusmenuServer *)user_data;
763+
764+ menuitem_signals_create(mi, server);
765+ g_list_foreach(dbusmenu_menuitem_get_children(mi), added_check_children, server);
766+
767+ return;
768+}
769+
770+/* Callback for when a child is added. We need to connect everything
771+ up and signal that the layout has changed. */
772 static void
773 menuitem_child_added (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, guint pos, DbusmenuServer * server)
774 {
775 menuitem_signals_create(child, server);
776+ g_list_foreach(dbusmenu_menuitem_get_children(child), added_check_children, server);
777+
778 /* TODO: We probably need to group the layout update signals to make the number more reasonble. */
779 DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
780 priv->layout_revision++;
781@@ -378,7 +397,7 @@
782 if (parent == 0) {
783 if (priv->root == NULL) {
784 /* g_debug("Getting layout without root node!"); */
785- g_ptr_array_add(xmlarray, g_strdup("<menu/>"));
786+ g_ptr_array_add(xmlarray, g_strdup("<menu id=\"0\"/>"));
787 } else {
788 dbusmenu_menuitem_buildxml(priv->root, xmlarray);
789 }
790
791=== modified file 'tests/Makefile.am'
792--- tests/Makefile.am 2010-02-05 18:35:58 +0000
793+++ tests/Makefile.am 2010-02-18 17:06:16 +0000
794@@ -5,6 +5,7 @@
795 test-glib-objects-test \
796 test-glib-layout \
797 test-glib-properties \
798+ test-glib-proxy \
799 test-glib-simple-items \
800 test-gtk-label \
801 test-gtk-reorder
802@@ -16,6 +17,9 @@
803 test-glib-layout-server \
804 test-glib-properties-client \
805 test-glib-properties-server \
806+ test-glib-proxy-client \
807+ test-glib-proxy-server \
808+ test-glib-proxy-proxy \
809 test-gtk-label-client \
810 test-gtk-label-server \
811 test-glib-simple-items \
812@@ -127,6 +131,56 @@
813 ../libdbusmenu-glib/libdbusmenu-glib.la \
814 $(DBUSMENUGLIB_LIBS)
815
816+######################
817+# Test Glib Proxy
818+######################
819+
820+test-glib-proxy: test-glib-proxy-client test-glib-proxy-server test-glib-proxy-proxy Makefile.am
821+ @echo "#!/bin/bash" > $@
822+ @echo $(DBUS_RUNNER) --task ./test-glib-proxy-client --task-name Client --task ./test-glib-proxy-server --task-name Server --ignore-return \\ >> $@
823+ @echo --task ./test-glib-proxy-proxy --parameter test.proxy.first_proxy --parameter test.proxy.second_proxy --task-name Proxy01 --ignore-return \\ >> $@
824+ @echo --task ./test-glib-proxy-proxy --parameter test.proxy.second_proxy --parameter test.proxy.third_proxy --task-name Proxy02 --ignore-return \\ >> $@
825+ @echo --task ./test-glib-proxy-proxy --parameter test.proxy.third_proxy --parameter test.proxy.fourth_proxy --task-name Proxy03 --ignore-return \\ >> $@
826+ @echo --task ./test-glib-proxy-proxy --parameter test.proxy.fourth_proxy --parameter test.proxy.last_proxy --task-name Proxy04 --ignore-return \\ >> $@
827+ @echo --task ./test-glib-proxy-proxy --parameter test.proxy.last_proxy --parameter test.proxy.server --task-name Proxy05 --ignore-return >> $@
828+ @chmod +x $@
829+
830+test_glib_proxy_server_SOURCES = \
831+ test-glib-proxy.h \
832+ test-glib-proxy-server.c
833+
834+test_glib_proxy_server_CFLAGS = \
835+ -I $(srcdir)/.. \
836+ $(DBUSMENUGLIB_CFLAGS) -Wall -Werror
837+
838+test_glib_proxy_server_LDADD = \
839+ ../libdbusmenu-glib/libdbusmenu-glib.la \
840+ $(DBUSMENUGLIB_LIBS)
841+
842+test_glib_proxy_client_SOURCES = \
843+ test-glib-proxy.h \
844+ test-glib-proxy-client.c
845+
846+test_glib_proxy_client_CFLAGS = \
847+ -I $(srcdir)/.. \
848+ $(DBUSMENUGLIB_CFLAGS) -Wall -Werror
849+
850+test_glib_proxy_client_LDADD = \
851+ ../libdbusmenu-glib/libdbusmenu-glib.la \
852+ $(DBUSMENUGLIB_LIBS)
853+
854+test_glib_proxy_proxy_SOURCES = \
855+ test-glib-proxy.h \
856+ test-glib-proxy-proxy.c
857+
858+test_glib_proxy_proxy_CFLAGS = \
859+ -I $(srcdir)/.. \
860+ $(DBUSMENUGLIB_CFLAGS) -Wall -Werror
861+
862+test_glib_proxy_proxy_LDADD = \
863+ ../libdbusmenu-glib/libdbusmenu-glib.la \
864+ $(DBUSMENUGLIB_LIBS)
865+
866 #########################
867 # Test Glib Simple Items
868 #########################
869
870=== added file 'tests/test-glib-proxy-client.c'
871--- tests/test-glib-proxy-client.c 1970-01-01 00:00:00 +0000
872+++ tests/test-glib-proxy-client.c 2010-02-18 17:06:16 +0000
873@@ -0,0 +1,171 @@
874+/*
875+A test for libdbusmenu to ensure its quality.
876+
877+Copyright 2009 Canonical Ltd.
878+
879+Authors:
880+ Ted Gould <ted@canonical.com>
881+
882+This program is free software: you can redistribute it and/or modify it
883+under the terms of the GNU General Public License version 3, as published
884+by the Free Software Foundation.
885+
886+This program is distributed in the hope that it will be useful, but
887+WITHOUT ANY WARRANTY; without even the implied warranties of
888+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
889+PURPOSE. See the GNU General Public License for more details.
890+
891+You should have received a copy of the GNU General Public License along
892+with this program. If not, see <http://www.gnu.org/licenses/>.
893+*/
894+
895+#include <glib.h>
896+
897+#include <libdbusmenu-glib/client.h>
898+#include <libdbusmenu-glib/menuitem.h>
899+
900+#include "test-glib-proxy.h"
901+
902+static guint layouton = -1;
903+static GMainLoop * mainloop = NULL;
904+static gboolean passed = TRUE;
905+static guint death_timer = 0;
906+
907+static gboolean
908+verify_props (DbusmenuMenuitem * mi, gchar ** properties)
909+{
910+ if (properties == NULL) {
911+ return TRUE;
912+ }
913+
914+ /* Verify they're all there and correct */
915+ guint i;
916+ for (i = 0; properties[i] != NULL; i += 2) {
917+ const gchar * value = dbusmenu_menuitem_property_get(mi, properties[i]);
918+ if (g_strcmp0(value, properties[i + 1])) {
919+ g_debug("\tFailed as property '%s' should be '%s' and is '%s'", properties[i], properties[i+1], value);
920+ return FALSE;
921+ }
922+ }
923+
924+ /* Verify that we don't have any extras */
925+ // GList * props = dbusmenu_menuitem_properties_list(mi);
926+
927+ return TRUE;
928+}
929+
930+static gboolean
931+verify_root_to_layout(DbusmenuMenuitem * mi, proplayout_t * layout)
932+{
933+ g_debug("Verifying ID: %d", layout->id);
934+
935+ if (!verify_props(mi, layout->properties)) {
936+ g_debug("\tFailed as unable to verify properties.");
937+ return FALSE;
938+ }
939+
940+ GList * children = dbusmenu_menuitem_get_children(mi);
941+
942+ if (children == NULL && layout->submenu == NULL) {
943+ g_debug("\tPassed: %d", layout->id);
944+ return TRUE;
945+ }
946+ if (children == NULL || layout->submenu == NULL) {
947+ if (children == NULL) {
948+ g_debug("\tFailed as there are no children but we have submenus");
949+ } else {
950+ g_debug("\tFailed as we have children but no submenu");
951+ }
952+ return FALSE;
953+ }
954+
955+ guint i = 0;
956+ for (i = 0; children != NULL && layout->submenu[i].id != -1; children = g_list_next(children), i++) {
957+ if (!verify_root_to_layout(DBUSMENU_MENUITEM(children->data), &layout->submenu[i])) {
958+ return FALSE;
959+ }
960+ }
961+
962+ if (children == NULL && layout->submenu[i].id == -1) {
963+ g_debug("\tPassed: %d", layout->id);
964+ return TRUE;
965+ }
966+
967+ if (children != NULL) {
968+ g_debug("\tFailed as there are still children but no submenus. (ID: %d)", layout->id);
969+ } else {
970+ g_debug("\tFailed as there are still submenus but no children. (ID: %d)", layout->id);
971+ }
972+ return FALSE;
973+}
974+
975+static gboolean
976+timer_func (gpointer data)
977+{
978+ g_debug("Death timer. Oops. Got to: %d", layouton);
979+ passed = FALSE;
980+ g_main_loop_quit(mainloop);
981+ return FALSE;
982+}
983+
984+static gboolean layout_verify_timer (gpointer data);
985+
986+static void
987+layout_updated (DbusmenuClient * client, gpointer data)
988+{
989+ g_debug("Layout Updated");
990+ if (dbusmenu_client_get_root(client) == NULL) {
991+ g_debug("\tIgnored, no root");
992+ return;
993+ }
994+ layouton++;
995+ g_timeout_add (1500, layout_verify_timer, client);
996+ return;
997+}
998+
999+static gboolean
1000+layout_verify_timer (gpointer data)
1001+{
1002+ g_debug("Verifing Layout: %d", layouton);
1003+ DbusmenuMenuitem * menuroot = dbusmenu_client_get_root(DBUSMENU_CLIENT(data));
1004+ proplayout_t * layout = &layouts[layouton];
1005+
1006+ if (!verify_root_to_layout(menuroot, layout)) {
1007+ g_debug("FAILED LAYOUT: %d", layouton);
1008+ passed = FALSE;
1009+ } else {
1010+ /* Extend our death */
1011+ g_source_remove(death_timer);
1012+ death_timer = g_timeout_add_seconds(10, timer_func, data);
1013+ }
1014+
1015+ if (layouts[layouton+1].id == -1) {
1016+ g_main_loop_quit(mainloop);
1017+ }
1018+
1019+ return FALSE;
1020+}
1021+
1022+int
1023+main (int argc, char ** argv)
1024+{
1025+ g_type_init();
1026+
1027+ DbusmenuClient * client = dbusmenu_client_new("test.proxy.first_proxy", "/org/test");
1028+ g_signal_connect(G_OBJECT(client), DBUSMENU_CLIENT_SIGNAL_LAYOUT_UPDATED, G_CALLBACK(layout_updated), NULL);
1029+
1030+ death_timer = g_timeout_add_seconds(10, timer_func, client);
1031+
1032+ mainloop = g_main_loop_new(NULL, FALSE);
1033+ g_main_loop_run(mainloop);
1034+
1035+ g_object_unref(G_OBJECT(client));
1036+
1037+ if (passed) {
1038+ g_debug("Quiting");
1039+ return 0;
1040+ } else {
1041+ g_debug("Quiting as we're a failure");
1042+ return 1;
1043+ }
1044+}
1045
1046=== added file 'tests/test-glib-proxy-proxy.c'
1047--- tests/test-glib-proxy-proxy.c 1970-01-01 00:00:00 +0000
1048+++ tests/test-glib-proxy-proxy.c 2010-02-18 17:06:16 +0000
1049@@ -0,0 +1,80 @@
1050+#include <glib.h>
1051+
1052+#include <dbus/dbus.h>
1053+#include <dbus/dbus-glib.h>
1054+#include <dbus/dbus-glib-lowlevel.h>
1055+#include <dbus/dbus-glib-bindings.h>
1056+
1057+#include <libdbusmenu-glib/menuitem.h>
1058+#include <libdbusmenu-glib/menuitem-proxy.h>
1059+#include <libdbusmenu-glib/server.h>
1060+#include <libdbusmenu-glib/client.h>
1061+
1062+#include "test-glib-proxy.h"
1063+
1064+static DbusmenuServer * server = NULL;
1065+static DbusmenuClient * client = NULL;
1066+static GMainLoop * mainloop = NULL;
1067+
1068+void
1069+root_changed (DbusmenuClient * client, DbusmenuMenuitem * newroot, gpointer user_data)
1070+{
1071+ g_debug("New root: %X", (guint)newroot);
1072+
1073+ if (newroot == NULL) {
1074+ g_debug("Root removed, exiting");
1075+ g_main_loop_quit(mainloop);
1076+ return;
1077+ }
1078+
1079+ DbusmenuMenuitemProxy * pmi = dbusmenu_menuitem_proxy_new(newroot);
1080+ dbusmenu_server_set_root(server, DBUSMENU_MENUITEM(pmi));
1081+ return;
1082+}
1083+
1084+int
1085+main (int argc, char ** argv)
1086+{
1087+ g_type_init();
1088+
1089+ if (argc != 3) {
1090+ g_error ("Need two params");
1091+ return 1;
1092+ }
1093+
1094+ gchar * whoami = argv[1];
1095+ gchar * myproxy = argv[2];
1096+
1097+ g_debug("I am '%s' and I'm proxying '%s'", whoami, myproxy);
1098+
1099+ GError * error = NULL;
1100+ DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
1101+
1102+ g_debug("DBus ID: %s", dbus_connection_get_server_id(dbus_g_connection_get_connection(connection)));
1103+
1104+ DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
1105+ guint nameret = 0;
1106+
1107+ if (!org_freedesktop_DBus_request_name(bus_proxy, whoami, 0, &nameret, &error)) {
1108+ g_error("Unable to call to request name");
1109+ return 1;
1110+ }
1111+
1112+ if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1113+ g_error("Unable to get name");
1114+ return 1;
1115+ }
1116+
1117+ server = dbusmenu_server_new("/org/test");
1118+ client = dbusmenu_client_new(myproxy, "/org/test");
1119+
1120+ g_signal_connect(client, DBUSMENU_CLIENT_SIGNAL_ROOT_CHANGED, G_CALLBACK(root_changed), server);
1121+
1122+ mainloop = g_main_loop_new(NULL, FALSE);
1123+ g_main_loop_run(mainloop);
1124+
1125+ g_object_unref(G_OBJECT(server));
1126+ g_debug("Quiting");
1127+
1128+ return 0;
1129+}
1130
1131=== added file 'tests/test-glib-proxy-server.c'
1132--- tests/test-glib-proxy-server.c 1970-01-01 00:00:00 +0000
1133+++ tests/test-glib-proxy-server.c 2010-02-18 17:06:16 +0000
1134@@ -0,0 +1,126 @@
1135+/*
1136+A test for libdbusmenu to ensure its quality.
1137+
1138+Copyright 2009 Canonical Ltd.
1139+
1140+Authors:
1141+ Ted Gould <ted@canonical.com>
1142+
1143+This program is free software: you can redistribute it and/or modify it
1144+under the terms of the GNU General Public License version 3, as published
1145+by the Free Software Foundation.
1146+
1147+This program is distributed in the hope that it will be useful, but
1148+WITHOUT ANY WARRANTY; without even the implied warranties of
1149+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1150+PURPOSE. See the GNU General Public License for more details.
1151+
1152+You should have received a copy of the GNU General Public License along
1153+with this program. If not, see <http://www.gnu.org/licenses/>.
1154+*/
1155+
1156+#include <glib.h>
1157+
1158+#include <dbus/dbus.h>
1159+#include <dbus/dbus-glib.h>
1160+#include <dbus/dbus-glib-lowlevel.h>
1161+#include <dbus/dbus-glib-bindings.h>
1162+
1163+#include <libdbusmenu-glib/menuitem.h>
1164+#include <libdbusmenu-glib/server.h>
1165+
1166+#include "test-glib-proxy.h"
1167+
1168+static void
1169+set_props (DbusmenuMenuitem * mi, gchar ** props)
1170+{
1171+ if (props == NULL) return;
1172+
1173+ guint i;
1174+ for (i = 0; props[i] != NULL; i += 2) {
1175+ dbusmenu_menuitem_property_set(mi, props[i], props[i+1]);
1176+ }
1177+
1178+ return;
1179+}
1180+
1181+static DbusmenuMenuitem *
1182+layout2menuitem (proplayout_t * layout)
1183+{
1184+ if (layout == NULL || layout->id == -1) return NULL;
1185+
1186+ DbusmenuMenuitem * local = dbusmenu_menuitem_new();
1187+ set_props(local, layout->properties);
1188+
1189+ if (layout->submenu != NULL) {
1190+ guint count;
1191+ for (count = 0; layout->submenu[count].id != -1; count++) {
1192+ DbusmenuMenuitem * child = layout2menuitem(&layout->submenu[count]);
1193+ if (child != NULL) {
1194+ dbusmenu_menuitem_child_append(local, child);
1195+ }
1196+ }
1197+ }
1198+
1199+ /* g_debug("Layout to menu return: 0x%X", (unsigned int)local); */
1200+ return local;
1201+}
1202+
1203+static guint layouton = 0;
1204+static DbusmenuServer * server = NULL;
1205+static GMainLoop * mainloop = NULL;
1206+
1207+static gboolean
1208+timer_func (gpointer data)
1209+{
1210+ if (layouts[layouton].id == -1) {
1211+ g_main_loop_quit(mainloop);
1212+ return FALSE;
1213+ }
1214+ g_debug("Updating to Layout %d", layouton);
1215+
1216+ DbusmenuMenuitem * mi = layout2menuitem(&layouts[layouton]);
1217+ dbusmenu_server_set_root(server, mi);
1218+ g_object_unref(G_OBJECT(mi));
1219+ layouton++;
1220+
1221+ return TRUE;
1222+}
1223+
1224+int
1225+main (int argc, char ** argv)
1226+{
1227+ g_type_init();
1228+
1229+ GError * error = NULL;
1230+ DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
1231+
1232+ g_debug("DBus ID: %s", dbus_connection_get_server_id(dbus_g_connection_get_connection(connection)));
1233+
1234+ DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
1235+ guint nameret = 0;
1236+
1237+ if (!org_freedesktop_DBus_request_name(bus_proxy, "test.proxy.server", 0, &nameret, &error)) {
1238+ g_error("Unable to call to request name");
1239+ return 1;
1240+ }
1241+
1242+ if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1243+ g_error("Unable to get name");
1244+ return 1;
1245+ }
1246+
1247+ server = dbusmenu_server_new("/org/test");
1248+
1249+ timer_func(NULL);
1250+ g_timeout_add(2500, timer_func, NULL);
1251+
1252+ mainloop = g_main_loop_new(NULL, FALSE);
1253+ g_main_loop_run(mainloop);
1254+
1255+ g_object_unref(G_OBJECT(server));
1256+ g_debug("Quiting");
1257+
1258+ return 0;
1259+}
1260+
1261
1262=== added file 'tests/test-glib-proxy.h'
1263--- tests/test-glib-proxy.h 1970-01-01 00:00:00 +0000
1264+++ tests/test-glib-proxy.h 2010-02-18 17:06:16 +0000
1265@@ -0,0 +1,142 @@
1266+/*
1267+A test for libdbusmenu to ensure its quality.
1268+
1269+Copyright 2009 Canonical Ltd.
1270+
1271+Authors:
1272+ Ted Gould <ted@canonical.com>
1273+
1274+This program is free software: you can redistribute it and/or modify it
1275+under the terms of the GNU General Public License version 3, as published
1276+by the Free Software Foundation.
1277+
1278+This program is distributed in the hope that it will be useful, but
1279+WITHOUT ANY WARRANTY; without even the implied warranties of
1280+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1281+PURPOSE. See the GNU General Public License for more details.
1282+
1283+You should have received a copy of the GNU General Public License along
1284+with this program. If not, see <http://www.gnu.org/licenses/>.
1285+*/
1286+
1287+
1288+#include <glib.h>
1289+
1290+typedef struct _proplayout_t proplayout_t;
1291+struct _proplayout_t {
1292+ gint id;
1293+ gchar ** properties;
1294+ proplayout_t * submenu;
1295+};
1296+
1297+gchar * props1[] = {"property1", "value1", "property2", "value2", NULL};
1298+gchar * props2[] = {"property00", "value00", "property01", "value01", "property02", "value02", "property03", "value03", "property04", "value04",
1299+ "property05", "value05", "property06", "value06", "property07", "value07", "property08", "value08", "property09", "value09",
1300+ "property10", "value10", "property11", "value11", "property12", "value12", "property13", "value13", "property14", "value14",
1301+ "property15", "value15", "property16", "value16", "property17", "value17", "property18", "value18", "property19", "value19",
1302+ "property20", "value20", "property21", "value21", "property22", "value22", "property23", "value23", "property24", "value24",
1303+ "property25", "value25", "property26", "value26", "property27", "value27", "property28", "value28", "property29", "value29",
1304+ "property30", "value30", "property31", "value31", "property32", "value32", "property33", "value33", "property34", "value34",
1305+ "property35", "value35", "property36", "value36", "property37", "value37", "property38", "value38", "property39", "value39",
1306+ "property40", "value40", "property41", "value41", "property42", "value42", "property43", "value43", "property44", "value44",
1307+ "property45", "value45", "property46", "value46", "property47", "value47", "property48", "value48", "property49", "value49",
1308+ "property50", "value50", "property51", "value51", "property52", "value52", "property53", "value53", "property54", "value54",
1309+ "property55", "value55", "property56", "value56", "property57", "value57", "property58", "value58", "property59", "value59",
1310+ "property60", "value60", "property61", "value61", "property62", "value62", "property63", "value63", "property64", "value64",
1311+ "property65", "value65", "property66", "value66", "property67", "value67", "property68", "value68", "property69", "value69",
1312+ "property70", "value70", "property71", "value71", "property72", "value72", "property73", "value73", "property74", "value74",
1313+ "property75", "value75", "property76", "value76", "property77", "value77", "property78", "value78", "property79", "value79",
1314+ "property80", "value80", "property81", "value81", "property82", "value82", "property83", "value83", "property84", "value84",
1315+ "property85", "value85", "property86", "value86", "property87", "value87", "property88", "value88", "property89", "value89",
1316+ "property90", "value90", "property91", "value91", "property92", "value92", "property93", "value93", "property94", "value94",
1317+ "property95", "value95", "property96", "value96", "property97", "value97", "property98", "value98", "property99", "value99",
1318+ NULL};
1319+gchar * props3[] = {"property name that is really long and will ensure that we can really have long property names, which could be important at some point.",
1320+ "And a property name that is really long should have a value that is really long, because well, that's an important part of the yin and yang of software testing.",
1321+ NULL};
1322+gchar * props4[] = {"icon-name", "network-status", "label", "Look at network", "right-column", "10:32", NULL};
1323+
1324+
1325+proplayout_t submenu_4_1[] = {
1326+ {id: 10, properties: props2, submenu: NULL},
1327+ {id: 11, properties: props2, submenu: NULL},
1328+ {id: 12, properties: props2, submenu: NULL},
1329+ {id: 13, properties: props2, submenu: NULL},
1330+ {id: 14, properties: props2, submenu: NULL},
1331+ {id: 15, properties: props2, submenu: NULL},
1332+ {id: 16, properties: props2, submenu: NULL},
1333+ {id: 17, properties: props2, submenu: NULL},
1334+ {id: 18, properties: props2, submenu: NULL},
1335+ {id: 19, properties: props2, submenu: NULL},
1336+ {id: -1, properties: NULL, submenu: NULL}
1337+};
1338+
1339+proplayout_t submenu_4_2[] = {
1340+ {id: 20, properties: props2, submenu: NULL},
1341+ {id: 21, properties: props2, submenu: NULL},
1342+ {id: 22, properties: props2, submenu: NULL},
1343+ {id: 23, properties: props2, submenu: NULL},
1344+ {id: 24, properties: props2, submenu: NULL},
1345+ {id: 25, properties: props2, submenu: NULL},
1346+ {id: 26, properties: props2, submenu: NULL},
1347+ {id: 27, properties: props2, submenu: NULL},
1348+ {id: 28, properties: props2, submenu: NULL},
1349+ {id: 29, properties: props2, submenu: NULL},
1350+ {id: -1, properties: NULL, submenu: NULL}
1351+};
1352+
1353+proplayout_t submenu_4_3[] = {
1354+ {id: 30, properties: props2, submenu: NULL},
1355+ {id: 31, properties: props2, submenu: NULL},
1356+ {id: 32, properties: props2, submenu: NULL},
1357+ {id: 33, properties: props2, submenu: NULL},
1358+ {id: 34, properties: props2, submenu: NULL},
1359+ {id: 35, properties: props2, submenu: NULL},
1360+ {id: 36, properties: props2, submenu: NULL},
1361+ {id: 37, properties: props2, submenu: NULL},
1362+ {id: 38, properties: props2, submenu: NULL},
1363+ {id: 39, properties: props2, submenu: NULL},
1364+ {id: -1, properties: NULL, submenu: NULL}
1365+};
1366+
1367+proplayout_t submenu_4_0[] = {
1368+ {id: 1, properties: props2, submenu: submenu_4_1},
1369+ {id: 2, properties: props2, submenu: submenu_4_2},
1370+ {id: 3, properties: props2, submenu: submenu_4_3},
1371+ {id: -1, properties: NULL, submenu: NULL}
1372+};
1373+
1374+proplayout_t submenu_5_5[] = {
1375+ {id: 205, properties: props3, submenu: NULL},
1376+ {id: -1, properties: NULL, submenu: NULL}
1377+};
1378+
1379+proplayout_t submenu_5_4[] = {
1380+ {id: 204, properties: props3, submenu: submenu_5_5},
1381+ {id: -1, properties: NULL, submenu: NULL}
1382+};
1383+
1384+proplayout_t submenu_5_3[] = {
1385+ {id: 203, properties: props3, submenu: submenu_5_4},
1386+ {id: -1, properties: NULL, submenu: NULL}
1387+};
1388+
1389+proplayout_t submenu_5_2[] = {
1390+ {id: 202, properties: props3, submenu: submenu_5_3},
1391+ {id: -1, properties: NULL, submenu: NULL}
1392+};
1393+
1394+proplayout_t submenu_5_1[] = {
1395+ {id: 201, properties: props3, submenu: submenu_5_2},
1396+ {id: -1, properties: NULL, submenu: NULL}
1397+};
1398+
1399+proplayout_t layouts[] = {
1400+ {id: 1, properties: props1, submenu: NULL},
1401+ {id: 10, properties: props2, submenu: submenu_4_1},
1402+ {id: 20, properties: props3, submenu: submenu_4_2},
1403+ {id: 100, properties: props2, submenu: submenu_4_0},
1404+ {id: 200, properties: props3, submenu: submenu_5_1},
1405+ {id: -1, properties: NULL, submenu: NULL}
1406+};
1407+

Subscribers

People subscribed via source and target branches

to all changes: