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
=== modified file '.bzrignore'
--- .bzrignore 2011-01-27 19:48:12 +0000
+++ .bzrignore 2011-01-27 19:48:12 +0000
@@ -229,4 +229,8 @@
229libdbusmenu-gtk/libdbusmenu_gtk_la-serializablemenuitem.lo229libdbusmenu-gtk/libdbusmenu_gtk_la-serializablemenuitem.lo
230docs/libdbusmenu-gtk/reference/html/DbusmenuGtkSerializableMenuItem.html230docs/libdbusmenu-gtk/reference/html/DbusmenuGtkSerializableMenuItem.html
231docs/libdbusmenu-gtk/reference/tmpl/serializablemenuitem.sgml231docs/libdbusmenu-gtk/reference/tmpl/serializablemenuitem.sgml
232libdbusmenu-gtk/libdbusmenu_gtk_la-parser.lo
233test-gtk-parser
234test-gtk-parser-test
235test-gtk-parser.xml
232>>>>>>> MERGE-SOURCE236>>>>>>> MERGE-SOURCE
233237
=== modified file 'libdbusmenu-glib/client.h'
--- libdbusmenu-glib/client.h 2011-01-27 19:48:12 +0000
+++ libdbusmenu-glib/client.h 2011-01-27 19:48:12 +0000
@@ -110,7 +110,28 @@
110 DbusmenuClientPrivate * priv;110 DbusmenuClientPrivate * priv;
111};111};
112112
113/**
114 DbusmenuClientTypeHandler:
115 @newitem: The #DbusmenuMenuitem that was created
116 @parent: The parent of @newitem or #NULL if none
117 @client: A pointer to the #DbusmenuClient
118 @user_data: The data you gave us
119
120 The type handler is called when a dbusmenu item is created
121 with a matching type as setup in #dbusmenu_client_add_type_handler
122*/
113typedef gboolean (*DbusmenuClientTypeHandler) (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);123typedef gboolean (*DbusmenuClientTypeHandler) (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
124
125/**
126 DbusmenuClientTypeDestroyHandler:
127 @client: A pointer to the #DbusmenuClient
128 @type: The type that this handler was registered with
129 @user_data: The data you gave us
130
131 This handler is called when the type becomes unregistered by the
132 client. This is usally caused by the #DbusmenuClient being destroyed
133 and should free memory or unref objects in @user_data.
134*/
114typedef void (*DbusmenuClientTypeDestroyHandler) (DbusmenuClient * client, const gchar * type, gpointer user_data);135typedef void (*DbusmenuClientTypeDestroyHandler) (DbusmenuClient * client, const gchar * type, gpointer user_data);
115136
116GType dbusmenu_client_get_type (void);137GType dbusmenu_client_get_type (void);
117138
=== modified file 'libdbusmenu-gtk/Makefile.am'
--- libdbusmenu-gtk/Makefile.am 2011-01-27 19:48:12 +0000
+++ libdbusmenu-gtk/Makefile.am 2011-01-27 19:48:12 +0000
@@ -28,6 +28,7 @@
28 parser.h28 parser.h
29=======29=======
30 menuitem.h \30 menuitem.h \
31 parser.h \
31 serializablemenuitem.h32 serializablemenuitem.h
32>>>>>>> MERGE-SOURCE33>>>>>>> MERGE-SOURCE
3334
@@ -45,6 +46,8 @@
45 parser.c46 parser.c
46=======47=======
47 menuitem.c \48 menuitem.c \
49 parser.h \
50 parser.c \
48 serializablemenuitem.h \51 serializablemenuitem.h \
49 serializablemenuitem.c52 serializablemenuitem.c
50>>>>>>> MERGE-SOURCE53>>>>>>> MERGE-SOURCE
5154
=== modified file 'libdbusmenu-gtk/parser.c'
--- libdbusmenu-gtk/parser.c 2011-01-27 14:50:24 +0000
+++ libdbusmenu-gtk/parser.c 2011-01-27 19:48:12 +0000
@@ -1,3 +1,4 @@
1<<<<<<< TREE
1/*2/*
2Parse to take a set of GTK Menus and turn them into something that can3Parse to take a set of GTK Menus and turn them into something that can
3be sent over the wire.4be sent over the wire.
@@ -665,3 +666,703 @@
665 return FALSE;666 return FALSE;
666}667}
667668
669=======
670/*
671Parse to take a set of GTK Menus and turn them into something that can
672be sent over the wire.
673
674Copyright 2011 Canonical Ltd.
675
676Authors:
677 Numerous (check Bazaar)
678
679This program is free software: you can redistribute it and/or modify it
680under the terms of either or both of the following licenses:
681
6821) the GNU Lesser General Public License version 3, as published by the
683Free Software Foundation; and/or
6842) the GNU Lesser General Public License version 2.1, as published by
685the Free Software Foundation.
686
687This program is distributed in the hope that it will be useful, but
688WITHOUT ANY WARRANTY; without even the implied warranties of
689MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
690PURPOSE. See the applicable version of the GNU Lesser General Public
691License for more details.
692
693You should have received a copy of both the GNU Lesser General Public
694License version 3 and version 2.1 along with this program. If not, see
695<http://www.gnu.org/licenses/>
696*/
697
698#include "parser.h"
699#include "menuitem.h"
700#include "serializablemenuitem.h"
701
702#define CACHED_MENUITEM "dbusmenu-gtk-parser-cached-item"
703
704typedef struct _RecurseContext
705{
706 GtkWidget * toplevel;
707 gint count;
708 DbusmenuMenuitem *stack[30];
709} RecurseContext;
710
711static void parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse);
712static DbusmenuMenuitem * construct_dbusmenu_for_widget (GtkWidget * widget);
713static void accel_changed (GtkWidget * widget,
714 gpointer data);
715static gboolean update_stock_item (DbusmenuMenuitem * menuitem,
716 GtkWidget * widget);
717static void checkbox_toggled (GtkWidget * widget,
718 DbusmenuMenuitem * mi);
719static void update_icon_name (DbusmenuMenuitem * menuitem,
720 GtkWidget * widget);
721static GtkWidget * find_menu_label (GtkWidget * widget);
722static void label_notify_cb (GtkWidget * widget,
723 GParamSpec * pspec,
724 gpointer data);
725static void action_notify_cb (GtkAction * action,
726 GParamSpec * pspec,
727 gpointer data);
728static void item_activated (DbusmenuMenuitem * item,
729 guint timestamp,
730 gpointer user_data);
731static gboolean item_about_to_show (DbusmenuMenuitem * item,
732 gpointer user_data);
733static void widget_notify_cb (GtkWidget * widget,
734 GParamSpec * pspec,
735 gpointer data);
736static gboolean should_show_image (GtkImage * image);
737static void menuitem_notify_cb (GtkWidget * widget,
738 GParamSpec * pspec,
739 gpointer data);
740
741DbusmenuMenuitem *
742dbusmenu_gtk_parse_menu_structure (GtkWidget * widget)
743{
744 RecurseContext recurse = {0};
745
746 recurse.count = -1;
747 recurse.toplevel = gtk_widget_get_toplevel(widget);
748
749 parse_menu_structure_helper(widget, &recurse);
750
751 if (recurse.stack[0] != NULL && DBUSMENU_IS_MENUITEM(recurse.stack[0])) {
752 return recurse.stack[0];
753 }
754
755 return NULL;
756}
757
758static void
759dbusmenu_cache_freed (gpointer data, GObject * obj)
760{
761 /* If the dbusmenu item is killed we don't need to remove
762 the weak ref as well. */
763 g_object_steal_data(G_OBJECT(data), CACHED_MENUITEM);
764 return;
765}
766
767static void
768object_cache_freed (gpointer data)
769{
770 g_object_weak_unref(G_OBJECT(data), dbusmenu_cache_freed, data);
771 return;
772}
773
774static void
775parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse)
776{
777 if (GTK_IS_CONTAINER (widget))
778 {
779 gboolean increment = GTK_IS_MENU_SHELL (widget) || GTK_IS_MENU_ITEM (widget);
780
781 if (increment)
782 recurse->count++;
783
784 /* Okay, this is a little janky and all.. but some applications update some
785 * menuitem properties such as sensitivity on the activate callback. This
786 * seems a little weird, but it's not our place to judge when all this code
787 * is so crazy. So we're going to get ever crazier and activate all the
788 * menus that are directly below the menubar and force the applications to
789 * update their sensitivity. The menus won't actually popup in the app
790 * window due to our gtk+ patches.
791 *
792 * Note that this will not force menuitems in submenus to be updated as well.
793 */
794 if (recurse->count == 0 && GTK_IS_MENU_BAR (widget))
795 {
796 GList *children = gtk_container_get_children (GTK_CONTAINER (widget));
797
798 for (; children != NULL; children = children->next)
799 {
800 gtk_menu_shell_activate_item (GTK_MENU_SHELL (widget),
801 children->data,
802 TRUE);
803 }
804
805 g_list_free (children);
806 }
807
808 if (recurse->count > -1 && increment)
809 {
810 gpointer pmi = g_object_get_data(G_OBJECT(widget), CACHED_MENUITEM);
811 DbusmenuMenuitem *dmi = NULL;
812 if (pmi != NULL) dmi = DBUSMENU_MENUITEM(pmi);
813
814 if (dmi != NULL)
815 {
816 if (increment)
817 recurse->count--;
818
819 return;
820 }
821 else
822 {
823 recurse->stack[recurse->count] = construct_dbusmenu_for_widget (widget);
824 g_object_set_data_full(G_OBJECT(widget), CACHED_MENUITEM, recurse->stack[recurse->count], object_cache_freed);
825 g_object_weak_ref(G_OBJECT(recurse->stack[recurse->count]), dbusmenu_cache_freed, widget);
826 }
827
828 if (!gtk_widget_get_visible (widget))
829 {
830 g_signal_connect (G_OBJECT (widget),
831 "notify::visible",
832 G_CALLBACK (menuitem_notify_cb),
833 recurse->toplevel);
834 }
835
836 if (GTK_IS_TEAROFF_MENU_ITEM (widget))
837 {
838 dbusmenu_menuitem_property_set_bool (recurse->stack[recurse->count],
839 DBUSMENU_MENUITEM_PROP_VISIBLE,
840 FALSE);
841 }
842
843 if (recurse->count > 0)
844 {
845 GList *children = NULL;
846 GList *peek = NULL;
847
848 if (recurse->stack[recurse->count - 1])
849 {
850 children = dbusmenu_menuitem_get_children (recurse->stack[recurse->count - 1]);
851
852 if (children)
853 {
854 peek = g_list_find (children, recurse->stack[recurse->count]);
855 }
856
857 if (!peek)
858 {
859 /* Should we set a weak ref on the parent? */
860 g_object_set_data (G_OBJECT (recurse->stack[recurse->count]),
861 "dbusmenu-parent",
862 recurse->stack[recurse->count - 1]);
863 dbusmenu_menuitem_child_append (recurse->stack[recurse->count - 1],
864 recurse->stack[recurse->count]);
865 }
866 }
867 else
868 {
869 DbusmenuMenuitem *item = NULL; /* g_hash_table_lookup (recurse->context->lookup,
870 gtk_widget_get_parent (widget)); */
871
872 if (item)
873 {
874 children = dbusmenu_menuitem_get_children (item);
875
876 if (children)
877 {
878 peek = g_list_find (children, recurse->stack[recurse->count]);
879 }
880
881 if (!peek)
882 {
883 g_object_set_data (G_OBJECT (recurse->stack[recurse->count]),
884 "dbusmenu-parent",
885 recurse->stack[recurse->count - 1]);
886
887 dbusmenu_menuitem_child_append (item, recurse->stack[recurse->count]);
888 }
889 }
890 }
891 }
892 }
893
894 gtk_container_foreach (GTK_CONTAINER (widget),
895 (GtkCallback)parse_menu_structure_helper,
896 recurse);
897
898 if (GTK_IS_MENU_ITEM (widget))
899 {
900 GtkWidget *menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
901
902 if (menu != NULL)
903 {
904 parse_menu_structure_helper (menu, recurse);
905 }
906 }
907
908 if (increment)
909 recurse->count--;
910 }
911}
912
913/* Turn a widget into a dbusmenu item depending on the type of GTK
914 object that it is. */
915static DbusmenuMenuitem *
916construct_dbusmenu_for_widget (GtkWidget * widget)
917{
918 /* If it's a subclass of our serializable menu item then we can
919 use its own build function */
920 if (DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM(widget)) {
921 DbusmenuGtkSerializableMenuItem * smi = DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM(widget);
922 return dbusmenu_gtk_serializable_menu_item_build_menuitem(smi);
923 }
924
925 /* If it's a standard GTK Menu Item we need to do some of our own work */
926 if (GTK_IS_MENU_ITEM (widget))
927 {
928 DbusmenuMenuitem *mi = dbusmenu_menuitem_new ();
929
930 gboolean visible = FALSE;
931 gboolean sensitive = FALSE;
932 if (GTK_IS_SEPARATOR_MENU_ITEM (widget))
933 {
934 dbusmenu_menuitem_property_set (mi,
935 "type",
936 "separator");
937
938 visible = gtk_widget_get_visible (widget);
939 sensitive = gtk_widget_get_sensitive (widget);
940 }
941 else
942 {
943 gboolean label_set = FALSE;
944
945 g_signal_connect (widget,
946 "accel-closures-changed",
947 G_CALLBACK (accel_changed),
948 mi);
949
950 if (GTK_IS_CHECK_MENU_ITEM (widget))
951 {
952 dbusmenu_menuitem_property_set (mi,
953 DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE,
954 gtk_check_menu_item_get_draw_as_radio (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_RADIO : DBUSMENU_MENUITEM_TOGGLE_CHECK);
955
956 dbusmenu_menuitem_property_set_int (mi,
957 DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
958 gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
959
960 g_signal_connect (widget,
961 "activate",
962 G_CALLBACK (checkbox_toggled),
963 mi);
964 }
965
966 if (GTK_IS_IMAGE_MENU_ITEM (widget))
967 {
968 GtkWidget *image;
969 GtkImageType image_type;
970
971 image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (widget));
972
973 if (GTK_IS_IMAGE (image))
974 {
975 image_type = gtk_image_get_storage_type (GTK_IMAGE (image));
976
977 if (image_type == GTK_IMAGE_STOCK)
978 {
979 label_set = update_stock_item (mi, image);
980 }
981 else if (image_type == GTK_IMAGE_ICON_NAME)
982 {
983 update_icon_name (mi, image);
984 }
985 else if (image_type == GTK_IMAGE_PIXBUF)
986 {
987 dbusmenu_menuitem_property_set_image (mi,
988 DBUSMENU_MENUITEM_PROP_ICON_DATA,
989 gtk_image_get_pixbuf (GTK_IMAGE (image)));
990 }
991 }
992 }
993
994 GtkWidget *label = find_menu_label (widget);
995
996 dbusmenu_menuitem_property_set (mi,
997 "label",
998 label ? gtk_label_get_text (GTK_LABEL (label)) : NULL);
999
1000 if (label)
1001 {
1002 // Sometimes, an app will directly find and modify the label
1003 // (like empathy), so watch the label especially for that.
1004 g_signal_connect (G_OBJECT (label),
1005 "notify",
1006 G_CALLBACK (label_notify_cb),
1007 mi);
1008 }
1009
1010 if (GTK_IS_ACTIVATABLE (widget))
1011 {
1012 GtkActivatable *activatable = GTK_ACTIVATABLE (widget);
1013
1014 if (gtk_activatable_get_use_action_appearance (activatable))
1015 {
1016 GtkAction *action = gtk_activatable_get_related_action (activatable);
1017
1018 if (action)
1019 {
1020 visible = gtk_action_is_visible (action);
1021 sensitive = gtk_action_is_sensitive (action);
1022
1023 g_signal_connect_object (action, "notify",
1024 G_CALLBACK (action_notify_cb),
1025 mi,
1026 G_CONNECT_AFTER);
1027 }
1028 }
1029 }
1030
1031 if (!g_object_get_data (G_OBJECT (widget), "gtk-empty-menu-item") && !GTK_IS_TEAROFF_MENU_ITEM (widget))
1032 {
1033 visible = gtk_widget_get_visible (widget);
1034 sensitive = gtk_widget_get_sensitive (widget);
1035 }
1036
1037 dbusmenu_menuitem_property_set_shortcut_menuitem (mi, GTK_MENU_ITEM (widget));
1038
1039 g_signal_connect (G_OBJECT (mi),
1040 DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
1041 G_CALLBACK (item_activated),
1042 widget);
1043
1044 g_signal_connect (G_OBJECT (mi),
1045 DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW,
1046 G_CALLBACK (item_about_to_show),
1047 widget);
1048 }
1049
1050 dbusmenu_menuitem_property_set_bool (mi,
1051 DBUSMENU_MENUITEM_PROP_VISIBLE,
1052 visible);
1053
1054 dbusmenu_menuitem_property_set_bool (mi,
1055 DBUSMENU_MENUITEM_PROP_ENABLED,
1056 sensitive);
1057
1058 g_signal_connect (widget,
1059 "notify",
1060 G_CALLBACK (widget_notify_cb),
1061 mi);
1062 return mi;
1063 }
1064
1065 /* If it's none of those we're going to just create a
1066 generic menuitem as a place holder for it. */
1067 return dbusmenu_menuitem_new();
1068}
1069
1070static void
1071menuitem_notify_cb (GtkWidget *widget,
1072 GParamSpec *pspec,
1073 gpointer data)
1074{
1075 if (pspec->name == g_intern_static_string ("visible"))
1076 {
1077 GtkWidget * new_toplevel = gtk_widget_get_toplevel (widget);
1078 GtkWidget * old_toplevel = GTK_WIDGET(data);
1079
1080 if (new_toplevel == old_toplevel) {
1081 /* TODO: Figure this out -> rebuild (context->bridge, window); */
1082 }
1083
1084 /* We only care about this once, so let's disconnect now. */
1085 g_signal_handlers_disconnect_by_func (widget,
1086 G_CALLBACK (menuitem_notify_cb),
1087 data);
1088 }
1089}
1090
1091static void
1092accel_changed (GtkWidget *widget,
1093 gpointer data)
1094{
1095 DbusmenuMenuitem *mi = (DbusmenuMenuitem *)data;
1096 dbusmenu_menuitem_property_set_shortcut_menuitem (mi, GTK_MENU_ITEM (widget));
1097}
1098
1099static gboolean
1100update_stock_item (DbusmenuMenuitem *menuitem,
1101 GtkWidget *widget)
1102{
1103 GtkStockItem stock;
1104 GtkImage *image;
1105
1106 g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
1107
1108 image = GTK_IMAGE (widget);
1109
1110 if (gtk_image_get_storage_type (image) != GTK_IMAGE_STOCK)
1111 return FALSE;
1112
1113 gchar * stock_id = NULL;
1114 gtk_image_get_stock(image, &stock_id, NULL);
1115
1116 gtk_stock_lookup (stock_id, &stock);
1117
1118 if (should_show_image (image))
1119 dbusmenu_menuitem_property_set (menuitem,
1120 DBUSMENU_MENUITEM_PROP_ICON_NAME,
1121 stock_id);
1122 else
1123 dbusmenu_menuitem_property_remove (menuitem,
1124 DBUSMENU_MENUITEM_PROP_ICON_NAME);
1125
1126 const gchar *label = dbusmenu_menuitem_property_get (menuitem,
1127 DBUSMENU_MENUITEM_PROP_LABEL);
1128
1129 if (stock.label != NULL && label != NULL)
1130 {
1131 dbusmenu_menuitem_property_set (menuitem,
1132 DBUSMENU_MENUITEM_PROP_LABEL,
1133 stock.label);
1134
1135 return TRUE;
1136 }
1137
1138 return FALSE;
1139}
1140
1141static void
1142checkbox_toggled (GtkWidget *widget, DbusmenuMenuitem *mi)
1143{
1144 dbusmenu_menuitem_property_set_int (mi,
1145 DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
1146 gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
1147}
1148
1149static void
1150update_icon_name (DbusmenuMenuitem *menuitem,
1151 GtkWidget *widget)
1152{
1153 GtkImage *image;
1154
1155 g_return_if_fail (GTK_IS_IMAGE (widget));
1156
1157 image = GTK_IMAGE (widget);
1158
1159 if (gtk_image_get_storage_type (image) != GTK_IMAGE_ICON_NAME)
1160 return;
1161
1162 if (should_show_image (image)) {
1163 const gchar * icon_name = NULL;
1164 gtk_image_get_icon_name(image, &icon_name, NULL);
1165 dbusmenu_menuitem_property_set (menuitem,
1166 DBUSMENU_MENUITEM_PROP_ICON_NAME,
1167 icon_name);
1168 } else {
1169 dbusmenu_menuitem_property_remove (menuitem,
1170 DBUSMENU_MENUITEM_PROP_ICON_NAME);
1171 }
1172}
1173
1174static GtkWidget *
1175find_menu_label (GtkWidget *widget)
1176{
1177 GtkWidget *label = NULL;
1178
1179 if (GTK_IS_LABEL (widget))
1180 return widget;
1181
1182 if (GTK_IS_CONTAINER (widget))
1183 {
1184 GList *children;
1185 GList *l;
1186
1187 children = gtk_container_get_children (GTK_CONTAINER (widget));
1188
1189 for (l = children; l; l = l->next)
1190 {
1191 label = find_menu_label (l->data);
1192
1193 if (label)
1194 break;
1195 }
1196
1197 g_list_free (children);
1198 }
1199
1200 return label;
1201}
1202
1203static void
1204label_notify_cb (GtkWidget *widget,
1205 GParamSpec *pspec,
1206 gpointer data)
1207{
1208 DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
1209
1210 if (pspec->name == g_intern_static_string ("label"))
1211 {
1212 dbusmenu_menuitem_property_set (child,
1213 DBUSMENU_MENUITEM_PROP_LABEL,
1214 gtk_label_get_text (GTK_LABEL (widget)));
1215 }
1216}
1217
1218static void
1219action_notify_cb (GtkAction *action,
1220 GParamSpec *pspec,
1221 gpointer data)
1222{
1223 DbusmenuMenuitem *mi = (DbusmenuMenuitem *)data;
1224
1225 if (pspec->name == g_intern_static_string ("sensitive"))
1226 {
1227 dbusmenu_menuitem_property_set_bool (mi,
1228 DBUSMENU_MENUITEM_PROP_ENABLED,
1229 gtk_action_is_sensitive (action));
1230 }
1231 else if (pspec->name == g_intern_static_string ("visible"))
1232 {
1233 dbusmenu_menuitem_property_set_bool (mi,
1234 DBUSMENU_MENUITEM_PROP_VISIBLE,
1235 gtk_action_is_visible (action));
1236 }
1237 else if (pspec->name == g_intern_static_string ("active"))
1238 {
1239 dbusmenu_menuitem_property_set_bool (mi,
1240 DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
1241 gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
1242 }
1243 else if (pspec->name == g_intern_static_string ("label"))
1244 {
1245 dbusmenu_menuitem_property_set (mi,
1246 DBUSMENU_MENUITEM_PROP_LABEL,
1247 gtk_action_get_label (action));
1248 }
1249}
1250
1251static void
1252item_activated (DbusmenuMenuitem *item, guint timestamp, gpointer user_data)
1253{
1254 GtkWidget *child;
1255
1256 if (user_data != NULL)
1257 {
1258 child = (GtkWidget *)user_data;
1259
1260 if (GTK_IS_MENU_ITEM (child))
1261 {
1262 gtk_menu_item_activate (GTK_MENU_ITEM (child));
1263 }
1264 }
1265}
1266
1267static gboolean
1268item_about_to_show (DbusmenuMenuitem *item, gpointer user_data)
1269{
1270 GtkWidget *child;
1271
1272 if (user_data != NULL)
1273 {
1274 child = (GtkWidget *)user_data;
1275
1276 if (GTK_IS_MENU_ITEM (child))
1277 {
1278 // Only called for items with submens. So we activate it here in
1279 // case the program dynamically creates menus (like empathy does)
1280 gtk_menu_item_activate (GTK_MENU_ITEM (child));
1281 }
1282 }
1283
1284 return TRUE;
1285}
1286
1287static void
1288widget_notify_cb (GtkWidget *widget,
1289 GParamSpec *pspec,
1290 gpointer data)
1291{
1292 DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
1293
1294 if (pspec->name == g_intern_static_string ("sensitive"))
1295 {
1296 dbusmenu_menuitem_property_set_bool (child,
1297 DBUSMENU_MENUITEM_PROP_ENABLED,
1298 gtk_widget_get_sensitive (widget));
1299 }
1300 else if (pspec->name == g_intern_static_string ("label"))
1301 {
1302 dbusmenu_menuitem_property_set (child,
1303 DBUSMENU_MENUITEM_PROP_LABEL,
1304 gtk_menu_item_get_label (GTK_MENU_ITEM (widget)));
1305 }
1306 else if (pspec->name == g_intern_static_string ("visible"))
1307 {
1308 dbusmenu_menuitem_property_set_bool (child,
1309 DBUSMENU_MENUITEM_PROP_VISIBLE,
1310 gtk_widget_get_visible (widget));
1311 }
1312 else if (pspec->name == g_intern_static_string ("stock"))
1313 {
1314 update_stock_item (child, widget);
1315 }
1316 else if (pspec->name == g_intern_static_string ("icon-name"))
1317 {
1318 update_icon_name (child, widget);
1319 }
1320 else if (pspec->name == g_intern_static_string ("parent"))
1321 {
1322 /*
1323 * We probably should have added a 'remove' method to the
1324 * UbuntuMenuProxy early on, but it's late in the cycle now.
1325 */
1326 if (gtk_widget_get_parent (widget) == NULL)
1327 {
1328 g_signal_handlers_disconnect_by_func (widget,
1329 G_CALLBACK (widget_notify_cb),
1330 child);
1331
1332 DbusmenuMenuitem *parent = g_object_get_data (G_OBJECT (child), "dbusmenu-parent");
1333
1334 if (DBUSMENU_IS_MENUITEM (parent) && DBUSMENU_IS_MENUITEM (child))
1335 {
1336 dbusmenu_menuitem_child_delete (parent, child);
1337 }
1338 }
1339 }
1340}
1341
1342static gboolean
1343should_show_image (GtkImage *image)
1344{
1345 GtkWidget *item;
1346
1347 item = gtk_widget_get_ancestor (GTK_WIDGET (image),
1348 GTK_TYPE_IMAGE_MENU_ITEM);
1349
1350 if (item)
1351 {
1352 GtkSettings *settings;
1353 gboolean gtk_menu_images;
1354
1355 settings = gtk_widget_get_settings (item);
1356
1357 g_object_get (settings, "gtk-menu-images", &gtk_menu_images, NULL);
1358
1359 if (gtk_menu_images)
1360 return TRUE;
1361
1362 return gtk_image_menu_item_get_always_show_image (GTK_IMAGE_MENU_ITEM (item));
1363 }
1364
1365 return FALSE;
1366}
1367
1368>>>>>>> MERGE-SOURCE
6681369
=== modified file 'libdbusmenu-gtk/serializablemenuitem.c'
--- libdbusmenu-gtk/serializablemenuitem.c 2011-01-27 19:48:12 +0000
+++ libdbusmenu-gtk/serializablemenuitem.c 2011-01-27 19:48:12 +0000
@@ -166,7 +166,7 @@
166}166}
167167
168/**168/**
169 dbusmenu_gtk_serializable_menu_item_build_dbusmenu_menuitem:169 dbusmenu_gtk_serializable_menu_item_build_menuitem:
170 @smi: #DbusmenuGtkSerializableMenuItem to build a #DbusmenuMenuitem mirroring170 @smi: #DbusmenuGtkSerializableMenuItem to build a #DbusmenuMenuitem mirroring
171171
172 This function is for menu items that are instanciated from172 This function is for menu items that are instanciated from
@@ -179,7 +179,7 @@
179 set by this object.179 set by this object.
180*/180*/
181DbusmenuMenuitem *181DbusmenuMenuitem *
182dbusmenu_gtk_serializable_menu_item_build_dbusmenu_menuitem (DbusmenuGtkSerializableMenuItem * smi)182dbusmenu_gtk_serializable_menu_item_build_menuitem (DbusmenuGtkSerializableMenuItem * smi)
183{183{
184 g_return_val_if_fail(DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM(smi), NULL);184 g_return_val_if_fail(DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM(smi), NULL);
185185
@@ -207,7 +207,7 @@
207 DbusmenuGtkSerializableMenuItem * smi = DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM(g_object_new(th->type, NULL));207 DbusmenuGtkSerializableMenuItem * smi = DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM(g_object_new(th->type, NULL));
208 g_return_val_if_fail(smi != NULL, FALSE);208 g_return_val_if_fail(smi != NULL, FALSE);
209209
210 dbusmenu_gtk_serializable_menu_item_set_dbusmenu_menuitem(smi, newitem);210 dbusmenu_gtk_serializable_menu_item_set_menuitem(smi, newitem);
211 dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, GTK_MENU_ITEM(smi), parent);211 dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, GTK_MENU_ITEM(smi), parent);
212212
213 return TRUE;213 return TRUE;
@@ -265,7 +265,7 @@
265}265}
266266
267/**267/**
268 dbusmenu_gtk_serializable_menu_item_set_dbusmenu_menuitem:268 dbusmenu_gtk_serializable_menu_item_set_menuitem:
269 @smi: #DbusmenuGtkSerializableMenuItem to set the @DbusmenuGtkSerializableMenuItem::dbusmenu-menuitem of269 @smi: #DbusmenuGtkSerializableMenuItem to set the @DbusmenuGtkSerializableMenuItem::dbusmenu-menuitem of
270 @mi: Menuitem to get the properties from270 @mi: Menuitem to get the properties from
271271
@@ -276,7 +276,7 @@
276 pick up this property being set.276 pick up this property being set.
277*/277*/
278void278void
279dbusmenu_gtk_serializable_menu_item_set_dbusmenu_menuitem (DbusmenuGtkSerializableMenuItem * smi, DbusmenuMenuitem * mi)279dbusmenu_gtk_serializable_menu_item_set_menuitem (DbusmenuGtkSerializableMenuItem * smi, DbusmenuMenuitem * mi)
280{280{
281 g_return_if_fail(DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM(smi));281 g_return_if_fail(DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM(smi));
282 g_return_if_fail(mi != NULL);282 g_return_if_fail(mi != NULL);
283283
=== modified file 'libdbusmenu-gtk/serializablemenuitem.h'
--- libdbusmenu-gtk/serializablemenuitem.h 2011-01-27 19:48:12 +0000
+++ libdbusmenu-gtk/serializablemenuitem.h 2011-01-27 19:48:12 +0000
@@ -90,6 +90,13 @@
90 DbusmenuGtkSerializableMenuItem:90 DbusmenuGtkSerializableMenuItem:
91 @parent: Inherit from GtkMenuItem91 @parent: Inherit from GtkMenuItem
92 @priv: Blind structure of private variables92 @priv: Blind structure of private variables
93
94 The Serializable Menuitem provides a way for menu items to be created
95 that can easily be picked up by the Dbusmenu GTK Parser. This way
96 you can create custom items, and transport them across dbusmenu to
97 your menus or the appmenu on the other side of the bus. By providing
98 these function the parser has enough information to both serialize, and
99 deserialize on the other side, the menuitem you've so carefully created.
93*/100*/
94struct _DbusmenuGtkSerializableMenuItem {101struct _DbusmenuGtkSerializableMenuItem {
95 GtkMenuItem parent;102 GtkMenuItem parent;
@@ -99,9 +106,9 @@
99106
100GType dbusmenu_gtk_serializable_menu_item_get_type (void);107GType dbusmenu_gtk_serializable_menu_item_get_type (void);
101108
102DbusmenuMenuitem * dbusmenu_gtk_serializable_menu_item_build_dbusmenu_menuitem (DbusmenuGtkSerializableMenuItem * smi);109DbusmenuMenuitem * dbusmenu_gtk_serializable_menu_item_build_menuitem (DbusmenuGtkSerializableMenuItem * smi);
103void dbusmenu_gtk_serializable_menu_item_register_to_client (DbusmenuClient * client, GType item_type);110void dbusmenu_gtk_serializable_menu_item_register_to_client (DbusmenuClient * client, GType item_type);
104void dbusmenu_gtk_serializable_menu_item_set_dbusmenu_menuitem (DbusmenuGtkSerializableMenuItem * smi, DbusmenuMenuitem * mi);111void dbusmenu_gtk_serializable_menu_item_set_menuitem (DbusmenuGtkSerializableMenuItem * smi, DbusmenuMenuitem * mi);
105112
106G_END_DECLS113G_END_DECLS
107114

Subscribers

People subscribed via source and target branches