From cd3e84356de102eab24e57042285c28ac2b2c970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vivek=20Das=C2=A0Mohapatra?= Date: Sun, 15 Jul 2018 18:59:59 +0100 Subject: [PATCH] GTK3 menu bars force frame resizing (Bug#22000) Menu bars force the frame they are in to resize when the menu bar width exceeds the frame width, both at the point the menu bar grows past the frame width and whenever the gtk idle resize callback is triggered. The effect is that the user's frame width is effectively ignored, and emacs will semi-predictably resize itself to accommodate the menu bar. This effect can be suppressed by wrapping the menu bar in a scrollable window. --- src/gtkutil.c | 34 +++++++++++++++++++++++++++++----- src/xterm.h | 1 + 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/gtkutil.c b/src/gtkutil.c index 69325ff00a..d16274f6ab 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -3461,6 +3461,7 @@ xg_update_frame_menubar (struct frame *f) { struct x_output *x = f->output_data.x; GtkRequisition req; + GtkScrolledWindow *sw; if (!x->menubar_widget || gtk_widget_get_mapped (x->menubar_widget)) return; @@ -3470,12 +3471,33 @@ xg_update_frame_menubar (struct frame *f) block_input (); - gtk_box_pack_start (GTK_BOX (x->vbox_widget), x->menubar_widget, - FALSE, FALSE, 0); - gtk_box_reorder_child (GTK_BOX (x->vbox_widget), x->menubar_widget, 0); + /* Put the menu bar inside a scrolled window so that adding items + to the menu bar (such as when entering dired mode or activating + a minor more) does not trigger a frame resize:*/ + x->menubar_viewport = gtk_scrolled_window_new(NULL, NULL); + sw = GTK_SCROLLED_WINDOW (x->menubar_viewport); + gtk_scrolled_window_set_policy (sw, GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER); + + /* Leave the keyboard focus where it is when clicking the scrollwindow: */ +#if GTK_CHECK_VERSION (3, 20, 0) + gtk_widget_set_focus_on_click (GTK_WIDGET(sw), FALSE); +#endif + +#if GTK_CHECK_VERSION (3, 16, 0) + /* If we don't set this then the scrollable keeps focus when the user + interacts with the scrollbar, at least until the menubar is clicked. + Overlay scrolling is more compact but until the focus problem is fixed + it's not livable with. */ + gtk_scrolled_window_set_overlay_scrolling (sw, FALSE); +#endif + + gtk_container_add (GTK_CONTAINER (sw), x->menubar_widget); + + gtk_box_pack_start (GTK_BOX (x->vbox_widget), GTK_WIDGET(sw), FALSE, FALSE, 0); + gtk_box_reorder_child (GTK_BOX (x->vbox_widget), GTK_WIDGET(sw), 0); g_signal_connect (x->menubar_widget, "map", G_CALLBACK (menubar_map_cb), f); - gtk_widget_show_all (x->menubar_widget); + gtk_widget_show_all (x->menubar_viewport); gtk_widget_get_preferred_size (x->menubar_widget, NULL, &req); if (FRAME_MENUBAR_HEIGHT (f) != req.height) @@ -3498,9 +3520,11 @@ free_frame_menubar (struct frame *f) { block_input (); - gtk_container_remove (GTK_CONTAINER (x->vbox_widget), x->menubar_widget); + gtk_container_remove (GTK_CONTAINER (x->menubar_viewport), x->menubar_widget); + gtk_container_remove (GTK_CONTAINER (x->vbox_widget), x->menubar_viewport); /* The menubar and its children shall be deleted when removed from the container. */ + x->menubar_viewport = 0; x->menubar_widget = 0; FRAME_MENUBAR_HEIGHT (f) = 0; adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines); diff --git a/src/xterm.h b/src/xterm.h index 1849a5c953..9bf3d9778b 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -583,6 +583,7 @@ struct x_output /* The widget used for laying out widgets horizontally. */ GtkWidget *hbox_widget; /* The menubar in this frame. */ + GtkWidget *menubar_viewport; GtkWidget *menubar_widget; /* The tool bar in this frame */ GtkWidget *toolbar_widget; -- 2.11.0