Michael Terry has proposed merging lp:~mterry/dbusmenu/watch-for-new-items into
lp:dbusmenu.
Requested reviews:
DBus Menu Team (dbusmenu-team)
Related bugs:
#709839 some apps are missing menu items
https://bugs.launchpad.net/bugs/709839
For more details, see:
https://code.launchpad.net/~mterry/dbusmenu/watch-for-new-items/+merge/48644
This branch does a few things, but most importantly, it watches GtkMenuShells
for the addition of new items, fixing bugs where menu items don't appear but
should, such as bug 709839.
So, here's what it does:
* Consolidates the creation of new dbusmenu_items into a helper function.
There are several things we want to do for each menu item, no matter who
creates it, like adding a ParserData object or connecting to its destruction.
* Connect to a new callback to GtkMenuShells ("child-added"). This involves
adding a new entry, 'shell' to the ParserData blob.
* Remove a duplicate line from dbusmenu_cache_freed that was leftover from my
addition of ParserData. The line disconnected from widget_notify_cb, but
there's already a block that does.
* Fix a memory leak when iterating over the children of the topmost
GtkMenuShell. It tried to free the list iterator instead of the list itself.
* When adding a new child to a dbusmenu_item, make sure to add it at the right
position. This never mattered before, since we did one iteration and were
done, but now that we pay attention to insertions, we need to make sure we
insert at the correct place.
--
https://code.launchpad.net/~mterry/dbusmenu/watch-for-new-items/+merge/48644
Your team ayatana-commits is subscribed to branch lp:dbusmenu.
=== modified file 'libdbusmenu-gtk/parser.c'
--- libdbusmenu-gtk/parser.c 2011-02-03 13:43:56 +0000
+++ libdbusmenu-gtk/parser.c 2011-02-04 19:14:16 +0000
@@ -38,6 +38,7 @@
GtkWidget *label;
GtkAction *action;
GtkWidget *widget;
+ GtkWidget *shell;
} ParserData;
typedef struct _RecurseContext
@@ -63,6 +64,9 @@
static void action_notify_cb (GtkAction * action,
GParamSpec * pspec,
gpointer data);
+static void child_added_cb (GtkContainer * menu,
+ GtkWidget * widget,
+ gpointer data);
static void item_activated (DbusmenuMenuitem * item,
guint timestamp,
gpointer user_data);
@@ -109,7 +113,6 @@
/* If the dbusmenu item is killed we don't need to remove
the weak ref as well. */
g_object_steal_data(G_OBJECT(data), CACHED_MENUITEM);
- g_signal_handlers_disconnect_by_func(data, G_CALLBACK(widget_notify_cb), obj);
ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(obj), PARSER_DATA);
@@ -128,6 +131,11 @@
g_object_remove_weak_pointer(G_OBJECT(pdata->widget), (gpointer*)&pdata->widget);
}
+ if (pdata != NULL && pdata->shell != NULL) {
+ g_signal_handlers_disconnect_by_func(pdata->shell, G_CALLBACK(child_added_cb), obj);
+ g_object_remove_weak_pointer(G_OBJECT(pdata->shell), (gpointer*)&pdata->shell);
+ }
+
return;
}
@@ -143,6 +151,45 @@
return;
}
+static gint
+get_child_position (GtkWidget * child)
+{
+ GtkWidget * parent = gtk_widget_get_parent (child);
+ if (parent == NULL || !GTK_IS_CONTAINER (parent))
+ return -1;
+
+ GList * children = gtk_container_get_children (GTK_CONTAINER (parent));
+ GList * iter;
+ gint position = 0;
+
+ for (iter = children; iter != NULL; iter = iter->next) {
+ if (iter->data == child)
+ break;
+ ++position;
+ }
+
+ g_list_free (children);
+
+ if (iter == NULL)
+ return -1;
+ else
+ return position;
+}
+
+static DbusmenuMenuitem *
+new_menuitem (GtkWidget * widget)
+{
+ DbusmenuMenuitem * item = dbusmenu_menuitem_new();
+
+ ParserData *pdata = g_new0 (ParserData, 1);
+ g_object_set_data_full(G_OBJECT(item), PARSER_DATA, pdata, g_free);
+
+ g_object_set_data_full(G_OBJECT(widget), CACHED_MENUITEM, item, object_cache_freed);
+ g_object_weak_ref(G_OBJECT(item), dbusmenu_cache_freed, widget);
+
+ return item;
+}
+
static void
parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse)
{
@@ -161,10 +208,11 @@
*/
if (recurse->parent == NULL && GTK_IS_MENU_BAR(widget)) {
GList *children = gtk_container_get_children (GTK_CONTAINER (widget));
+ GList *iter;
- for (; children != NULL; children = children->next) {
+ for (iter = children; iter != NULL; iter = iter->next) {
gtk_menu_shell_activate_item (GTK_MENU_SHELL (widget),
- children->data,
+ iter->data,
TRUE);
}
@@ -172,9 +220,18 @@
}
if (recurse->parent == NULL) {
- recurse->parent = dbusmenu_menuitem_new();
+ recurse->parent = new_menuitem(widget);
}
+ ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(recurse->parent), PARSER_DATA);
+
+ pdata->shell = widget;
+ g_signal_connect (G_OBJECT (widget),
+ "child-added",
+ G_CALLBACK (child_added_cb),
+ recurse->parent);
+ g_object_add_weak_pointer(G_OBJECT (widget), (gpointer*)&pdata->shell);
+
gtk_container_foreach (GTK_CONTAINER (widget),
(GtkCallback)parse_menu_structure_helper,
recurse);
@@ -194,8 +251,6 @@
/* We don't have one, so we'll need to build it */
if (thisitem == NULL) {
thisitem = construct_dbusmenu_for_widget (widget);
- g_object_set_data_full(G_OBJECT(widget), CACHED_MENUITEM, thisitem, object_cache_freed);
- g_object_weak_ref(G_OBJECT(thisitem), dbusmenu_cache_freed, widget);
if (!gtk_widget_get_visible (widget)) {
g_signal_connect (G_OBJECT (widget),
@@ -227,8 +282,14 @@
g_object_set_data (G_OBJECT (thisitem),
"dbusmenu-parent",
recurse->parent);
- dbusmenu_menuitem_child_append (recurse->parent,
- thisitem);
+ gint pos = get_child_position (widget);
+ if (pos >= 0)
+ dbusmenu_menuitem_child_add_position (recurse->parent,
+ thisitem,
+ pos);
+ else
+ dbusmenu_menuitem_child_append (recurse->parent,
+ thisitem);
}
}
@@ -265,10 +326,9 @@
/* If it's a standard GTK Menu Item we need to do some of our own work */
if (GTK_IS_MENU_ITEM (widget))
{
- DbusmenuMenuitem *mi = dbusmenu_menuitem_new ();
+ DbusmenuMenuitem *mi = new_menuitem(widget);
- ParserData *pdata = g_new0 (ParserData, 1);
- g_object_set_data_full (G_OBJECT (mi), PARSER_DATA, pdata, g_free);
+ ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(mi), PARSER_DATA);
gboolean visible = FALSE;
gboolean sensitive = FALSE;
@@ -414,7 +474,7 @@
/* If it's none of those we're going to just create a
generic menuitem as a place holder for it. */
- return dbusmenu_menuitem_new();
+ return new_menuitem(widget);
}
static void
@@ -720,6 +780,19 @@
}
}
+/* A child item was added to a menu we're watching. Let's try to integrate it. */
+static void
+child_added_cb (GtkContainer *menu, GtkWidget *widget, gpointer data)
+{
+ DbusmenuMenuitem *menuitem = (DbusmenuMenuitem *)data;
+
+ RecurseContext recurse = {0};
+ recurse.toplevel = gtk_widget_get_toplevel(GTK_WIDGET(menu));
+ recurse.parent = menuitem;
+
+ parse_menu_structure_helper(widget, &recurse);
+}
+
static gboolean
should_show_image (GtkImage *image)
{
_______________________________________________
Mailing list: https://launchpad.net/~ayatana-commits
Post to : [email protected]
Unsubscribe : https://launchpad.net/~ayatana-commits
More help : https://help.launchpad.net/ListHelp