mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-14 14:20:21 +00:00
gtkmenu: add gtk_menu_popup_at_* ()
Adds the following functions: gtk_menu_popup_at_rect () gtk_menu_popup_at_widget () gtk_menu_popup_at_pointer () https://bugzilla.gnome.org/show_bug.cgi?id=756579
This commit is contained in:
parent
b3a530cb72
commit
b03361366a
@ -387,6 +387,9 @@ HTML_IMAGES = \
|
|||||||
$(srcdir)/images/panes.png \
|
$(srcdir)/images/panes.png \
|
||||||
$(srcdir)/images/pagesetupdialog.png \
|
$(srcdir)/images/pagesetupdialog.png \
|
||||||
$(srcdir)/images/placessidebar.png \
|
$(srcdir)/images/placessidebar.png \
|
||||||
|
$(srcdir)/images/popup-anchors.png \
|
||||||
|
$(srcdir)/images/popup-flip.png \
|
||||||
|
$(srcdir)/images/popup-slide.png \
|
||||||
$(srcdir)/images/printdialog.png \
|
$(srcdir)/images/printdialog.png \
|
||||||
$(srcdir)/images/progressbar.png \
|
$(srcdir)/images/progressbar.png \
|
||||||
$(srcdir)/images/radio-group.png \
|
$(srcdir)/images/radio-group.png \
|
||||||
|
@ -2246,6 +2246,9 @@ gtk_menu_new_from_model
|
|||||||
gtk_menu_set_screen
|
gtk_menu_set_screen
|
||||||
gtk_menu_reorder_child
|
gtk_menu_reorder_child
|
||||||
gtk_menu_attach
|
gtk_menu_attach
|
||||||
|
gtk_menu_popup_at_rect
|
||||||
|
gtk_menu_popup_at_widget
|
||||||
|
gtk_menu_popup_at_pointer
|
||||||
gtk_menu_popup_for_device
|
gtk_menu_popup_for_device
|
||||||
gtk_menu_popup
|
gtk_menu_popup
|
||||||
gtk_menu_set_accel_group
|
gtk_menu_set_accel_group
|
||||||
|
BIN
docs/reference/gtk/images/popup-anchors.png
Normal file
BIN
docs/reference/gtk/images/popup-anchors.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
745
docs/reference/gtk/images/popup-at.svg
Normal file
745
docs/reference/gtk/images/popup-at.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 126 KiB |
BIN
docs/reference/gtk/images/popup-flip.png
Normal file
BIN
docs/reference/gtk/images/popup-flip.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
BIN
docs/reference/gtk/images/popup-slide.png
Normal file
BIN
docs/reference/gtk/images/popup-slide.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
@ -106,6 +106,7 @@ VOID:POINTER
|
|||||||
VOID:POINTER,INT
|
VOID:POINTER,INT
|
||||||
VOID:POINTER,BOOLEAN
|
VOID:POINTER,BOOLEAN
|
||||||
VOID:POINTER,POINTER,BOOLEAN
|
VOID:POINTER,POINTER,BOOLEAN
|
||||||
|
VOID:POINTER,POINTER,BOOLEAN,BOOLEAN
|
||||||
VOID:POINTER,POINTER,POINTER
|
VOID:POINTER,POINTER,POINTER
|
||||||
VOID:POINTER,UINT
|
VOID:POINTER,UINT
|
||||||
VOID:STRING
|
VOID:STRING
|
||||||
|
809
gtk/gtkmenu.c
809
gtk/gtkmenu.c
@ -137,6 +137,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "a11y/gtkmenuaccessible.h"
|
#include "a11y/gtkmenuaccessible.h"
|
||||||
|
#include "gdk/gdk-private.h"
|
||||||
|
|
||||||
#define NAVIGATION_REGION_OVERSHOOT 50 /* How much the navigation region
|
#define NAVIGATION_REGION_OVERSHOOT 50 /* How much the navigation region
|
||||||
* extends below the submenu
|
* extends below the submenu
|
||||||
@ -183,6 +184,7 @@ typedef struct
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
MOVE_SCROLL,
|
MOVE_SCROLL,
|
||||||
|
POPPED_UP,
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -195,7 +197,11 @@ enum {
|
|||||||
PROP_TEAROFF_STATE,
|
PROP_TEAROFF_STATE,
|
||||||
PROP_TEAROFF_TITLE,
|
PROP_TEAROFF_TITLE,
|
||||||
PROP_MONITOR,
|
PROP_MONITOR,
|
||||||
PROP_RESERVE_TOGGLE_SIZE
|
PROP_RESERVE_TOGGLE_SIZE,
|
||||||
|
PROP_ANCHOR_HINTS,
|
||||||
|
PROP_RECT_ANCHOR_DX,
|
||||||
|
PROP_RECT_ANCHOR_DY,
|
||||||
|
PROP_MENU_TYPE_HINT
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -561,6 +567,57 @@ gtk_menu_class_init (GtkMenuClass *class)
|
|||||||
G_TYPE_NONE, 1,
|
G_TYPE_NONE, 1,
|
||||||
GTK_TYPE_SCROLL_TYPE);
|
GTK_TYPE_SCROLL_TYPE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkMenu::popped-up:
|
||||||
|
* @menu: the #GtkMenu that popped up
|
||||||
|
* @flipped_rect: (nullable): the position of @menu after any possible
|
||||||
|
* flipping or %NULL if the backend can't obtain it
|
||||||
|
* @final_rect: (nullable): the final position of @menu or %NULL if the
|
||||||
|
* backend can't obtain it
|
||||||
|
* @flipped_x: %TRUE if the anchors were flipped horizontally
|
||||||
|
* @flipped_y: %TRUE if the anchors were flipped vertically
|
||||||
|
*
|
||||||
|
* Emitted when the position of @menu is finalized after being popped up
|
||||||
|
* using gtk_menu_popup_at_rect (), gtk_menu_popup_at_widget (), or
|
||||||
|
* gtk_menu_popup_at_pointer ().
|
||||||
|
*
|
||||||
|
* @menu might be flipped over the anchor rectangle in order to keep it
|
||||||
|
* on-screen, in which case @flipped_x and @flipped_y will be set to %TRUE
|
||||||
|
* accordingly.
|
||||||
|
*
|
||||||
|
* @flipped_rect is the ideal position of @menu after any possible flipping,
|
||||||
|
* but before any possible sliding. @final_rect is @flipped_rect, but possibly
|
||||||
|
* translated in the case that flipping is still ineffective in keeping @menu
|
||||||
|
* on-screen.
|
||||||
|
*
|
||||||
|
* ![](popup-slide.png)
|
||||||
|
*
|
||||||
|
* The blue menu is @menu's ideal position, the green menu is @flipped_rect,
|
||||||
|
* and the red menu is @final_rect.
|
||||||
|
*
|
||||||
|
* See gtk_menu_popup_at_rect (), gtk_menu_popup_at_widget (),
|
||||||
|
* gtk_menu_popup_at_pointer (), #GtkMenu:anchor-hints,
|
||||||
|
* #GtkMenu:rect-anchor-dx, #GtkMenu:rect-anchor-dy, and
|
||||||
|
* #GtkMenu:menu-type-hint.
|
||||||
|
*
|
||||||
|
* Since: 3.22
|
||||||
|
* Stability: Unstable
|
||||||
|
*/
|
||||||
|
menu_signals[POPPED_UP] =
|
||||||
|
g_signal_new_class_handler (I_("popped-up"),
|
||||||
|
G_OBJECT_CLASS_TYPE (gobject_class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
_gtk_marshal_VOID__POINTER_POINTER_BOOLEAN_BOOLEAN,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
4,
|
||||||
|
G_TYPE_POINTER,
|
||||||
|
G_TYPE_POINTER,
|
||||||
|
G_TYPE_BOOLEAN,
|
||||||
|
G_TYPE_BOOLEAN);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GtkMenu:active:
|
* GtkMenu:active:
|
||||||
*
|
*
|
||||||
@ -693,6 +750,120 @@ gtk_menu_class_init (GtkMenuClass *class)
|
|||||||
TRUE,
|
TRUE,
|
||||||
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
|
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkMenu:anchor-hints:
|
||||||
|
*
|
||||||
|
* Positioning hints for aligning the menu relative to a rectangle.
|
||||||
|
*
|
||||||
|
* These hints determine how the menu should be positioned in the case that
|
||||||
|
* the menu would fall off-screen if placed in its ideal position.
|
||||||
|
*
|
||||||
|
* ![](popup-flip.png)
|
||||||
|
*
|
||||||
|
* For example, %GDK_ANCHOR_FLIP_Y will replace %GDK_GRAVITY_NORTH_WEST with
|
||||||
|
* %GDK_GRAVITY_SOUTH_WEST and vice versa if the menu extends beyond the
|
||||||
|
* bottom edge of the monitor.
|
||||||
|
*
|
||||||
|
* See gtk_menu_popup_at_rect (), gtk_menu_popup_at_widget (),
|
||||||
|
* gtk_menu_popup_at_pointer (), #GtkMenu:rect-anchor-dx,
|
||||||
|
* #GtkMenu:rect-anchor-dy, #GtkMenu:menu-type-hint, and #GtkMenu::popped-up.
|
||||||
|
*
|
||||||
|
* Since: 3.22
|
||||||
|
* Stability: Unstable
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_ANCHOR_HINTS,
|
||||||
|
g_param_spec_flags ("anchor-hints",
|
||||||
|
P_("Anchor hints"),
|
||||||
|
P_("Positioning hints for when the menu might fall off-screen"),
|
||||||
|
GDK_TYPE_ANCHOR_HINTS,
|
||||||
|
GDK_ANCHOR_FLIP |
|
||||||
|
GDK_ANCHOR_SLIDE |
|
||||||
|
GDK_ANCHOR_RESIZE,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT |
|
||||||
|
G_PARAM_STATIC_NAME |
|
||||||
|
G_PARAM_STATIC_NICK |
|
||||||
|
G_PARAM_STATIC_BLURB));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkMenu:rect-anchor-dx:
|
||||||
|
*
|
||||||
|
* Horizontal offset to apply to the menu, i.e. the rectangle or widget
|
||||||
|
* anchor.
|
||||||
|
*
|
||||||
|
* See gtk_menu_popup_at_rect (), gtk_menu_popup_at_widget (),
|
||||||
|
* gtk_menu_popup_at_pointer (), #GtkMenu:anchor-hints,
|
||||||
|
* #GtkMenu:rect-anchor-dy, #GtkMenu:menu-type-hint, and #GtkMenu::popped-up.
|
||||||
|
*
|
||||||
|
* Since: 3.22
|
||||||
|
* Stability: Unstable
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_RECT_ANCHOR_DX,
|
||||||
|
g_param_spec_int ("rect-anchor-dx",
|
||||||
|
P_("Rect anchor dx"),
|
||||||
|
P_("Rect anchor horizontal offset"),
|
||||||
|
G_MININT,
|
||||||
|
G_MAXINT,
|
||||||
|
0,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT |
|
||||||
|
G_PARAM_STATIC_NAME |
|
||||||
|
G_PARAM_STATIC_NICK |
|
||||||
|
G_PARAM_STATIC_BLURB));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkMenu:rect-anchor-dy:
|
||||||
|
*
|
||||||
|
* Vertical offset to apply to the menu, i.e. the rectangle or widget anchor.
|
||||||
|
*
|
||||||
|
* See gtk_menu_popup_at_rect (), gtk_menu_popup_at_widget (),
|
||||||
|
* gtk_menu_popup_at_pointer (), #GtkMenu:anchor-hints,
|
||||||
|
* #GtkMenu:rect-anchor-dx, #GtkMenu:menu-type-hint, and #GtkMenu::popped-up.
|
||||||
|
*
|
||||||
|
* Since: 3.22
|
||||||
|
* Stability: Unstable
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_RECT_ANCHOR_DY,
|
||||||
|
g_param_spec_int ("rect-anchor-dy",
|
||||||
|
P_("Rect anchor dy"),
|
||||||
|
P_("Rect anchor vertical offset"),
|
||||||
|
G_MININT,
|
||||||
|
G_MAXINT,
|
||||||
|
0,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT |
|
||||||
|
G_PARAM_STATIC_NAME |
|
||||||
|
G_PARAM_STATIC_NICK |
|
||||||
|
G_PARAM_STATIC_BLURB));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkMenu:menu-type-hint:
|
||||||
|
*
|
||||||
|
* The #GdkWindowTypeHint to use for the menu's #GdkWindow.
|
||||||
|
*
|
||||||
|
* See gtk_menu_popup_at_rect (), gtk_menu_popup_at_widget (),
|
||||||
|
* gtk_menu_popup_at_pointer (), #GtkMenu:anchor-hints,
|
||||||
|
* #GtkMenu:rect-anchor-dx, #GtkMenu:rect-anchor-dy, and #GtkMenu::popped-up.
|
||||||
|
*
|
||||||
|
* Since: 3.22
|
||||||
|
* Stability: Unstable
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_MENU_TYPE_HINT,
|
||||||
|
g_param_spec_enum ("menu-type-hint",
|
||||||
|
P_("Menu type hint"),
|
||||||
|
P_("Menu window type hint"),
|
||||||
|
GDK_TYPE_WINDOW_TYPE_HINT,
|
||||||
|
GDK_WINDOW_TYPE_HINT_POPUP_MENU,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT |
|
||||||
|
G_PARAM_STATIC_NAME |
|
||||||
|
G_PARAM_STATIC_NICK |
|
||||||
|
G_PARAM_STATIC_BLURB));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GtkMenu:horizontal-padding:
|
* GtkMenu:horizontal-padding:
|
||||||
*
|
*
|
||||||
@ -964,6 +1135,18 @@ G_GNUC_END_IGNORE_DEPRECATIONS;
|
|||||||
case PROP_RESERVE_TOGGLE_SIZE:
|
case PROP_RESERVE_TOGGLE_SIZE:
|
||||||
gtk_menu_set_reserve_toggle_size (menu, g_value_get_boolean (value));
|
gtk_menu_set_reserve_toggle_size (menu, g_value_get_boolean (value));
|
||||||
break;
|
break;
|
||||||
|
case PROP_ANCHOR_HINTS:
|
||||||
|
menu->priv->anchor_hints = g_value_get_flags (value);
|
||||||
|
break;
|
||||||
|
case PROP_RECT_ANCHOR_DX:
|
||||||
|
menu->priv->rect_anchor_dx = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
case PROP_RECT_ANCHOR_DY:
|
||||||
|
menu->priv->rect_anchor_dy = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
case PROP_MENU_TYPE_HINT:
|
||||||
|
menu->priv->menu_type_hint = g_value_get_enum (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -1008,6 +1191,18 @@ G_GNUC_END_IGNORE_DEPRECATIONS;
|
|||||||
case PROP_RESERVE_TOGGLE_SIZE:
|
case PROP_RESERVE_TOGGLE_SIZE:
|
||||||
g_value_set_boolean (value, gtk_menu_get_reserve_toggle_size (menu));
|
g_value_set_boolean (value, gtk_menu_get_reserve_toggle_size (menu));
|
||||||
break;
|
break;
|
||||||
|
case PROP_ANCHOR_HINTS:
|
||||||
|
g_value_set_flags (value, menu->priv->anchor_hints);
|
||||||
|
break;
|
||||||
|
case PROP_RECT_ANCHOR_DX:
|
||||||
|
g_value_set_int (value, menu->priv->rect_anchor_dx);
|
||||||
|
break;
|
||||||
|
case PROP_RECT_ANCHOR_DY:
|
||||||
|
g_value_set_int (value, menu->priv->rect_anchor_dy);
|
||||||
|
break;
|
||||||
|
case PROP_MENU_TYPE_HINT:
|
||||||
|
g_value_set_enum (value, menu->priv->menu_type_hint);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -1167,6 +1362,23 @@ gtk_menu_init (GtkMenu *menu)
|
|||||||
gtk_css_node_set_state (bottom_arrow_node, gtk_css_node_get_state (widget_node));
|
gtk_css_node_set_state (bottom_arrow_node, gtk_css_node_get_state (widget_node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
moved_to_rect_cb (GdkWindow *window,
|
||||||
|
const GdkRectangle *flipped_rect,
|
||||||
|
const GdkRectangle *final_rect,
|
||||||
|
gboolean flipped_x,
|
||||||
|
gboolean flipped_y,
|
||||||
|
GtkMenu *menu)
|
||||||
|
{
|
||||||
|
g_signal_emit (menu,
|
||||||
|
menu_signals[POPPED_UP],
|
||||||
|
0,
|
||||||
|
flipped_rect,
|
||||||
|
final_rect,
|
||||||
|
flipped_x,
|
||||||
|
flipped_y);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_menu_destroy (GtkWidget *widget)
|
gtk_menu_destroy (GtkWidget *widget)
|
||||||
{
|
{
|
||||||
@ -1194,7 +1406,10 @@ gtk_menu_destroy (GtkWidget *widget)
|
|||||||
g_clear_object (&priv->accel_group);
|
g_clear_object (&priv->accel_group);
|
||||||
|
|
||||||
if (priv->toplevel)
|
if (priv->toplevel)
|
||||||
gtk_widget_destroy (priv->toplevel);
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (priv->toplevel, moved_to_rect_cb, menu);
|
||||||
|
gtk_widget_destroy (priv->toplevel);
|
||||||
|
}
|
||||||
|
|
||||||
if (priv->tearoff_window)
|
if (priv->tearoff_window)
|
||||||
gtk_widget_destroy (priv->tearoff_window);
|
gtk_widget_destroy (priv->tearoff_window);
|
||||||
@ -1549,53 +1764,16 @@ associate_menu_grab_transfer_window (GtkMenu *menu)
|
|||||||
g_object_set_data (G_OBJECT (toplevel_window), I_("gdk-attached-grab-window"), transfer_window);
|
g_object_set_data (G_OBJECT (toplevel_window), I_("gdk-attached-grab-window"), transfer_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void
|
||||||
* gtk_menu_popup_for_device:
|
gtk_menu_popup_internal (GtkMenu *menu,
|
||||||
* @menu: a #GtkMenu
|
GdkDevice *device,
|
||||||
* @device: (allow-none): a #GdkDevice
|
GtkWidget *parent_menu_shell,
|
||||||
* @parent_menu_shell: (allow-none): the menu shell containing the triggering
|
GtkWidget *parent_menu_item,
|
||||||
* menu item, or %NULL
|
GtkMenuPositionFunc func,
|
||||||
* @parent_menu_item: (allow-none): the menu item whose activation triggered
|
gpointer data,
|
||||||
* the popup, or %NULL
|
GDestroyNotify destroy,
|
||||||
* @func: (allow-none): a user supplied function used to position the menu,
|
guint button,
|
||||||
* or %NULL
|
guint32 activate_time)
|
||||||
* @data: (allow-none): user supplied data to be passed to @func
|
|
||||||
* @destroy: (allow-none): destroy notify for @data
|
|
||||||
* @button: the mouse button which was pressed to initiate the event
|
|
||||||
* @activate_time: the time at which the activation event occurred
|
|
||||||
*
|
|
||||||
* Displays a menu and makes it available for selection.
|
|
||||||
*
|
|
||||||
* Applications can use this function to display context-sensitive menus,
|
|
||||||
* and will typically supply %NULL for the @parent_menu_shell,
|
|
||||||
* @parent_menu_item, @func, @data and @destroy parameters. The default
|
|
||||||
* menu positioning function will position the menu at the current position
|
|
||||||
* of @device (or its corresponding pointer).
|
|
||||||
*
|
|
||||||
* The @button parameter should be the mouse button pressed to initiate
|
|
||||||
* the menu popup. If the menu popup was initiated by something other than
|
|
||||||
* a mouse button press, such as a mouse button release or a keypress,
|
|
||||||
* @button should be 0.
|
|
||||||
*
|
|
||||||
* The @activate_time parameter is used to conflict-resolve initiation of
|
|
||||||
* concurrent requests for mouse/keyboard grab requests. To function
|
|
||||||
* properly, this needs to be the time stamp of the user event (such as
|
|
||||||
* a mouse click or key press) that caused the initiation of the popup.
|
|
||||||
* Only if no such event is available, gtk_get_current_event_time() can
|
|
||||||
* be used instead.
|
|
||||||
*
|
|
||||||
* Since: 3.0
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
gtk_menu_popup_for_device (GtkMenu *menu,
|
|
||||||
GdkDevice *device,
|
|
||||||
GtkWidget *parent_menu_shell,
|
|
||||||
GtkWidget *parent_menu_item,
|
|
||||||
GtkMenuPositionFunc func,
|
|
||||||
gpointer data,
|
|
||||||
GDestroyNotify destroy,
|
|
||||||
guint button,
|
|
||||||
guint32 activate_time)
|
|
||||||
{
|
{
|
||||||
GtkMenuPrivate *priv = menu->priv;
|
GtkMenuPrivate *priv = menu->priv;
|
||||||
GtkWidget *widget;
|
GtkWidget *widget;
|
||||||
@ -1801,6 +1979,73 @@ gtk_menu_popup_for_device (GtkMenu *menu,
|
|||||||
_gtk_menu_shell_update_mnemonics (menu_shell);
|
_gtk_menu_shell_update_mnemonics (menu_shell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_menu_popup_for_device:
|
||||||
|
* @menu: a #GtkMenu
|
||||||
|
* @device: (allow-none): a #GdkDevice
|
||||||
|
* @parent_menu_shell: (allow-none): the menu shell containing the triggering
|
||||||
|
* menu item, or %NULL
|
||||||
|
* @parent_menu_item: (allow-none): the menu item whose activation triggered
|
||||||
|
* the popup, or %NULL
|
||||||
|
* @func: (allow-none): a user supplied function used to position the menu,
|
||||||
|
* or %NULL
|
||||||
|
* @data: (allow-none): user supplied data to be passed to @func
|
||||||
|
* @destroy: (allow-none): destroy notify for @data
|
||||||
|
* @button: the mouse button which was pressed to initiate the event
|
||||||
|
* @activate_time: the time at which the activation event occurred
|
||||||
|
*
|
||||||
|
* Displays a menu and makes it available for selection.
|
||||||
|
*
|
||||||
|
* Applications can use this function to display context-sensitive menus,
|
||||||
|
* and will typically supply %NULL for the @parent_menu_shell,
|
||||||
|
* @parent_menu_item, @func, @data and @destroy parameters. The default
|
||||||
|
* menu positioning function will position the menu at the current position
|
||||||
|
* of @device (or its corresponding pointer).
|
||||||
|
*
|
||||||
|
* The @button parameter should be the mouse button pressed to initiate
|
||||||
|
* the menu popup. If the menu popup was initiated by something other than
|
||||||
|
* a mouse button press, such as a mouse button release or a keypress,
|
||||||
|
* @button should be 0.
|
||||||
|
*
|
||||||
|
* The @activate_time parameter is used to conflict-resolve initiation of
|
||||||
|
* concurrent requests for mouse/keyboard grab requests. To function
|
||||||
|
* properly, this needs to be the time stamp of the user event (such as
|
||||||
|
* a mouse click or key press) that caused the initiation of the popup.
|
||||||
|
* Only if no such event is available, gtk_get_current_event_time() can
|
||||||
|
* be used instead.
|
||||||
|
*
|
||||||
|
* Since: 3.0
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gtk_menu_popup_for_device (GtkMenu *menu,
|
||||||
|
GdkDevice *device,
|
||||||
|
GtkWidget *parent_menu_shell,
|
||||||
|
GtkWidget *parent_menu_item,
|
||||||
|
GtkMenuPositionFunc func,
|
||||||
|
gpointer data,
|
||||||
|
GDestroyNotify destroy,
|
||||||
|
guint button,
|
||||||
|
guint32 activate_time)
|
||||||
|
{
|
||||||
|
GtkMenuPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (GTK_IS_MENU (menu));
|
||||||
|
|
||||||
|
priv = menu->priv;
|
||||||
|
priv->rect_window = NULL;
|
||||||
|
priv->widget = NULL;
|
||||||
|
|
||||||
|
gtk_menu_popup_internal (menu,
|
||||||
|
device,
|
||||||
|
parent_menu_shell,
|
||||||
|
parent_menu_item,
|
||||||
|
func,
|
||||||
|
data,
|
||||||
|
destroy,
|
||||||
|
button,
|
||||||
|
activate_time);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gtk_menu_popup:
|
* gtk_menu_popup:
|
||||||
* @menu: a #GtkMenu
|
* @menu: a #GtkMenu
|
||||||
@ -1853,6 +2098,347 @@ gtk_menu_popup (GtkMenu *menu,
|
|||||||
button, activate_time);
|
button, activate_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GdkDevice *
|
||||||
|
get_device_for_event (const GdkEvent *event)
|
||||||
|
{
|
||||||
|
GdkDevice *device = NULL;
|
||||||
|
GdkSeat *seat = NULL;
|
||||||
|
GdkScreen *screen = NULL;
|
||||||
|
GdkDisplay *display = NULL;
|
||||||
|
|
||||||
|
device = gdk_event_get_device (event);
|
||||||
|
|
||||||
|
if (device)
|
||||||
|
return device;
|
||||||
|
|
||||||
|
seat = gdk_event_get_seat (event);
|
||||||
|
|
||||||
|
if (!seat)
|
||||||
|
{
|
||||||
|
screen = gdk_event_get_screen (event);
|
||||||
|
|
||||||
|
if (screen)
|
||||||
|
display = gdk_screen_get_display (screen);
|
||||||
|
|
||||||
|
if (!display)
|
||||||
|
{
|
||||||
|
g_warning ("no display for event, using default");
|
||||||
|
display = gdk_display_get_default ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (display)
|
||||||
|
seat = gdk_display_get_default_seat (display);
|
||||||
|
}
|
||||||
|
|
||||||
|
return seat ? gdk_seat_get_pointer (seat) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_menu_popup_at_rect:
|
||||||
|
* @menu: the #GtkMenu to pop up
|
||||||
|
* @rect_window: (not nullable): the #GdkWindow @rect is relative to
|
||||||
|
* @rect: (not nullable): the #GdkRectangle to align @menu with
|
||||||
|
* @rect_anchor: the point on @rect to align with @menu's anchor point
|
||||||
|
* @menu_anchor: the point on @menu to align with @rect's anchor point
|
||||||
|
* @trigger_event: (nullable): the #GdkEvent that initiated this request or
|
||||||
|
* %NULL if it's the current event
|
||||||
|
*
|
||||||
|
* Displays @menu and makes it available for selection.
|
||||||
|
*
|
||||||
|
* See gtk_menu_popup_at_widget () and gtk_menu_popup_at_pointer (), which
|
||||||
|
* handle more common cases for popping up menus.
|
||||||
|
*
|
||||||
|
* @menu will be positioned at @rect, aligning their anchor points. @rect is
|
||||||
|
* relative to the top-left corner of @rect_window. @rect_anchor and
|
||||||
|
* @menu_anchor determine anchor points on @rect and @menu to pin together.
|
||||||
|
* @menu can optionally be offset by #GtkMenu:rect-anchor-dx and
|
||||||
|
* #GtkMenu:rect-anchor-dy.
|
||||||
|
*
|
||||||
|
* Anchors should be specified under the assumption that the text direction is
|
||||||
|
* left-to-right; they will be flipped horizontally automatically if the text
|
||||||
|
* direction is right-to-left.
|
||||||
|
*
|
||||||
|
* Other properties that influence the behaviour of this function are
|
||||||
|
* #GtkMenu:anchor-hints and #GtkMenu:menu-type-hint. Connect to the
|
||||||
|
* #GtkMenu::popped-up signal to find out how it was actually positioned.
|
||||||
|
*
|
||||||
|
* Since: 3.22
|
||||||
|
* Stability: Unstable
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gtk_menu_popup_at_rect (GtkMenu *menu,
|
||||||
|
GdkWindow *rect_window,
|
||||||
|
const GdkRectangle *rect,
|
||||||
|
GdkGravity rect_anchor,
|
||||||
|
GdkGravity menu_anchor,
|
||||||
|
const GdkEvent *trigger_event)
|
||||||
|
{
|
||||||
|
GtkMenuPrivate *priv;
|
||||||
|
GdkEvent *current_event = NULL;
|
||||||
|
GdkDevice *device = NULL;
|
||||||
|
guint button = 0;
|
||||||
|
guint32 activate_time = GDK_CURRENT_TIME;
|
||||||
|
|
||||||
|
g_return_if_fail (GTK_IS_MENU (menu));
|
||||||
|
g_return_if_fail (GDK_IS_WINDOW (rect_window));
|
||||||
|
g_return_if_fail (rect);
|
||||||
|
|
||||||
|
priv = menu->priv;
|
||||||
|
priv->rect_window = rect_window;
|
||||||
|
priv->rect = *rect;
|
||||||
|
priv->widget = NULL;
|
||||||
|
priv->rect_anchor = rect_anchor;
|
||||||
|
priv->menu_anchor = menu_anchor;
|
||||||
|
|
||||||
|
if (!trigger_event)
|
||||||
|
{
|
||||||
|
current_event = gtk_get_current_event ();
|
||||||
|
trigger_event = current_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trigger_event)
|
||||||
|
{
|
||||||
|
device = get_device_for_event (trigger_event);
|
||||||
|
gdk_event_get_button (trigger_event, &button);
|
||||||
|
activate_time = gdk_event_get_time (trigger_event);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_warning ("no trigger event for menu popup");
|
||||||
|
|
||||||
|
gtk_menu_popup_internal (menu,
|
||||||
|
device,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
button,
|
||||||
|
activate_time);
|
||||||
|
|
||||||
|
g_clear_pointer (¤t_event, gdk_event_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_menu_popup_at_widget:
|
||||||
|
* @menu: the #GtkMenu to pop up
|
||||||
|
* @widget: (not nullable): the #GtkWidget to align @menu with
|
||||||
|
* @widget_anchor: the point on @widget to align with @menu's anchor point
|
||||||
|
* @menu_anchor: the point on @menu to align with @widget's anchor point
|
||||||
|
* @trigger_event: (nullable): the #GdkEvent that initiated this request or
|
||||||
|
* %NULL if it's the current event
|
||||||
|
*
|
||||||
|
* Displays @menu and makes it available for selection.
|
||||||
|
*
|
||||||
|
* See gtk_menu_popup_at_pointer () to pop up a menu at the master pointer.
|
||||||
|
* gtk_menu_popup_at_rect () also allows you to position a menu at an arbitrary
|
||||||
|
* rectangle.
|
||||||
|
*
|
||||||
|
* ![](popup-anchors.png)
|
||||||
|
*
|
||||||
|
* @menu will be positioned at @widget, aligning their anchor points.
|
||||||
|
* @widget_anchor and @menu_anchor determine anchor points on @widget and @menu
|
||||||
|
* to pin together. @menu can optionally be offset by #GtkMenu:rect-anchor-dx
|
||||||
|
* and #GtkMenu:rect-anchor-dy.
|
||||||
|
*
|
||||||
|
* Anchors should be specified under the assumption that the text direction is
|
||||||
|
* left-to-right; they will be flipped horizontally automatically if the text
|
||||||
|
* direction is right-to-left.
|
||||||
|
*
|
||||||
|
* Other properties that influence the behaviour of this function are
|
||||||
|
* #GtkMenu:anchor-hints and #GtkMenu:menu-type-hint. Connect to the
|
||||||
|
* #GtkMenu::popped-up signal to find out how it was actually positioned.
|
||||||
|
*
|
||||||
|
* Since: 3.22
|
||||||
|
* Stability: Unstable
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gtk_menu_popup_at_widget (GtkMenu *menu,
|
||||||
|
GtkWidget *widget,
|
||||||
|
GdkGravity widget_anchor,
|
||||||
|
GdkGravity menu_anchor,
|
||||||
|
const GdkEvent *trigger_event)
|
||||||
|
{
|
||||||
|
GtkMenuPrivate *priv;
|
||||||
|
GdkEvent *current_event = NULL;
|
||||||
|
GdkDevice *device = NULL;
|
||||||
|
guint button = 0;
|
||||||
|
guint32 activate_time = GDK_CURRENT_TIME;
|
||||||
|
GtkWidget *parent_menu_shell = NULL;
|
||||||
|
GtkWidget *parent_menu_item = NULL;
|
||||||
|
|
||||||
|
g_return_if_fail (GTK_IS_MENU (menu));
|
||||||
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||||
|
|
||||||
|
priv = menu->priv;
|
||||||
|
priv->rect_window = NULL;
|
||||||
|
priv->widget = widget;
|
||||||
|
priv->rect_anchor = widget_anchor;
|
||||||
|
priv->menu_anchor = menu_anchor;
|
||||||
|
|
||||||
|
if (!trigger_event)
|
||||||
|
{
|
||||||
|
current_event = gtk_get_current_event ();
|
||||||
|
trigger_event = current_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trigger_event)
|
||||||
|
{
|
||||||
|
device = get_device_for_event (trigger_event);
|
||||||
|
gdk_event_get_button (trigger_event, &button);
|
||||||
|
activate_time = gdk_event_get_time (trigger_event);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_warning ("no trigger event for menu popup");
|
||||||
|
|
||||||
|
if (GTK_IS_MENU_ITEM (priv->widget))
|
||||||
|
{
|
||||||
|
parent_menu_item = priv->widget;
|
||||||
|
|
||||||
|
if (GTK_IS_MENU_SHELL (gtk_widget_get_parent (parent_menu_item)))
|
||||||
|
parent_menu_shell = gtk_widget_get_parent (parent_menu_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_menu_popup_internal (menu,
|
||||||
|
device,
|
||||||
|
parent_menu_shell,
|
||||||
|
parent_menu_item,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
button,
|
||||||
|
activate_time);
|
||||||
|
|
||||||
|
g_clear_pointer (¤t_event, gdk_event_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_menu_popup_at_pointer:
|
||||||
|
* @menu: the #GtkMenu to pop up
|
||||||
|
* @trigger_event: (nullable): the #GdkEvent that initiated this request or
|
||||||
|
* %NULL if it's the current event
|
||||||
|
*
|
||||||
|
* Displays @menu and makes it available for selection.
|
||||||
|
*
|
||||||
|
* See gtk_menu_popup_at_widget () to pop up a menu at a widget.
|
||||||
|
* gtk_menu_popup_at_rect () also allows you to position a menu at an arbitrary
|
||||||
|
* rectangle.
|
||||||
|
*
|
||||||
|
* @menu will be positioned at the pointer associated with @trigger_event.
|
||||||
|
*
|
||||||
|
* Properties that influence the behaviour of this function are
|
||||||
|
* #GtkMenu:anchor-hints, #GtkMenu:rect-anchor-dx, #GtkMenu:rect-anchor-dy, and
|
||||||
|
* #GtkMenu:menu-type-hint. Connect to the #GtkMenu::popped-up signal to find
|
||||||
|
* out how it was actually positioned.
|
||||||
|
*
|
||||||
|
* Since: 3.22
|
||||||
|
* Stability: Unstable
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gtk_menu_popup_at_pointer (GtkMenu *menu,
|
||||||
|
const GdkEvent *trigger_event)
|
||||||
|
{
|
||||||
|
GdkEvent *current_event = NULL;
|
||||||
|
GdkWindow *rect_window = NULL;
|
||||||
|
GdkDevice *device = NULL;
|
||||||
|
GdkRectangle rect = { 0, 0, 1, 1 };
|
||||||
|
|
||||||
|
g_return_if_fail (GTK_IS_MENU (menu));
|
||||||
|
|
||||||
|
if (!trigger_event)
|
||||||
|
{
|
||||||
|
current_event = gtk_get_current_event ();
|
||||||
|
trigger_event = current_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trigger_event)
|
||||||
|
{
|
||||||
|
rect_window = gdk_event_get_window (trigger_event);
|
||||||
|
|
||||||
|
if (rect_window)
|
||||||
|
{
|
||||||
|
device = get_device_for_event (trigger_event);
|
||||||
|
|
||||||
|
if (device && gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
|
||||||
|
device = gdk_device_get_associated_device (device);
|
||||||
|
|
||||||
|
if (device)
|
||||||
|
gdk_window_get_device_position (rect_window, device, &rect.x, &rect.y, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_warning ("no trigger event for menu popup");
|
||||||
|
|
||||||
|
gtk_menu_popup_at_rect (menu,
|
||||||
|
rect_window,
|
||||||
|
&rect,
|
||||||
|
GDK_GRAVITY_SOUTH_EAST,
|
||||||
|
GDK_GRAVITY_NORTH_WEST,
|
||||||
|
trigger_event);
|
||||||
|
|
||||||
|
g_clear_pointer (¤t_event, gdk_event_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_arrows_border (GtkMenu *menu,
|
||||||
|
GtkBorder *border)
|
||||||
|
{
|
||||||
|
GtkMenuPrivate *priv = menu->priv;
|
||||||
|
gint top_arrow_height, bottom_arrow_height;
|
||||||
|
|
||||||
|
gtk_css_gadget_get_preferred_size (priv->top_arrow_gadget,
|
||||||
|
GTK_ORIENTATION_VERTICAL,
|
||||||
|
-1,
|
||||||
|
&top_arrow_height, NULL,
|
||||||
|
NULL, NULL);
|
||||||
|
gtk_css_gadget_get_preferred_size (priv->bottom_arrow_gadget,
|
||||||
|
GTK_ORIENTATION_VERTICAL,
|
||||||
|
-1,
|
||||||
|
&bottom_arrow_height, NULL,
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
border->top = priv->upper_arrow_visible ? top_arrow_height : 0;
|
||||||
|
border->bottom = priv->lower_arrow_visible ? bottom_arrow_height : 0;
|
||||||
|
border->left = border->right = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_menu_update_scroll_offset:
|
||||||
|
* @menu: the #GtkMenu that popped up
|
||||||
|
* @flipped_rect: (nullable): the position of @menu after any possible flipping
|
||||||
|
* or %NULL if unknown
|
||||||
|
* @final_rect: (nullable): the final position of @menu or %NULL if unknown
|
||||||
|
* @flipped_x: %TRUE if the anchors were flipped horizontally
|
||||||
|
* @flipped_y: %TRUE if the anchors were flipped vertically
|
||||||
|
* @user_data: user data
|
||||||
|
*
|
||||||
|
* Updates the scroll offset of @menu based on the amount of sliding done while
|
||||||
|
* positioning @menu. Connect this to the #GtkMenu::popped-up signal to keep the
|
||||||
|
* contents of the menu vertically aligned with their ideal position, for combo
|
||||||
|
* boxes for example.
|
||||||
|
*
|
||||||
|
* Since: 3.22
|
||||||
|
* Stability: Private
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gtk_menu_update_scroll_offset (GtkMenu *menu,
|
||||||
|
const GdkRectangle *flipped_rect,
|
||||||
|
const GdkRectangle *final_rect,
|
||||||
|
gboolean flipped_x,
|
||||||
|
gboolean flipped_y,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GtkBorder arrows_border;
|
||||||
|
|
||||||
|
g_return_if_fail (GTK_IS_MENU (menu));
|
||||||
|
|
||||||
|
if (!flipped_rect || !final_rect)
|
||||||
|
return;
|
||||||
|
|
||||||
|
get_arrows_border (menu, &arrows_border);
|
||||||
|
menu->priv->scroll_offset = arrows_border.top + (final_rect->y - flipped_rect->y);
|
||||||
|
gtk_menu_scroll_to (menu, menu->priv->scroll_offset);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gtk_menu_popdown:
|
* gtk_menu_popdown:
|
||||||
* @menu: a #GtkMenu
|
* @menu: a #GtkMenu
|
||||||
@ -2517,29 +3103,6 @@ gtk_menu_reorder_child (GtkMenu *menu,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
get_arrows_border (GtkMenu *menu,
|
|
||||||
GtkBorder *border)
|
|
||||||
{
|
|
||||||
GtkMenuPrivate *priv = menu->priv;
|
|
||||||
gint top_arrow_height, bottom_arrow_height;
|
|
||||||
|
|
||||||
gtk_css_gadget_get_preferred_size (priv->top_arrow_gadget,
|
|
||||||
GTK_ORIENTATION_VERTICAL,
|
|
||||||
-1,
|
|
||||||
&top_arrow_height, NULL,
|
|
||||||
NULL, NULL);
|
|
||||||
gtk_css_gadget_get_preferred_size (priv->bottom_arrow_gadget,
|
|
||||||
GTK_ORIENTATION_VERTICAL,
|
|
||||||
-1,
|
|
||||||
&bottom_arrow_height, NULL,
|
|
||||||
NULL, NULL);
|
|
||||||
|
|
||||||
border->top = priv->upper_arrow_visible ? top_arrow_height : 0;
|
|
||||||
border->bottom = priv->lower_arrow_visible ? bottom_arrow_height : 0;
|
|
||||||
border->left = border->right = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
get_menu_padding (GtkWidget *widget,
|
get_menu_padding (GtkWidget *widget,
|
||||||
GtkBorder *padding)
|
GtkBorder *padding)
|
||||||
@ -4280,8 +4843,8 @@ gtk_menu_deactivate (GtkMenuShell *menu_shell)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_menu_position (GtkMenu *menu,
|
gtk_menu_position_legacy (GtkMenu *menu,
|
||||||
gboolean set_scroll_offset)
|
gboolean set_scroll_offset)
|
||||||
{
|
{
|
||||||
GtkMenuPrivate *priv = menu->priv;
|
GtkMenuPrivate *priv = menu->priv;
|
||||||
GtkWidget *widget;
|
GtkWidget *widget;
|
||||||
@ -4519,6 +5082,104 @@ gtk_menu_position (GtkMenu *menu,
|
|||||||
priv->scroll_offset = scroll_offset;
|
priv->scroll_offset = scroll_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GdkGravity
|
||||||
|
get_horizontally_flipped_anchor (GdkGravity anchor)
|
||||||
|
{
|
||||||
|
switch (anchor)
|
||||||
|
{
|
||||||
|
case GDK_GRAVITY_STATIC:
|
||||||
|
case GDK_GRAVITY_NORTH_WEST:
|
||||||
|
return GDK_GRAVITY_NORTH_EAST;
|
||||||
|
case GDK_GRAVITY_NORTH:
|
||||||
|
return GDK_GRAVITY_NORTH;
|
||||||
|
case GDK_GRAVITY_NORTH_EAST:
|
||||||
|
return GDK_GRAVITY_NORTH_WEST;
|
||||||
|
case GDK_GRAVITY_WEST:
|
||||||
|
return GDK_GRAVITY_EAST;
|
||||||
|
case GDK_GRAVITY_CENTER:
|
||||||
|
return GDK_GRAVITY_CENTER;
|
||||||
|
case GDK_GRAVITY_EAST:
|
||||||
|
return GDK_GRAVITY_WEST;
|
||||||
|
case GDK_GRAVITY_SOUTH_WEST:
|
||||||
|
return GDK_GRAVITY_SOUTH_EAST;
|
||||||
|
case GDK_GRAVITY_SOUTH:
|
||||||
|
return GDK_GRAVITY_SOUTH;
|
||||||
|
case GDK_GRAVITY_SOUTH_EAST:
|
||||||
|
return GDK_GRAVITY_SOUTH_WEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_warning ("unknown GdkGravity: %d", anchor);
|
||||||
|
return anchor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_menu_position (GtkMenu *menu,
|
||||||
|
gboolean set_scroll_offset)
|
||||||
|
{
|
||||||
|
GtkMenuPrivate *priv = menu->priv;
|
||||||
|
GdkWindow *rect_window = NULL;
|
||||||
|
GdkRectangle rect;
|
||||||
|
GtkTextDirection text_direction = GTK_TEXT_DIR_NONE;
|
||||||
|
GdkGravity rect_anchor;
|
||||||
|
GdkGravity menu_anchor;
|
||||||
|
GdkWindow *toplevel;
|
||||||
|
|
||||||
|
if (priv->rect_window)
|
||||||
|
{
|
||||||
|
rect_window = priv->rect_window;
|
||||||
|
rect = priv->rect;
|
||||||
|
}
|
||||||
|
else if (priv->widget)
|
||||||
|
{
|
||||||
|
rect_window = gtk_widget_get_window (priv->widget);
|
||||||
|
gtk_widget_get_allocation (priv->widget, &rect);
|
||||||
|
text_direction = gtk_widget_get_direction (priv->widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rect_window)
|
||||||
|
{
|
||||||
|
gtk_menu_position_legacy (menu, set_scroll_offset);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Realize so we have the proper width and height to figure out
|
||||||
|
* the right place to popup the menu.
|
||||||
|
*/
|
||||||
|
gtk_widget_realize (priv->toplevel);
|
||||||
|
|
||||||
|
if (!gtk_widget_get_visible (priv->toplevel))
|
||||||
|
gtk_window_set_type_hint (GTK_WINDOW (priv->toplevel), priv->menu_type_hint);
|
||||||
|
|
||||||
|
if (text_direction == GTK_TEXT_DIR_NONE)
|
||||||
|
text_direction = gtk_widget_get_direction (GTK_WIDGET (menu));
|
||||||
|
|
||||||
|
if (text_direction == GTK_TEXT_DIR_RTL)
|
||||||
|
{
|
||||||
|
rect_anchor = get_horizontally_flipped_anchor (priv->rect_anchor);
|
||||||
|
menu_anchor = get_horizontally_flipped_anchor (priv->menu_anchor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rect_anchor = priv->rect_anchor;
|
||||||
|
menu_anchor = priv->menu_anchor;
|
||||||
|
}
|
||||||
|
|
||||||
|
toplevel = gtk_widget_get_window (priv->toplevel);
|
||||||
|
|
||||||
|
gdk_window_set_transient_for (toplevel, rect_window);
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_func (toplevel, moved_to_rect_cb, menu);
|
||||||
|
g_signal_connect (toplevel, "moved-to-rect", G_CALLBACK (moved_to_rect_cb), menu);
|
||||||
|
|
||||||
|
GDK_PRIVATE_CALL (gdk_window_move_to_rect) (toplevel,
|
||||||
|
&rect,
|
||||||
|
rect_anchor,
|
||||||
|
menu_anchor,
|
||||||
|
priv->anchor_hints,
|
||||||
|
priv->rect_anchor_dx,
|
||||||
|
priv->rect_anchor_dy);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_menu_remove_scroll_timeout (GtkMenu *menu)
|
gtk_menu_remove_scroll_timeout (GtkMenu *menu)
|
||||||
{
|
{
|
||||||
|
@ -152,6 +152,22 @@ void gtk_menu_popup_for_device (GtkMenu *menu,
|
|||||||
GDestroyNotify destroy,
|
GDestroyNotify destroy,
|
||||||
guint button,
|
guint button,
|
||||||
guint32 activate_time);
|
guint32 activate_time);
|
||||||
|
GDK_AVAILABLE_IN_3_22
|
||||||
|
void gtk_menu_popup_at_rect (GtkMenu *menu,
|
||||||
|
GdkWindow *rect_window,
|
||||||
|
const GdkRectangle *rect,
|
||||||
|
GdkGravity rect_anchor,
|
||||||
|
GdkGravity menu_anchor,
|
||||||
|
const GdkEvent *trigger_event);
|
||||||
|
GDK_AVAILABLE_IN_3_22
|
||||||
|
void gtk_menu_popup_at_widget (GtkMenu *menu,
|
||||||
|
GtkWidget *widget,
|
||||||
|
GdkGravity widget_anchor,
|
||||||
|
GdkGravity menu_anchor,
|
||||||
|
const GdkEvent *trigger_event);
|
||||||
|
GDK_AVAILABLE_IN_3_22
|
||||||
|
void gtk_menu_popup_at_pointer (GtkMenu *menu,
|
||||||
|
const GdkEvent *trigger_event);
|
||||||
|
|
||||||
/* Position the menu according to its position function. Called
|
/* Position the menu according to its position function. Called
|
||||||
* from gtkmenuitem.c when a menu-item changes its allocation
|
* from gtkmenuitem.c when a menu-item changes its allocation
|
||||||
|
@ -53,6 +53,16 @@ struct _GtkMenuPrivate
|
|||||||
gint position_x;
|
gint position_x;
|
||||||
gint position_y;
|
gint position_y;
|
||||||
|
|
||||||
|
GdkWindow *rect_window;
|
||||||
|
GdkRectangle rect;
|
||||||
|
GtkWidget *widget;
|
||||||
|
GdkGravity rect_anchor;
|
||||||
|
GdkGravity menu_anchor;
|
||||||
|
GdkAnchorHints anchor_hints;
|
||||||
|
gint rect_anchor_dx;
|
||||||
|
gint rect_anchor_dy;
|
||||||
|
GdkWindowTypeHint menu_type_hint;
|
||||||
|
|
||||||
guint toggle_size;
|
guint toggle_size;
|
||||||
guint accel_size;
|
guint accel_size;
|
||||||
|
|
||||||
@ -130,6 +140,14 @@ struct _GtkMenuPrivate
|
|||||||
gint initial_drag_offset;
|
gint initial_drag_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
|
void gtk_menu_update_scroll_offset (GtkMenu *menu,
|
||||||
|
const GdkRectangle *flipped_rect,
|
||||||
|
const GdkRectangle *final_rect,
|
||||||
|
gboolean flipped_x,
|
||||||
|
gboolean flipped_y,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GTK_MENU_PRIVATE_H__ */
|
#endif /* __GTK_MENU_PRIVATE_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user