forked from AuroraMiddleware/gtk
port to new gtk_menu_popup_at_* () functions
https://bugzilla.gnome.org/show_bug.cgi?id=756579
This commit is contained in:
parent
05b9bc5cff
commit
8701e34f74
@ -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
|
||||
copy_activate_cb (GtkWidget *widget,
|
||||
GtkLinkButton *link_button)
|
||||
@ -385,22 +348,9 @@ copy_activate_cb (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
gtk_link_button_do_popup (GtkLinkButton *link_button,
|
||||
GdkEventButton *event)
|
||||
const GdkEvent *event)
|
||||
{
|
||||
GtkLinkButtonPrivate *priv = link_button->priv;
|
||||
gint button;
|
||||
guint time;
|
||||
|
||||
if (event)
|
||||
{
|
||||
button = event->button;
|
||||
time = event->time;
|
||||
}
|
||||
else
|
||||
{
|
||||
button = 0;
|
||||
time = gtk_get_current_event_time ();
|
||||
}
|
||||
|
||||
if (gtk_widget_get_realized (GTK_WIDGET (link_button)))
|
||||
{
|
||||
@ -423,15 +373,16 @@ gtk_link_button_do_popup (GtkLinkButton *link_button,
|
||||
gtk_widget_show (menu_item);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menu_item);
|
||||
|
||||
if (button)
|
||||
gtk_menu_popup (GTK_MENU (priv->popup_menu), NULL, NULL,
|
||||
NULL, NULL,
|
||||
button, time);
|
||||
if (event && gdk_event_triggers_context_menu (event))
|
||||
gtk_menu_popup_at_pointer (GTK_MENU (priv->popup_menu), event);
|
||||
else
|
||||
{
|
||||
gtk_menu_popup (GTK_MENU (priv->popup_menu), NULL, NULL,
|
||||
popup_position_func, link_button,
|
||||
button, time);
|
||||
gtk_menu_popup_at_widget (GTK_MENU (priv->popup_menu),
|
||||
GTK_WIDGET (link_button),
|
||||
GDK_GRAVITY_SOUTH,
|
||||
GDK_GRAVITY_NORTH_WEST,
|
||||
event);
|
||||
|
||||
gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->popup_menu), FALSE);
|
||||
}
|
||||
}
|
||||
@ -449,7 +400,7 @@ gtk_link_button_button_press (GtkWidget *widget,
|
||||
if (gdk_event_triggers_context_menu ((GdkEvent *) event) &&
|
||||
GTK_LINK_BUTTON (widget)->priv->uri != NULL)
|
||||
{
|
||||
gtk_link_button_do_popup (GTK_LINK_BUTTON (widget), event);
|
||||
gtk_link_button_do_popup (GTK_LINK_BUTTON (widget), (GdkEvent *) event);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -240,150 +240,13 @@ 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)
|
||||
{
|
||||
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;
|
||||
|
||||
/* treat the default align value like START */
|
||||
if (align == GTK_ALIGN_FILL)
|
||||
align = GTK_ALIGN_START;
|
||||
|
||||
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->arrow_type == GTK_ARROW_UP && *y - menu_allocation.height >= workarea.y)
|
||||
{
|
||||
*y -= menu_allocation.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
|
||||
gdk_window_get_origin (gtk_button_get_event_window (GTK_BUTTON (menu_button)), x, y);
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
gtk_widget_get_allocation (priv->menu, &menu_allocation);
|
||||
|
||||
if ((priv->arrow_type == GTK_ARROW_RIGHT && direction == GTK_TEXT_DIR_LTR) ||
|
||||
(priv->arrow_type == GTK_ARROW_LEFT && direction == GTK_TEXT_DIR_RTL))
|
||||
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* treat the default align value like START */
|
||||
if (align == GTK_ALIGN_FILL)
|
||||
align = GTK_ALIGN_START;
|
||||
|
||||
if (align == GTK_ALIGN_CENTER)
|
||||
*y -= (menu_allocation.height - allocation.height) / 2;
|
||||
else if (align == GTK_ALIGN_END)
|
||||
*y -= menu_allocation.height - allocation.height;
|
||||
|
||||
*push_in = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
popup_menu (GtkMenuButton *menu_button,
|
||||
GdkEvent *event)
|
||||
{
|
||||
GtkMenuButtonPrivate *priv = menu_button->priv;
|
||||
GtkMenuPositionFunc func;
|
||||
GdkDevice *device;
|
||||
guint button;
|
||||
guint32 time;
|
||||
GdkGravity widget_anchor = GDK_GRAVITY_SOUTH_WEST;
|
||||
GdkGravity menu_anchor = GDK_GRAVITY_NORTH_WEST;
|
||||
|
||||
if (priv->func)
|
||||
priv->func (priv->user_data);
|
||||
@ -393,37 +256,142 @@ popup_menu (GtkMenuButton *menu_button,
|
||||
|
||||
switch (priv->arrow_type)
|
||||
{
|
||||
case GTK_ARROW_UP:
|
||||
g_object_set (priv->menu,
|
||||
"anchor-hints", (GDK_ANCHOR_FLIP_Y |
|
||||
GDK_ANCHOR_SLIDE |
|
||||
GDK_ANCHOR_RESIZE),
|
||||
NULL);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GTK_ARROW_LEFT:
|
||||
g_object_set (priv->menu,
|
||||
"anchor-hints", (GDK_ANCHOR_FLIP_X |
|
||||
GDK_ANCHOR_SLIDE |
|
||||
GDK_ANCHOR_RESIZE),
|
||||
NULL);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GTK_ARROW_RIGHT:
|
||||
func = (GtkMenuPositionFunc) menu_position_side_func;
|
||||
g_object_set (priv->menu,
|
||||
"anchor-hints", (GDK_ANCHOR_FLIP_X |
|
||||
GDK_ANCHOR_SLIDE |
|
||||
GDK_ANCHOR_RESIZE),
|
||||
NULL);
|
||||
|
||||
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;
|
||||
default:
|
||||
func = (GtkMenuPositionFunc) menu_position_up_down_func;
|
||||
|
||||
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 (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;
|
||||
|
||||
case GTK_ARROW_NONE:
|
||||
g_object_set (priv->menu,
|
||||
"anchor-hints", (GDK_ANCHOR_FLIP_Y |
|
||||
GDK_ANCHOR_SLIDE |
|
||||
GDK_ANCHOR_RESIZE),
|
||||
NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
gtk_menu_popup_for_device (GTK_MENU (priv->menu),
|
||||
device,
|
||||
NULL, NULL,
|
||||
func,
|
||||
gtk_menu_popup_at_widget (GTK_MENU (priv->menu),
|
||||
GTK_WIDGET (menu_button),
|
||||
NULL,
|
||||
button,
|
||||
time);
|
||||
widget_anchor,
|
||||
menu_anchor,
|
||||
event);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -171,11 +171,6 @@ static gboolean gtk_menu_item_mnemonic_activate (GtkWidget *widget,
|
||||
|
||||
static void gtk_menu_item_ensure_label (GtkMenuItem *menu_item);
|
||||
static gint gtk_menu_item_popup_timeout (gpointer data);
|
||||
static void gtk_menu_item_position_menu (GtkMenu *menu,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gboolean *push_in,
|
||||
gpointer user_data);
|
||||
static void gtk_menu_item_show_all (GtkWidget *widget);
|
||||
|
||||
static void gtk_menu_item_forall (GtkContainer *container,
|
||||
@ -1908,20 +1903,62 @@ free_timeval (GTimeVal *val)
|
||||
g_slice_free (GTimeVal, val);
|
||||
}
|
||||
|
||||
static void
|
||||
popped_up_cb (GtkMenu *menu,
|
||||
const GdkRectangle *flipped_rect,
|
||||
const GdkRectangle *final_rect,
|
||||
gboolean flipped_x,
|
||||
gboolean flipped_y,
|
||||
GtkMenuItem *menu_item)
|
||||
{
|
||||
GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (menu_item));
|
||||
GtkMenu *parent_menu = GTK_IS_MENU (parent) ? GTK_MENU (parent) : NULL;
|
||||
|
||||
if (parent_menu && GTK_IS_MENU_ITEM (parent_menu->priv->parent_menu_item))
|
||||
menu_item->priv->submenu_direction = GTK_MENU_ITEM (parent_menu->priv->parent_menu_item)->priv->submenu_direction;
|
||||
else
|
||||
{
|
||||
/* this case is stateful, do it at most once */
|
||||
g_signal_handlers_disconnect_by_func (menu, popped_up_cb, menu_item);
|
||||
}
|
||||
|
||||
if (flipped_x)
|
||||
{
|
||||
switch (menu_item->priv->submenu_direction)
|
||||
{
|
||||
case GTK_DIRECTION_LEFT:
|
||||
menu_item->priv->submenu_direction = GTK_DIRECTION_RIGHT;
|
||||
break;
|
||||
|
||||
case GTK_DIRECTION_RIGHT:
|
||||
menu_item->priv->submenu_direction = GTK_DIRECTION_LEFT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_item_real_popup_submenu (GtkWidget *widget,
|
||||
const GdkEvent *trigger_event,
|
||||
gboolean remember_exact_time)
|
||||
{
|
||||
GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
|
||||
GtkMenuItemPrivate *priv = menu_item->priv;
|
||||
GtkSubmenuDirection submenu_direction;
|
||||
GtkStyleContext *context;
|
||||
GtkBorder parent_padding;
|
||||
GtkBorder menu_padding;
|
||||
gint horizontal_offset;
|
||||
gint vertical_offset;
|
||||
GtkWidget *parent;
|
||||
GtkMenu *parent_menu;
|
||||
|
||||
parent = gtk_widget_get_parent (widget);
|
||||
parent_menu = GTK_IS_MENU (parent) ? GTK_MENU (parent) : NULL;
|
||||
|
||||
if (gtk_widget_is_sensitive (priv->submenu) && parent)
|
||||
{
|
||||
gboolean take_focus;
|
||||
GtkMenuPositionFunc menu_position_func;
|
||||
|
||||
take_focus = gtk_menu_shell_get_take_focus (GTK_MENU_SHELL (parent));
|
||||
gtk_menu_shell_set_take_focus (GTK_MENU_SHELL (priv->submenu), take_focus);
|
||||
@ -1942,24 +1979,91 @@ gtk_menu_item_real_popup_submenu (GtkWidget *widget,
|
||||
"gtk-menu-exact-popup-time", NULL);
|
||||
}
|
||||
|
||||
/* gtk_menu_item_position_menu positions the submenu from the
|
||||
* menuitems position. If the menuitem doesn't have a window,
|
||||
* that doesn't work. In that case we use the default
|
||||
* positioning function instead which places the submenu at the
|
||||
* mouse cursor.
|
||||
/* Position the submenu at the menu item if it is mapped.
|
||||
* Otherwise, position the submenu at the pointer device.
|
||||
*/
|
||||
if (gtk_widget_get_window (widget))
|
||||
menu_position_func = gtk_menu_item_position_menu;
|
||||
else
|
||||
menu_position_func = NULL;
|
||||
{
|
||||
switch (priv->submenu_placement)
|
||||
{
|
||||
case GTK_TOP_BOTTOM:
|
||||
g_object_set (priv->submenu,
|
||||
"anchor-hints", (GDK_ANCHOR_FLIP_Y |
|
||||
GDK_ANCHOR_SLIDE |
|
||||
GDK_ANCHOR_RESIZE),
|
||||
"menu-type-hint", (priv->from_menubar ?
|
||||
GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU :
|
||||
GDK_WINDOW_TYPE_HINT_POPUP_MENU),
|
||||
NULL);
|
||||
|
||||
gtk_menu_popup (GTK_MENU (priv->submenu),
|
||||
parent,
|
||||
gtk_menu_popup_at_widget (GTK_MENU (priv->submenu),
|
||||
widget,
|
||||
menu_position_func,
|
||||
menu_item,
|
||||
GTK_MENU_SHELL (parent)->priv->button,
|
||||
0);
|
||||
GDK_GRAVITY_SOUTH_WEST,
|
||||
GDK_GRAVITY_NORTH_WEST,
|
||||
trigger_event);
|
||||
|
||||
break;
|
||||
|
||||
case GTK_LEFT_RIGHT:
|
||||
if (parent_menu && GTK_IS_MENU_ITEM (parent_menu->priv->parent_menu_item))
|
||||
submenu_direction = GTK_MENU_ITEM (parent_menu->priv->parent_menu_item)->priv->submenu_direction;
|
||||
else
|
||||
submenu_direction = priv->submenu_direction;
|
||||
|
||||
g_signal_handlers_disconnect_by_func (priv->submenu, popped_up_cb, menu_item);
|
||||
g_signal_connect (priv->submenu, "popped-up", G_CALLBACK (popped_up_cb), menu_item);
|
||||
|
||||
gtk_widget_style_get (priv->submenu,
|
||||
"horizontal-offset", &horizontal_offset,
|
||||
"vertical-offset", &vertical_offset,
|
||||
NULL);
|
||||
|
||||
context = gtk_widget_get_style_context (parent);
|
||||
gtk_style_context_get_padding (context, gtk_style_context_get_state (context), &parent_padding);
|
||||
context = gtk_widget_get_style_context (priv->submenu);
|
||||
gtk_style_context_get_padding (context, gtk_style_context_get_state (context), &menu_padding);
|
||||
|
||||
g_object_set (priv->submenu,
|
||||
"anchor-hints", (GDK_ANCHOR_FLIP_X |
|
||||
GDK_ANCHOR_SLIDE |
|
||||
GDK_ANCHOR_RESIZE),
|
||||
"rect-anchor-dy", vertical_offset - menu_padding.top,
|
||||
NULL);
|
||||
|
||||
switch (submenu_direction)
|
||||
{
|
||||
case GTK_DIRECTION_RIGHT:
|
||||
g_object_set (priv->submenu,
|
||||
"rect-anchor-dx", horizontal_offset + parent_padding.right + menu_padding.left,
|
||||
NULL);
|
||||
|
||||
gtk_menu_popup_at_widget (GTK_MENU (priv->submenu),
|
||||
widget,
|
||||
GDK_GRAVITY_NORTH_EAST,
|
||||
GDK_GRAVITY_NORTH_WEST,
|
||||
trigger_event);
|
||||
|
||||
break;
|
||||
|
||||
case GTK_DIRECTION_LEFT:
|
||||
g_object_set (priv->submenu,
|
||||
"rect-anchor-dx", -(horizontal_offset + parent_padding.left + menu_padding.right),
|
||||
NULL);
|
||||
|
||||
gtk_menu_popup_at_widget (GTK_MENU (priv->submenu),
|
||||
widget,
|
||||
GDK_GRAVITY_NORTH_WEST,
|
||||
GDK_GRAVITY_NORTH_EAST,
|
||||
trigger_event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
gtk_menu_popup_at_pointer (GTK_MENU (priv->submenu), trigger_event);
|
||||
}
|
||||
|
||||
/* Enable themeing of the parent menu item depending on whether
|
||||
@ -1968,10 +2072,17 @@ gtk_menu_item_real_popup_submenu (GtkWidget *widget,
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkMenuItem *menu_item;
|
||||
GdkEvent *trigger_event;
|
||||
} PopupInfo;
|
||||
|
||||
static gint
|
||||
gtk_menu_item_popup_timeout (gpointer data)
|
||||
{
|
||||
GtkMenuItem *menu_item = GTK_MENU_ITEM (data);
|
||||
PopupInfo *info = data;
|
||||
GtkMenuItem *menu_item = info->menu_item;
|
||||
GtkMenuItemPrivate *priv = menu_item->priv;
|
||||
GtkWidget *parent;
|
||||
|
||||
@ -1980,13 +2091,19 @@ gtk_menu_item_popup_timeout (gpointer data)
|
||||
if ((GTK_IS_MENU_SHELL (parent) && GTK_MENU_SHELL (parent)->priv->active) ||
|
||||
(GTK_IS_MENU (parent) && GTK_MENU (parent)->priv->torn_off))
|
||||
{
|
||||
gtk_menu_item_real_popup_submenu (GTK_WIDGET (menu_item), TRUE);
|
||||
if (priv->timer_from_keypress && priv->submenu)
|
||||
gtk_menu_item_real_popup_submenu (GTK_WIDGET (menu_item), info->trigger_event, TRUE);
|
||||
if (info->trigger_event &&
|
||||
info->trigger_event->type != GDK_BUTTON_PRESS &&
|
||||
info->trigger_event->type != GDK_ENTER_NOTIFY &&
|
||||
priv->submenu)
|
||||
GTK_MENU_SHELL (priv->submenu)->priv->ignore_enter = TRUE;
|
||||
}
|
||||
|
||||
priv->timer = 0;
|
||||
|
||||
g_clear_pointer (&info->trigger_event, gdk_event_free);
|
||||
g_slice_free (PopupInfo, info);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -2022,28 +2139,21 @@ _gtk_menu_item_popup_submenu (GtkWidget *widget,
|
||||
|
||||
if (popup_delay > 0)
|
||||
{
|
||||
GdkEvent *event = gtk_get_current_event ();
|
||||
PopupInfo *info = g_slice_new (PopupInfo);
|
||||
|
||||
info->menu_item = menu_item;
|
||||
info->trigger_event = gtk_get_current_event ();
|
||||
|
||||
priv->timer = gdk_threads_add_timeout (popup_delay,
|
||||
gtk_menu_item_popup_timeout,
|
||||
menu_item);
|
||||
info);
|
||||
g_source_set_name_by_id (priv->timer, "[gtk+] gtk_menu_item_popup_timeout");
|
||||
|
||||
if (event &&
|
||||
event->type != GDK_BUTTON_PRESS &&
|
||||
event->type != GDK_ENTER_NOTIFY)
|
||||
priv->timer_from_keypress = TRUE;
|
||||
else
|
||||
priv->timer_from_keypress = FALSE;
|
||||
|
||||
if (event)
|
||||
gdk_event_free (event);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_menu_item_real_popup_submenu (widget, FALSE);
|
||||
gtk_menu_item_real_popup_submenu (widget, NULL, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2069,176 +2179,6 @@ _gtk_menu_item_popdown_submenu (GtkWidget *widget)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_offsets (GtkMenu *menu,
|
||||
gint *horizontal_offset,
|
||||
gint *vertical_offset)
|
||||
{
|
||||
GtkStyleContext *context;
|
||||
GtkBorder padding;
|
||||
|
||||
gtk_widget_style_get (GTK_WIDGET (menu),
|
||||
"horizontal-offset", horizontal_offset,
|
||||
"vertical-offset", vertical_offset,
|
||||
NULL);
|
||||
|
||||
context = gtk_widget_get_style_context (GTK_WIDGET (menu));
|
||||
gtk_style_context_get_padding (context, gtk_style_context_get_state (context), &padding);
|
||||
|
||||
*vertical_offset -= padding.top;
|
||||
*horizontal_offset += padding.left;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_item_position_menu (GtkMenu *menu,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gboolean *push_in,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkMenuItem *menu_item = GTK_MENU_ITEM (user_data);
|
||||
GtkMenuItemPrivate *priv = menu_item->priv;
|
||||
GtkAllocation allocation;
|
||||
GtkWidget *widget;
|
||||
GtkMenuItem *parent_menu_item;
|
||||
GtkWidget *parent;
|
||||
GdkDisplay *display;
|
||||
gint twidth, theight;
|
||||
gint tx, ty;
|
||||
GtkTextDirection direction;
|
||||
GdkMonitor *monitor;
|
||||
GdkRectangle workarea;
|
||||
gint horizontal_offset;
|
||||
gint vertical_offset;
|
||||
gint available_left, available_right;
|
||||
GtkStyleContext *context;
|
||||
GtkBorder parent_padding;
|
||||
|
||||
g_return_if_fail (menu != NULL);
|
||||
g_return_if_fail (x != NULL);
|
||||
g_return_if_fail (y != NULL);
|
||||
|
||||
widget = GTK_WIDGET (user_data);
|
||||
|
||||
if (push_in)
|
||||
*push_in = FALSE;
|
||||
|
||||
direction = gtk_widget_get_direction (widget);
|
||||
|
||||
twidth = gtk_widget_get_allocated_width (GTK_WIDGET (menu));
|
||||
theight = gtk_widget_get_allocated_height (GTK_WIDGET (menu));
|
||||
|
||||
display = gtk_widget_get_display (GTK_WIDGET (menu));
|
||||
monitor = gdk_display_get_monitor_at_window (display, priv->event_window);
|
||||
gdk_monitor_get_workarea (monitor, &workarea);
|
||||
|
||||
if (!gdk_window_get_origin (gtk_widget_get_window (widget), &tx, &ty))
|
||||
{
|
||||
g_warning ("Menu not on screen");
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
tx += allocation.x;
|
||||
ty += allocation.y;
|
||||
|
||||
get_offsets (menu, &horizontal_offset, &vertical_offset);
|
||||
|
||||
available_left = tx - workarea.x;
|
||||
available_right = workarea.x + workarea.width - (tx + allocation.width);
|
||||
|
||||
parent = gtk_widget_get_parent (widget);
|
||||
priv->from_menubar = GTK_IS_MENU_BAR (parent);
|
||||
|
||||
switch (priv->submenu_placement)
|
||||
{
|
||||
case GTK_TOP_BOTTOM:
|
||||
if (direction == GTK_TEXT_DIR_LTR)
|
||||
priv->submenu_direction = GTK_DIRECTION_RIGHT;
|
||||
else
|
||||
{
|
||||
priv->submenu_direction = GTK_DIRECTION_LEFT;
|
||||
tx += allocation.width - twidth;
|
||||
}
|
||||
if ((ty + allocation.height + theight) <= workarea.y + workarea.height)
|
||||
ty += allocation.height;
|
||||
else if ((ty - theight) >= workarea.y)
|
||||
ty -= theight;
|
||||
else if (workarea.y + workarea.height - (ty + allocation.height) > ty)
|
||||
ty += allocation.height;
|
||||
else
|
||||
ty -= theight;
|
||||
break;
|
||||
|
||||
case GTK_LEFT_RIGHT:
|
||||
if (GTK_IS_MENU (parent))
|
||||
parent_menu_item = GTK_MENU_ITEM (GTK_MENU (parent)->priv->parent_menu_item);
|
||||
else
|
||||
parent_menu_item = NULL;
|
||||
|
||||
context = gtk_widget_get_style_context (parent);
|
||||
gtk_style_context_get_padding (context, gtk_style_context_get_state (context), &parent_padding);
|
||||
|
||||
if (parent_menu_item && !GTK_MENU (parent)->priv->torn_off)
|
||||
{
|
||||
priv->submenu_direction = parent_menu_item->priv->submenu_direction;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (direction == GTK_TEXT_DIR_LTR)
|
||||
priv->submenu_direction = GTK_DIRECTION_RIGHT;
|
||||
else
|
||||
priv->submenu_direction = GTK_DIRECTION_LEFT;
|
||||
}
|
||||
|
||||
switch (priv->submenu_direction)
|
||||
{
|
||||
case GTK_DIRECTION_LEFT:
|
||||
if (tx - twidth - parent_padding.left - horizontal_offset >= workarea.x ||
|
||||
available_left >= available_right)
|
||||
tx -= twidth + parent_padding.left + horizontal_offset;
|
||||
else
|
||||
{
|
||||
priv->submenu_direction = GTK_DIRECTION_RIGHT;
|
||||
tx += allocation.width + parent_padding.right + horizontal_offset;
|
||||
}
|
||||
break;
|
||||
|
||||
case GTK_DIRECTION_RIGHT:
|
||||
if (tx + allocation.width + parent_padding.right + horizontal_offset + twidth <= workarea.x + workarea.width ||
|
||||
available_right >= available_left)
|
||||
tx += allocation.width + parent_padding.right + horizontal_offset;
|
||||
else
|
||||
{
|
||||
priv->submenu_direction = GTK_DIRECTION_LEFT;
|
||||
tx -= twidth + parent_padding.left + horizontal_offset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ty += vertical_offset;
|
||||
|
||||
/* If the height of the menu doesn't fit we move it upward. */
|
||||
ty = CLAMP (ty, workarea.y, MAX (workarea.y, workarea.y + workarea.height - theight));
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we have negative, tx, here it is because we can't get
|
||||
* the menu all the way on screen. Favor the left portion.
|
||||
*/
|
||||
*x = CLAMP (tx, workarea.x, MAX (workarea.x, workarea.x + workarea.width - twidth));
|
||||
*y = ty;
|
||||
|
||||
gtk_menu_place_on_monitor (menu, monitor);
|
||||
|
||||
if (!gtk_widget_get_visible (menu->priv->toplevel))
|
||||
{
|
||||
gtk_window_set_type_hint (GTK_WINDOW (menu->priv->toplevel), priv->from_menubar?
|
||||
GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU : GDK_WINDOW_TYPE_HINT_POPUP_MENU);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_menu_item_set_right_justified:
|
||||
* @menu_item: a #GtkMenuItem.
|
||||
|
@ -47,7 +47,6 @@ struct _GtkMenuItemPrivate
|
||||
guint submenu_placement : 1;
|
||||
guint submenu_direction : 1;
|
||||
guint right_justify : 1;
|
||||
guint timer_from_keypress : 1;
|
||||
guint from_menubar : 1;
|
||||
guint use_action_appearance : 1;
|
||||
guint reserve_indicator : 1;
|
||||
|
@ -1299,16 +1299,11 @@ on_end_process_activated (GtkMenuItem *item,
|
||||
|
||||
static gboolean
|
||||
do_popup_menu_for_process_tree_view (GtkWidget *widget,
|
||||
GdkEventButton *event,
|
||||
const GdkEvent *event,
|
||||
GtkMountOperation *op)
|
||||
{
|
||||
GtkWidget *menu;
|
||||
GtkWidget *item;
|
||||
gint button;
|
||||
gint event_time;
|
||||
gboolean popped_up_menu;
|
||||
|
||||
popped_up_menu = FALSE;
|
||||
|
||||
menu = gtk_menu_new ();
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (menu),
|
||||
@ -1321,14 +1316,14 @@ do_popup_menu_for_process_tree_view (GtkWidget *widget,
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||
gtk_widget_show_all (menu);
|
||||
|
||||
if (event != NULL)
|
||||
if (event && gdk_event_triggers_context_menu (event))
|
||||
{
|
||||
GtkTreePath *path;
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (op->priv->process_tree_view),
|
||||
(gint) event->x,
|
||||
(gint) event->y,
|
||||
(gint) event->button.x,
|
||||
(gint) event->button.y,
|
||||
&path,
|
||||
NULL,
|
||||
NULL,
|
||||
@ -1341,30 +1336,12 @@ do_popup_menu_for_process_tree_view (GtkWidget *widget,
|
||||
else
|
||||
{
|
||||
/* don't popup a menu if the user right-clicked in an area with no rows */
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
button = event->button;
|
||||
event_time = event->time;
|
||||
}
|
||||
else
|
||||
{
|
||||
button = 0;
|
||||
event_time = gtk_get_current_event_time ();
|
||||
}
|
||||
|
||||
gtk_menu_popup (GTK_MENU (menu),
|
||||
NULL,
|
||||
widget,
|
||||
NULL,
|
||||
NULL,
|
||||
button,
|
||||
event_time);
|
||||
|
||||
popped_up_menu = TRUE;
|
||||
|
||||
out:
|
||||
return popped_up_menu;
|
||||
gtk_menu_popup_at_pointer (GTK_MENU (menu), event);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -1387,7 +1364,7 @@ on_button_press_event_for_process_tree_view (GtkWidget *widget,
|
||||
|
||||
if (gdk_event_triggers_context_menu ((GdkEvent *) event))
|
||||
{
|
||||
ret = do_popup_menu_for_process_tree_view (widget, event, op);
|
||||
ret = do_popup_menu_for_process_tree_view (widget, (GdkEvent *) event, op);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -2750,8 +2750,7 @@ gtk_notebook_button_press (GtkWidget *widget,
|
||||
|
||||
if (priv->menu && gdk_event_triggers_context_menu ((GdkEvent *) event))
|
||||
{
|
||||
gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL,
|
||||
NULL, NULL, 3, event->time);
|
||||
gtk_menu_popup_at_pointer (GTK_MENU (priv->menu), (GdkEvent *) event);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -2794,58 +2793,50 @@ gtk_notebook_button_press (GtkWidget *widget,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
popup_position_func (GtkMenu *menu,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gboolean *push_in,
|
||||
gpointer data)
|
||||
{
|
||||
GtkNotebook *notebook = data;
|
||||
GtkNotebookPrivate *priv = notebook->priv;
|
||||
GtkAllocation allocation;
|
||||
GtkWidget *w;
|
||||
GtkRequisition requisition;
|
||||
|
||||
if (priv->focus_tab)
|
||||
{
|
||||
GtkNotebookPage *page;
|
||||
|
||||
page = priv->focus_tab->data;
|
||||
w = page->tab_label;
|
||||
}
|
||||
else
|
||||
{
|
||||
w = GTK_WIDGET (notebook);
|
||||
}
|
||||
|
||||
gdk_window_get_origin (gtk_widget_get_window (w), x, y);
|
||||
|
||||
gtk_widget_get_allocation (w, &allocation);
|
||||
gtk_widget_get_preferred_size (GTK_WIDGET (menu),
|
||||
&requisition, NULL);
|
||||
|
||||
if (gtk_widget_get_direction (w) == GTK_TEXT_DIR_RTL)
|
||||
*x += allocation.x + allocation.width - requisition.width;
|
||||
else
|
||||
*x += allocation.x;
|
||||
|
||||
*y += allocation.y + allocation.height;
|
||||
|
||||
*push_in = FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_notebook_popup_menu (GtkWidget *widget)
|
||||
{
|
||||
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
|
||||
GtkNotebookPrivate *priv = notebook->priv;
|
||||
GtkNotebookPage *page;
|
||||
GtkWidget *tab_label = NULL;
|
||||
|
||||
if (priv->menu)
|
||||
{
|
||||
gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL,
|
||||
popup_position_func, notebook,
|
||||
0, gtk_get_current_event_time ());
|
||||
if (priv->focus_tab)
|
||||
{
|
||||
page = priv->focus_tab->data;
|
||||
tab_label = page->tab_label;
|
||||
}
|
||||
|
||||
if (tab_label)
|
||||
{
|
||||
g_object_set (priv->menu,
|
||||
"anchor-hints", (GDK_ANCHOR_FLIP_Y |
|
||||
GDK_ANCHOR_SLIDE |
|
||||
GDK_ANCHOR_RESIZE),
|
||||
NULL);
|
||||
|
||||
gtk_menu_popup_at_widget (GTK_MENU (priv->menu),
|
||||
tab_label,
|
||||
GDK_GRAVITY_SOUTH_WEST,
|
||||
GDK_GRAVITY_NORTH_WEST,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_set (priv->menu,
|
||||
"anchor-hints", (GDK_ANCHOR_SLIDE |
|
||||
GDK_ANCHOR_RESIZE),
|
||||
NULL);
|
||||
|
||||
gtk_menu_popup_at_widget (GTK_MENU (priv->menu),
|
||||
widget,
|
||||
GDK_GRAVITY_NORTH_WEST,
|
||||
GDK_GRAVITY_NORTH_WEST,
|
||||
NULL);
|
||||
}
|
||||
|
||||
gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menu), FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1665,7 +1665,6 @@ popup_menu (GtkPlacesViewRow *row,
|
||||
{
|
||||
GtkPlacesViewPrivate *priv;
|
||||
GtkWidget *view;
|
||||
gint button;
|
||||
|
||||
view = gtk_widget_get_ancestor (GTK_WIDGET (row), GTK_TYPE_PLACES_VIEW);
|
||||
priv = gtk_places_view_get_instance_private (GTK_PLACES_VIEW (view));
|
||||
@ -1674,30 +1673,7 @@ popup_menu (GtkPlacesViewRow *row,
|
||||
|
||||
build_popup_menu (GTK_PLACES_VIEW (view), row);
|
||||
|
||||
/* The event button needs to be 0 if we're popping up this menu from
|
||||
* a button release, else a 2nd click outside the menu with any button
|
||||
* other than the one that invoked the menu will be ignored (instead
|
||||
* of dismissing the menu). This is a subtle fragility of the GTK menu code.
|
||||
*/
|
||||
if (event)
|
||||
{
|
||||
if (event->type == GDK_BUTTON_PRESS)
|
||||
button = 0;
|
||||
else
|
||||
button = event->button;
|
||||
}
|
||||
else
|
||||
{
|
||||
button = 0;
|
||||
}
|
||||
|
||||
gtk_menu_popup (GTK_MENU (priv->popup_menu),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
button,
|
||||
event ? event->time : gtk_get_current_event_time ());
|
||||
gtk_menu_popup_at_pointer (GTK_MENU (priv->popup_menu), (GdkEvent *) event);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -1727,62 +1727,23 @@ recent_view_menu_build (GtkRecentChooserDefault *impl)
|
||||
recent_view_menu_ensure_state (impl);
|
||||
}
|
||||
|
||||
/* taken from gtkfilechooserdefault.c */
|
||||
static void
|
||||
popup_position_func (GtkMenu *menu,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gboolean *push_in,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
GtkWidget *widget = GTK_WIDGET (user_data);
|
||||
GtkRequisition req;
|
||||
GdkDisplay *display;
|
||||
GdkMonitor *monitor;
|
||||
GdkRectangle workarea;
|
||||
|
||||
if (G_UNLIKELY (!gtk_widget_get_realized (widget)))
|
||||
return;
|
||||
|
||||
gdk_window_get_origin (gtk_widget_get_window (widget), x, y);
|
||||
|
||||
gtk_widget_get_preferred_size (GTK_WIDGET (menu), &req, NULL);
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
*x += (allocation.width - req.width) / 2;
|
||||
*y += (allocation.height - req.height) / 2;
|
||||
|
||||
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, &workarea);
|
||||
|
||||
*x = CLAMP (*x, workarea.x, workarea.x + MAX (0, workarea.width - req.width));
|
||||
*y = CLAMP (*y, workarea.y, workarea.y + MAX (0, workarea.height - req.height));
|
||||
|
||||
*push_in = FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
recent_view_menu_popup (GtkRecentChooserDefault *impl,
|
||||
GdkEventButton *event)
|
||||
{
|
||||
recent_view_menu_build (impl);
|
||||
|
||||
if (event)
|
||||
gtk_menu_popup (GTK_MENU (impl->priv->recent_popup_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 (impl->priv->recent_popup_menu), (GdkEvent *) event);
|
||||
else
|
||||
{
|
||||
gtk_menu_popup (GTK_MENU (impl->priv->recent_popup_menu),
|
||||
NULL, NULL,
|
||||
popup_position_func, impl->priv->recent_view,
|
||||
0, GDK_CURRENT_TIME);
|
||||
gtk_menu_shell_select_first (GTK_MENU_SHELL (impl->priv->recent_popup_menu),
|
||||
FALSE);
|
||||
gtk_menu_popup_at_widget (GTK_MENU (impl->priv->recent_popup_menu),
|
||||
impl->priv->recent_view,
|
||||
GDK_GRAVITY_CENTER,
|
||||
GDK_GRAVITY_CENTER,
|
||||
(GdkEvent *) event);
|
||||
|
||||
gtk_menu_shell_select_first (GTK_MENU_SHELL (impl->priv->recent_popup_menu), FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9347,91 +9347,10 @@ popup_menu_detach (GtkWidget *attach_widget,
|
||||
GTK_TEXT_VIEW (attach_widget)->priv->popup_menu = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
popup_position_func (GtkMenu *menu,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gboolean *push_in,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
GtkTextView *text_view;
|
||||
GtkWidget *widget;
|
||||
GdkRectangle cursor_rect;
|
||||
GdkRectangle onscreen_rect;
|
||||
gint root_x, root_y;
|
||||
GtkTextIter iter;
|
||||
GtkRequisition req;
|
||||
GdkDisplay *display;
|
||||
GdkMonitor *monitor;
|
||||
GdkRectangle workarea;
|
||||
|
||||
text_view = GTK_TEXT_VIEW (user_data);
|
||||
widget = GTK_WIDGET (text_view);
|
||||
|
||||
g_return_if_fail (gtk_widget_get_realized (widget));
|
||||
|
||||
display = gtk_widget_get_display (widget);
|
||||
|
||||
gdk_window_get_origin (gtk_widget_get_window (widget),
|
||||
&root_x, &root_y);
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (get_buffer (text_view),
|
||||
&iter,
|
||||
gtk_text_buffer_get_insert (get_buffer (text_view)));
|
||||
|
||||
gtk_text_view_get_iter_location (text_view,
|
||||
&iter,
|
||||
&cursor_rect);
|
||||
|
||||
gtk_text_view_get_visible_rect (text_view, &onscreen_rect);
|
||||
|
||||
gtk_widget_get_preferred_size (text_view->priv->popup_menu,
|
||||
&req, NULL);
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
/* can't use rectangle_intersect since cursor rect can have 0 width */
|
||||
if (cursor_rect.x >= onscreen_rect.x &&
|
||||
cursor_rect.x < onscreen_rect.x + onscreen_rect.width &&
|
||||
cursor_rect.y >= onscreen_rect.y &&
|
||||
cursor_rect.y < onscreen_rect.y + onscreen_rect.height)
|
||||
{
|
||||
gtk_text_view_buffer_to_window_coords (text_view,
|
||||
GTK_TEXT_WINDOW_WIDGET,
|
||||
cursor_rect.x, cursor_rect.y,
|
||||
&cursor_rect.x, &cursor_rect.y);
|
||||
|
||||
*x = root_x + cursor_rect.x + cursor_rect.width;
|
||||
*y = root_y + cursor_rect.y + cursor_rect.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just center the menu, since cursor is offscreen. */
|
||||
*x = root_x + (allocation.width / 2 - req.width / 2);
|
||||
*y = root_y + (allocation.height / 2 - req.height / 2);
|
||||
}
|
||||
|
||||
/* Ensure sanity */
|
||||
*x = CLAMP (*x, root_x, (root_x + allocation.width));
|
||||
*y = CLAMP (*y, root_y, (root_y + allocation.height));
|
||||
|
||||
monitor = gdk_display_get_monitor_at_point (display, *x, *y);
|
||||
gtk_menu_place_on_monitor (menu, monitor);
|
||||
gdk_monitor_get_workarea (monitor, &workarea);
|
||||
|
||||
*x = CLAMP (*x, workarea.x, workarea.x + MAX (0, workarea.width - req.width));
|
||||
*y = CLAMP (*y, workarea.y, workarea.y + MAX (0, workarea.height - req.height));
|
||||
|
||||
*push_in = FALSE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkTextView *text_view;
|
||||
guint button;
|
||||
guint time;
|
||||
GdkDevice *device;
|
||||
GdkEvent *trigger_event;
|
||||
} PopupInfo;
|
||||
|
||||
static gboolean
|
||||
@ -9475,6 +9394,9 @@ popup_targets_received (GtkClipboard *clipboard,
|
||||
gboolean can_insert;
|
||||
GtkTextIter iter;
|
||||
GtkTextIter sel_start, sel_end;
|
||||
GdkRectangle iter_location;
|
||||
GdkRectangle visible_rect;
|
||||
gboolean is_visible;
|
||||
|
||||
clipboard_contains_text = gtk_selection_data_targets_include_text (data);
|
||||
|
||||
@ -9532,19 +9454,46 @@ popup_targets_received (GtkClipboard *clipboard,
|
||||
g_signal_emit (text_view, signals[POPULATE_POPUP],
|
||||
0, priv->popup_menu);
|
||||
|
||||
if (info->device)
|
||||
gtk_menu_popup_for_device (GTK_MENU (priv->popup_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 (priv->popup_menu), info->trigger_event);
|
||||
else
|
||||
{
|
||||
gtk_menu_popup (GTK_MENU (priv->popup_menu), NULL, NULL,
|
||||
popup_position_func, text_view,
|
||||
0, gtk_get_current_event_time ());
|
||||
gtk_text_view_get_iter_location (text_view, &iter, &iter_location);
|
||||
gtk_text_view_get_visible_rect (text_view, &visible_rect);
|
||||
|
||||
is_visible = (iter_location.x + iter_location.width > visible_rect.x &&
|
||||
iter_location.x < visible_rect.x + visible_rect.width &&
|
||||
iter_location.y + iter_location.height > visible_rect.y &&
|
||||
iter_location.y < visible_rect.y + visible_rect.height);
|
||||
|
||||
if (is_visible)
|
||||
{
|
||||
gtk_text_view_buffer_to_window_coords (text_view,
|
||||
GTK_TEXT_WINDOW_WIDGET,
|
||||
iter_location.x,
|
||||
iter_location.y,
|
||||
&iter_location.x,
|
||||
&iter_location.y);
|
||||
|
||||
gtk_menu_popup_at_rect (GTK_MENU (priv->popup_menu),
|
||||
gtk_widget_get_window (GTK_WIDGET (text_view)),
|
||||
&iter_location,
|
||||
GDK_GRAVITY_SOUTH_EAST,
|
||||
GDK_GRAVITY_NORTH_WEST,
|
||||
info->trigger_event);
|
||||
}
|
||||
else
|
||||
gtk_menu_popup_at_widget (GTK_MENU (priv->popup_menu),
|
||||
GTK_WIDGET (text_view),
|
||||
GDK_GRAVITY_CENTER,
|
||||
GDK_GRAVITY_CENTER,
|
||||
info->trigger_event);
|
||||
|
||||
gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->popup_menu), FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
g_clear_pointer (&info->trigger_event, gdk_event_free);
|
||||
g_object_unref (text_view);
|
||||
g_slice_free (PopupInfo, info);
|
||||
}
|
||||
@ -9560,19 +9509,7 @@ gtk_text_view_do_popup (GtkTextView *text_view,
|
||||
* we get them, then we actually pop up the menu.
|
||||
*/
|
||||
info->text_view = g_object_ref (text_view);
|
||||
|
||||
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 (text_view),
|
||||
GDK_SELECTION_CLIPBOARD),
|
||||
|
101
gtk/gtktoolbar.c
101
gtk/gtktoolbar.c
@ -2617,80 +2617,53 @@ gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
menu_position_func (GtkMenu *menu,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gboolean *push_in,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
GtkToolbar *toolbar = GTK_TOOLBAR (user_data);
|
||||
GtkToolbarPrivate *priv = toolbar->priv;
|
||||
GtkRequisition req;
|
||||
GtkRequisition menu_req;
|
||||
GdkRectangle workarea;
|
||||
GdkMonitor *monitor;
|
||||
GdkDisplay *display;
|
||||
|
||||
gtk_widget_get_preferred_size (priv->arrow_button,
|
||||
&req, NULL);
|
||||
gtk_widget_get_preferred_size (GTK_WIDGET (menu),
|
||||
&menu_req, NULL);
|
||||
|
||||
display = gtk_widget_get_display (GTK_WIDGET (menu));
|
||||
monitor = gdk_display_get_monitor_at_window (display,
|
||||
gtk_widget_get_window (priv->arrow_button));
|
||||
gdk_monitor_get_workarea (monitor, &workarea);
|
||||
|
||||
gtk_widget_get_allocation (priv->arrow_button, &allocation);
|
||||
|
||||
gdk_window_get_origin (gtk_button_get_event_window (GTK_BUTTON (priv->arrow_button)), x, y);
|
||||
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
|
||||
*x += allocation.width - req.width;
|
||||
else
|
||||
*x += req.width - menu_req.width;
|
||||
|
||||
if ((*y + allocation.height + menu_req.height) <= workarea.y + workarea.height)
|
||||
*y += allocation.height;
|
||||
else if ((*y - menu_req.height) >= workarea.y)
|
||||
*y -= menu_req.height;
|
||||
else if (workarea.y + workarea.height - (*y + allocation.height) > *y)
|
||||
*y += allocation.height;
|
||||
else
|
||||
*y -= menu_req.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
|
||||
*x += allocation.width;
|
||||
else
|
||||
*x -= menu_req.width;
|
||||
|
||||
if (*y + menu_req.height > workarea.y + workarea.height &&
|
||||
*y + allocation.height - workarea.y > workarea.y + workarea.height - *y)
|
||||
*y += allocation.height - menu_req.height;
|
||||
}
|
||||
|
||||
*push_in = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
show_menu (GtkToolbar *toolbar,
|
||||
GdkEventButton *event)
|
||||
{
|
||||
GtkToolbarPrivate *priv = toolbar->priv;
|
||||
GtkRequisition minimum_size;
|
||||
|
||||
rebuild_menu (toolbar);
|
||||
|
||||
gtk_widget_show_all (GTK_WIDGET (priv->menu));
|
||||
|
||||
gtk_menu_popup (priv->menu, NULL, NULL,
|
||||
menu_position_func, toolbar,
|
||||
event? event->button : 0,
|
||||
event? event->time : gtk_get_current_event_time());
|
||||
switch (priv->orientation)
|
||||
{
|
||||
case GTK_ORIENTATION_HORIZONTAL:
|
||||
gtk_widget_get_preferred_size (priv->arrow_button, &minimum_size, NULL);
|
||||
|
||||
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,
|
||||
"rect-anchor-dx", -minimum_size.width,
|
||||
NULL);
|
||||
|
||||
gtk_menu_popup_at_widget (priv->menu,
|
||||
priv->arrow_button,
|
||||
GDK_GRAVITY_SOUTH_EAST,
|
||||
GDK_GRAVITY_NORTH_WEST,
|
||||
(GdkEvent *) event);
|
||||
|
||||
break;
|
||||
|
||||
case GTK_ORIENTATION_VERTICAL:
|
||||
g_object_set (priv->menu,
|
||||
"anchor-hints", (GDK_ANCHOR_FLIP_X |
|
||||
GDK_ANCHOR_SLIDE |
|
||||
GDK_ANCHOR_RESIZE),
|
||||
NULL);
|
||||
|
||||
gtk_menu_popup_at_widget (priv->menu,
|
||||
priv->arrow_button,
|
||||
GDK_GRAVITY_NORTH_EAST,
|
||||
GDK_GRAVITY_NORTH_WEST,
|
||||
(GdkEvent *) event);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -8843,15 +8843,6 @@ popup_menu_detach (GtkWidget *widget,
|
||||
GTK_WINDOW (widget)->priv->popup_menu = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
popup_position_func (GtkMenu *menu,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gboolean *push_in,
|
||||
gpointer user_data)
|
||||
{
|
||||
}
|
||||
|
||||
static GdkWindowState
|
||||
gtk_window_get_state (GtkWindow *window)
|
||||
{
|
||||
@ -9064,17 +9055,7 @@ gtk_window_do_popup_fallback (GtkWindow *window,
|
||||
g_signal_connect (G_OBJECT (menuitem), "activate",
|
||||
G_CALLBACK (close_window_clicked), window);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
|
||||
|
||||
if (event)
|
||||
gtk_menu_popup (GTK_MENU (priv->popup_menu),
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
event->button, event->time);
|
||||
else
|
||||
gtk_menu_popup (GTK_MENU (priv->popup_menu),
|
||||
NULL, NULL,
|
||||
popup_position_func, window,
|
||||
0, gtk_get_current_event_time ());
|
||||
gtk_menu_popup_at_pointer (GTK_MENU (priv->popup_menu), (GdkEvent *) event);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user