diff options
author | William Hua <william.hua@canonical.com> | 2015-09-27 00:26:43 -0400 |
---|---|---|
committer | William Hua <william.hua@canonical.com> | 2016-01-06 11:36:58 -0500 |
commit | 3d1ad162a0bf15f7423228ecc1bcc88408bec7e2 (patch) | |
tree | 77d0e87d6c6696e8ba64c95812a9b1101a7b8748 | |
parent | 0bbfba800e83b4df24d4655a5e982fd12f32fb62 (diff) | |
download | gtk+-wip/attachment-parameters-4.tar.gz |
gtkcombobox: use gtk_menu_popup_with_params ()wip/attachment-parameters-4
-rw-r--r-- | gtk/gtkcombobox.c | 324 |
1 files changed, 124 insertions, 200 deletions
diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c index df7f52e827..951bdd633e 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); @@ -2388,8 +2206,6 @@ gtk_combo_box_menu_popup (GtkComboBox *combo_box, if (priv->wrap_width == 0) { - GtkAllocation content_allocation; - gtk_css_gadget_get_content_allocation (priv->gadget, &content_allocation, NULL); width = content_allocation.width; gtk_widget_set_size_request (priv->popup_widget, -1, -1); @@ -2403,10 +2219,118 @@ 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); + + gdk_window_get_root_coords (attach_window, + content_allocation.x, + content_allocation.y, + &content_allocation.x, + &content_allocation.y); + + content_allocation.x -= x; + content_allocation.y -= y; + + 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 |