From 7a1b473ce826804cd47019e74e007ede7a6d2576 Mon Sep 17 00:00:00 2001 From: Daniel Colascione Date: Sun, 12 Jan 2014 17:40:35 -0800 Subject: [PATCH] Make GTK+ menus work correctly with Unity global menu --- src/ChangeLog | 13 +++++++++++++ src/gtkutil.c | 38 ++++++++++++++++++++++++++------------ src/gtkutil.h | 2 +- src/xmenu.c | 2 +- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 8df6e31521d..d39377f4ef3 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,16 @@ +2014-01-13 Daniel Colascione + + Fix menu item updating in the presence of the Unity global menu + GTK+ module. + + * gtkutil.h (xg_have_tear_offs): Add frame parameter + * gtkutil.c (xg_have_tear_offs): Count the global menu as a + tear-off. + (xg_update_menubar,xg_update_menu_item): Call g_object_notify when + updating menus; explain why. + * xmenu.c (set_frame_menubar): Call xg_have_tear_offs with new + parameter. + 2014-01-07 Paul Eggert Fix misdisplay of interlaced GIFs with libgif5 (Bug#16372). diff --git a/src/gtkutil.c b/src/gtkutil.c index 21c3f7ddd8b..6e039c7a141 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -2414,9 +2414,12 @@ static int xg_detached_menus; /* Return true if there are detached menus. */ bool -xg_have_tear_offs (void) +xg_have_tear_offs (struct frame *f) { - return xg_detached_menus > 0; + /* If the frame's menubar height is zero, the menu bar is probably + being redirected outside the window to some kind of global menu; + this situation is the moral equivalent of a tear-off. */ + return FRAME_MENUBAR_HEIGHT (f) == 0 || xg_detached_menus > 0; } /* Callback invoked when a detached menu window is removed. Here we @@ -2449,9 +2452,9 @@ tearoff_activate (GtkWidget *widget, gpointer client_data) } #else /* ! HAVE_GTK_TEAROFF_MENU_ITEM_NEW */ bool -xg_have_tear_offs (void) +xg_have_tear_offs (struct frame *f) { - return false; + return FRAME_MENUBAR_HEIGHT (f) == 0; } #endif /* ! HAVE_GTK_TEAROFF_MENU_ITEM_NEW */ @@ -2897,7 +2900,13 @@ xg_update_menubar (GtkWidget *menubar, char *utf8_label = get_utf8_string (val->name); GtkWidget *submenu = gtk_menu_item_get_submenu (witem); + /* GTK menu items don't notice when their labels have been + changed from underneath them, so we have to explicitly + use g_object_notify to tell listeners (e.g., a GMenuModel + bridge that might be loaded) that the item's label has + changed. */ gtk_label_set_text (wlabel, utf8_label); + g_object_notify (G_OBJECT (witem), "label"); #ifdef HAVE_GTK_TEAROFF_MENU_ITEM_NEW /* If this item has a submenu that has been detached, change @@ -2934,6 +2943,7 @@ xg_update_menubar (GtkWidget *menubar, select_cb, deactivate_cb, highlight_cb, 0, 0, 0, 0, cl_data, 0); + gtk_widget_set_name (w, MENU_ITEM_NAME); gtk_menu_shell_insert (GTK_MENU_SHELL (menubar), w, pos); gtk_menu_item_set_submenu (GTK_MENU_ITEM (w), submenu); @@ -2993,6 +3003,7 @@ xg_update_menu_item (widget_value *val, const char *old_label = 0; const char *old_key = 0; xg_menu_item_cb_data *cb_data; + bool label_changed = false; wchild = XG_BIN_CHILD (w); utf8_label = get_utf8_string (val->name); @@ -3037,15 +3048,20 @@ xg_update_menu_item (widget_value *val, } } - if (wkey) old_key = gtk_label_get_label (wkey); if (wlbl) old_label = gtk_label_get_label (wlbl); if (wkey && utf8_key && (! old_key || strcmp (utf8_key, old_key) != 0)) - gtk_label_set_text (wkey, utf8_key); + { + label_changed = true; + gtk_label_set_text (wkey, utf8_key); + } if (! old_label || strcmp (utf8_label, old_label) != 0) - gtk_label_set_text (wlbl, utf8_label); + { + label_changed = true; + gtk_label_set_text (wlbl, utf8_label); + } if (utf8_key) g_free (utf8_key); if (utf8_label) g_free (utf8_label); @@ -3077,6 +3093,9 @@ xg_update_menu_item (widget_value *val, cb_data->select_id = 0; } } + + if (label_changed) /* See comment in xg_update_menubar. */ + g_object_notify (G_OBJECT (w), "label"); } /* Update the toggle menu item W so it corresponds to VAL. */ @@ -3359,11 +3378,6 @@ xg_update_frame_menubar (struct frame *f) gtk_widget_show_all (x->menubar_widget); gtk_widget_get_preferred_size (x->menubar_widget, NULL, &req); - /* If menu bar doesn't know its height yet, cheat a little so the frame - doesn't jump so much when resized later in menubar_map_cb. */ - if (req.height == 0) - req.height = 23; - if (FRAME_MENUBAR_HEIGHT (f) != req.height) { FRAME_MENUBAR_HEIGHT (f) = req.height; diff --git a/src/gtkutil.h b/src/gtkutil.h index 09f0d3fd2a8..12bf461fd69 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -107,7 +107,7 @@ extern void xg_update_frame_menubar (struct frame *f); extern bool xg_event_is_for_menubar (struct frame *, const XEvent *); -extern bool xg_have_tear_offs (void); +extern bool xg_have_tear_offs (struct frame *f); extern ptrdiff_t xg_get_scroll_id_for_window (Display *dpy, Window wid); diff --git a/src/xmenu.c b/src/xmenu.c index e7e44d4e47f..6f628527a6d 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -796,7 +796,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) #ifdef USE_GTK /* If we have detached menus, we must update deep so detached menus also gets updated. */ - deep_p = deep_p || xg_have_tear_offs (); + deep_p = deep_p || xg_have_tear_offs (f); #endif if (deep_p) -- 2.39.2