[gtk/keymap-rework-2: 1/34] Add gdk_event_matches



commit e8330c5eec5067d760973bd2628660771c95f142
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Apr 4 17:51:32 2020 -0400

    Add gdk_event_matches
    
    Move the elaborate key event matching code from
    GtkShortcutTrigger to GdkEvent, which greatly reduces
    the amount of keymap api use outside of GDK.

 docs/reference/gtk/gtk4-sections.txt |   1 -
 gdk/gdkevents.c                      | 156 +++++++++++++++++++++++++++++++++++
 gdk/gdkevents.h                      |  11 +++
 gtk/gtkshortcutcontroller.c          |   6 +-
 gtk/gtkshortcuttrigger.c             | 123 +++------------------------
 gtk/gtkshortcuttrigger.h             |  21 +----
 testsuite/gtk/shortcuts.c            |  14 ++--
 7 files changed, 191 insertions(+), 141 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index e944c9256f..9b085828f1 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -5960,7 +5960,6 @@ gtk_event_controller_motion_get_type
 GtkShortcutTrigger
 GtkNeverTrigger
 
-GtkShortcutTriggerMatch
 gtk_shortcut_trigger_trigger
 gtk_shortcut_trigger_hash
 gtk_shortcut_trigger_equal
diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
index 097198ef29..1d53d9c30b 100644
--- a/gdk/gdkevents.c
+++ b/gdk/gdkevents.c
@@ -2110,3 +2110,159 @@ gdk_grab_broken_event_get_grab_surface (GdkEvent *event)
 
   return event->grab_broken.grab_surface;
 }
+
+static gboolean
+translate_keyboard_accel_state (GdkKeymap       *keymap,
+                                guint            hardware_keycode,
+                                GdkModifierType  state,
+                                gint             group,
+                                guint           *keyval,
+                                gint            *effective_group,
+                                gint            *level,
+                                GdkModifierType *consumed_modifiers)
+{
+  GdkModifierType mask;
+  GdkModifierType shift_group_mask;
+  gboolean group_mask_disabled = FALSE;
+  gboolean retval;
+
+  mask = gdk_keymap_get_modifier_mask (keymap,
+                                       GDK_MODIFIER_INTENT_DEFAULT_MOD_MASK);
+
+  /* if the group-toggling modifier is part of the accel mod mask, and
+   * it is active, disable it for matching
+   */
+  shift_group_mask = gdk_keymap_get_modifier_mask (keymap,
+                                                   GDK_MODIFIER_INTENT_SHIFT_GROUP);
+  if (mask & state & shift_group_mask)
+    {
+      state &= ~shift_group_mask;
+      group = 0;
+      group_mask_disabled = TRUE;
+    }
+
+  retval = gdk_keymap_translate_keyboard_state (keymap,
+                                                hardware_keycode, state, group,
+                                                keyval,
+                                                effective_group, level,
+                                                consumed_modifiers);
+
+  /* add back the group mask, we want to match against the modifier,
+   * but not against the keyval from its group
+   */
+  if (group_mask_disabled)
+    {
+      if (effective_group)
+        *effective_group = 1;
+
+      if (consumed_modifiers)
+        *consumed_modifiers &= ~shift_group_mask;
+    }
+
+  return retval;
+}
+
+
+GdkEventMatch
+gdk_event_matches (GdkEvent        *event,
+                   guint            match_keyval,
+                   GdkModifierType  match_modifiers)
+{
+  guint keycode;
+  GdkModifierType state;
+  GdkModifierType mask;
+  int group;
+  GdkKeymap *keymap;
+  guint keyval;
+  int effective_group;
+  int level;
+  GdkModifierType consumed_modifiers;
+  GdkModifierType shift_group_mask;
+  gboolean group_mod_is_accel_mod = FALSE;
+  const GdkModifierType xmods = GDK_MOD2_MASK|GDK_MOD3_MASK|GDK_MOD4_MASK|GDK_MOD5_MASK;
+  const GdkModifierType vmods = GDK_SUPER_MASK|GDK_HYPER_MASK|GDK_META_MASK;
+  GdkModifierType modifiers;
+
+  if (gdk_event_get_event_type (event) != GDK_KEY_PRESS)
+    return GDK_EVENT_MATCH_NONE;
+
+  keycode = gdk_key_event_get_keycode (event);
+  state = gdk_event_get_modifier_state (event);
+  group = gdk_key_event_get_group (event);
+  keymap = gdk_display_get_keymap (gdk_event_get_display (event));
+
+  mask = gdk_keymap_get_modifier_mask (keymap,
+                                       GDK_MODIFIER_INTENT_DEFAULT_MOD_MASK);
+
+  /* We don't want Caps_Lock to affect keybinding lookups.
+   */
+  state &= ~GDK_LOCK_MASK;
+
+  translate_keyboard_accel_state (keymap,
+                                  keycode, state, group,
+                                  &keyval,
+                                  &effective_group, &level,
+                                  &consumed_modifiers);
+
+  /* if the group-toggling modifier is part of the default accel mod
+   * mask, and it is active, disable it for matching
+   */
+  shift_group_mask = gdk_keymap_get_modifier_mask (keymap,
+                                                   GDK_MODIFIER_INTENT_SHIFT_GROUP);
+  if (mask & shift_group_mask)
+    group_mod_is_accel_mod = TRUE;
+
+  gdk_keymap_map_virtual_modifiers (keymap, &mask);
+  gdk_keymap_add_virtual_modifiers (keymap, &state);
+
+  modifiers = match_modifiers;
+  if (gdk_keymap_map_virtual_modifiers (keymap, &modifiers) &&
+      ((modifiers & ~consumed_modifiers & mask & ~vmods) == (state & ~consumed_modifiers & mask & ~vmods) ||
+       (modifiers & ~consumed_modifiers & mask & ~xmods) == (state & ~consumed_modifiers & mask & ~xmods)))
+    {
+      /* modifier match */
+      GdkKeymapKey *keys;
+      int n_keys;
+      int i;
+      guint key;
+
+      /* Shift gets consumed and applied for the event,
+       * so apply it to our keyval to match
+       */
+      key = match_keyval;
+      if (match_modifiers & GDK_SHIFT_MASK)
+        {
+          if (key == GDK_KEY_Tab)
+            key = GDK_KEY_ISO_Left_Tab;
+          else
+            key = gdk_keyval_to_upper (key);
+        }
+
+      if (keyval == key && /* exact match */
+          (!group_mod_is_accel_mod ||
+           (state & shift_group_mask) == (match_modifiers & shift_group_mask)))
+        return GDK_EVENT_MATCH_EXACT;
+
+      gdk_keymap_get_entries_for_keyval (keymap, match_keyval, &keys, &n_keys);
+
+      for (i = 0; i < n_keys; i++)
+        {
+          if (keys[i].keycode == keycode &&
+              keys[i].level == level &&
+              /* Only match for group if it's an accel mod */
+              (!group_mod_is_accel_mod ||
+               keys[i].group == effective_group))
+            {
+              /* partial match */
+              g_free (keys);
+
+              return GDK_EVENT_MATCH_PARTIAL;
+            }
+        }
+
+      g_free (keys);
+    }
+
+
+  return GDK_EVENT_MATCH_NONE;
+}
diff --git a/gdk/gdkevents.h b/gdk/gdkevents.h
index 888ca9e5c5..944047d946 100644
--- a/gdk/gdkevents.h
+++ b/gdk/gdkevents.h
@@ -428,6 +428,17 @@ gboolean                gdk_events_get_center           (GdkEvent *event1,
                                                          double   *x,
                                                          double   *y);
 
+typedef enum {
+  GDK_EVENT_MATCH_NONE,
+  GDK_EVENT_MATCH_PARTIAL,
+  GDK_EVENT_MATCH_EXACT
+} GdkEventMatch;
+
+GDK_AVAILABLE_IN_ALL
+GdkEventMatch          gdk_event_matches (GdkEvent        *event,
+                                          guint            keyval,
+                                          GdkModifierType  modifiers);
+
 G_END_DECLS
 
 #endif /* __GDK_EVENTS_H__ */
diff --git a/gtk/gtkshortcutcontroller.c b/gtk/gtkshortcutcontroller.c
index 8fa081f977..9a817ac286 100644
--- a/gtk/gtkshortcutcontroller.c
+++ b/gtk/gtkshortcutcontroller.c
@@ -313,16 +313,16 @@ gtk_shortcut_controller_run_controllers (GtkEventController *controller,
 
       switch (gtk_shortcut_trigger_trigger (gtk_shortcut_get_trigger (shortcut), event, enable_mnemonics))
         {
-        case GTK_SHORTCUT_TRIGGER_MATCH_PARTIAL:
+        case GDK_EVENT_MATCH_PARTIAL:
           if (!has_exact)
             break;
           G_GNUC_FALLTHROUGH;
 
-        case GTK_SHORTCUT_TRIGGER_MATCH_NONE:
+        case GDK_EVENT_MATCH_NONE:
           g_object_unref (shortcut);
           continue;
 
-        case GTK_SHORTCUT_TRIGGER_MATCH_EXACT:
+        case GDK_EVENT_MATCH_EXACT:
           if (!has_exact)
             {
               g_slist_free_full (shortcuts, shortcut_data_free);
diff --git a/gtk/gtkshortcuttrigger.c b/gtk/gtkshortcuttrigger.c
index 722a41fafd..ad58a14c80 100644
--- a/gtk/gtkshortcuttrigger.c
+++ b/gtk/gtkshortcuttrigger.c
@@ -59,8 +59,7 @@ struct _GtkShortcutTriggerClass
 {
   GObjectClass parent_class;
 
-  GtkShortcutTriggerMatch
-                  (* trigger)     (GtkShortcutTrigger  *trigger,
+  GdkEventMatch   (* trigger)     (GtkShortcutTrigger  *trigger,
                                    GdkEvent            *event,
                                    gboolean             enable_mnemonics);
   guint           (* hash)        (GtkShortcutTrigger  *trigger);
@@ -97,12 +96,12 @@ gtk_shortcut_trigger_init (GtkShortcutTrigger *self)
  *
  * Returns: Whether the event triggered the shortcut
  **/
-GtkShortcutTriggerMatch
+GdkEventMatch
 gtk_shortcut_trigger_trigger (GtkShortcutTrigger *self,
                               GdkEvent           *event,
                               gboolean            enable_mnemonics)
 {
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (self), GTK_SHORTCUT_TRIGGER_MATCH_NONE);
+  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (self), GDK_EVENT_MATCH_NONE);
 
   return GTK_SHORTCUT_TRIGGER_GET_CLASS (self)->trigger (self, event, enable_mnemonics);
 }
@@ -410,12 +409,12 @@ gtk_never_trigger_finalize (GObject *gobject)
   G_OBJECT_CLASS (gtk_never_trigger_parent_class)->finalize (gobject);
 }
 
-static GtkShortcutTriggerMatch
+static GdkEventMatch
 gtk_never_trigger_trigger (GtkShortcutTrigger *trigger,
                            GdkEvent           *event,
                            gboolean            enable_mnemonics)
 {
-  return GTK_SHORTCUT_TRIGGER_MATCH_NONE;
+  return GDK_EVENT_MATCH_NONE;
 }
 
 static guint
@@ -510,110 +509,14 @@ enum
 
 static GParamSpec *keyval_props[KEYVAL_N_PROPS];
 
-static GtkShortcutTriggerMatch
+static GdkEventMatch
 gtk_keyval_trigger_trigger (GtkShortcutTrigger *trigger,
                             GdkEvent           *event,
                             gboolean            enable_mnemonics)
 {
   GtkKeyvalTrigger *self = GTK_KEYVAL_TRIGGER (trigger);
-  guint keycode;
-  GdkModifierType state;
-  GdkModifierType mask;
-  int group;
-  GdkKeymap *keymap;
-  guint keyval;
-  int effective_group;
-  int level;
-  GdkModifierType consumed_modifiers;
-  GdkModifierType shift_group_mask;
-  gboolean group_mod_is_accel_mod = FALSE;
-  const GdkModifierType xmods = GDK_MOD2_MASK|GDK_MOD3_MASK|GDK_MOD4_MASK|GDK_MOD5_MASK;
-  const GdkModifierType vmods = GDK_SUPER_MASK|GDK_HYPER_MASK|GDK_META_MASK;
-  GdkModifierType modifiers;
-
-  if (gdk_event_get_event_type (event) != GDK_KEY_PRESS)
-    return GTK_SHORTCUT_TRIGGER_MATCH_NONE;
-
-  mask = gtk_accelerator_get_default_mod_mask ();
-
-  keycode = gdk_key_event_get_keycode (event);
-  state = gdk_event_get_modifier_state (event);
-  group = gdk_key_event_get_group (event);
-  keymap = gdk_display_get_keymap (gdk_event_get_display (event));
-
-  /* We don't want Caps_Lock to affect keybinding lookups.
-   */
-  state &= ~GDK_LOCK_MASK;
-
-  _gtk_translate_keyboard_accel_state (keymap,
-                                       keycode, state, mask, group,
-                                       &keyval,
-                                       &effective_group, &level,
-                                       &consumed_modifiers);
-
-  /* if the group-toggling modifier is part of the default accel mod
-   * mask, and it is active, disable it for matching
-   */
-  shift_group_mask = gdk_keymap_get_modifier_mask (keymap,
-                                                   GDK_MODIFIER_INTENT_SHIFT_GROUP);
-  if (mask & shift_group_mask)
-    group_mod_is_accel_mod = TRUE;
-
-  gdk_keymap_map_virtual_modifiers (keymap, &mask);
-  gdk_keymap_add_virtual_modifiers (keymap, &state);
-
-  modifiers = self->modifiers;
-  if (gdk_keymap_map_virtual_modifiers (keymap, &modifiers) &&
-      ((modifiers & ~consumed_modifiers & mask & ~vmods) == (state & ~consumed_modifiers & mask & ~vmods) ||
-       (modifiers & ~consumed_modifiers & mask & ~xmods) == (state & ~consumed_modifiers & mask & ~xmods)))
-    {
-      /* modifier match */
-      GdkKeymapKey *keys;
-      int n_keys;
-      int i;
-      guint key;
-
-      /* Shift gets consumed and applied for the event,
-       * so apply it to our keyval to match
-       */
-      key = self->keyval;
-      if (self->modifiers & GDK_SHIFT_MASK)
-        {
-          if (key == GDK_KEY_Tab)
-            key = GDK_KEY_ISO_Left_Tab;
-          else
-            key = gdk_keyval_to_upper (key);
-        }
-
-      if (keyval == key && /* exact match */
-          (!group_mod_is_accel_mod ||
-           (state & shift_group_mask) == (self->modifiers & shift_group_mask)))
-        return GTK_SHORTCUT_TRIGGER_MATCH_EXACT;
-
-      gdk_keymap_get_entries_for_keyval (keymap,
-                                         self->keyval,
-                                         &keys, &n_keys);
-
-      for (i = 0; i < n_keys; i++)
-        {
-          if (keys[i].keycode == keycode &&
-              keys[i].level == level &&
-              /* Only match for group if it's an accel mod */
-              (!group_mod_is_accel_mod ||
-               keys[i].group == effective_group))
-            {
-              /* partial match */
-              g_free (keys);
-
-              return GTK_SHORTCUT_TRIGGER_MATCH_PARTIAL;
-            }
-        }
- 
-      g_free (keys);
-    }
-
 
-  return GTK_SHORTCUT_TRIGGER_MATCH_NONE;
+  return gdk_event_matches (event, self->keyval, self->modifiers);
 }
 
 static guint
@@ -849,7 +752,7 @@ enum
 
 static GParamSpec *mnemonic_props[MNEMONIC_N_PROPS];
 
-static GtkShortcutTriggerMatch
+static GdkEventMatch
 gtk_mnemonic_trigger_trigger (GtkShortcutTrigger *trigger,
                               GdkEvent           *event,
                               gboolean            enable_mnemonics)
@@ -858,10 +761,10 @@ gtk_mnemonic_trigger_trigger (GtkShortcutTrigger *trigger,
   guint keyval;
 
   if (!enable_mnemonics)
-    return GTK_SHORTCUT_TRIGGER_MATCH_NONE;
+    return GDK_EVENT_MATCH_NONE;
 
   if (gdk_event_get_event_type (event) != GDK_KEY_PRESS)
-    return GTK_SHORTCUT_TRIGGER_MATCH_NONE;
+    return GDK_EVENT_MATCH_NONE;
 
   /* XXX: This needs to deal with groups */
   keyval = gdk_key_event_get_keyval (event);
@@ -872,9 +775,9 @@ gtk_mnemonic_trigger_trigger (GtkShortcutTrigger *trigger,
     keyval = gdk_keyval_to_lower (keyval);
 
   if (keyval != self->keyval)
-    return GTK_SHORTCUT_TRIGGER_MATCH_NONE;
+    return GDK_EVENT_MATCH_NONE;
 
-  return GTK_SHORTCUT_TRIGGER_MATCH_EXACT;
+  return GDK_EVENT_MATCH_EXACT;
 }
 
 static guint
@@ -1085,7 +988,7 @@ gtk_alternative_trigger_dispose (GObject *gobject)
   G_OBJECT_CLASS (gtk_alternative_trigger_parent_class)->dispose (gobject);
 }
 
-static GtkShortcutTriggerMatch
+static GdkEventMatch
 gtk_alternative_trigger_trigger (GtkShortcutTrigger *trigger,
                                  GdkEvent           *event,
                                  gboolean            enable_mnemonics)
diff --git a/gtk/gtkshortcuttrigger.h b/gtk/gtkshortcuttrigger.h
index eba7bde4f4..36f092339d 100644
--- a/gtk/gtkshortcuttrigger.h
+++ b/gtk/gtkshortcuttrigger.h
@@ -36,25 +36,6 @@ G_BEGIN_DECLS
  * A trigger for a key shortcut.
  */
 
-/**
- * GtkShortcutTriggerMatch:
- * @GTK_SHORTCUT_TRIGGER_MATCH_NONE: The key event does not
- *     match the trigger
- * @GTK_SHORTCUT_TRIGGER_MATCH_PARTIAL: The key event matches
- *     the trigger if keyboard state (specifically, the currently
- *     active group) is ignored
- * @GTK_SHORTCUT_TRIGGER_MATCH_EXACT: The key event matches
- *     the trigger
- *
- * The possible return values from gtk_shortcut_trigger_trigger()
- * describe if a key event triggers a shortcut.
- */
-typedef enum {
-  GTK_SHORTCUT_TRIGGER_MATCH_NONE,
-  GTK_SHORTCUT_TRIGGER_MATCH_PARTIAL,
-  GTK_SHORTCUT_TRIGGER_MATCH_EXACT,
-} GtkShortcutTriggerMatch;
-
 GDK_AVAILABLE_IN_ALL
 GDK_DECLARE_INTERNAL_TYPE (GtkShortcutTrigger, gtk_shortcut_trigger, GTK, SHORTCUT_TRIGGER, GObject)
 
@@ -84,7 +65,7 @@ gint                    gtk_shortcut_trigger_compare            (gconstpointer
                                                                  gconstpointer       trigger2);
 
 GDK_AVAILABLE_IN_ALL
-GtkShortcutTriggerMatch gtk_shortcut_trigger_trigger            (GtkShortcutTrigger *self,
+GdkEventMatch           gtk_shortcut_trigger_trigger            (GtkShortcutTrigger *self,
                                                                  GdkEvent           *event,
                                                                  gboolean            enable_mnemonics);
 
diff --git a/testsuite/gtk/shortcuts.c b/testsuite/gtk/shortcuts.c
index 916a8f0424..174d3aba87 100644
--- a/testsuite/gtk/shortcuts.c
+++ b/testsuite/gtk/shortcuts.c
@@ -340,14 +340,14 @@ test_trigger_trigger (void)
     guint keyval;
     GdkModifierType state;
     gboolean mnemonic;
-    GtkShortcutTriggerMatch result[4];
+    GdkEventMatch result[4];
   } tests[] = {
-    { GDK_KEY_a, GDK_CONTROL_MASK, FALSE, { GTK_SHORTCUT_TRIGGER_MATCH_NONE, 
GTK_SHORTCUT_TRIGGER_MATCH_EXACT, GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_EXACT } }, 
-    { GDK_KEY_a, GDK_CONTROL_MASK, TRUE,  { GTK_SHORTCUT_TRIGGER_MATCH_NONE, 
GTK_SHORTCUT_TRIGGER_MATCH_EXACT, GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_EXACT } }, 
-    { GDK_KEY_a, GDK_SHIFT_MASK,   FALSE, { GTK_SHORTCUT_TRIGGER_MATCH_NONE, 
GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE } }, 
-    { GDK_KEY_a, GDK_SHIFT_MASK,   TRUE,  { GTK_SHORTCUT_TRIGGER_MATCH_NONE, 
GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE } }, 
-    { GDK_KEY_u, GDK_SHIFT_MASK,   FALSE, { GTK_SHORTCUT_TRIGGER_MATCH_NONE, 
GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE } }, 
-    { GDK_KEY_u, GDK_SHIFT_MASK,   TRUE,  { GTK_SHORTCUT_TRIGGER_MATCH_NONE, 
GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_EXACT, GTK_SHORTCUT_TRIGGER_MATCH_EXACT } }, 
+    { GDK_KEY_a, GDK_CONTROL_MASK, FALSE, { GDK_EVENT_MATCH_NONE, GDK_EVENT_MATCH_EXACT, 
GDK_EVENT_MATCH_NONE, GDK_EVENT_MATCH_EXACT } }, 
+    { GDK_KEY_a, GDK_CONTROL_MASK, TRUE,  { GDK_EVENT_MATCH_NONE, GDK_EVENT_MATCH_EXACT, 
GDK_EVENT_MATCH_NONE, GDK_EVENT_MATCH_EXACT } }, 
+    { GDK_KEY_a, GDK_SHIFT_MASK,   FALSE, { GDK_EVENT_MATCH_NONE, GDK_EVENT_MATCH_NONE, 
GDK_EVENT_MATCH_NONE, GDK_EVENT_MATCH_NONE } }, 
+    { GDK_KEY_a, GDK_SHIFT_MASK,   TRUE,  { GDK_EVENT_MATCH_NONE, GDK_EVENT_MATCH_NONE, 
GDK_EVENT_MATCH_NONE, GDK_EVENT_MATCH_NONE } }, 
+    { GDK_KEY_u, GDK_SHIFT_MASK,   FALSE, { GDK_EVENT_MATCH_NONE, GDK_EVENT_MATCH_NONE, 
GDK_EVENT_MATCH_NONE, GDK_EVENT_MATCH_NONE } }, 
+    { GDK_KEY_u, GDK_SHIFT_MASK,   TRUE,  { GDK_EVENT_MATCH_NONE, GDK_EVENT_MATCH_NONE, 
GDK_EVENT_MATCH_EXACT, GDK_EVENT_MATCH_EXACT } }, 
   };
   int i, j;
 


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