[gtk+/wip/attente/popup-at: 3/5] gtkmenu: position menu using gdk_window_move_to_rect ()
- From: William Hua <williamhua src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/attente/popup-at: 3/5] gtkmenu: position menu using gdk_window_move_to_rect ()
- Date: Thu, 30 Jun 2016 17:25:44 +0000 (UTC)
commit 281ba394907e40b826c6e6f4d389dddf8aa4c91f
Author: William Hua <william hua canonical com>
Date: Wed Jun 29 16:42:42 2016 -0400
gtkmenu: position menu using gdk_window_move_to_rect ()
gtk/gtkmenu.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 104 insertions(+), 4 deletions(-)
---
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c
index aaa498b..54eb2cf 100644
--- a/gtk/gtkmenu.c
+++ b/gtk/gtkmenu.c
@@ -137,6 +137,7 @@
#include "a11y/gtkmenuaccessible.h"
+#include "gdk/gdk-private.h"
#define NAVIGATION_REGION_OVERSHOOT 50 /* How much the navigation region
* extends below the submenu
@@ -4759,11 +4760,58 @@ gtk_menu_deactivate (GtkMenuShell *menu_shell)
gtk_menu_shell_deactivate (GTK_MENU_SHELL (parent));
}
+static GdkGravity
+get_horizontally_flipped_anchor (GdkGravity anchor)
+{
+ switch (anchor)
+ {
+ case GDK_GRAVITY_STATIC:
+ case GDK_GRAVITY_NORTH_WEST:
+ return GDK_GRAVITY_NORTH_EAST;
+ case GDK_GRAVITY_NORTH:
+ return GDK_GRAVITY_NORTH;
+ case GDK_GRAVITY_NORTH_EAST:
+ return GDK_GRAVITY_NORTH_WEST;
+ case GDK_GRAVITY_WEST:
+ return GDK_GRAVITY_EAST;
+ case GDK_GRAVITY_CENTER:
+ return GDK_GRAVITY_CENTER;
+ case GDK_GRAVITY_EAST:
+ return GDK_GRAVITY_WEST;
+ case GDK_GRAVITY_SOUTH_WEST:
+ return GDK_GRAVITY_SOUTH_EAST;
+ case GDK_GRAVITY_SOUTH:
+ return GDK_GRAVITY_SOUTH;
+ case GDK_GRAVITY_SOUTH_EAST:
+ return GDK_GRAVITY_SOUTH_WEST;
+ default:
+ g_warning ("unknown GdkGravity: %d", anchor);
+ return anchor;
+ }
+}
+
+static void
+moved_to_rect_cb (GdkWindow *window,
+ const GdkRectangle *flipped_rect,
+ const GdkRectangle *slid_rect,
+ gboolean flipped_x,
+ gboolean flipped_y,
+ GtkMenu *menu)
+{
+ g_signal_emit (menu, menu_signals[POPPED_UP], 0, flipped_rect, slid_rect, flipped_x, flipped_y);
+}
+
static void
gtk_menu_position (GtkMenu *menu,
gboolean set_scroll_offset)
{
GtkMenuPrivate *priv = menu->priv;
+ GdkWindow *transient_for = NULL;
+ GdkRectangle rect;
+ GtkTextDirection text_direction = GTK_TEXT_DIR_NONE;
+ GdkGravity rect_anchor;
+ GdkGravity menu_anchor;
+ GdkWindow *toplevel;
GtkWidget *widget;
GtkRequisition requisition;
gint x, y;
@@ -4778,15 +4826,67 @@ gtk_menu_position (GtkMenu *menu,
widget = GTK_WIDGET (menu);
- display = gtk_widget_get_display (widget);
- pointer = _gtk_menu_shell_get_grab_device (GTK_MENU_SHELL (menu));
- gdk_device_get_position (pointer, NULL, &x, &y);
-
/* Realize so we have the proper width and height to figure out
* the right place to popup the menu.
*/
gtk_widget_realize (priv->toplevel);
+ if (priv->transient_for)
+ {
+ transient_for = priv->transient_for;
+ rect = priv->rect;
+ }
+ else if (priv->widget)
+ {
+ if (gtk_widget_get_parent (priv->widget))
+ transient_for = gtk_widget_get_window (gtk_widget_get_parent (priv->widget));
+ else
+ transient_for = gtk_widget_get_window (priv->widget);
+
+ gtk_widget_get_allocation (priv->widget, &rect);
+ text_direction = gtk_widget_get_direction (priv->widget);
+ }
+
+ if (transient_for)
+ {
+ if (!gtk_widget_get_visible (priv->toplevel))
+ gtk_window_set_type_hint (GTK_WINDOW (priv->toplevel), priv->menu_type_hint);
+
+ if (text_direction == GTK_TEXT_DIR_NONE)
+ text_direction = gtk_widget_get_direction (widget);
+
+ 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;
+ }
+
+ toplevel = gtk_widget_get_window (priv->toplevel);
+
+ 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);
+
+ GDK_PRIVATE_CALL (gdk_window_move_to_rect) (toplevel,
+ transient_for,
+ &rect,
+ rect_anchor,
+ menu_anchor,
+ priv->anchor_hints,
+ priv->rect_anchor_dx,
+ priv->rect_anchor_dy);
+
+ return;
+ }
+
+ display = gtk_widget_get_display (widget);
+ pointer = _gtk_menu_shell_get_grab_device (GTK_MENU_SHELL (menu));
+ gdk_device_get_position (pointer, NULL, &x, &y);
+
_gtk_window_get_shadow_width (GTK_WINDOW (priv->toplevel), &border);
requisition.width = gtk_widget_get_allocated_width (widget);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]