[gtk/wip/matthiasc/context-menu: 1062/1062] Work towards generic menu popup
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/matthiasc/context-menu: 1062/1062] Work towards generic menu popup
- Date: Mon, 10 Jun 2019 15:33:01 +0000 (UTC)
commit 6b15fa5267d0b065181a6c30499553df4b3725b6
Author: Matthias Clasen <mclasen redhat com>
Date: Thu Apr 18 20:14:34 2019 +0000
Work towards generic menu popup
Repurpose the ::popup-menu signal for popping
up context menus. Widgets such as GtkText or
GtkLabel can override the class handler to update
their actions before chaining up. Make GtkWidget
handle context-menu popup automatically. I had
to add a property to turn this off off, for complex
cases like GtkText.
gtk/gtklabel.c | 188 ++++++++++++++++---------------------------------
gtk/gtktext.c | 66 ++---------------
gtk/gtkwidget.c | 116 ++++++++++++++++++++++++++++++
gtk/gtkwidgetprivate.h | 5 ++
4 files changed, 185 insertions(+), 190 deletions(-)
---
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index 8cb67ed8bf..2a53191553 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -354,12 +354,12 @@ struct _GtkLabelSelectionInfo
{
gint selection_anchor;
gint selection_end;
- GtkWidget *popup_menu;
GtkCssNode *selection_node;
GdkContentProvider *provider;
GList *links;
GtkLabelLink *active_link;
+ GtkLabelLink *context_link;
GtkGesture *drag_gesture;
GtkGesture *click_gesture;
@@ -442,7 +442,6 @@ static gboolean gtk_label_focus (GtkWidget *widget,
static void gtk_label_realize (GtkWidget *widget);
static void gtk_label_unrealize (GtkWidget *widget);
-static void gtk_label_unmap (GtkWidget *widget);
static void gtk_label_motion (GtkEventControllerMotion *controller,
double x,
@@ -535,8 +534,6 @@ static void gtk_label_move_cursor (GtkLabel *label,
gboolean extend_selection);
static void gtk_label_copy_clipboard (GtkLabel *label);
static void gtk_label_select_all (GtkLabel *label);
-static void gtk_label_do_popup (GtkLabel *label,
- const GdkEvent *event);
static gint gtk_label_move_forward_word (GtkLabel *label,
gint start);
static gint gtk_label_move_backward_word (GtkLabel *label,
@@ -634,13 +631,12 @@ gtk_label_class_init (GtkLabelClass *class)
widget_class->snapshot = gtk_label_snapshot;
widget_class->realize = gtk_label_realize;
widget_class->unrealize = gtk_label_unrealize;
- widget_class->unmap = gtk_label_unmap;
widget_class->root = gtk_label_root;
widget_class->unroot = gtk_label_unroot;
widget_class->mnemonic_activate = gtk_label_mnemonic_activate;
+ widget_class->popup_menu = gtk_label_popup_menu;
widget_class->drag_data_get = gtk_label_drag_data_get;
widget_class->grab_focus = gtk_label_grab_focus;
- widget_class->popup_menu = gtk_label_popup_menu;
widget_class->focus = gtk_label_focus;
widget_class->get_request_mode = gtk_label_get_request_mode;
widget_class->measure = gtk_label_measure;
@@ -1312,6 +1308,7 @@ gtk_label_init (GtkLabel *label)
gtk_label_add_context_actions (label);
menu = gtk_label_get_default_menu ();
+ g_object_set (label, "handle-context-menu", FALSE, NULL);
gtk_widget_set_context_menu (GTK_WIDGET (label), menu);
g_object_unref (menu);
}
@@ -4105,24 +4102,6 @@ gtk_label_unrealize (GtkWidget *widget)
GTK_WIDGET_CLASS (gtk_label_parent_class)->unrealize (widget);
}
-static void
-gtk_label_unmap (GtkWidget *widget)
-{
- GtkLabel *label = GTK_LABEL (widget);
- GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
-
- if (priv->select_info)
- {
- if (priv->select_info->popup_menu)
- {
- gtk_widget_destroy (priv->select_info->popup_menu);
- priv->select_info->popup_menu = NULL;
- }
- }
-
- GTK_WIDGET_CLASS (gtk_label_parent_class)->unmap (widget);
-}
-
static gboolean
get_layout_index (GtkLabel *label,
gint x,
@@ -4461,7 +4440,7 @@ gtk_label_click_gesture_pressed (GtkGestureClick *gesture,
{
info->link_clicked = 1;
update_link_state (label);
- gtk_label_do_popup (label, event);
+ gtk_widget_popup_context_menu (widget);
return;
}
else if (button == GDK_BUTTON_PRIMARY)
@@ -4484,7 +4463,7 @@ gtk_label_click_gesture_pressed (GtkGestureClick *gesture,
info->select_words = FALSE;
if (gdk_event_triggers_context_menu (event))
- gtk_label_do_popup (label, event);
+ gtk_widget_popup_context_menu (GTK_WIDGET (label));
else if (button == GDK_BUTTON_PRIMARY)
{
if (!gtk_widget_has_focus (widget))
@@ -5962,25 +5941,6 @@ gtk_label_select_all (GtkLabel *label)
gtk_label_select_region_index (label, 0, strlen (priv->text));
}
-static void
-popup_menu_detach (GtkWidget *attach_widget,
- GtkMenu *menu)
-{
- GtkLabel *label = GTK_LABEL (attach_widget);
- GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
-
- if (priv->select_info)
- priv->select_info->popup_menu = NULL;
-}
-
-static gboolean
-gtk_label_popup_menu (GtkWidget *widget)
-{
- gtk_label_do_popup (GTK_LABEL (widget), NULL);
-
- return TRUE;
-}
-
static void
open_link_activated (GSimpleAction *action,
GVariant *parameter,
@@ -5988,14 +5948,10 @@ open_link_activated (GSimpleAction *action,
{
GtkLabel *label = GTK_LABEL (user_data);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
- GtkLabelLink *link = NULL;
- int pos = g_variant_get_int32 (parameter);
-
- link = g_list_nth_data (priv->select_info->links, pos);
- if (link == NULL)
- return;
+ GtkLabelLink *link = priv->select_info->context_link;
- emit_activate_link (label, link);
+ if (link)
+ emit_activate_link (label, link);
}
static void
@@ -6005,16 +5961,15 @@ copy_link_activated (GSimpleAction *action,
{
GtkLabel *label = GTK_LABEL (user_data);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
- GtkLabelLink *link = NULL;
- int pos = g_variant_get_int32 (parameter);
- GdkClipboard *clipboard;
+ GtkLabelLink *link = priv->select_info->context_link;
- link = g_list_nth_data (priv->select_info->links, pos);
- if (link == NULL)
- return;
+ if (link)
+ {
+ GdkClipboard *clipboard;
- clipboard = gtk_widget_get_clipboard (GTK_WIDGET (label));
- gdk_clipboard_set_text (clipboard, link->uri);
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (label));
+ gdk_clipboard_set_text (clipboard, link->uri);
+ }
}
static void
@@ -6049,19 +6004,39 @@ gtk_label_update_clipboard_actions (GtkLabel *label)
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), gtk_label_get_selectable (label));
}
+static void
+gtk_label_update_link_actions (GtkLabel *label)
+{
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+ gboolean have_selection = FALSE;
+ GAction *action;
+ GtkLabelLink *link;
+
+ have_selection = priv->select_info->selection_anchor != priv->select_info->selection_end;
+ if (priv->select_info->link_clicked)
+ link = priv->select_info->active_link;
+ else
+ link = gtk_label_get_focus_link (label);
+
+ action = g_action_map_lookup_action (priv->context_actions, "open-link");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !have_selection && link);
+ action = g_action_map_lookup_action (priv->context_actions, "copy-link");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !have_selection && link);
+}
+
static void
gtk_label_add_context_actions (GtkLabel *label)
{
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
GActionEntry entries[] = {
- { "open-link", open_link_activated, "i", NULL, NULL },
- { "copy-link", copy_link_activated, "i", NULL, NULL },
{ "cut-clipboard", NULL, NULL, NULL, NULL },
{ "copy-clipboard", copy_clipboard_activated, NULL, NULL, NULL },
{ "paste-clipboard", NULL, NULL, NULL, NULL },
{ "delete-selection", NULL, NULL, NULL, NULL },
{ "select-all", select_all_activated, NULL, NULL, NULL },
+ { "open-link", open_link_activated, NULL, NULL, NULL },
+ { "copy-link", copy_link_activated, NULL, NULL, NULL },
};
GSimpleActionGroup *actions = g_simple_action_group_new ();
@@ -6081,6 +6056,10 @@ gtk_label_add_context_actions (GtkLabel *label)
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "select-all");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "open-link");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "copy-link");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
gtk_widget_insert_action_group (GTK_WIDGET (label), "context", G_ACTION_GROUP (actions));
}
@@ -6089,6 +6068,7 @@ static GMenuModel *
gtk_label_get_default_menu (void)
{
GMenu *menu, *section;
+ GMenuItem *item;
menu = g_menu_new ();
@@ -6105,89 +6085,39 @@ gtk_label_get_default_menu (void)
g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
g_object_unref (section);
- return G_MENU_MODEL (menu);
-}
-
-static GMenuModel *
-get_link_context_menu (GtkLabel *label,
- GtkLabelLink *link)
-{
- GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
- GMenu *menu;
- GMenuItem *item;
- int index;
-
- index = g_list_index (priv->select_info->links, link);
-
- menu = g_menu_new ();
+ section = g_menu_new ();
item = g_menu_item_new (_("_Open Link"), "context.open-link");
- g_menu_item_set_attribute (item, "target", "i", index);
- g_menu_append_item (menu, item);
+ g_menu_item_set_attribute (item, "hidden-when", "s", "action-disabled");
+ g_menu_append_item (section, item);
g_object_unref (item);
-
- item = g_menu_item_new (_("_Copy Link Address"), "context.copy-link");
- g_menu_item_set_attribute (item, "target", "i", index);
- g_menu_append_item (menu, item);
+ item = g_menu_item_new (_("Copy _Link Address"), "context.copy-link");
+ g_menu_item_set_attribute (item, "hidden-when", "s", "action-disabled");
+ g_menu_append_item (section, item);
g_object_unref (item);
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
+ g_object_unref (section);
return G_MENU_MODEL (menu);
}
-static void
-gtk_label_do_popup (GtkLabel *label,
- const GdkEvent *event)
+static gboolean
+gtk_label_popup_menu (GtkWidget *widget)
{
+ GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
- GtkWidget *menu;
- GMenuModel *model;
- GtkLabelLink *link;
- gboolean have_selection;
if (!priv->select_info)
- return;
+ return FALSE;
gtk_label_update_clipboard_actions (label);
+ gtk_label_update_link_actions (label);
- if (priv->select_info->popup_menu)
- gtk_widget_destroy (priv->select_info->popup_menu);
-
- have_selection = priv->select_info->selection_anchor != priv->select_info->selection_end;
- if (event)
- {
- if (priv->select_info->link_clicked)
- link = priv->select_info->active_link;
- else
- link = NULL;
- }
- else
- link = gtk_label_get_focus_link (label);
-
- if (!have_selection && link)
- model = get_link_context_menu (label, link);
- else
- model = g_object_ref (gtk_widget_get_context_menu (GTK_WIDGET (label)));
-
- priv->select_info->popup_menu = menu = gtk_menu_new_from_model (model);
-
- g_object_unref (model);
-
- g_object_set_data (G_OBJECT (menu), "link", link);
-
- gtk_style_context_add_class (gtk_widget_get_style_context (menu), GTK_STYLE_CLASS_CONTEXT_MENU);
- gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (label), popup_menu_detach);
-
- if (event && gdk_event_triggers_context_menu (event))
- gtk_menu_popup_at_pointer (GTK_MENU (menu), event);
+ if (priv->select_info->link_clicked)
+ priv->select_info->context_link = priv->select_info->active_link;
else
- {
- gtk_menu_popup_at_widget (GTK_MENU (menu),
- GTK_WIDGET (label),
- GDK_GRAVITY_SOUTH,
- GDK_GRAVITY_NORTH_WEST,
- event);
+ priv->select_info->context_link = gtk_label_get_focus_link (label);
- gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
- }
+ return GTK_WIDGET_CLASS (gtk_label_parent_class)->popup_menu (widget);
}
static void
diff --git a/gtk/gtktext.c b/gtk/gtktext.c
index 532f2f91ff..6bcdc024dc 100644
--- a/gtk/gtktext.c
+++ b/gtk/gtktext.c
@@ -146,7 +146,6 @@ struct _GtkTextPrivate
{
GtkEntryBuffer *buffer;
GtkIMContext *im_context;
- GtkWidget *popup_menu;
int text_baseline;
@@ -514,8 +513,6 @@ static void gtk_text_paste (GtkText *self,
GdkClipboard *clipboard);
static void gtk_text_update_primary_selection (GtkText *self);
static void gtk_text_schedule_im_reset (GtkText *self);
-static void gtk_text_do_popup (GtkText *self,
- const GdkEvent *event);
static gboolean gtk_text_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling);
static void gtk_text_check_cursor_blink (GtkText *self);
@@ -1703,6 +1700,7 @@ gtk_text_init (GtkText *self)
gtk_text_add_context_actions (self);
menu = gtk_text_get_default_menu ();
+ g_object_set (self, "handle-context-menu", FALSE, NULL);
gtk_widget_set_context_menu (GTK_WIDGET (self), menu);
g_object_unref (menu);
}
@@ -2017,12 +2015,6 @@ gtk_text_unrealize (GtkWidget *widget)
if (gdk_clipboard_get_content (clipboard) == priv->selection_content)
gdk_clipboard_set_content (clipboard, NULL);
- if (priv->popup_menu)
- {
- gtk_widget_destroy (priv->popup_menu);
- priv->popup_menu = NULL;
- }
-
GTK_WIDGET_CLASS (gtk_text_parent_class)->unrealize (widget);
}
@@ -2444,7 +2436,8 @@ gtk_text_click_gesture_pressed (GtkGestureClick *gesture,
if (gdk_event_triggers_context_menu (event))
{
- gtk_text_do_popup (self, event);
+ gtk_text_update_clipboard_actions (self);
+ gtk_widget_popup_context_menu (widget);
}
else if (n_press == 1 && button == GDK_BUTTON_MIDDLE &&
get_middle_click_paste (self))
@@ -5768,60 +5761,11 @@ gtk_text_mnemonic_activate (GtkWidget *widget,
return GDK_EVENT_STOP;
}
-static void
-popup_menu_detach (GtkWidget *attach_widget,
- GtkMenu *menu)
-{
- GtkText *self_attach = GTK_TEXT (attach_widget);
- GtkTextPrivate *priv_attach = gtk_text_get_instance_private (self_attach);
-
- priv_attach->popup_menu = NULL;
-}
-
-static void
-gtk_text_do_popup (GtkText *self,
- const GdkEvent *event)
-{
- GtkTextPrivate *priv = gtk_text_get_instance_private (self);
- GMenuModel *model;
- GtkWidget *menu;
- GdkEvent *trigger_event;
-
- if (!gtk_widget_get_realized (GTK_WIDGET (self)))
- return;
-
- gtk_text_update_clipboard_actions (self);
-
- if (priv->popup_menu)
- gtk_widget_destroy (priv->popup_menu);
-
- model = gtk_widget_get_context_menu (GTK_WIDGET (self));
- priv->popup_menu = menu = gtk_menu_new_from_model (model);
-
- gtk_style_context_add_class (gtk_widget_get_style_context (menu), GTK_STYLE_CLASS_CONTEXT_MENU);
- gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (self), popup_menu_detach);
-
- trigger_event = event ? gdk_event_copy (event) : gtk_get_current_event ();
- 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),
- GTK_WIDGET (self),
- GDK_GRAVITY_SOUTH_EAST,
- GDK_GRAVITY_NORTH_WEST,
- trigger_event);
- gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
- }
-
- g_clear_object (&trigger_event);
-}
-
static gboolean
gtk_text_popup_menu (GtkWidget *widget)
{
- gtk_text_do_popup (GTK_TEXT (widget), NULL);
- return GDK_EVENT_STOP;
+ gtk_text_update_clipboard_actions (GTK_TEXT (widget));
+ return GTK_WIDGET_CLASS (gtk_text_parent_class)->popup_menu (widget);
}
static void
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 01e6a1d447..65ea45b2c8 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -73,6 +73,7 @@
#include "gtkwindowgroup.h"
#include "gtkwindowprivate.h"
#include "gtknativeprivate.h"
+#include "gtkgestureclick.h"
#include "a11y/gtkwidgetaccessible.h"
#include "inspector/window.h"
@@ -576,6 +577,7 @@ enum {
PROP_CSS_NAME,
PROP_LAYOUT_MANAGER,
PROP_CONTEXT_MENU,
+ PROP_HANDLE_CONTEXT_MENU,
NUM_PROPERTIES
};
@@ -665,6 +667,7 @@ static void gtk_widget_real_measure (GtkWidget
static void gtk_widget_real_state_flags_changed (GtkWidget *widget,
GtkStateFlags old_state);
static AtkObject* gtk_widget_real_get_accessible (GtkWidget *widget);
+static gboolean gtk_widget_real_popup_menu (GtkWidget *widget);
static void gtk_widget_accessible_interface_init (AtkImplementorIface *iface);
static AtkObject* gtk_widget_ref_accessible (AtkImplementor *implementor);
static gboolean gtk_widget_real_can_activate_accel (GtkWidget *widget,
@@ -861,6 +864,61 @@ gtk_widget_real_unroot (GtkWidget *widget)
gtk_widget_forall (widget, (GtkCallback) gtk_widget_unroot, NULL);
}
+static void
+popup_menu_detach (GtkWidget *widget,
+ GtkMenu *menu)
+{
+ GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+
+ priv->popup_menu = NULL;
+}
+
+static gboolean
+gtk_widget_real_popup_menu (GtkWidget *widget)
+{
+ GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+ GtkWidget *menu;
+ const GdkEvent *event;
+
+ if (!gtk_widget_get_realized (widget))
+ return FALSE;
+
+ if (!priv->context_menu)
+ return FALSE;
+
+ if (priv->popup_menu)
+ gtk_widget_destroy (priv->popup_menu);
+
+ priv->popup_menu = menu = gtk_menu_new_from_model (priv->context_menu);
+ gtk_style_context_add_class (gtk_widget_get_style_context (menu), GTK_STYLE_CLASS_CONTEXT_MENU);
+ gtk_menu_attach_to_widget (GTK_MENU (menu), widget, popup_menu_detach);
+
+ event = gtk_get_current_event ();
+ if (event && gdk_event_triggers_context_menu (event))
+ gtk_menu_popup_at_pointer (GTK_MENU (menu), event);
+ else
+ {
+ gtk_menu_popup_at_widget (GTK_MENU (menu),
+ widget,
+ GDK_GRAVITY_SOUTH_EAST,
+ GDK_GRAVITY_NORTH_WEST,
+ event);
+ gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
+ }
+
+ return TRUE;
+}
+
+gboolean
+gtk_widget_popup_context_menu (GtkWidget *widget)
+{
+ gboolean handled;
+
+ g_signal_emit (widget, widget_signals[POPUP_MENU], 0, &handled);
+
+ return handled;
+}
+
static void
gtk_widget_class_init (GtkWidgetClass *klass)
{
@@ -923,6 +981,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
klass->can_activate_accel = gtk_widget_real_can_activate_accel;
klass->query_tooltip = gtk_widget_real_query_tooltip;
klass->style_updated = gtk_widget_real_style_updated;
+ klass->popup_menu = gtk_widget_real_popup_menu;
/* Accessibility support */
klass->priv->accessible_type = GTK_TYPE_ACCESSIBLE;
@@ -1368,6 +1427,13 @@ gtk_widget_class_init (GtkWidgetClass *klass)
G_TYPE_MENU_MODEL,
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+ widget_props[PROP_HANDLE_CONTEXT_MENU] =
+ g_param_spec_boolean ("handle-context-menu",
+ P_("Handle Context Menu"),
+ P_("Whether the context menu should be handled automatically"),
+ TRUE,
+ GTK_PARAM_READWRITE);
+
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, widget_props);
/**
@@ -2310,6 +2376,9 @@ gtk_widget_set_property (GObject *object,
case PROP_CONTEXT_MENU:
gtk_widget_set_context_menu (widget, g_value_get_object (value));
break;
+ case PROP_HANDLE_CONTEXT_MENU:
+ priv->handle_context_menu = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -2459,6 +2528,9 @@ gtk_widget_get_property (GObject *object,
case PROP_CONTEXT_MENU:
g_value_set_object (value, gtk_widget_get_context_menu (widget));
break;
+ case PROP_HANDLE_CONTEXT_MENU:
+ g_value_set_boolean (value, priv->handle_context_menu);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -2805,6 +2877,7 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
priv->highlight_resize = FALSE;
#endif
priv->can_target = TRUE;
+ priv->handle_context_menu = TRUE;
switch (_gtk_widget_get_direction (widget))
{
@@ -8225,6 +8298,12 @@ gtk_widget_real_unrealize (GtkWidget *widget)
priv->realized = FALSE;
g_clear_object (&priv->surface);
+
+ if (priv->popup_menu)
+ {
+ gtk_widget_destroy (priv->popup_menu);
+ priv->popup_menu = NULL;
+ }
}
void
@@ -13426,6 +13505,23 @@ gtk_widget_get_layout_manager (GtkWidget *widget)
return priv->layout_manager;
}
+static void
+popup_controller_pressed (GtkGestureClick *gesture,
+ int n_press,
+ double widget_x,
+ double widget_y,
+ GtkWidget *widget)
+{
+ GdkEvent *event;
+
+ event = gtk_get_current_event ();
+ if (event && gdk_event_triggers_context_menu (event))
+ {
+ gboolean handled;
+ g_signal_emit (widget, widget_signals[POPUP_MENU], 0, &handled);
+ }
+}
+
/**
* gtk_widget_set_context_menu:
* @widget: a #GtkWidget
@@ -13445,6 +13541,26 @@ gtk_widget_set_context_menu (GtkWidget *widget,
if (g_set_object (&priv->context_menu, menu))
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_CONTEXT_MENU]);
+
+ if (priv->context_menu && priv->handle_context_menu)
+ {
+ if (!priv->popup_controller)
+ {
+ priv->popup_controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (priv->popup_controller), 0);
+ g_signal_connect (priv->popup_controller, "pressed",
+ G_CALLBACK (popup_controller_pressed), widget);
+ gtk_widget_add_controller (widget, priv->popup_controller);
+ }
+ }
+ else
+ {
+ if (priv->popup_controller)
+ {
+ gtk_widget_remove_controller (widget, priv->popup_controller);
+ priv->popup_controller = NULL;
+ }
+ }
}
/**
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index cf44b5582f..46cca274d9 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -111,6 +111,8 @@ struct _GtkWidgetPrivate
guint halign : 4;
guint valign : 4;
+ guint handle_context_menu : 1;
+
GtkOverflow overflow;
guint8 alpha;
guint8 user_alpha;
@@ -207,6 +209,8 @@ struct _GtkWidgetPrivate
GdkCursor *cursor;
GMenuModel *context_menu;
+ GtkWidget *popup_menu;
+ GtkEventController *popup_controller;
};
void gtk_widget_root (GtkWidget *widget);
@@ -359,6 +363,7 @@ void gtk_widget_cancel_event_sequence (GtkWidget
gboolean gtk_widget_run_controllers (GtkWidget *widget,
const GdkEvent *event,
GtkPropagationPhase phase);
+gboolean gtk_widget_popup_context_menu (GtkWidget *widget);
guint gtk_widget_add_surface_transform_changed_callback (GtkWidget
*widget,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]