[gtk+/wip/attachment-parameters-4: 20/20] gtkcombobox: use gtk_menu_popup_with_params ()
- From: William Hua <williamhua src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/attachment-parameters-4: 20/20] gtkcombobox: use gtk_menu_popup_with_params ()
- Date: Wed, 6 Jan 2016 06:27:49 +0000 (UTC)
commit 4c4233db8b61b43755a1f120d51f58f5fec201f7
Author: William Hua <william hua canonical com>
Date: Sun Sep 27 00:26:43 2015 -0400
gtkcombobox: use gtk_menu_popup_with_params ()
gtk/gtkcombobox.c | 313 ++++++++++++++++++++---------------------------------
1 files changed, 115 insertions(+), 198 deletions(-)
---
diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c
index df7f52e..8a6e047 100644
--- a/gtk/gtkcombobox.c
+++ b/gtk/gtkcombobox.c
@@ -287,21 +287,6 @@ static void gtk_combo_box_menu_hide (GtkWidget *menu,
static void gtk_combo_box_set_popup_widget (GtkComboBox *combo_box,
GtkWidget *popup);
-static void gtk_combo_box_menu_position_below (GtkMenu *menu,
- gint *x,
- gint *y,
- gint *push_in,
- gpointer user_data);
-static void gtk_combo_box_menu_position_over (GtkMenu *menu,
- gint *x,
- gint *y,
- gint *push_in,
- gpointer user_data);
-static void gtk_combo_box_menu_position (GtkMenu *menu,
- gint *x,
- gint *y,
- gint *push_in,
- gpointer user_data);
static void gtk_combo_box_unset_model (GtkComboBox *combo_box);
@@ -1984,185 +1969,6 @@ gtk_combo_box_set_popup_widget (GtkComboBox *combo_box,
}
static void
-gtk_combo_box_menu_position_below (GtkMenu *menu,
- gint *x,
- gint *y,
- gint *push_in,
- gpointer user_data)
-{
- GtkComboBox *combo_box = GTK_COMBO_BOX (user_data);
- GtkComboBoxPrivate *priv = combo_box->priv;
- GtkAllocation child_allocation, border_allocation, content_allocation;
- gint sx, sy;
- GtkWidget *child;
- GtkRequisition req;
- GdkScreen *screen;
- gint monitor_num;
- GdkRectangle monitor;
-
- /* FIXME: is using the size request here broken? */
- child = gtk_bin_get_child (GTK_BIN (combo_box));
-
- sx = sy = 0;
-
- gtk_css_gadget_get_border_allocation (priv->gadget, &border_allocation, NULL);
- gtk_css_gadget_get_content_allocation (priv->gadget, &content_allocation, NULL);
- gtk_widget_get_allocation (child, &child_allocation);
-
- if (!gtk_widget_get_has_window (child))
- {
- sx += child_allocation.x;
- sy += child_allocation.y;
- }
-
- gdk_window_get_root_coords (gtk_widget_get_window (child),
- sx, sy, &sx, &sy);
-
- if (gtk_widget_get_direction (GTK_WIDGET (combo_box)) == GTK_TEXT_DIR_RTL)
- sx += (content_allocation.x - border_allocation.x);
- else
- sx -= (content_allocation.x - border_allocation.x);
-
- if (combo_box->priv->popup_fixed_width)
- gtk_widget_get_preferred_size (GTK_WIDGET (menu), &req, NULL);
- else
- gtk_widget_get_preferred_size (GTK_WIDGET (menu), NULL, &req);
-
- if (gtk_widget_get_direction (GTK_WIDGET (combo_box)) == GTK_TEXT_DIR_LTR)
- *x = sx;
- else
- *x = sx + child_allocation.width - req.width;
- *y = sy;
-
- screen = gtk_widget_get_screen (GTK_WIDGET (combo_box));
- monitor_num = gdk_screen_get_monitor_at_window (screen,
- gtk_widget_get_window (GTK_WIDGET (combo_box)));
- gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor);
-
- if (*x < monitor.x)
- *x = monitor.x;
- else if (*x + req.width > monitor.x + monitor.width)
- *x = monitor.x + monitor.width - req.width;
-
- if (monitor.y + monitor.height - *y - child_allocation.height >= req.height)
- *y += child_allocation.height;
- else if (*y - monitor.y >= req.height)
- *y -= req.height;
- else if (monitor.y + monitor.height - *y - child_allocation.height > *y - monitor.y)
- *y += child_allocation.height;
- else
- *y -= req.height;
-
- *push_in = FALSE;
-}
-
-static void
-gtk_combo_box_menu_position_over (GtkMenu *menu,
- gint *x,
- gint *y,
- gboolean *push_in,
- gpointer user_data)
-{
- GtkComboBox *combo_box = GTK_COMBO_BOX (user_data);
- GtkWidget *widget = GTK_WIDGET (combo_box);
- GtkComboBoxPrivate *priv = combo_box->priv;
- GtkWidget *active;
- GtkWidget *child;
- GtkAllocation content_allocation;
- GtkAllocation child_allocation;
- GList *children;
- gint screen_width;
- gint menu_xpos;
- gint menu_ypos;
- gint menu_width;
-
- active = gtk_menu_get_active (GTK_MENU (priv->popup_widget));
-
- gtk_css_gadget_get_content_allocation (priv->gadget, &content_allocation, NULL);
-
- menu_xpos = content_allocation.x;
- menu_ypos = content_allocation.y + content_allocation.height / 2 - 2;
-
- if (priv->popup_fixed_width)
- gtk_widget_get_preferred_width (GTK_WIDGET (menu), &menu_width, NULL);
- else
- gtk_widget_get_preferred_width (GTK_WIDGET (menu), NULL, &menu_width);
-
- if (active != NULL)
- {
- gtk_widget_get_allocation (active, &child_allocation);
- menu_ypos -= child_allocation.height / 2;
- }
-
- children = GTK_MENU_SHELL (priv->popup_widget)->priv->children;
- while (children)
- {
- child = children->data;
-
- if (active == child)
- break;
-
- if (gtk_widget_get_visible (child))
- {
- gtk_widget_get_allocation (child, &child_allocation);
-
- menu_ypos -= child_allocation.height;
- }
-
- children = children->next;
- }
-
- if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
- menu_xpos = menu_xpos + content_allocation.width - menu_width;
-
- gdk_window_get_root_coords (gtk_widget_get_window (widget),
- menu_xpos, menu_ypos,
- &menu_xpos, &menu_ypos);
-
- /* Clamp the position on screen */
- screen_width = gdk_screen_get_width (gtk_widget_get_screen (widget));
-
- if (menu_xpos < 0)
- menu_xpos = 0;
- else if ((menu_xpos + menu_width) > screen_width)
- menu_xpos -= ((menu_xpos + menu_width) - screen_width);
-
- *x = menu_xpos;
- *y = menu_ypos;
-
- *push_in = TRUE;
-}
-
-static void
-gtk_combo_box_menu_position (GtkMenu *menu,
- gint *x,
- gint *y,
- gint *push_in,
- gpointer user_data)
-{
- GtkComboBox *combo_box = GTK_COMBO_BOX (user_data);
- GtkComboBoxPrivate *priv = combo_box->priv;
- GtkWidget *menu_item;
-
- if (priv->wrap_width > 0 || priv->cell_view == NULL)
- gtk_combo_box_menu_position_below (menu, x, y, push_in, user_data);
- else
- {
- /* FIXME handle nested menus better */
- menu_item = gtk_menu_get_active (GTK_MENU (priv->popup_widget));
- if (menu_item)
- gtk_menu_shell_select_item (GTK_MENU_SHELL (priv->popup_widget),
- menu_item);
-
- gtk_combo_box_menu_position_over (menu, x, y, push_in, user_data);
- }
-
- if (!gtk_widget_get_visible (GTK_MENU (priv->popup_widget)->priv->toplevel))
- gtk_window_set_type_hint (GTK_WINDOW (GTK_MENU (priv->popup_widget)->priv->toplevel),
- GDK_WINDOW_TYPE_HINT_COMBO);
-}
-
-static void
gtk_combo_box_list_position (GtkComboBox *combo_box,
gint *x,
gint *y,
@@ -2369,6 +2175,18 @@ gtk_combo_box_menu_popup (GtkComboBox *combo_box,
GtkTreePath *path;
gint active_item;
gint width, min_width, nat_width;
+ GdkAttachParams *params;
+ GdkWindow *attach_window;
+ gint x = 0;
+ gint y = 0;
+ gint offset_y = 0;
+ GtkWidget *attach_widget;
+ GtkWidget *active_widget;
+ GtkAllocation border_allocation;
+ GtkAllocation content_allocation;
+ GdkBorder margin;
+ gint height;
+ GList *i;
update_menu_sensitivity (combo_box, priv->popup_widget);
@@ -2403,10 +2221,109 @@ gtk_combo_box_menu_popup (GtkComboBox *combo_box,
gtk_widget_set_size_request (priv->popup_widget, width, -1);
}
- gtk_menu_popup (GTK_MENU (priv->popup_widget),
- NULL, NULL,
- gtk_combo_box_menu_position, combo_box,
- button, activate_time);
+ params = gtk_menu_create_params (GTK_MENU (priv->popup_widget));
+
+ if (priv->wrap_width > 0 || priv->cell_view == NULL)
+ {
+ attach_widget = gtk_bin_get_child (GTK_BIN (combo_box));
+
+ gtk_css_gadget_get_border_allocation (priv->gadget, &border_allocation, NULL);
+ gtk_css_gadget_get_content_allocation (priv->gadget, &content_allocation, NULL);
+
+ margin.top = content_allocation.y - border_allocation.y;
+ margin.left = content_allocation.x - border_allocation.x;
+ margin.right = content_allocation.x - border_allocation.x;
+ margin.bottom = content_allocation.y - border_allocation.y;
+
+ gdk_attach_params_set_attach_margin (params, &margin);
+
+ gdk_attach_params_add_primary_rules (params,
+ GDK_ATTACH_AXIS_Y | GDK_ATTACH_RECT_MAX | GDK_ATTACH_WINDOW_MIN,
+ GDK_ATTACH_AXIS_Y | GDK_ATTACH_RECT_MIN | GDK_ATTACH_WINDOW_MAX,
+ NULL);
+
+ gdk_attach_params_add_secondary_rules (params,
+ GDK_ATTACH_AXIS_X | GDK_ATTACH_RECT_MIN | GDK_ATTACH_WINDOW_MIN,
+ GDK_ATTACH_AXIS_X | GDK_ATTACH_RECT_MAX | GDK_ATTACH_WINDOW_MAX,
+ NULL);
+
+ gdk_attach_params_set_position_callback (params,
+ gtk_menu_update_scroll_offset,
+ g_object_ref (priv->popup_widget),
+ g_object_unref);
+
+ gtk_menu_popup_with_params (GTK_MENU (priv->popup_widget),
+ NULL,
+ NULL,
+ attach_widget,
+ button,
+ activate_time,
+ TRUE,
+ GDK_WINDOW_TYPE_HINT_COMBO,
+ params);
+ }
+ else
+ {
+ attach_widget = GTK_WIDGET (combo_box);
+ active_widget = gtk_menu_get_active (GTK_MENU (priv->popup_widget));
+ i = GTK_MENU_SHELL (priv->popup_widget)->priv->children;
+
+ attach_window = gtk_widget_get_window (attach_widget);
+
+ if (attach_window)
+ gdk_window_get_root_origin (attach_window, &x, &y);
+
+ gtk_css_gadget_get_content_allocation (priv->gadget, &content_allocation, NULL);
+
+ if (active_widget)
+ gtk_menu_shell_select_item (GTK_MENU_SHELL (priv->popup_widget), active_widget);
+ else if (i)
+ active_widget = i->data;
+
+ for (; i && i->data != active_widget; i = i->next)
+ {
+ if (gtk_widget_get_visible (i->data))
+ {
+ gtk_widget_get_preferred_height (i->data, &height, NULL);
+ offset_y -= height;
+ }
+ }
+
+ if (i && gtk_widget_get_visible (active_widget))
+ {
+ gtk_widget_get_preferred_height (active_widget, &height, NULL);
+ offset_y -= height / 2;
+ }
+
+ gdk_attach_params_set_attach_origin (params, x, y);
+ gdk_attach_params_set_attach_rect (params, &content_allocation);
+
+ gdk_attach_params_set_window_offset (params, 0, offset_y);
+
+ gdk_attach_params_add_primary_rules (params,
+ GDK_ATTACH_AXIS_Y | GDK_ATTACH_RECT_MID | GDK_ATTACH_WINDOW_MIN,
+ NULL);
+
+ gdk_attach_params_add_secondary_rules (params,
+ GDK_ATTACH_AXIS_X | GDK_ATTACH_RECT_MIN | GDK_ATTACH_WINDOW_MIN,
+ GDK_ATTACH_AXIS_X | GDK_ATTACH_RECT_MAX | GDK_ATTACH_WINDOW_MAX,
+ NULL);
+
+ gdk_attach_params_set_position_callback (params,
+ gtk_menu_update_scroll_offset,
+ g_object_ref (priv->popup_widget),
+ g_object_unref);
+
+ gtk_menu_popup_with_params (GTK_MENU (priv->popup_widget),
+ NULL,
+ NULL,
+ NULL,
+ button,
+ activate_time,
+ TRUE,
+ GDK_WINDOW_TYPE_HINT_COMBO,
+ params);
+ }
}
static gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]