summaryrefslogtreecommitdiff
path: root/gtk/gtkmenubutton.c
diff options
context:
space:
mode:
authorWilliam Hua <william.hua@canonical.com>2016-07-12 14:08:36 -0400
committerWilliam Hua <william.hua@canonical.com>2016-07-19 09:38:54 -0400
commit8701e34f749cf196c9726c01c03f35ce4eb39836 (patch)
tree1608d0bcc69917633b1640dfa7a3651158868880 /gtk/gtkmenubutton.c
parent05b9bc5cff5f2bd625412ddac2184af8c026895b (diff)
downloadgtk+-8701e34f749cf196c9726c01c03f35ce4eb39836.tar.gz
port to new gtk_menu_popup_at_* () functions
https://bugzilla.gnome.org/show_bug.cgi?id=756579
Diffstat (limited to 'gtk/gtkmenubutton.c')
-rw-r--r--gtk/gtkmenubutton.c294
1 files changed, 131 insertions, 163 deletions
diff --git a/gtk/gtkmenubutton.c b/gtk/gtkmenubutton.c
index 1f402fab7d..347cf25b6b 100644
--- a/gtk/gtkmenubutton.c
+++ b/gtk/gtkmenubutton.c
@@ -241,189 +241,157 @@ gtk_menu_button_state_flags_changed (GtkWidget *widget,
}
static void
-menu_position_up_down_func (GtkMenu *menu,
- gint *x,
- gint *y,
- gboolean *push_in,
- GtkMenuButton *menu_button)
+popup_menu (GtkMenuButton *menu_button,
+ GdkEvent *event)
{
GtkMenuButtonPrivate *priv = menu_button->priv;
- GtkWidget *widget = GTK_WIDGET (menu_button);
- GtkWidget *toplevel;
- GtkTextDirection direction;
- GdkRectangle workarea;
- GdkDisplay *display;
- GdkMonitor *monitor;
- GdkWindow *window;
- GtkAllocation menu_allocation, allocation, arrow_allocation;
- GtkAlign align;
-
- /* In the common case the menu button is showing a dropdown menu, set the
- * corresponding type hint on the toplevel, so the WM can omit the top side
- * of the shadows.
- */
- if (priv->arrow_type == GTK_ARROW_DOWN)
- {
- toplevel = gtk_widget_get_toplevel (priv->menu);
- gtk_window_set_type_hint (GTK_WINDOW (toplevel), GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU);
- }
-
- align = gtk_widget_get_halign (priv->menu);
- direction = gtk_widget_get_direction (widget);
- window = gtk_widget_get_window (priv->align_widget ? priv->align_widget : widget);
-
- display = gtk_widget_get_display (GTK_WIDGET (menu));
- monitor = gdk_display_get_monitor_at_window (display, window);
- gdk_monitor_get_workarea (monitor, &workarea);
-
- gtk_widget_get_allocation (priv->align_widget ? priv->align_widget : widget, &allocation);
- gtk_widget_get_allocation (widget, &arrow_allocation);
- gtk_widget_get_allocation (priv->menu, &menu_allocation);
-
- gdk_window_get_origin (window, x, y);
- *x += allocation.x;
- *y += allocation.y;
+ GdkGravity widget_anchor = GDK_GRAVITY_SOUTH_WEST;
+ GdkGravity menu_anchor = GDK_GRAVITY_NORTH_WEST;
- /* treat the default align value like START */
- if (align == GTK_ALIGN_FILL)
- align = GTK_ALIGN_START;
+ if (priv->func)
+ priv->func (priv->user_data);
- if (align == GTK_ALIGN_CENTER)
- *x -= (menu_allocation.width - allocation.width) / 2;
- else if ((align == GTK_ALIGN_START && direction == GTK_TEXT_DIR_LTR) ||
- (align == GTK_ALIGN_END && direction == GTK_TEXT_DIR_RTL))
- *x += MAX (allocation.width - menu_allocation.width, 0);
- else if (menu_allocation.width > allocation.width)
- *x -= menu_allocation.width - allocation.width;
+ if (!priv->menu)
+ return;
- if (priv->arrow_type == GTK_ARROW_UP && *y - menu_allocation.height >= workarea.y)
- {
- *y -= menu_allocation.height;
- }
- else
+ switch (priv->arrow_type)
{
- if ((*y + arrow_allocation.height + menu_allocation.height) <= workarea.y + workarea.height)
- *y += arrow_allocation.height;
- else if ((*y - menu_allocation.height) >= workarea.y)
- *y -= menu_allocation.height;
- else if (workarea.y + workarea.height - (*y + arrow_allocation.height) > *y)
- *y += arrow_allocation.height;
- else
- *y -= menu_allocation.height;
- }
-
- *push_in = FALSE;
-}
-
-static void
-menu_position_side_func (GtkMenu *menu,
- gint *x,
- gint *y,
- gboolean *push_in,
- GtkMenuButton *menu_button)
-{
- GtkMenuButtonPrivate *priv = menu_button->priv;
- GtkAllocation allocation;
- GtkAllocation menu_allocation;
- GtkWidget *widget = GTK_WIDGET (menu_button);
- GdkDisplay *display;
- GdkMonitor *monitor;
- GdkRectangle workarea;
- GdkWindow *window;
- GtkAlign align;
- GtkTextDirection direction;
-
- window = gtk_widget_get_window (widget);
-
- direction = gtk_widget_get_direction (widget);
- align = gtk_widget_get_valign (GTK_WIDGET (menu));
- display = gtk_widget_get_display (GTK_WIDGET (menu));
- monitor = gdk_display_get_monitor_at_window (display, window);
- gdk_monitor_get_workarea (monitor, &workarea);
+ case GTK_ARROW_UP:
+ g_object_set (priv->menu,
+ "anchor-hints", (GDK_ANCHOR_FLIP_Y |
+ GDK_ANCHOR_SLIDE |
+ GDK_ANCHOR_RESIZE),
+ NULL);
- gdk_window_get_origin (gtk_button_get_event_window (GTK_BUTTON (menu_button)), x, y);
+ switch (gtk_widget_get_halign (priv->menu))
+ {
+ case GTK_ALIGN_FILL:
+ case GTK_ALIGN_START:
+ case GTK_ALIGN_BASELINE:
+ widget_anchor = GDK_GRAVITY_NORTH_WEST;
+ menu_anchor = GDK_GRAVITY_SOUTH_WEST;
+ break;
+
+ case GTK_ALIGN_END:
+ widget_anchor = GDK_GRAVITY_NORTH_EAST;
+ menu_anchor = GDK_GRAVITY_SOUTH_EAST;
+ break;
+
+ case GTK_ALIGN_CENTER:
+ widget_anchor = GDK_GRAVITY_NORTH;
+ menu_anchor = GDK_GRAVITY_SOUTH;
+ break;
+ }
- gtk_widget_get_allocation (widget, &allocation);
- gtk_widget_get_allocation (priv->menu, &menu_allocation);
+ break;
- if ((priv->arrow_type == GTK_ARROW_RIGHT && direction == GTK_TEXT_DIR_LTR) ||
- (priv->arrow_type == GTK_ARROW_LEFT && direction == GTK_TEXT_DIR_RTL))
+ case GTK_ARROW_DOWN:
+ /* In the common case the menu button is showing a dropdown menu, set the
+ * corresponding type hint on the toplevel, so the WM can omit the top side
+ * of the shadows.
+ */
+ g_object_set (priv->menu,
+ "anchor-hints", (GDK_ANCHOR_FLIP_Y |
+ GDK_ANCHOR_SLIDE |
+ GDK_ANCHOR_RESIZE),
+ "menu-type-hint", GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU,
+ NULL);
+
+ switch (gtk_widget_get_halign (priv->menu))
+ {
+ case GTK_ALIGN_FILL:
+ case GTK_ALIGN_START:
+ case GTK_ALIGN_BASELINE:
+ widget_anchor = GDK_GRAVITY_SOUTH_WEST;
+ menu_anchor = GDK_GRAVITY_NORTH_WEST;
+ break;
+
+ case GTK_ALIGN_END:
+ widget_anchor = GDK_GRAVITY_SOUTH_EAST;
+ menu_anchor = GDK_GRAVITY_NORTH_EAST;
+ break;
+
+ case GTK_ALIGN_CENTER:
+ widget_anchor = GDK_GRAVITY_SOUTH;
+ menu_anchor = GDK_GRAVITY_NORTH;
+ break;
+ }
- {
- if (*x + allocation.width + menu_allocation.width <= workarea.x + workarea.width)
- *x += allocation.width;
- else
- *x -= menu_allocation.width;
- }
- else
- {
- if (*x - menu_allocation.width >= workarea.x)
- *x -= menu_allocation.width;
- else
- *x += allocation.width;
- }
+ break;
- /* treat the default align value like START */
- if (align == GTK_ALIGN_FILL)
- align = GTK_ALIGN_START;
+ case GTK_ARROW_LEFT:
+ g_object_set (priv->menu,
+ "anchor-hints", (GDK_ANCHOR_FLIP_X |
+ GDK_ANCHOR_SLIDE |
+ GDK_ANCHOR_RESIZE),
+ NULL);
- if (align == GTK_ALIGN_CENTER)
- *y -= (menu_allocation.height - allocation.height) / 2;
- else if (align == GTK_ALIGN_END)
- *y -= menu_allocation.height - allocation.height;
+ switch (gtk_widget_get_valign (priv->menu))
+ {
+ case GTK_ALIGN_FILL:
+ case GTK_ALIGN_START:
+ case GTK_ALIGN_BASELINE:
+ widget_anchor = GDK_GRAVITY_NORTH_WEST;
+ menu_anchor = GDK_GRAVITY_NORTH_EAST;
+ break;
+
+ case GTK_ALIGN_END:
+ widget_anchor = GDK_GRAVITY_SOUTH_WEST;
+ menu_anchor = GDK_GRAVITY_SOUTH_EAST;
+ break;
+
+ case GTK_ALIGN_CENTER:
+ widget_anchor = GDK_GRAVITY_WEST;
+ menu_anchor = GDK_GRAVITY_EAST;
+ break;
+ }
- *push_in = FALSE;
-}
+ break;
-static void
-popup_menu (GtkMenuButton *menu_button,
- GdkEvent *event)
-{
- GtkMenuButtonPrivate *priv = menu_button->priv;
- GtkMenuPositionFunc func;
- GdkDevice *device;
- guint button;
- guint32 time;
+ case GTK_ARROW_RIGHT:
+ g_object_set (priv->menu,
+ "anchor-hints", (GDK_ANCHOR_FLIP_X |
+ GDK_ANCHOR_SLIDE |
+ GDK_ANCHOR_RESIZE),
+ NULL);
- if (priv->func)
- priv->func (priv->user_data);
+ switch (gtk_widget_get_valign (priv->menu))
+ {
+ case GTK_ALIGN_FILL:
+ case GTK_ALIGN_START:
+ case GTK_ALIGN_BASELINE:
+ widget_anchor = GDK_GRAVITY_NORTH_EAST;
+ menu_anchor = GDK_GRAVITY_NORTH_WEST;
+ break;
+
+ case GTK_ALIGN_END:
+ widget_anchor = GDK_GRAVITY_SOUTH_EAST;
+ menu_anchor = GDK_GRAVITY_SOUTH_WEST;
+ break;
+
+ case GTK_ALIGN_CENTER:
+ widget_anchor = GDK_GRAVITY_EAST;
+ menu_anchor = GDK_GRAVITY_WEST;
+ break;
+ }
- if (!priv->menu)
- return;
+ break;
- switch (priv->arrow_type)
- {
- case GTK_ARROW_LEFT:
- case GTK_ARROW_RIGHT:
- func = (GtkMenuPositionFunc) menu_position_side_func;
- break;
- default:
- func = (GtkMenuPositionFunc) menu_position_up_down_func;
- break;
- }
+ case GTK_ARROW_NONE:
+ g_object_set (priv->menu,
+ "anchor-hints", (GDK_ANCHOR_FLIP_Y |
+ GDK_ANCHOR_SLIDE |
+ GDK_ANCHOR_RESIZE),
+ NULL);
- if (event != NULL &&
- gdk_event_get_screen (event) == gtk_widget_get_screen (GTK_WIDGET (menu_button)))
- {
- device = gdk_event_get_device (event);
- gdk_event_get_button (event, &button);
- time = gdk_event_get_time (event);
- }
- else
- {
- device = NULL;
- button = 0;
- time = gtk_get_current_event_time ();
+ break;
}
- gtk_menu_popup_for_device (GTK_MENU (priv->menu),
- device,
- NULL, NULL,
- func,
- GTK_WIDGET (menu_button),
- NULL,
- button,
- time);
+ gtk_menu_popup_at_widget (GTK_MENU (priv->menu),
+ GTK_WIDGET (menu_button),
+ widget_anchor,
+ menu_anchor,
+ event);
}
static void