[gimp] app, libgimpwidgets: new gimp_event_triggers_context_menu() and use it…



commit 4b681eb44839e734b426d1f06f105a18cdd8808a
Author: Jehan <jehan girinstud io>
Date:   Sat Jun 19 00:31:40 2021 +0200

    app, libgimpwidgets: new gimp_event_triggers_context_menu() and use it…
    
    … for the container tree view contextual menu.
    
    A very annoying point of contextual menus is that they happen on button
    press whereas menu item selection happens on button release. When the
    menu corner is positionned on the click position, nothing bad happens;
    yet when place is missing on screen, the menu might get positionned over
    the pointer position. And worse, the mouse position might be just over
    an activatable menu item. So we end up in this weird situation where a
    click implies: press, menu opens, release, random item (whatever is
    below the pointer) is selected and menu closes.
    
    To get rid of this weird case, let's have our contextual menu happen on
    button release. In reality, I don't think anyone cares that it happens
    on press or release, you just "click". But what you certainly don't want
    is to click random menu items!

 app/widgets/gimpcontainertreeview.c |  2 +-
 libgimpwidgets/gimpwidgetsutils.c   | 48 +++++++++++++++++++++++++++++++++++++
 libgimpwidgets/gimpwidgetsutils.h   |  3 +++
 3 files changed, 52 insertions(+), 1 deletion(-)
---
diff --git a/app/widgets/gimpcontainertreeview.c b/app/widgets/gimpcontainertreeview.c
index 6177aa0621..9f993d2483 100644
--- a/app/widgets/gimpcontainertreeview.c
+++ b/app/widgets/gimpcontainertreeview.c
@@ -1486,7 +1486,7 @@ gimp_container_tree_view_button (GtkWidget             *widget,
 
       g_object_ref (tree_view);
 
-      if (gdk_event_triggers_context_menu ((GdkEvent *) bevent))
+      if (gimp_event_triggers_context_menu ((GdkEvent *) bevent, TRUE))
         {
           /* If the clicked item is not selected, it becomes the new
            * selection. Otherwise, we use the current selection. This
diff --git a/libgimpwidgets/gimpwidgetsutils.c b/libgimpwidgets/gimpwidgetsutils.c
index 654afd2ddd..4c46e83d04 100644
--- a/libgimpwidgets/gimpwidgetsutils.c
+++ b/libgimpwidgets/gimpwidgetsutils.c
@@ -108,6 +108,54 @@ find_mnemonic_widget (GtkWidget *widget,
   return NULL;
 }
 
+/**
+ * gimp_event_triggers_context_menu:
+ * @event:      The #GdkEvent to verify.
+ * @on_release: Whether a menu is triggered on a button release event
+ *              instead of a press event.
+ *
+ * Alternative of gdk_event_triggers_context_menu() with the additional
+ * feature of allowing a menu triggering to happen on a button release
+ * event. All the other rules on whether @event should trigger a
+ * contextual menu are exactly the same. Only the swapping to release
+ * state as additional feature is different.
+ *
+ * Returns: %TRUE if the event should trigger a context menu.
+ *
+ * Since: 3.0
+ **/
+gboolean
+gimp_event_triggers_context_menu (const GdkEvent *event,
+                                  gboolean        on_release)
+{
+  GdkEvent *copy_event;
+  gboolean  trigger = FALSE;
+
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  copy_event = gdk_event_copy (event);
+
+  /* It's an ugly trick because GDK only considers press events as
+   * menu-triggering events. We want to use the same per-platform
+   * conventions as set in GTK/GDK, except for this small point.
+   * So when we want a menu-triggering on release events, we just
+   * temporary simulate the event to be a PRESS event and pass it to
+   * the usual function.
+   */
+  if (on_release)
+    {
+      if (event->type == GDK_BUTTON_RELEASE)
+        copy_event->type = GDK_BUTTON_PRESS;
+      else if (event->type == GDK_BUTTON_PRESS)
+        copy_event->type = GDK_BUTTON_RELEASE;
+    }
+  trigger = gdk_event_triggers_context_menu (copy_event);
+
+  gdk_event_free (copy_event);
+
+  return trigger;
+}
+
 /**
  * gimp_grid_attach_aligned:
  * @grid:       The #GtkGrid the widgets will be attached to.
diff --git a/libgimpwidgets/gimpwidgetsutils.h b/libgimpwidgets/gimpwidgetsutils.h
index d126d03ba2..b75d60808a 100644
--- a/libgimpwidgets/gimpwidgetsutils.h
+++ b/libgimpwidgets/gimpwidgetsutils.h
@@ -30,6 +30,9 @@ G_BEGIN_DECLS
 /* For information look into the C source or the html documentation */
 
 
+gboolean             gimp_event_triggers_context_menu (const GdkEvent   *event,
+                                                       gboolean          on_release);
+
 GtkWidget          * gimp_grid_attach_aligned        (GtkGrid           *grid,
                                                       gint               left,
                                                       gint               top,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]