Commit 8701e34f authored by William Hua's avatar William Hua

port to new gtk_menu_popup_at_* () functions

https://bugzilla.gnome.org/show_bug.cgi?id=756579
parent 05b9bc5c
......@@ -193,7 +193,7 @@ button_press (GtkWidget *widget,
gtk_widget_show (item);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, button->time);
gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *) button);
return TRUE;
}
......
......@@ -966,7 +966,7 @@ end_cb (GtkMenuItem *item, GtkWidget *scrollbar)
static gboolean
scrollbar_popup (GtkWidget *scrollbar, GtkWidget *menu)
{
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL);
return TRUE;
}
......
......@@ -157,8 +157,7 @@ icon_press_cb (GtkEntry *entry,
gpointer data)
{
if (position == GTK_ENTRY_ICON_PRIMARY)
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
event->button, event->time);
gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *) event);
}
static void
......
......@@ -1422,40 +1422,6 @@ palette_set_color (GtkWidget *drawing_area,
I_("color_val"), new_color, (GDestroyNotify)g_free);
}
static void
popup_position_func (GtkMenu *menu,
gint *x,
gint *y,
gboolean *push_in,
gpointer user_data)
{
GtkAllocation allocation;
GtkWidget *widget;
GtkRequisition req;
gint root_x, root_y;
GdkScreen *screen;
widget = GTK_WIDGET (user_data);
g_return_if_fail (gtk_widget_get_realized (widget));
gdk_window_get_origin (gtk_widget_get_window (widget),
&root_x, &root_y);
gtk_widget_get_preferred_size (GTK_WIDGET (menu),
&req, NULL);
gtk_widget_get_allocation (widget, &allocation);
/* Put corner of menu centered on color cell */
*x = root_x + allocation.width / 2;
*y = root_y + allocation.height / 2;
/* Ensure sanity */
screen = gtk_widget_get_screen (widget);
*x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width));
*y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height));
}
static void
save_color_selected (GtkWidget *menuitem,
gpointer data)
......@@ -1477,7 +1443,7 @@ save_color_selected (GtkWidget *menuitem,
static void
do_popup (GtkColorSelection *colorsel,
GtkWidget *drawing_area,
guint32 timestamp)
const GdkEvent *trigger_event)
{
GtkWidget *menu;
GtkWidget *mi;
......@@ -1499,9 +1465,14 @@ do_popup (GtkColorSelection *colorsel,
gtk_widget_show_all (mi);
gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
popup_position_func, drawing_area,
3, timestamp);
if (trigger_event && gdk_event_triggers_context_menu (trigger_event))
gtk_menu_popup_at_pointer (GTK_MENU (menu), trigger_event);
else
gtk_menu_popup_at_widget (GTK_MENU (menu),
drawing_area,
GDK_GRAVITY_CENTER,
GDK_GRAVITY_NORTH_WEST,
trigger_event);
}
......@@ -1540,7 +1511,7 @@ palette_press (GtkWidget *drawing_area,
if (gdk_event_triggers_context_menu ((GdkEvent *) event))
{
do_popup (colorsel, drawing_area, event->time);
do_popup (colorsel, drawing_area, (GdkEvent *) event);
return TRUE;
}
......@@ -1638,9 +1609,7 @@ static gboolean
palette_popup (GtkWidget *widget,
gpointer data)
{
GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
do_popup (colorsel, widget, GDK_CURRENT_TIME);
do_popup (data, widget, NULL);
return TRUE;
}
......
......@@ -257,8 +257,7 @@ widget_button_press_event_cb (GtkWidget *widget,
if (n_children > 0)
/* actually popup the menu */
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
event->button, event->time);
gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *) event);
g_list_free (children);
}
......
......@@ -306,21 +306,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);
......@@ -1921,187 +1906,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;
GdkDisplay *display;
GdkMonitor *monitor;
GdkRectangle area;
/* 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;
display = gtk_widget_get_display (GTK_WIDGET (combo_box));
monitor = gdk_display_get_monitor_at_window (display, gtk_widget_get_window (GTK_WIDGET (combo_box)));
gdk_monitor_get_workarea (monitor, &area);
if (*x < area.x)
*x = area.x;
else if (*x + req.width > area.x + area.width)
*x = area.x + area.width - req.width;
if (area.y + area.height - *y - child_allocation.height >= req.height)
*y += child_allocation.height;
else if (*y - area.y >= req.height)
*y -= req.height;
else if (area.y + area.height - *y - child_allocation.height > *y - area.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 menu_xpos;
gint menu_ypos;
gint menu_width;
GdkDisplay *display;
GdkMonitor *monitor;
GdkRectangle workarea;
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 */
display = gtk_widget_get_display (widget);
monitor = gdk_display_get_monitor_at_window (display, gtk_widget_get_window (widget));
gdk_monitor_get_workarea (monitor, &workarea);
if (menu_xpos < workarea.x)
menu_xpos = workarea.x;
else if ((menu_xpos + menu_width) > workarea.x + workarea.width)
menu_xpos -= (menu_xpos + menu_width) - (workarea.x + workarea.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,
......@@ -2309,6 +2113,13 @@ gtk_combo_box_menu_popup (GtkComboBox *combo_box,
GtkTreePath *path;
gint active_item;
gint width, min_width, nat_width;
GtkAllocation border_allocation;
GtkAllocation content_allocation;
gint rect_anchor_dy = -2;
gint child_height;
GtkWidget *active;
GtkWidget *child;
GList *i;
update_menu_sensitivity (combo_box, priv->popup_widget);
......@@ -2328,8 +2139,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);
......@@ -2343,10 +2152,82 @@ 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);
g_signal_handlers_disconnect_by_func (priv->popup_widget,
gtk_menu_update_scroll_offset,
NULL);
g_object_set (priv->popup_widget, "menu-type-hint", GDK_WINDOW_TYPE_HINT_COMBO, NULL);
if (priv->wrap_width > 0 || priv->cell_view == NULL)
{
gtk_css_gadget_get_border_allocation (priv->gadget, &border_allocation, NULL);
gtk_css_gadget_get_content_allocation (priv->gadget, &content_allocation, NULL);
g_object_set (priv->popup_widget,
"anchor-hints", (GDK_ANCHOR_FLIP_Y |
GDK_ANCHOR_SLIDE |
GDK_ANCHOR_RESIZE),
"rect-anchor-dx", border_allocation.x - content_allocation.x,
NULL);
gtk_menu_popup_at_widget (GTK_MENU (priv->popup_widget),
gtk_bin_get_child (GTK_BIN (combo_box)),
GDK_GRAVITY_SOUTH_WEST,
GDK_GRAVITY_NORTH_WEST,
NULL);
}
else
{
/* FIXME handle nested menus better */
active = gtk_menu_get_active (GTK_MENU (priv->popup_widget));
if (active)
gtk_menu_shell_select_item (GTK_MENU_SHELL (priv->popup_widget), active);
else
{
for (i = GTK_MENU_SHELL (priv->popup_widget)->priv->children; i && !active; i = i->next)
{
child = i->data;
if (child && gtk_widget_get_visible (child))
active = child;
}
}
if (active)
{
for (i = GTK_MENU_SHELL (priv->popup_widget)->priv->children; i && i->data != active; i = i->next)
{
child = i->data;
if (child && gtk_widget_get_visible (child))
{
gtk_widget_get_preferred_height (child, &child_height, NULL);
rect_anchor_dy -= child_height;
}
}
gtk_widget_get_preferred_height (active, &child_height, NULL);
rect_anchor_dy -= child_height / 2;
}
g_object_set (priv->popup_widget,
"anchor-hints", (GDK_ANCHOR_SLIDE |
GDK_ANCHOR_RESIZE),
"rect-anchor-dy", rect_anchor_dy,
NULL);
g_signal_connect (priv->popup_widget,
"popped-up",
G_CALLBACK (gtk_menu_update_scroll_offset),
NULL);
gtk_menu_popup_at_widget (GTK_MENU (priv->popup_widget),
GTK_WIDGET (combo_box),
GDK_GRAVITY_WEST,
GDK_GRAVITY_NORTH_WEST,
NULL);
}
}
static gboolean
......
......@@ -9430,56 +9430,10 @@ popup_menu_detach (GtkWidget *attach_widget,
priv_attach->popup_menu = NULL;
}
static void
popup_position_func (GtkMenu *menu,
gint *x,
gint *y,
gboolean *push_in,
gpointer user_data)
{
GtkEntry *entry = GTK_ENTRY (user_data);
GtkEntryPrivate *priv = entry->priv;
GtkWidget *widget = GTK_WIDGET (entry);
GdkDisplay *display;
GtkRequisition menu_req;
GdkMonitor *monitor;
GdkRectangle area;
gint strong_x, height;
g_return_if_fail (gtk_widget_get_realized (widget));
gdk_window_get_origin (priv->text_area, x, y);
display = gtk_widget_get_display (widget);
monitor = gdk_display_get_monitor_at_window (display, priv->text_area);
gtk_menu_place_on_monitor (menu, monitor);
gdk_monitor_get_workarea (monitor, &area);
gtk_widget_get_preferred_size (priv->popup_menu, &menu_req, NULL);
height = gdk_window_get_height (priv->text_area);
gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &strong_x, NULL);
*x += 0 + strong_x - priv->scroll_offset;
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
*x -= menu_req.width;
if ((*y + height + menu_req.height) <= area.y + area.height)
*y += height;
else if ((*y - menu_req.height) >= area.y)
*y -= menu_req.height;
else if (area.y + area.height - (*y + height) > *y)
*y += height;
else
*y -= menu_req.height;
*push_in = FALSE;
}
typedef struct
{
GtkEntry *entry;
guint button;
guint time;
GdkDevice *device;
GdkEvent *trigger_event;
} PopupInfo;
static void
......@@ -9490,6 +9444,7 @@ popup_targets_received (GtkClipboard *clipboard,
PopupInfo *info = user_data;
GtkEntry *entry = info->entry;
GtkEntryPrivate *info_entry_priv = entry->priv;
GdkRectangle rect = { 0, 0, 1, 0 };
if (gtk_widget_get_realized (GTK_WIDGET (entry)))
{
......@@ -9540,19 +9495,26 @@ popup_targets_received (GtkClipboard *clipboard,
g_signal_emit (entry, signals[POPULATE_POPUP], 0, menu);
if (info->device)
gtk_menu_popup_for_device (GTK_MENU (menu),
info->device, NULL, NULL, NULL, NULL, NULL,
info->button, info->time);
if (info->trigger_event && gdk_event_triggers_context_menu (info->trigger_event))
gtk_menu_popup_at_pointer (GTK_MENU (menu), info->trigger_event);
else
{
gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
popup_position_func, entry,
0, gtk_get_current_event_time ());
{
gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &rect.x, NULL);
rect.x -= info_entry_priv->scroll_offset;
rect.height = gdk_window_get_height (info_entry_priv->text_area);
gtk_menu_popup_at_rect (GTK_MENU (menu),
info_entry_priv->text_area,
&rect,
GDK_GRAVITY_SOUTH_EAST,
GDK_GRAVITY_NORTH_WEST,
info->trigger_event);
gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
}
}
}
g_clear_pointer (&info->trigger_event, gdk_event_free);
g_object_unref (entry);
g_slice_free (PopupInfo, info);
}
......@@ -9568,19 +9530,7 @@ gtk_entry_do_popup (GtkEntry *entry,
* we get them, then we actually pop up the menu.
*/
info->entry = g_object_ref (entry);
if (event)
{
gdk_event_get_button (event, &info->button);
info->time = gdk_event_get_time (event);
info->device = gdk_event_get_device (event);
}
else
{
info->button = 0;
info->time = gtk_get_current_event_time ();
info->device = NULL;
}
info->trigger_event = event ? gdk_event_copy (event) : gtk_get_current_event ();
gtk_clipboard_request_contents (gtk_widget_get_clipboard (GTK_WIDGET (entry), GDK_SELECTION_CLIPBOARD),
gdk_atom_intern_static_string ("TARGETS"),
......
......@@ -512,7 +512,7 @@ static void gtk_label_move_cursor (GtkLabel *label,
static void gtk_label_copy_clipboard (GtkLabel *label);
static void gtk_label_select_all (GtkLabel *label);
static void gtk_label_do_popup (GtkLabel *label,
GdkEventButton *event);
const GdkEvent *event);
static gint gtk_label_move_forward_word (GtkLabel *label,
gint start);
static gint gtk_label_move_backward_word (GtkLabel *label,
......@@ -4954,7 +4954,7 @@ gtk_label_multipress_gesture_pressed (GtkGestureMultiPress *gesture,
{
info->link_clicked = 1;
update_link_state (label);
gtk_label_do_popup (label, (GdkEventButton*) event);
gtk_label_do_popup (label, event);
return;
}
else if (button == GDK_BUTTON_PRIMARY)
......@@ -4977,7 +4977,7 @@ gtk_label_multipress_gesture_pressed (GtkGestureMultiPress *gesture,
info->select_words = FALSE;
if (gdk_event_triggers_context_menu (event))
gtk_label_do_popup (label, (GdkEventButton*) event);
gtk_label_do_popup (label, event);
else if (button == GDK_BUTTON_PRIMARY)
{
if (!gtk_widget_has_focus (widget))
......@@ -6544,48 +6544,6 @@ popup_menu_detach (GtkWidget *attach_widget,
priv->select_info->popup_menu = NULL;
}
static void
popup_position_func (GtkMenu *menu,
gint *x,
gint *y,
gboolean *push_in,
gpointer user_data)
{
GtkLabel *label;
GtkWidget *widget;
GtkAllocation allocation;
GtkRequisition req;
GdkDisplay *display;
GdkMonitor *monitor;
GdkRectangle workarea;
label = GTK_LABEL (user_data);
widget = GTK_WIDGET (label);
g_return_if_fail (gtk_widget_get_realized (widget));
display = gtk_widget_get_display (widget);
monitor = gdk_display_get_monitor_at_window (display,
gtk_widget_get_window (widget));
gdk_monitor_get_workarea (monitor, &workarea);
gdk_window_get_origin (gtk_widget_get_window (widget), x, y);
gtk_widget_get_allocation (widget, &allocation);
*x += allocation.x;
*y += allocation.y;
gtk_widget_get_preferred_size (GTK_WIDGET (menu), &req, NULL);
gtk_widget_get_allocation (widget, &allocation);
*x += allocation.width / 2;
*y += allocation.height;
*x = CLAMP (*x, 0, MAX (0, workarea.width - req.width));
*y = CLAMP (*y, 0, MAX (0, workarea.height - req.height));
}
static void
open_link_activate_cb (GtkMenuItem *menuitem,
GtkLabel *label)
......@@ -6618,7 +6576,7 @@ gtk_label_popup_menu (GtkWidget *widget)
static void
gtk_label_do_popup (GtkLabel *label,
GdkEventButton *event)
const GdkEvent *event)
{
GtkLabelPrivate *priv = label->priv;
GtkWidget *menuitem;
......@@ -6695,15 +6653,16 @@ gtk_label_do_popup (GtkLabel *label,
g_signal_emit (label, signals[POPULATE_POPUP], 0, menu);
if (event)
gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
NULL, NULL,
event->button, event->time);
if (event && gdk_event_triggers_context_menu ((GdkEvent *) event))
gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *) event);
else
{
gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
popup_position_func, label,
0, gtk_get_current_event_time ());
gtk_menu_popup_at_widget (GTK_MENU (menu),
GTK_WIDGET (label),
GDK_GRAVITY_SOUTH,
GDK_GRAVITY_NORTH_WEST,
event);
gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
}
}
......
......@@ -335,43 +335,6 @@ popup_menu_detach (GtkWidget *attach_widget,
link_button->priv->popup_menu = NULL;
}
static void
popup_position_func (GtkMenu *menu,
gint *x,
gint *y,
gboolean *push_in,
gpointer user_data)
{
GtkLinkButton *link_button = GTK_LINK_BUTTON (user_data);
GtkLinkButtonPrivate *priv = link_button->priv;
GtkAllocation allocation;
GtkWidget *widget = GTK_WIDGET (link_button);
GdkDisplay *display;
GdkMonitor *monitor;
GtkRequisition req;
GdkRectangle area;
g_return_if_fail (gtk_widget_get_realized (widget));
gdk_window_get_origin (gtk_widget_get_window (widget), x, y);
gtk_widget_get_preferred_size (priv->popup_menu, &req, NULL);
gtk_widget_get_allocation (widget, &allocation);
*x += allocation.width / 2;
*y += allocation.height;
display = gtk_widget_get_display (widget);
monitor = gdk_display_get_monitor_at_point (display, *x, *y);
gtk_menu_place_on_monitor (menu, monitor);
gdk_monitor_get_workarea (monitor, &area);
*x = CLAMP (*x, area.x, area.x + MAX (0, area.width - req.width));
*y = CLAMP (*y, area.y, area.y + MAX (0, area.height - req.height));
*push_in = FALSE;
}
static void