summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ã…dahl <jadahl@gmail.com>2016-10-14 16:41:50 +0800
committerMatthias Clasen <mclasen@redhat.com>2016-10-21 11:55:39 -0400
commit3ad1677a3a96c245ffc0d2090c4706e164dfb712 (patch)
treef63812caf02c68ce113b83f777fd2dfffb58293c
parent2b527d6e976c623246d77deb504cc76f6f39adfc (diff)
downloadgtk+-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.c59
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