[gtk+/wip/attente/popup-at: 4/7] 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: 4/7] gtkmenu: position menu using gdk_window_move_to_rect ()
- Date: Sat, 16 Jul 2016 14:38:01 +0000 (UTC)
commit 0698281257a9a5be89144ec73b8b1bf7559e222f
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 ()
https://bugzilla.gnome.org/show_bug.cgi?id=756579
gtk/gtkmenu.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 122 insertions(+), 3 deletions(-)
---
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c
index 391ab87..238c27e 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
@@ -1362,6 +1363,23 @@ gtk_menu_init (GtkMenu *menu)
}
static void
+moved_to_rect_cb (GdkWindow *window,
+ const GdkRectangle *flipped_rect,
+ const GdkRectangle *final_rect,
+ gboolean flipped_x,
+ gboolean flipped_y,
+ GtkMenu *menu)
+{
+ g_signal_emit (menu,
+ menu_signals[POPPED_UP],
+ 0,
+ flipped_rect,
+ final_rect,
+ flipped_x,
+ flipped_y);
+}
+
+static void
gtk_menu_destroy (GtkWidget *widget)
{
GtkMenu *menu = GTK_MENU (widget);
@@ -1388,7 +1406,10 @@ gtk_menu_destroy (GtkWidget *widget)
g_clear_object (&priv->accel_group);
if (priv->toplevel)
- gtk_widget_destroy (priv->toplevel);
+ {
+ g_signal_handlers_disconnect_by_func (priv->toplevel, moved_to_rect_cb, menu);
+ gtk_widget_destroy (priv->toplevel);
+ }
if (priv->tearoff_window)
gtk_widget_destroy (priv->tearoff_window);
@@ -4822,8 +4843,8 @@ gtk_menu_deactivate (GtkMenuShell *menu_shell)
}
static void
-gtk_menu_position (GtkMenu *menu,
- gboolean set_scroll_offset)
+gtk_menu_position_legacy (GtkMenu *menu,
+ gboolean set_scroll_offset)
{
GtkMenuPrivate *priv = menu->priv;
GtkWidget *widget;
@@ -5061,6 +5082,104 @@ gtk_menu_position (GtkMenu *menu,
priv->scroll_offset = scroll_offset;
}
+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;
+ }
+
+ g_warning ("unknown GdkGravity: %d", anchor);
+ return anchor;
+}
+
+static void
+gtk_menu_position (GtkMenu *menu,
+ gboolean set_scroll_offset)
+{
+ GtkMenuPrivate *priv = menu->priv;
+ GdkWindow *rect_window = NULL;
+ GdkRectangle rect;
+ GtkTextDirection text_direction = GTK_TEXT_DIR_NONE;
+ GdkGravity rect_anchor;
+ GdkGravity menu_anchor;
+ GdkWindow *toplevel;
+
+ if (priv->rect_window)
+ {
+ rect_window = priv->rect_window;
+ rect = priv->rect;
+ }
+ else if (priv->widget)
+ {
+ rect_window = gtk_widget_get_window (priv->widget);
+ gtk_widget_get_allocation (priv->widget, &rect);
+ text_direction = gtk_widget_get_direction (priv->widget);
+ }
+
+ if (!rect_window)
+ {
+ gtk_menu_position_legacy (menu, set_scroll_offset);
+ return;
+ }
+
+ /* 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 (!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 (GTK_WIDGET (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;
+ }
+
+ toplevel = gtk_widget_get_window (priv->toplevel);
+
+ 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);
+
+ 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);
+}
+
static void
gtk_menu_remove_scroll_timeout (GtkMenu *menu)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]