[gtk/keymap-rework: 2/21] Add gdk_event_get_match



commit d2087a23fc4347df8b7188271d17e5875041873a
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Apr 4 20:02:20 2020 -0400

    Add gdk_event_get_match
    
    This is a counterpart to gdk_event_matches() that can
    be used to obtain a shortcut matching an event.

 docs/reference/gdk/gdk4-sections.txt |   5 ++
 gdk/gdkevents.c                      | 114 ++++++++++++++++++++++++++++++-----
 gdk/gdkevents.h                      |  15 +++++
 3 files changed, 119 insertions(+), 15 deletions(-)
---
diff --git a/docs/reference/gdk/gdk4-sections.txt b/docs/reference/gdk/gdk4-sections.txt
index fb0341f9b8..553982ca50 100644
--- a/docs/reference/gdk/gdk4-sections.txt
+++ b/docs/reference/gdk/gdk4-sections.txt
@@ -566,6 +566,11 @@ gdk_events_get_angle
 gdk_events_get_center
 gdk_events_get_distance
 
+<SUBSECTION>
+GdkEventMatch
+gdk_event_matches
+gdk_event_get_match
+
 <SUBSECTION Standard>
 GDK_TYPE_EVENT
 GDK_TYPE_EVENT_MASK
diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
index 1d53d9c30b..5ab593eefb 100644
--- a/gdk/gdkevents.c
+++ b/gdk/gdkevents.c
@@ -2162,18 +2162,30 @@ translate_keyboard_accel_state (GdkKeymap       *keymap,
   return retval;
 }
 
-
+/**
+ * gdk_event_matches:
+ * @event: the #GdkEvent
+ * @keyval: the keyval to match
+ * @modifiers: the modifiers to match
+ *
+ * Matches an event against a keyboard shortcut that is specified
+ * as a keyval and modifiers. Note that partial matches are possible
+ * where the combination matches if the currently active group is
+ * ignored.
+ *
+ * Returns: a GdkEventMatch value describing whether @event matches
+ */
 GdkEventMatch
 gdk_event_matches (GdkEvent        *event,
-                   guint            match_keyval,
-                   GdkModifierType  match_modifiers)
+                   guint            keyval,
+                   GdkModifierType  modifiers)
 {
   guint keycode;
   GdkModifierType state;
   GdkModifierType mask;
   int group;
   GdkKeymap *keymap;
-  guint keyval;
+  guint ev_keyval;
   int effective_group;
   int level;
   GdkModifierType consumed_modifiers;
@@ -2181,7 +2193,7 @@ gdk_event_matches (GdkEvent        *event,
   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;
+  GdkModifierType mods;
 
   if (gdk_event_get_event_type (event) != GDK_KEY_PRESS)
     return GDK_EVENT_MATCH_NONE;
@@ -2200,7 +2212,7 @@ gdk_event_matches (GdkEvent        *event,
 
   translate_keyboard_accel_state (keymap,
                                   keycode, state, group,
-                                  &keyval,
+                                  &ev_keyval,
                                   &effective_group, &level,
                                   &consumed_modifiers);
 
@@ -2215,10 +2227,10 @@ gdk_event_matches (GdkEvent        *event,
   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)))
+  mods = modifiers;
+  if (gdk_keymap_map_virtual_modifiers (keymap, &mods) &&
+      ((mods & ~consumed_modifiers & mask & ~vmods) == (state & ~consumed_modifiers & mask & ~vmods) ||
+       (mods & ~consumed_modifiers & mask & ~xmods) == (state & ~consumed_modifiers & mask & ~xmods)))
     {
       /* modifier match */
       GdkKeymapKey *keys;
@@ -2229,8 +2241,8 @@ gdk_event_matches (GdkEvent        *event,
       /* 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)
+      key = keyval;
+      if (modifiers & GDK_SHIFT_MASK)
         {
           if (key == GDK_KEY_Tab)
             key = GDK_KEY_ISO_Left_Tab;
@@ -2238,12 +2250,12 @@ gdk_event_matches (GdkEvent        *event,
             key = gdk_keyval_to_upper (key);
         }
 
-      if (keyval == key && /* exact match */
+      if (ev_keyval == key && /* exact match */
           (!group_mod_is_accel_mod ||
-           (state & shift_group_mask) == (match_modifiers & shift_group_mask)))
+           (state & shift_group_mask) == (modifiers & shift_group_mask)))
         return GDK_EVENT_MATCH_EXACT;
 
-      gdk_keymap_get_entries_for_keyval (keymap, match_keyval, &keys, &n_keys);
+      gdk_keymap_get_entries_for_keyval (keymap, keyval, &keys, &n_keys);
 
       for (i = 0; i < n_keys; i++)
         {
@@ -2266,3 +2278,75 @@ gdk_event_matches (GdkEvent        *event,
 
   return GDK_EVENT_MATCH_NONE;
 }
+
+/**
+ * gdk_event_get_match:
+ * @event: a #GdkEvent
+ * @keyval: (out): return location for a keyval
+ * @modifiers: (out): return location for modifiers
+ *
+ * Gets a keyval and modifier combination that will cause
+ * gdk_event_match() to successfully match the given event.
+ *
+ * Returns: %TRUE on success
+ */
+gboolean
+gdk_event_get_match (GdkEvent        *event,
+                     guint           *keyval,
+                     GdkModifierType *modifiers)
+{
+  GdkKeymap *keymap;
+  GdkModifierType mask;
+  guint keycode;
+  guint group;
+  guint key;
+  guint accel_key;
+  GdkModifierType accel_mods;
+  GdkModifierType consumed_modifiers;
+
+  if (gdk_event_get_event_type (event) != GDK_KEY_PRESS)
+    return FALSE;
+
+  keymap = gdk_display_get_keymap (gdk_event_get_display (event));
+
+  mask = gdk_keymap_get_modifier_mask (keymap,
+                                       GDK_MODIFIER_INTENT_DEFAULT_MOD_MASK);
+
+  keycode = gdk_key_event_get_keycode (event);
+  group = gdk_key_event_get_group (event);
+  accel_key = gdk_key_event_get_keyval (event);
+  accel_mods = gdk_event_get_modifier_state (event);
+
+  if (accel_key == GDK_KEY_Sys_Req &&
+      (accel_mods & GDK_MOD1_MASK) != 0)
+    {
+      /* HACK: we don't want to use SysRq as a keybinding (but we do
+       * want Alt+Print), so we avoid translation from Alt+Print to SysRq
+       */
+      *keyval = GDK_KEY_Print;
+      *modifiers = accel_mods & mask;
+      return TRUE;
+    }
+
+  translate_keyboard_accel_state (keymap,
+                                  keycode,
+                                  accel_mods,
+                                  group,
+                                  &key, NULL, NULL, &consumed_modifiers);
+
+  accel_key = gdk_keyval_to_lower (key);
+
+  if (accel_key == GDK_KEY_ISO_Left_Tab)
+    accel_key = GDK_KEY_Tab;
+
+  accel_mods &= mask & ~consumed_modifiers;
+
+  /* Put shift back if it changed the case of the key, not otherwise. */
+  if (accel_key != key)
+    accel_mods |= GDK_SHIFT_MASK;
+
+  *keyval = accel_key;
+  *modifiers = accel_mods;
+
+  return TRUE;
+}
diff --git a/gdk/gdkevents.h b/gdk/gdkevents.h
index 944047d946..6d5fa26dbf 100644
--- a/gdk/gdkevents.h
+++ b/gdk/gdkevents.h
@@ -428,6 +428,16 @@ gboolean                gdk_events_get_center           (GdkEvent *event1,
                                                          double   *x,
                                                          double   *y);
 
+/**
+ * GdkEventMatch:
+ * @GDK_EVENT_MATCH_NONE: The key event does not match
+ * @GDK_EVENT_MATCH_PARTIAL: The key event matches if keyboard state
+ *     (specifically, the currently active group) is ignored
+ * @GDK_EVENT_MATCH_EXACT: The key event matches
+ *
+ * The possible return values from gdk_event_matches()
+ * describe how well an event matches a given keyval and modifiers.
+ */
 typedef enum {
   GDK_EVENT_MATCH_NONE,
   GDK_EVENT_MATCH_PARTIAL,
@@ -439,6 +449,11 @@ GdkEventMatch          gdk_event_matches (GdkEvent        *event,
                                           guint            keyval,
                                           GdkModifierType  modifiers);
 
+GDK_AVAILABLE_IN_ALL
+gboolean               gdk_event_get_match (GdkEvent        *event,
+                                            guint           *keyval,
+                                            GdkModifierType *modifiers);
+
 G_END_DECLS
 
 #endif /* __GDK_EVENTS_H__ */


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