[gtk/wip/matthiasc/context-menu: 4/13] label: Redo context menus
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/matthiasc/context-menu: 4/13] label: Redo context menus
- Date: Thu, 13 Jun 2019 12:03:00 +0000 (UTC)
commit 964b2574cff262ed24fb4de92def082552b16dd1
Author: Matthias Clasen <mclasen redhat com>
Date: Sun Jan 27 16:43:54 2019 -0500
label: Redo context menus
Drop the ::populate-popup signal and implement
the new context menu api. Things are a bit more
complicated here, since we have different menus
on links and selectable text.
docs/reference/gtk/gtk4-sections.txt | 3 +
gtk/gtklabel.c | 419 +++++++++++++++++++++--------------
gtk/gtklabel.h | 7 +
3 files changed, 264 insertions(+), 165 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 3d7fcdcd54..1e265b63b0 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -1719,6 +1719,9 @@ gtk_label_set_single_line_mode
gtk_label_get_current_uri
gtk_label_set_track_visited_links
gtk_label_get_track_visited_links
+gtk_label_set_extra_menu
+gtk_label_get_extra_menu
+
<SUBSECTION Standard>
GTK_LABEL
GTK_IS_LABEL
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index ffc6d05e6e..6bc134edc2 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -55,6 +55,8 @@
#include "gtktypebuiltins.h"
#include "gtkwidgetprivate.h"
#include "gtkwindow.h"
+#include "gtkpopovermenu.h"
+#include "gtknative.h"
#include "a11y/gtklabelaccessibleprivate.h"
@@ -269,9 +271,6 @@ struct _GtkLabelClass
gboolean extend_selection);
void (* copy_clipboard) (GtkLabel *label);
- void (* populate_popup) (GtkLabel *label,
- GtkMenu *menu);
-
gboolean (*activate_link) (GtkLabel *label,
const gchar *uri);
};
@@ -286,6 +285,10 @@ struct _GtkLabelPrivate
PangoAttrList *markup_attrs;
PangoLayout *layout;
+ GActionMap *context_actions;
+ GtkWidget *popup_menu;
+ GMenuModel *extra_menu;
+
gchar *label;
gchar *text;
@@ -355,12 +358,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;
@@ -378,7 +381,6 @@ struct _GtkLabelSelectionInfo
enum {
MOVE_CURSOR,
COPY_CLIPBOARD,
- POPULATE_POPUP,
ACTIVATE_LINK,
ACTIVATE_CURRENT_LINK,
LAST_SIGNAL
@@ -407,6 +409,7 @@ enum {
PROP_LINES,
PROP_XALIGN,
PROP_YALIGN,
+ PROP_EXTRA_MENU,
NUM_PROPERTIES
};
@@ -444,7 +447,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,
@@ -483,6 +485,9 @@ static void gtk_label_recalculate (GtkLabel *label);
static void gtk_label_root (GtkWidget *widget);
static void gtk_label_unroot (GtkWidget *widget);
static gboolean gtk_label_popup_menu (GtkWidget *widget);
+static void gtk_label_do_popup (GtkLabel *label,
+ double x,
+ double y);
static void gtk_label_set_selectable_hint (GtkLabel *label);
static void gtk_label_ensure_select_info (GtkLabel *label);
@@ -536,8 +541,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,
@@ -572,6 +575,9 @@ static void gtk_label_drag_gesture_update (GtkGestureDrag *gesture,
gdouble offset_y,
GtkLabel *label);
+static void gtk_label_add_context_actions (GtkLabel *label);
+static void gtk_label_update_clipboard_actions (GtkLabel *label);
+
static GtkSizeRequestMode gtk_label_get_request_mode (GtkWidget *widget);
static void gtk_label_measure (GtkWidget *widget,
GtkOrientation orientation,
@@ -581,6 +587,8 @@ static void gtk_label_measure (GtkWidget *widget,
int *minimum_baseline,
int *natural_baseline);
+
+
static GtkBuildableIface *buildable_parent_iface = NULL;
G_DEFINE_TYPE_WITH_CODE (GtkLabel, gtk_label, GTK_TYPE_WIDGET,
@@ -630,13 +638,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;
@@ -701,28 +708,6 @@ gtk_label_class_init (GtkLabelClass *class)
NULL,
G_TYPE_NONE, 0);
- /**
- * GtkLabel::populate-popup:
- * @label: The label on which the signal is emitted
- * @menu: the menu that is being populated
- *
- * The ::populate-popup signal gets emitted before showing the
- * context menu of the label. Note that only selectable labels
- * have context menus.
- *
- * If you need to add items to the context menu, connect
- * to this signal and append your menuitems to the @menu.
- */
- signals[POPULATE_POPUP] =
- g_signal_new (I_("populate-popup"),
- G_OBJECT_CLASS_TYPE (gobject_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkLabelClass, populate_popup),
- NULL, NULL,
- NULL,
- G_TYPE_NONE, 1,
- GTK_TYPE_MENU);
-
/**
* GtkLabel::activate-current-link:
* @label: The label on which the signal was emitted
@@ -1019,6 +1004,19 @@ gtk_label_class_init (GtkLabelClass *class)
-1,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+ /**
+ * GtkLabel:extra-menu:
+ *
+ * A menu model whose contents will be appended to
+ * the context menu.
+ */
+ label_props[PROP_EXTRA_MENU] =
+ g_param_spec_object ("extra-menu",
+ P_("Extra menu"),
+ P_("Menu model to append to the context menu"),
+ G_TYPE_MENU_MODEL,
+ GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, label_props);
/*
@@ -1211,6 +1209,9 @@ gtk_label_set_property (GObject *object,
case PROP_YALIGN:
gtk_label_set_yalign (label, g_value_get_float (value));
break;
+ case PROP_EXTRA_MENU:
+ gtk_label_set_extra_menu (label, g_value_get_object (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1288,6 +1289,9 @@ gtk_label_get_property (GObject *object,
case PROP_YALIGN:
g_value_set_float (value, gtk_label_get_yalign (label));
break;
+ case PROP_EXTRA_MENU:
+ g_value_set_object (value, gtk_label_get_extra_menu (label));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1326,6 +1330,8 @@ gtk_label_init (GtkLabel *label)
priv->mnemonic_window = NULL;
priv->mnemonics_visible = TRUE;
+
+ gtk_label_add_context_actions (label);
}
@@ -3199,6 +3205,10 @@ gtk_label_finalize (GObject *object)
gtk_label_clear_links (label);
g_free (priv->select_info);
+ g_clear_object (&priv->context_actions);
+ g_clear_pointer (&priv->popup_menu, gtk_widget_unparent);
+ g_clear_object (&priv->extra_menu);
+
G_OBJECT_CLASS (gtk_label_parent_class)->finalize (object);
}
@@ -3681,6 +3691,9 @@ gtk_label_size_allocate (GtkWidget *widget,
else
pango_layout_set_width (priv->layout, -1);
}
+
+ if (priv->popup_menu)
+ gtk_native_check_resize (GTK_NATIVE (priv->popup_menu));
}
static void
@@ -4115,24 +4128,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,
@@ -4471,7 +4466,7 @@ gtk_label_click_gesture_pressed (GtkGestureClick *gesture,
{
info->link_clicked = 1;
update_link_state (label);
- gtk_label_do_popup (label, event);
+ gtk_label_do_popup (label, widget_x, widget_y);
return;
}
else if (button == GDK_BUTTON_PRIMARY)
@@ -4494,7 +4489,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_label_do_popup (label, widget_x, widget_y);
else if (button == GDK_BUTTON_PRIMARY)
{
if (!gtk_widget_has_focus (widget))
@@ -5972,167 +5967,220 @@ gtk_label_select_all (GtkLabel *label)
gtk_label_select_region_index (label, 0, strlen (priv->text));
}
-/* Quick hack of a popup menu
- */
static void
-activate_cb (GtkWidget *menuitem,
- GtkLabel *label)
+open_link_activated (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
- const gchar *signal = g_object_get_qdata (G_OBJECT (menuitem), quark_gtk_signal);
- g_signal_emit_by_name (label, signal);
+ GtkLabel *label = GTK_LABEL (user_data);
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+ GtkLabelLink *link = priv->select_info->context_link;
+
+ if (link)
+ emit_activate_link (label, link);
}
static void
-append_action_signal (GtkLabel *label,
- GtkWidget *menu,
- const gchar *text,
- const gchar *signal,
- gboolean sensitive)
+copy_link_activated (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
- GtkWidget *menuitem = gtk_menu_item_new_with_mnemonic (text);
+ GtkLabel *label = GTK_LABEL (user_data);
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+ GtkLabelLink *link = priv->select_info->context_link;
- g_object_set_qdata (G_OBJECT (menuitem), quark_gtk_signal, (char *)signal);
- g_signal_connect (menuitem, "activate",
- G_CALLBACK (activate_cb), label);
+ if (link)
+ {
+ GdkClipboard *clipboard;
- gtk_widget_set_sensitive (menuitem, sensitive);
-
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (label));
+ gdk_clipboard_set_text (clipboard, link->uri);
+ }
+}
+
+static void
+copy_clipboard_activated (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ g_signal_emit_by_name (user_data, "copy-clipboard");
+}
+
+static void
+select_all_activated (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ gtk_label_select_all (GTK_LABEL (user_data));
}
static void
-popup_menu_detach (GtkWidget *attach_widget,
- GtkMenu *menu)
+gtk_label_update_clipboard_actions (GtkLabel *label)
{
- GtkLabel *label = GTK_LABEL (attach_widget);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+ gboolean have_selection = FALSE;
+ GAction *action;
if (priv->select_info)
- priv->select_info->popup_menu = NULL;
+ have_selection = priv->select_info->selection_anchor != priv->select_info->selection_end;
+
+ action = g_action_map_lookup_action (priv->context_actions, "copy-clipboard");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), have_selection);
+ action = g_action_map_lookup_action (priv->context_actions, "select-all");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), gtk_label_get_selectable (label));
}
static void
-open_link_activate_cb (GtkMenuItem *menuitem,
- GtkLabel *label)
+gtk_label_update_link_actions (GtkLabel *label)
{
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+ gboolean have_selection = FALSE;
+ GAction *action;
GtkLabelLink *link;
- link = g_object_get_qdata (G_OBJECT (menuitem), quark_link);
- emit_activate_link (label, 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
-copy_link_activate_cb (GtkMenuItem *menuitem,
- GtkLabel *label)
+gtk_label_add_context_actions (GtkLabel *label)
{
- GtkLabelLink *link;
- GdkClipboard *clipboard;
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+
+ GActionEntry entries[] = {
+ { "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 ();
+ GAction *action;
+
+ priv->context_actions = G_ACTION_MAP (actions);
+
+ g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), label);
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "cut-clipboard");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "copy-clipboard");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "paste-clipboard");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "delete-selection");
+ 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);
- link = g_object_get_qdata (G_OBJECT (menuitem), quark_link);
- clipboard = gtk_widget_get_clipboard (GTK_WIDGET (label));
- gdk_clipboard_set_text (clipboard, link->uri);
+ gtk_widget_insert_action_group (GTK_WIDGET (label), "context", G_ACTION_GROUP (actions));
}
-static gboolean
-gtk_label_popup_menu (GtkWidget *widget)
+static GMenuModel *
+gtk_label_get_menu_model (GtkLabel *label)
{
- gtk_label_do_popup (GTK_LABEL (widget), NULL);
-
- return TRUE;
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+ GMenu *menu, *section;
+ GMenuItem *item;
+
+ menu = g_menu_new ();
+
+ section = g_menu_new ();
+ g_menu_append (section, _("Cu_t"), "context.cut-clipboard");
+ g_menu_append (section, _("_Copy"), "context.copy-clipboard");
+ g_menu_append (section, _("_Paste"), "context.paste-clipboard");
+ g_menu_append (section, _("_Delete"), "context.delete-selection");
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
+ g_object_unref (section);
+
+ section = g_menu_new ();
+ g_menu_append (section, _("Select _All"), "context.select-all");
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
+ g_object_unref (section);
+
+ section = g_menu_new ();
+ item = g_menu_item_new (_("_Open Link"), "context.open-link");
+ 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, "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);
+
+ if (priv->extra_menu)
+ g_menu_append_section (menu, NULL, priv->extra_menu);
+
+ return G_MENU_MODEL (menu);
}
static void
-gtk_label_do_popup (GtkLabel *label,
- const GdkEvent *event)
+gtk_label_do_popup (GtkLabel *label,
+ double x,
+ double y)
{
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
- GtkWidget *menuitem;
- GtkWidget *menu;
- gboolean have_selection;
- GtkLabelLink *link;
- if (!priv->select_info)
- return;
+ 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);
-
- priv->select_info->popup_menu = menu = gtk_menu_new ();
- gtk_style_context_add_class (gtk_widget_get_style_context (menu),
- GTK_STYLE_CLASS_CONTEXT_MENU);
+ if (!priv->popup_menu)
+ {
+ GMenuModel *model;
- gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (label), popup_menu_detach);
+ model = gtk_label_get_menu_model (label);
+ priv->popup_menu = gtk_popover_menu_new_from_model (GTK_WIDGET (label), model);
+ gtk_popover_set_position (GTK_POPOVER (priv->popup_menu), GTK_POS_BOTTOM);
- have_selection =
- priv->select_info->selection_anchor != priv->select_info->selection_end;
+ gtk_popover_set_has_arrow (GTK_POPOVER (priv->popup_menu), FALSE);
+ gtk_widget_set_halign (priv->popup_menu, GTK_ALIGN_START);
- if (event)
- {
- if (priv->select_info->link_clicked)
- link = priv->select_info->active_link;
- else
- link = NULL;
+ g_object_unref (model);
}
- else
- link = gtk_label_get_focus_link (label);
- if (!have_selection && link)
+ if (x != -1 && y != -1)
{
- /* Open Link */
- menuitem = gtk_menu_item_new_with_mnemonic (_("_Open Link"));
- g_object_set_qdata (G_OBJECT (menuitem), quark_link, link);
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-
- g_signal_connect (G_OBJECT (menuitem), "activate",
- G_CALLBACK (open_link_activate_cb), label);
-
- /* Copy Link Address */
- menuitem = gtk_menu_item_new_with_mnemonic (_("Copy _Link Address"));
- g_object_set_qdata (G_OBJECT (menuitem), quark_link, link);
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-
- g_signal_connect (G_OBJECT (menuitem), "activate",
- G_CALLBACK (copy_link_activate_cb), label);
+ GdkRectangle rect = { x, y, 1, 1 };
+ gtk_popover_set_pointing_to (GTK_POPOVER (priv->popup_menu), &rect);
}
else
- {
- append_action_signal (label, menu, _("Cu_t"), "cut-clipboard", FALSE);
- append_action_signal (label, menu, _("_Copy"), "copy-clipboard", have_selection);
- append_action_signal (label, menu, _("_Paste"), "paste-clipboard", FALSE);
-
- menuitem = gtk_menu_item_new_with_mnemonic (_("_Delete"));
- gtk_widget_set_sensitive (menuitem, FALSE);
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-
- menuitem = gtk_separator_menu_item_new ();
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-
- menuitem = gtk_menu_item_new_with_mnemonic (_("Select _All"));
- g_signal_connect_swapped (menuitem, "activate",
- G_CALLBACK (gtk_label_select_all), label);
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
- }
+ gtk_popover_set_pointing_to (GTK_POPOVER (priv->popup_menu), NULL);
+
+ gtk_popover_popup (GTK_POPOVER (priv->popup_menu));
+}
+
+static gboolean
+gtk_label_popup_menu (GtkWidget *widget)
+{
+ GtkLabel *label = GTK_LABEL (widget);
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
- g_signal_emit (label, signals[POPULATE_POPUP], 0, menu);
+ if (!priv->select_info)
+ return FALSE;
- 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);
- }
+ gtk_label_do_popup (label, -1, -1);
+ return TRUE;
}
static void
@@ -6646,3 +6694,44 @@ gtk_label_get_yalign (GtkLabel *label)
return priv->yalign;
}
+
+/**
+ * gtk_label_set_extra_menu:
+ * @label: a #GtkLabel
+ * @model: (allow-none): a #GMenuModel
+ *
+ * Sets a menu model to add when constructing
+ * the context menu for @label.
+ */
+void
+gtk_label_set_extra_menu (GtkLabel *label,
+ GMenuModel *model)
+{
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+
+ g_return_if_fail (GTK_IS_LABEL (label));
+
+ if (g_set_object (&priv->extra_menu, model))
+ {
+ g_clear_pointer (&priv->popup_menu, gtk_widget_unparent);
+ g_object_notify_by_pspec (G_OBJECT (label), label_props[PROP_EXTRA_MENU]);
+ }
+}
+
+/**
+ * gtk_label_get_extra_menu:
+ * @label: a #GtkLabel
+ *
+ * Gets the menu model set with gtk_label_set_extra_menu().
+ *
+ * Returns: (transfer none): (nullable): the menu model
+ */
+GMenuModel *
+gtk_label_get_extra_menu (GtkLabel *label)
+{
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+
+ g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
+
+ return priv->extra_menu;
+}
diff --git a/gtk/gtklabel.h b/gtk/gtklabel.h
index 6ccc389b73..c2b8bfe8e4 100644
--- a/gtk/gtklabel.h
+++ b/gtk/gtklabel.h
@@ -176,6 +176,13 @@ void gtk_label_set_yalign (GtkLabel *label,
GDK_AVAILABLE_IN_ALL
gfloat gtk_label_get_yalign (GtkLabel *label);
+GDK_AVAILABLE_IN_ALL
+void gtk_label_set_extra_menu (GtkLabel *label,
+ GMenuModel *model);
+GDK_AVAILABLE_IN_ALL
+GMenuModel * gtk_label_get_extra_menu (GtkLabel *label);
+
+
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkLabel, g_object_unref)
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]