[gtk/wip/matthiasc/context-menu: 14/23] label: Redo context menus



commit 2a94d9447c463300775442628003d1ccc2178ca6
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 |   2 +
 gtk/gtklabel.c                       | 379 ++++++++++++++++++++---------------
 gtk/gtklabel.h                       |   4 +
 3 files changed, 220 insertions(+), 165 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 191500511c..55e132e5f9 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -1716,6 +1716,8 @@ 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_add_to_context_menu
+
 <SUBSECTION Standard>
 GTK_LABEL
 GTK_IS_LABEL
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index ffc6d05e6e..ece8ba7392 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
@@ -444,7 +446,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 +484,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 +540,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 +574,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 +586,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 +637,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 +707,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
@@ -1326,6 +1310,8 @@ gtk_label_init (GtkLabel *label)
   priv->mnemonic_window = NULL;
 
   priv->mnemonics_visible = TRUE;
+
+  gtk_label_add_context_actions (label);
 }
 
 
@@ -3199,6 +3185,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 +3671,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 +4108,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 +4446,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 +4469,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 +5947,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);
 
-  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);
+  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);
+
+  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;
 
-  if (priv->select_info->popup_menu)
-    gtk_widget_destroy (priv->select_info->popup_menu);
+  gtk_label_update_clipboard_actions (label);
+  gtk_label_update_link_actions (label);
 
-  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 +6674,24 @@ gtk_label_get_yalign (GtkLabel *label)
 
   return priv->yalign;
 }
+
+/**
+ * gtk_label_add_to_context_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_add_to_context_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);
+}
+
diff --git a/gtk/gtklabel.h b/gtk/gtklabel.h
index 6ccc389b73..32cf85983f 100644
--- a/gtk/gtklabel.h
+++ b/gtk/gtklabel.h
@@ -176,6 +176,10 @@ void         gtk_label_set_yalign (GtkLabel *label,
 GDK_AVAILABLE_IN_ALL
 gfloat       gtk_label_get_yalign (GtkLabel *label);
 
+void gtk_label_add_to_context_menu (GtkLabel   *label,
+                                    GMenuModel *model);
+
+
 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]