diff options
author | Jonas Ã…dahl <jadahl@gmail.com> | 2016-10-14 16:41:50 +0800 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2016-10-21 11:55:39 -0400 |
commit | 3ad1677a3a96c245ffc0d2090c4706e164dfb712 (patch) | |
tree | f63812caf02c68ce113b83f777fd2dfffb58293c | |
parent | 2b527d6e976c623246d77deb504cc76f6f39adfc (diff) | |
download | gtk+-3ad1677a3a96c245ffc0d2090c4706e164dfb712.tar.gz |
GtkMenu: Try using gdk_window_move_to_rect() more often
With best-effort, try to use gdk_window_move_to_rect() more often, when
all pieces fit together. For the non-legacy paths to be triggered for
when gtk_menu_popup_for_device() or gtk_menu_popup() were used, the
following conditions must be met:
1) There is no custom positioning function specified
2) The menu is attached to a widget (using gtk_menu_attach_to_widget())
3) There is a associated grab device
https://bugzilla.gnome.org/show_bug.cgi?id=772922
-rw-r--r-- | gtk/gtkmenu.c | 59 |
1 files changed, 48 insertions, 11 deletions
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c index 0488d1f1e0..e77817fd1a 100644 --- a/gtk/gtkmenu.c +++ b/gtk/gtkmenu.c @@ -5164,7 +5164,16 @@ gtk_menu_position (GtkMenu *menu, GtkTextDirection text_direction = GTK_TEXT_DIR_NONE; GdkGravity rect_anchor; GdkGravity menu_anchor; + GdkAnchorHints anchor_hints; + gint rect_anchor_dx, rect_anchor_dy; GdkWindow *toplevel; + gboolean emulated_move_to_rect = FALSE; + + rect_anchor = priv->rect_anchor; + menu_anchor = priv->menu_anchor; + anchor_hints = priv->anchor_hints; + rect_anchor_dx = priv->rect_anchor_dx; + rect_anchor_dy = priv->rect_anchor_dy; if (priv->rect_window) { @@ -5177,6 +5186,36 @@ gtk_menu_position (GtkMenu *menu, gtk_widget_get_allocation (priv->widget, &rect); text_direction = gtk_widget_get_direction (priv->widget); } + else if (!priv->position_func) + { + GtkWidget *attach_widget; + GdkDevice *grab_device; + + /* + * One of the legacy gtk_menu_popup*() functions were used to popup but + * without a custom positioning function, so make an attempt to let the + * backend do the position constraining when required conditions are met. + */ + + grab_device = _gtk_menu_shell_get_grab_device (GTK_MENU_SHELL (menu)); + attach_widget = gtk_menu_get_attach_widget (menu); + + if (grab_device && attach_widget) + { + rect = (GdkRectangle) { 0, 0, 1, 1 }; + + rect_window = gtk_widget_get_window (attach_widget); + gdk_window_get_device_position (rect_window, grab_device, + &rect.x, &rect.y, NULL); + text_direction = gtk_widget_get_direction (attach_widget); + rect_anchor = GDK_GRAVITY_SOUTH_EAST; + menu_anchor = GDK_GRAVITY_NORTH_WEST; + anchor_hints = GDK_ANCHOR_FLIP | GDK_ANCHOR_SLIDE | GDK_ANCHOR_RESIZE; + rect_anchor_dx = 0; + rect_anchor_dy = 0; + emulated_move_to_rect = TRUE; + } + } if (!rect_window) { @@ -5197,13 +5236,8 @@ gtk_menu_position (GtkMenu *menu, if (text_direction == GTK_TEXT_DIR_RTL) { - rect_anchor = get_horizontally_flipped_anchor (priv->rect_anchor); - menu_anchor = get_horizontally_flipped_anchor (priv->menu_anchor); - } - else - { - rect_anchor = priv->rect_anchor; - menu_anchor = priv->menu_anchor; + rect_anchor = get_horizontally_flipped_anchor (rect_anchor); + menu_anchor = get_horizontally_flipped_anchor (menu_anchor); } toplevel = gtk_widget_get_window (priv->toplevel); @@ -5211,15 +5245,18 @@ gtk_menu_position (GtkMenu *menu, gdk_window_set_transient_for (toplevel, rect_window); g_signal_handlers_disconnect_by_func (toplevel, moved_to_rect_cb, menu); - g_signal_connect (toplevel, "moved-to-rect", G_CALLBACK (moved_to_rect_cb), menu); + + if (!emulated_move_to_rect) + g_signal_connect (toplevel, "moved-to-rect", G_CALLBACK (moved_to_rect_cb), + menu); GDK_PRIVATE_CALL (gdk_window_move_to_rect) (toplevel, &rect, rect_anchor, menu_anchor, - priv->anchor_hints, - priv->rect_anchor_dx, - priv->rect_anchor_dy); + anchor_hints, + rect_anchor_dx, + rect_anchor_dy); } static void |