Merge lp:~ted/libdbusmenu/parse-serializable-menuitem into lp:libdbusmenu/0.5

Proposed by Ted Gould
Status: Merged
Merged at revision: 198
Proposed branch: lp:~ted/libdbusmenu/parse-serializable-menuitem
Merge into: lp:libdbusmenu/0.5
Prerequisite: lp:~ted/libdbusmenu/serializable-menuitem
Diff against target: 857 lines (+743/-7) (has conflicts)
6 files modified
.bzrignore (+4/-0)
libdbusmenu-glib/client.h (+21/-0)
libdbusmenu-gtk/Makefile.am (+3/-0)
libdbusmenu-gtk/parser.c (+701/-0)
libdbusmenu-gtk/serializablemenuitem.c (+5/-5)
libdbusmenu-gtk/serializablemenuitem.h (+9/-2)
Text conflict in .bzrignore
Text conflict in libdbusmenu-gtk/Makefile.am
Text conflict in libdbusmenu-gtk/parser.c
To merge this branch: bzr merge lp:~ted/libdbusmenu/parse-serializable-menuitem
Reviewer Review Type Date Requested Status
Mikkel Kamstrup Erlandsen Pending
Review via email: mp+47710@code.launchpad.net

This proposal supersedes a proposal from 2011-01-27.

Description of the change

Makes the parser look at serializable menuitems. This is also dependent on the serializable menuitem branch, but I can't be dependent on two. Please ignore that file :)

Resubmitting so it's dependent on serializable-menuitem as the parser is now in trunk. Hopefully will create a better diff. (trying again)

To post a comment you must log in.
Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote : Posted in a previous version of this proposal

How does this branch relate to https://code.launchpad.net/~ted/dbusmenu/serializable-menuitem/+merge/47604 ? They look identical?

review: Needs Information

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2011-01-27 19:48:12 +0000
3+++ .bzrignore 2011-01-27 19:48:12 +0000
4@@ -229,4 +229,8 @@
5 libdbusmenu-gtk/libdbusmenu_gtk_la-serializablemenuitem.lo
6 docs/libdbusmenu-gtk/reference/html/DbusmenuGtkSerializableMenuItem.html
7 docs/libdbusmenu-gtk/reference/tmpl/serializablemenuitem.sgml
8+libdbusmenu-gtk/libdbusmenu_gtk_la-parser.lo
9+test-gtk-parser
10+test-gtk-parser-test
11+test-gtk-parser.xml
12 >>>>>>> MERGE-SOURCE
13
14=== modified file 'libdbusmenu-glib/client.h'
15--- libdbusmenu-glib/client.h 2011-01-27 19:48:12 +0000
16+++ libdbusmenu-glib/client.h 2011-01-27 19:48:12 +0000
17@@ -110,7 +110,28 @@
18 DbusmenuClientPrivate * priv;
19 };
20
21+/**
22+ DbusmenuClientTypeHandler:
23+ @newitem: The #DbusmenuMenuitem that was created
24+ @parent: The parent of @newitem or #NULL if none
25+ @client: A pointer to the #DbusmenuClient
26+ @user_data: The data you gave us
27+
28+ The type handler is called when a dbusmenu item is created
29+ with a matching type as setup in #dbusmenu_client_add_type_handler
30+*/
31 typedef gboolean (*DbusmenuClientTypeHandler) (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
32+
33+/**
34+ DbusmenuClientTypeDestroyHandler:
35+ @client: A pointer to the #DbusmenuClient
36+ @type: The type that this handler was registered with
37+ @user_data: The data you gave us
38+
39+ This handler is called when the type becomes unregistered by the
40+ client. This is usally caused by the #DbusmenuClient being destroyed
41+ and should free memory or unref objects in @user_data.
42+*/
43 typedef void (*DbusmenuClientTypeDestroyHandler) (DbusmenuClient * client, const gchar * type, gpointer user_data);
44
45 GType dbusmenu_client_get_type (void);
46
47=== modified file 'libdbusmenu-gtk/Makefile.am'
48--- libdbusmenu-gtk/Makefile.am 2011-01-27 19:48:12 +0000
49+++ libdbusmenu-gtk/Makefile.am 2011-01-27 19:48:12 +0000
50@@ -28,6 +28,7 @@
51 parser.h
52 =======
53 menuitem.h \
54+ parser.h \
55 serializablemenuitem.h
56 >>>>>>> MERGE-SOURCE
57
58@@ -45,6 +46,8 @@
59 parser.c
60 =======
61 menuitem.c \
62+ parser.h \
63+ parser.c \
64 serializablemenuitem.h \
65 serializablemenuitem.c
66 >>>>>>> MERGE-SOURCE
67
68=== modified file 'libdbusmenu-gtk/parser.c'
69--- libdbusmenu-gtk/parser.c 2011-01-27 14:50:24 +0000
70+++ libdbusmenu-gtk/parser.c 2011-01-27 19:48:12 +0000
71@@ -1,3 +1,4 @@
72+<<<<<<< TREE
73 /*
74 Parse to take a set of GTK Menus and turn them into something that can
75 be sent over the wire.
76@@ -665,3 +666,703 @@
77 return FALSE;
78 }
79
80+=======
81+/*
82+Parse to take a set of GTK Menus and turn them into something that can
83+be sent over the wire.
84+
85+Copyright 2011 Canonical Ltd.
86+
87+Authors:
88+ Numerous (check Bazaar)
89+
90+This program is free software: you can redistribute it and/or modify it
91+under the terms of either or both of the following licenses:
92+
93+1) the GNU Lesser General Public License version 3, as published by the
94+Free Software Foundation; and/or
95+2) the GNU Lesser General Public License version 2.1, as published by
96+the Free Software Foundation.
97+
98+This program is distributed in the hope that it will be useful, but
99+WITHOUT ANY WARRANTY; without even the implied warranties of
100+MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
101+PURPOSE. See the applicable version of the GNU Lesser General Public
102+License for more details.
103+
104+You should have received a copy of both the GNU Lesser General Public
105+License version 3 and version 2.1 along with this program. If not, see
106+<http://www.gnu.org/licenses/>
107+*/
108+
109+#include "parser.h"
110+#include "menuitem.h"
111+#include "serializablemenuitem.h"
112+
113+#define CACHED_MENUITEM "dbusmenu-gtk-parser-cached-item"
114+
115+typedef struct _RecurseContext
116+{
117+ GtkWidget * toplevel;
118+ gint count;
119+ DbusmenuMenuitem *stack[30];
120+} RecurseContext;
121+
122+static void parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse);
123+static DbusmenuMenuitem * construct_dbusmenu_for_widget (GtkWidget * widget);
124+static void accel_changed (GtkWidget * widget,
125+ gpointer data);
126+static gboolean update_stock_item (DbusmenuMenuitem * menuitem,
127+ GtkWidget * widget);
128+static void checkbox_toggled (GtkWidget * widget,
129+ DbusmenuMenuitem * mi);
130+static void update_icon_name (DbusmenuMenuitem * menuitem,
131+ GtkWidget * widget);
132+static GtkWidget * find_menu_label (GtkWidget * widget);
133+static void label_notify_cb (GtkWidget * widget,
134+ GParamSpec * pspec,
135+ gpointer data);
136+static void action_notify_cb (GtkAction * action,
137+ GParamSpec * pspec,
138+ gpointer data);
139+static void item_activated (DbusmenuMenuitem * item,
140+ guint timestamp,
141+ gpointer user_data);
142+static gboolean item_about_to_show (DbusmenuMenuitem * item,
143+ gpointer user_data);
144+static void widget_notify_cb (GtkWidget * widget,
145+ GParamSpec * pspec,
146+ gpointer data);
147+static gboolean should_show_image (GtkImage * image);
148+static void menuitem_notify_cb (GtkWidget * widget,
149+ GParamSpec * pspec,
150+ gpointer data);
151+
152+DbusmenuMenuitem *
153+dbusmenu_gtk_parse_menu_structure (GtkWidget * widget)
154+{
155+ RecurseContext recurse = {0};
156+
157+ recurse.count = -1;
158+ recurse.toplevel = gtk_widget_get_toplevel(widget);
159+
160+ parse_menu_structure_helper(widget, &recurse);
161+
162+ if (recurse.stack[0] != NULL && DBUSMENU_IS_MENUITEM(recurse.stack[0])) {
163+ return recurse.stack[0];
164+ }
165+
166+ return NULL;
167+}
168+
169+static void
170+dbusmenu_cache_freed (gpointer data, GObject * obj)
171+{
172+ /* If the dbusmenu item is killed we don't need to remove
173+ the weak ref as well. */
174+ g_object_steal_data(G_OBJECT(data), CACHED_MENUITEM);
175+ return;
176+}
177+
178+static void
179+object_cache_freed (gpointer data)
180+{
181+ g_object_weak_unref(G_OBJECT(data), dbusmenu_cache_freed, data);
182+ return;
183+}
184+
185+static void
186+parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse)
187+{
188+ if (GTK_IS_CONTAINER (widget))
189+ {
190+ gboolean increment = GTK_IS_MENU_SHELL (widget) || GTK_IS_MENU_ITEM (widget);
191+
192+ if (increment)
193+ recurse->count++;
194+
195+ /* Okay, this is a little janky and all.. but some applications update some
196+ * menuitem properties such as sensitivity on the activate callback. This
197+ * seems a little weird, but it's not our place to judge when all this code
198+ * is so crazy. So we're going to get ever crazier and activate all the
199+ * menus that are directly below the menubar and force the applications to
200+ * update their sensitivity. The menus won't actually popup in the app
201+ * window due to our gtk+ patches.
202+ *
203+ * Note that this will not force menuitems in submenus to be updated as well.
204+ */
205+ if (recurse->count == 0 && GTK_IS_MENU_BAR (widget))
206+ {
207+ GList *children = gtk_container_get_children (GTK_CONTAINER (widget));
208+
209+ for (; children != NULL; children = children->next)
210+ {
211+ gtk_menu_shell_activate_item (GTK_MENU_SHELL (widget),
212+ children->data,
213+ TRUE);
214+ }
215+
216+ g_list_free (children);
217+ }
218+
219+ if (recurse->count > -1 && increment)
220+ {
221+ gpointer pmi = g_object_get_data(G_OBJECT(widget), CACHED_MENUITEM);
222+ DbusmenuMenuitem *dmi = NULL;
223+ if (pmi != NULL) dmi = DBUSMENU_MENUITEM(pmi);
224+
225+ if (dmi != NULL)
226+ {
227+ if (increment)
228+ recurse->count--;
229+
230+ return;
231+ }
232+ else
233+ {
234+ recurse->stack[recurse->count] = construct_dbusmenu_for_widget (widget);
235+ g_object_set_data_full(G_OBJECT(widget), CACHED_MENUITEM, recurse->stack[recurse->count], object_cache_freed);
236+ g_object_weak_ref(G_OBJECT(recurse->stack[recurse->count]), dbusmenu_cache_freed, widget);
237+ }
238+
239+ if (!gtk_widget_get_visible (widget))
240+ {
241+ g_signal_connect (G_OBJECT (widget),
242+ "notify::visible",
243+ G_CALLBACK (menuitem_notify_cb),
244+ recurse->toplevel);
245+ }
246+
247+ if (GTK_IS_TEAROFF_MENU_ITEM (widget))
248+ {
249+ dbusmenu_menuitem_property_set_bool (recurse->stack[recurse->count],
250+ DBUSMENU_MENUITEM_PROP_VISIBLE,
251+ FALSE);
252+ }
253+
254+ if (recurse->count > 0)
255+ {
256+ GList *children = NULL;
257+ GList *peek = NULL;
258+
259+ if (recurse->stack[recurse->count - 1])
260+ {
261+ children = dbusmenu_menuitem_get_children (recurse->stack[recurse->count - 1]);
262+
263+ if (children)
264+ {
265+ peek = g_list_find (children, recurse->stack[recurse->count]);
266+ }
267+
268+ if (!peek)
269+ {
270+ /* Should we set a weak ref on the parent? */
271+ g_object_set_data (G_OBJECT (recurse->stack[recurse->count]),
272+ "dbusmenu-parent",
273+ recurse->stack[recurse->count - 1]);
274+ dbusmenu_menuitem_child_append (recurse->stack[recurse->count - 1],
275+ recurse->stack[recurse->count]);
276+ }
277+ }
278+ else
279+ {
280+ DbusmenuMenuitem *item = NULL; /* g_hash_table_lookup (recurse->context->lookup,
281+ gtk_widget_get_parent (widget)); */
282+
283+ if (item)
284+ {
285+ children = dbusmenu_menuitem_get_children (item);
286+
287+ if (children)
288+ {
289+ peek = g_list_find (children, recurse->stack[recurse->count]);
290+ }
291+
292+ if (!peek)
293+ {
294+ g_object_set_data (G_OBJECT (recurse->stack[recurse->count]),
295+ "dbusmenu-parent",
296+ recurse->stack[recurse->count - 1]);
297+
298+ dbusmenu_menuitem_child_append (item, recurse->stack[recurse->count]);
299+ }
300+ }
301+ }
302+ }
303+ }
304+
305+ gtk_container_foreach (GTK_CONTAINER (widget),
306+ (GtkCallback)parse_menu_structure_helper,
307+ recurse);
308+
309+ if (GTK_IS_MENU_ITEM (widget))
310+ {
311+ GtkWidget *menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
312+
313+ if (menu != NULL)
314+ {
315+ parse_menu_structure_helper (menu, recurse);
316+ }
317+ }
318+
319+ if (increment)
320+ recurse->count--;
321+ }
322+}
323+
324+/* Turn a widget into a dbusmenu item depending on the type of GTK
325+ object that it is. */
326+static DbusmenuMenuitem *
327+construct_dbusmenu_for_widget (GtkWidget * widget)
328+{
329+ /* If it's a subclass of our serializable menu item then we can
330+ use its own build function */
331+ if (DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM(widget)) {
332+ DbusmenuGtkSerializableMenuItem * smi = DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM(widget);
333+ return dbusmenu_gtk_serializable_menu_item_build_menuitem(smi);
334+ }
335+
336+ /* If it's a standard GTK Menu Item we need to do some of our own work */
337+ if (GTK_IS_MENU_ITEM (widget))
338+ {
339+ DbusmenuMenuitem *mi = dbusmenu_menuitem_new ();
340+
341+ gboolean visible = FALSE;
342+ gboolean sensitive = FALSE;
343+ if (GTK_IS_SEPARATOR_MENU_ITEM (widget))
344+ {
345+ dbusmenu_menuitem_property_set (mi,
346+ "type",
347+ "separator");
348+
349+ visible = gtk_widget_get_visible (widget);
350+ sensitive = gtk_widget_get_sensitive (widget);
351+ }
352+ else
353+ {
354+ gboolean label_set = FALSE;
355+
356+ g_signal_connect (widget,
357+ "accel-closures-changed",
358+ G_CALLBACK (accel_changed),
359+ mi);
360+
361+ if (GTK_IS_CHECK_MENU_ITEM (widget))
362+ {
363+ dbusmenu_menuitem_property_set (mi,
364+ DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE,
365+ gtk_check_menu_item_get_draw_as_radio (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_RADIO : DBUSMENU_MENUITEM_TOGGLE_CHECK);
366+
367+ dbusmenu_menuitem_property_set_int (mi,
368+ DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
369+ gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
370+
371+ g_signal_connect (widget,
372+ "activate",
373+ G_CALLBACK (checkbox_toggled),
374+ mi);
375+ }
376+
377+ if (GTK_IS_IMAGE_MENU_ITEM (widget))
378+ {
379+ GtkWidget *image;
380+ GtkImageType image_type;
381+
382+ image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (widget));
383+
384+ if (GTK_IS_IMAGE (image))
385+ {
386+ image_type = gtk_image_get_storage_type (GTK_IMAGE (image));
387+
388+ if (image_type == GTK_IMAGE_STOCK)
389+ {
390+ label_set = update_stock_item (mi, image);
391+ }
392+ else if (image_type == GTK_IMAGE_ICON_NAME)
393+ {
394+ update_icon_name (mi, image);
395+ }
396+ else if (image_type == GTK_IMAGE_PIXBUF)
397+ {
398+ dbusmenu_menuitem_property_set_image (mi,
399+ DBUSMENU_MENUITEM_PROP_ICON_DATA,
400+ gtk_image_get_pixbuf (GTK_IMAGE (image)));
401+ }
402+ }
403+ }
404+
405+ GtkWidget *label = find_menu_label (widget);
406+
407+ dbusmenu_menuitem_property_set (mi,
408+ "label",
409+ label ? gtk_label_get_text (GTK_LABEL (label)) : NULL);
410+
411+ if (label)
412+ {
413+ // Sometimes, an app will directly find and modify the label
414+ // (like empathy), so watch the label especially for that.
415+ g_signal_connect (G_OBJECT (label),
416+ "notify",
417+ G_CALLBACK (label_notify_cb),
418+ mi);
419+ }
420+
421+ if (GTK_IS_ACTIVATABLE (widget))
422+ {
423+ GtkActivatable *activatable = GTK_ACTIVATABLE (widget);
424+
425+ if (gtk_activatable_get_use_action_appearance (activatable))
426+ {
427+ GtkAction *action = gtk_activatable_get_related_action (activatable);
428+
429+ if (action)
430+ {
431+ visible = gtk_action_is_visible (action);
432+ sensitive = gtk_action_is_sensitive (action);
433+
434+ g_signal_connect_object (action, "notify",
435+ G_CALLBACK (action_notify_cb),
436+ mi,
437+ G_CONNECT_AFTER);
438+ }
439+ }
440+ }
441+
442+ if (!g_object_get_data (G_OBJECT (widget), "gtk-empty-menu-item") && !GTK_IS_TEAROFF_MENU_ITEM (widget))
443+ {
444+ visible = gtk_widget_get_visible (widget);
445+ sensitive = gtk_widget_get_sensitive (widget);
446+ }
447+
448+ dbusmenu_menuitem_property_set_shortcut_menuitem (mi, GTK_MENU_ITEM (widget));
449+
450+ g_signal_connect (G_OBJECT (mi),
451+ DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
452+ G_CALLBACK (item_activated),
453+ widget);
454+
455+ g_signal_connect (G_OBJECT (mi),
456+ DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW,
457+ G_CALLBACK (item_about_to_show),
458+ widget);
459+ }
460+
461+ dbusmenu_menuitem_property_set_bool (mi,
462+ DBUSMENU_MENUITEM_PROP_VISIBLE,
463+ visible);
464+
465+ dbusmenu_menuitem_property_set_bool (mi,
466+ DBUSMENU_MENUITEM_PROP_ENABLED,
467+ sensitive);
468+
469+ g_signal_connect (widget,
470+ "notify",
471+ G_CALLBACK (widget_notify_cb),
472+ mi);
473+ return mi;
474+ }
475+
476+ /* If it's none of those we're going to just create a
477+ generic menuitem as a place holder for it. */
478+ return dbusmenu_menuitem_new();
479+}
480+
481+static void
482+menuitem_notify_cb (GtkWidget *widget,
483+ GParamSpec *pspec,
484+ gpointer data)
485+{
486+ if (pspec->name == g_intern_static_string ("visible"))
487+ {
488+ GtkWidget * new_toplevel = gtk_widget_get_toplevel (widget);
489+ GtkWidget * old_toplevel = GTK_WIDGET(data);
490+
491+ if (new_toplevel == old_toplevel) {
492+ /* TODO: Figure this out -> rebuild (context->bridge, window); */
493+ }
494+
495+ /* We only care about this once, so let's disconnect now. */
496+ g_signal_handlers_disconnect_by_func (widget,
497+ G_CALLBACK (menuitem_notify_cb),
498+ data);
499+ }
500+}
501+
502+static void
503+accel_changed (GtkWidget *widget,
504+ gpointer data)
505+{
506+ DbusmenuMenuitem *mi = (DbusmenuMenuitem *)data;
507+ dbusmenu_menuitem_property_set_shortcut_menuitem (mi, GTK_MENU_ITEM (widget));
508+}
509+
510+static gboolean
511+update_stock_item (DbusmenuMenuitem *menuitem,
512+ GtkWidget *widget)
513+{
514+ GtkStockItem stock;
515+ GtkImage *image;
516+
517+ g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
518+
519+ image = GTK_IMAGE (widget);
520+
521+ if (gtk_image_get_storage_type (image) != GTK_IMAGE_STOCK)
522+ return FALSE;
523+
524+ gchar * stock_id = NULL;
525+ gtk_image_get_stock(image, &stock_id, NULL);
526+
527+ gtk_stock_lookup (stock_id, &stock);
528+
529+ if (should_show_image (image))
530+ dbusmenu_menuitem_property_set (menuitem,
531+ DBUSMENU_MENUITEM_PROP_ICON_NAME,
532+ stock_id);
533+ else
534+ dbusmenu_menuitem_property_remove (menuitem,
535+ DBUSMENU_MENUITEM_PROP_ICON_NAME);
536+
537+ const gchar *label = dbusmenu_menuitem_property_get (menuitem,
538+ DBUSMENU_MENUITEM_PROP_LABEL);
539+
540+ if (stock.label != NULL && label != NULL)
541+ {
542+ dbusmenu_menuitem_property_set (menuitem,
543+ DBUSMENU_MENUITEM_PROP_LABEL,
544+ stock.label);
545+
546+ return TRUE;
547+ }
548+
549+ return FALSE;
550+}
551+
552+static void
553+checkbox_toggled (GtkWidget *widget, DbusmenuMenuitem *mi)
554+{
555+ dbusmenu_menuitem_property_set_int (mi,
556+ DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
557+ gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
558+}
559+
560+static void
561+update_icon_name (DbusmenuMenuitem *menuitem,
562+ GtkWidget *widget)
563+{
564+ GtkImage *image;
565+
566+ g_return_if_fail (GTK_IS_IMAGE (widget));
567+
568+ image = GTK_IMAGE (widget);
569+
570+ if (gtk_image_get_storage_type (image) != GTK_IMAGE_ICON_NAME)
571+ return;
572+
573+ if (should_show_image (image)) {
574+ const gchar * icon_name = NULL;
575+ gtk_image_get_icon_name(image, &icon_name, NULL);
576+ dbusmenu_menuitem_property_set (menuitem,
577+ DBUSMENU_MENUITEM_PROP_ICON_NAME,
578+ icon_name);
579+ } else {
580+ dbusmenu_menuitem_property_remove (menuitem,
581+ DBUSMENU_MENUITEM_PROP_ICON_NAME);
582+ }
583+}
584+
585+static GtkWidget *
586+find_menu_label (GtkWidget *widget)
587+{
588+ GtkWidget *label = NULL;
589+
590+ if (GTK_IS_LABEL (widget))
591+ return widget;
592+
593+ if (GTK_IS_CONTAINER (widget))
594+ {
595+ GList *children;
596+ GList *l;
597+
598+ children = gtk_container_get_children (GTK_CONTAINER (widget));
599+
600+ for (l = children; l; l = l->next)
601+ {
602+ label = find_menu_label (l->data);
603+
604+ if (label)
605+ break;
606+ }
607+
608+ g_list_free (children);
609+ }
610+
611+ return label;
612+}
613+
614+static void
615+label_notify_cb (GtkWidget *widget,
616+ GParamSpec *pspec,
617+ gpointer data)
618+{
619+ DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
620+
621+ if (pspec->name == g_intern_static_string ("label"))
622+ {
623+ dbusmenu_menuitem_property_set (child,
624+ DBUSMENU_MENUITEM_PROP_LABEL,
625+ gtk_label_get_text (GTK_LABEL (widget)));
626+ }
627+}
628+
629+static void
630+action_notify_cb (GtkAction *action,
631+ GParamSpec *pspec,
632+ gpointer data)
633+{
634+ DbusmenuMenuitem *mi = (DbusmenuMenuitem *)data;
635+
636+ if (pspec->name == g_intern_static_string ("sensitive"))
637+ {
638+ dbusmenu_menuitem_property_set_bool (mi,
639+ DBUSMENU_MENUITEM_PROP_ENABLED,
640+ gtk_action_is_sensitive (action));
641+ }
642+ else if (pspec->name == g_intern_static_string ("visible"))
643+ {
644+ dbusmenu_menuitem_property_set_bool (mi,
645+ DBUSMENU_MENUITEM_PROP_VISIBLE,
646+ gtk_action_is_visible (action));
647+ }
648+ else if (pspec->name == g_intern_static_string ("active"))
649+ {
650+ dbusmenu_menuitem_property_set_bool (mi,
651+ DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
652+ gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
653+ }
654+ else if (pspec->name == g_intern_static_string ("label"))
655+ {
656+ dbusmenu_menuitem_property_set (mi,
657+ DBUSMENU_MENUITEM_PROP_LABEL,
658+ gtk_action_get_label (action));
659+ }
660+}
661+
662+static void
663+item_activated (DbusmenuMenuitem *item, guint timestamp, gpointer user_data)
664+{
665+ GtkWidget *child;
666+
667+ if (user_data != NULL)
668+ {
669+ child = (GtkWidget *)user_data;
670+
671+ if (GTK_IS_MENU_ITEM (child))
672+ {
673+ gtk_menu_item_activate (GTK_MENU_ITEM (child));
674+ }
675+ }
676+}
677+
678+static gboolean
679+item_about_to_show (DbusmenuMenuitem *item, gpointer user_data)
680+{
681+ GtkWidget *child;
682+
683+ if (user_data != NULL)
684+ {
685+ child = (GtkWidget *)user_data;
686+
687+ if (GTK_IS_MENU_ITEM (child))
688+ {
689+ // Only called for items with submens. So we activate it here in
690+ // case the program dynamically creates menus (like empathy does)
691+ gtk_menu_item_activate (GTK_MENU_ITEM (child));
692+ }
693+ }
694+
695+ return TRUE;
696+}
697+
698+static void
699+widget_notify_cb (GtkWidget *widget,
700+ GParamSpec *pspec,
701+ gpointer data)
702+{
703+ DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
704+
705+ if (pspec->name == g_intern_static_string ("sensitive"))
706+ {
707+ dbusmenu_menuitem_property_set_bool (child,
708+ DBUSMENU_MENUITEM_PROP_ENABLED,
709+ gtk_widget_get_sensitive (widget));
710+ }
711+ else if (pspec->name == g_intern_static_string ("label"))
712+ {
713+ dbusmenu_menuitem_property_set (child,
714+ DBUSMENU_MENUITEM_PROP_LABEL,
715+ gtk_menu_item_get_label (GTK_MENU_ITEM (widget)));
716+ }
717+ else if (pspec->name == g_intern_static_string ("visible"))
718+ {
719+ dbusmenu_menuitem_property_set_bool (child,
720+ DBUSMENU_MENUITEM_PROP_VISIBLE,
721+ gtk_widget_get_visible (widget));
722+ }
723+ else if (pspec->name == g_intern_static_string ("stock"))
724+ {
725+ update_stock_item (child, widget);
726+ }
727+ else if (pspec->name == g_intern_static_string ("icon-name"))
728+ {
729+ update_icon_name (child, widget);
730+ }
731+ else if (pspec->name == g_intern_static_string ("parent"))
732+ {
733+ /*
734+ * We probably should have added a 'remove' method to the
735+ * UbuntuMenuProxy early on, but it's late in the cycle now.
736+ */
737+ if (gtk_widget_get_parent (widget) == NULL)
738+ {
739+ g_signal_handlers_disconnect_by_func (widget,
740+ G_CALLBACK (widget_notify_cb),
741+ child);
742+
743+ DbusmenuMenuitem *parent = g_object_get_data (G_OBJECT (child), "dbusmenu-parent");
744+
745+ if (DBUSMENU_IS_MENUITEM (parent) && DBUSMENU_IS_MENUITEM (child))
746+ {
747+ dbusmenu_menuitem_child_delete (parent, child);
748+ }
749+ }
750+ }
751+}
752+
753+static gboolean
754+should_show_image (GtkImage *image)
755+{
756+ GtkWidget *item;
757+
758+ item = gtk_widget_get_ancestor (GTK_WIDGET (image),
759+ GTK_TYPE_IMAGE_MENU_ITEM);
760+
761+ if (item)
762+ {
763+ GtkSettings *settings;
764+ gboolean gtk_menu_images;
765+
766+ settings = gtk_widget_get_settings (item);
767+
768+ g_object_get (settings, "gtk-menu-images", &gtk_menu_images, NULL);
769+
770+ if (gtk_menu_images)
771+ return TRUE;
772+
773+ return gtk_image_menu_item_get_always_show_image (GTK_IMAGE_MENU_ITEM (item));
774+ }
775+
776+ return FALSE;
777+}
778+
779+>>>>>>> MERGE-SOURCE
780
781=== modified file 'libdbusmenu-gtk/serializablemenuitem.c'
782--- libdbusmenu-gtk/serializablemenuitem.c 2011-01-27 19:48:12 +0000
783+++ libdbusmenu-gtk/serializablemenuitem.c 2011-01-27 19:48:12 +0000
784@@ -166,7 +166,7 @@
785 }
786
787 /**
788- dbusmenu_gtk_serializable_menu_item_build_dbusmenu_menuitem:
789+ dbusmenu_gtk_serializable_menu_item_build_menuitem:
790 @smi: #DbusmenuGtkSerializableMenuItem to build a #DbusmenuMenuitem mirroring
791
792 This function is for menu items that are instanciated from
793@@ -179,7 +179,7 @@
794 set by this object.
795 */
796 DbusmenuMenuitem *
797-dbusmenu_gtk_serializable_menu_item_build_dbusmenu_menuitem (DbusmenuGtkSerializableMenuItem * smi)
798+dbusmenu_gtk_serializable_menu_item_build_menuitem (DbusmenuGtkSerializableMenuItem * smi)
799 {
800 g_return_val_if_fail(DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM(smi), NULL);
801
802@@ -207,7 +207,7 @@
803 DbusmenuGtkSerializableMenuItem * smi = DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM(g_object_new(th->type, NULL));
804 g_return_val_if_fail(smi != NULL, FALSE);
805
806- dbusmenu_gtk_serializable_menu_item_set_dbusmenu_menuitem(smi, newitem);
807+ dbusmenu_gtk_serializable_menu_item_set_menuitem(smi, newitem);
808 dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, GTK_MENU_ITEM(smi), parent);
809
810 return TRUE;
811@@ -265,7 +265,7 @@
812 }
813
814 /**
815- dbusmenu_gtk_serializable_menu_item_set_dbusmenu_menuitem:
816+ dbusmenu_gtk_serializable_menu_item_set_menuitem:
817 @smi: #DbusmenuGtkSerializableMenuItem to set the @DbusmenuGtkSerializableMenuItem::dbusmenu-menuitem of
818 @mi: Menuitem to get the properties from
819
820@@ -276,7 +276,7 @@
821 pick up this property being set.
822 */
823 void
824-dbusmenu_gtk_serializable_menu_item_set_dbusmenu_menuitem (DbusmenuGtkSerializableMenuItem * smi, DbusmenuMenuitem * mi)
825+dbusmenu_gtk_serializable_menu_item_set_menuitem (DbusmenuGtkSerializableMenuItem * smi, DbusmenuMenuitem * mi)
826 {
827 g_return_if_fail(DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM(smi));
828 g_return_if_fail(mi != NULL);
829
830=== modified file 'libdbusmenu-gtk/serializablemenuitem.h'
831--- libdbusmenu-gtk/serializablemenuitem.h 2011-01-27 19:48:12 +0000
832+++ libdbusmenu-gtk/serializablemenuitem.h 2011-01-27 19:48:12 +0000
833@@ -90,6 +90,13 @@
834 DbusmenuGtkSerializableMenuItem:
835 @parent: Inherit from GtkMenuItem
836 @priv: Blind structure of private variables
837+
838+ The Serializable Menuitem provides a way for menu items to be created
839+ that can easily be picked up by the Dbusmenu GTK Parser. This way
840+ you can create custom items, and transport them across dbusmenu to
841+ your menus or the appmenu on the other side of the bus. By providing
842+ these function the parser has enough information to both serialize, and
843+ deserialize on the other side, the menuitem you've so carefully created.
844 */
845 struct _DbusmenuGtkSerializableMenuItem {
846 GtkMenuItem parent;
847@@ -99,9 +106,9 @@
848
849 GType dbusmenu_gtk_serializable_menu_item_get_type (void);
850
851-DbusmenuMenuitem * dbusmenu_gtk_serializable_menu_item_build_dbusmenu_menuitem (DbusmenuGtkSerializableMenuItem * smi);
852+DbusmenuMenuitem * dbusmenu_gtk_serializable_menu_item_build_menuitem (DbusmenuGtkSerializableMenuItem * smi);
853 void dbusmenu_gtk_serializable_menu_item_register_to_client (DbusmenuClient * client, GType item_type);
854-void dbusmenu_gtk_serializable_menu_item_set_dbusmenu_menuitem (DbusmenuGtkSerializableMenuItem * smi, DbusmenuMenuitem * mi);
855+void dbusmenu_gtk_serializable_menu_item_set_menuitem (DbusmenuGtkSerializableMenuItem * smi, DbusmenuMenuitem * mi);
856
857 G_END_DECLS
858

Subscribers

People subscribed via source and target branches