[gtk/keymap-rework-2: 24/34] gdk: Redo key events



commit ef21604c8475e1b9cd6608729bceedf4370706a2
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Apr 5 14:40:55 2020 -0400

    gdk: Redo key events
    
    Add all of the keyboard translation results in the key event,
    so we can translate the keyboard state at the time the event
    is created, and avoid doing state translation at match time.
    
    We actually need to carry two sets of translation results,
    since we ignore CapsLock when matching accelerators, in
    gdk_event_matches().
    
    At the same time, drop the scancode field - it is only ever
    set on win32, and is basically unused in GTK.
    
    Update all callers.

 docs/reference/gdk/gdk4-sections.txt |   5 +-
 gdk/broadway/gdkeventsource.c        |  14 ++-
 gdk/gdkevents.c                      | 186 +++++++++++++----------------------
 gdk/gdkevents.h                      |   6 +-
 gdk/gdkeventsprivate.h               |  46 +++++----
 gdk/gdksurface.c                     |  29 +++---
 gdk/wayland/gdkdevice-wayland.c      |  57 +++++++++--
 gdk/wayland/gdkkeys-wayland.c        |   9 ++
 gdk/wayland/gdkprivate-wayland.h     |   2 +
 gdk/win32/gdkevents-win32.c          |   2 +-
 gdk/x11/gdkdevicemanager-xi2.c       |  39 ++++++--
 gdk/x11/gdkdrag-x11.c                |   2 +-
 gtk/gtkeventcontrollerkey.c          |   2 +-
 gtk/gtkimcontextsimple.c             |  17 ++--
 testsuite/gtk/shortcuts.c            |  59 ++++++-----
 15 files changed, 261 insertions(+), 214 deletions(-)
---
diff --git a/docs/reference/gdk/gdk4-sections.txt b/docs/reference/gdk/gdk4-sections.txt
index 64c9b98ffc..97df57c3ba 100644
--- a/docs/reference/gdk/gdk4-sections.txt
+++ b/docs/reference/gdk/gdk4-sections.txt
@@ -545,8 +545,9 @@ gdk_scroll_event_get_deltas
 gdk_scroll_event_is_stop
 gdk_key_event_get_keyval
 gdk_key_event_get_keycode
-gdk_key_event_get_scancode
-gdk_key_event_get_group
+gdk_key_event_get_consumed_modifiers
+gdk_key_event_get_layout
+gdk_key_event_get_level
 gdk_key_event_is_modifier
 gdk_focus_event_get_in
 gdk_touch_event_get_emulating_pointer
diff --git a/gdk/broadway/gdkeventsource.c b/gdk/broadway/gdkeventsource.c
index 0f83b8b6f6..86e19af155 100644
--- a/gdk/broadway/gdkeventsource.c
+++ b/gdk/broadway/gdkeventsource.c
@@ -266,6 +266,11 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
                                   GINT_TO_POINTER (message->key.surface_id));
     if (surface)
       {
+        GdkTranslatedKey translated;
+        translated.keyval = message->key.key;
+        translated.consumed = 0;
+        translated.layout = 0;
+        translated.level = 0;
         event = gdk_event_key_new (message->base.type == BROADWAY_EVENT_KEY_PRESS
                                      ? GDK_KEY_PRESS
                                      : GDK_KEY_RELEASE,
@@ -273,12 +278,11 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
                                    gdk_seat_get_keyboard (seat),
                                    gdk_seat_get_keyboard (seat),
                                    message->base.time,
-                                   message->key.state,
-                                   message->key.key,
                                    message->key.key,
-                                   message->key.key,
-                                   0,
-                                   FALSE);
+                                   message->key.state,
+                                   FALSE,
+                                   &translated,
+                                   &translated);
 
         node = _gdk_event_queue_append (display, event);
         _gdk_windowing_got_event (display, node, event, message->base.serial);
diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
index 100609f546..d4db2fb9f0 100644
--- a/gdk/gdkevents.c
+++ b/gdk/gdkevents.c
@@ -931,17 +931,16 @@ gdk_event_proximity_new (GdkEventType   type,
 }
 
 GdkEvent *
-gdk_event_key_new (GdkEventType     type,
-                   GdkSurface      *surface,
-                   GdkDevice       *device,
-                   GdkDevice       *source_device,
-                   guint32          time,
-                   GdkModifierType  state,
-                   guint            keyval,
-                   guint16          keycode,
-                   guint16          scancode,
-                   guint8           group,
-                   gboolean         is_modifier)
+gdk_event_key_new (GdkEventType      type,
+                   GdkSurface       *surface,
+                   GdkDevice        *device,
+                   GdkDevice        *source_device,
+                   guint32           time,
+                   guint             keycode,
+                   GdkModifierType   state,
+                   gboolean          is_modifier,
+                   GdkTranslatedKey *translated,
+                   GdkTranslatedKey *no_lock)
 {
   GdkEventKey *event;
 
@@ -956,12 +955,11 @@ gdk_event_key_new (GdkEventType     type,
   event->any.surface = g_object_ref (surface);
   event->any.device = g_object_ref (device);
   event->any.source_device = g_object_ref (source_device);
+  event->keycode = keycode;
   event->state = state;
-  event->keyval = keyval;
-  event->hardware_keycode = keycode;
-  event->key_scancode = scancode;
-  event->group = group;
   event->any.key_is_modifier = is_modifier;
+  event->translated[0] = *translated;
+  event->translated[1] = *no_lock;
 
   return (GdkEvent *)event;
 }
@@ -1669,7 +1667,7 @@ gdk_key_event_get_keyval (GdkEvent *event)
   g_return_val_if_fail (event->any.type == GDK_KEY_PRESS ||
                         event->any.type == GDK_KEY_RELEASE, 0);
 
-  return event->key.keyval;
+  return event->key.translated[0].keyval;
 }
 
 /**
@@ -1686,41 +1684,58 @@ gdk_key_event_get_keycode (GdkEvent *event)
   g_return_val_if_fail (event->any.type == GDK_KEY_PRESS ||
                         event->any.type == GDK_KEY_RELEASE, 0);
 
-  return event->key.hardware_keycode;
+  return event->key.keycode;
 }
 
 /**
- * gdk_key_event_get_scancode:
+ * gdk_key_event_get_level:
  * @event: a key event
  *
- * Extracts the scancode from a key event.
+ * Extracts the shift level from a key event.
  *
- * Returns: the scancode of @event
+ * Returns: the shift level of @event
  */
 guint
-gdk_key_event_get_scancode (GdkEvent *event)
+gdk_key_event_get_level (GdkEvent *event)
 {
   g_return_val_if_fail (event->any.type == GDK_KEY_PRESS ||
                         event->any.type == GDK_KEY_RELEASE, 0);
 
-  return event->key.key_scancode;
+  return event->key.translated[0].level;
 }
 
 /**
- * gdk_key_event_get_group:
+ * gdk_key_event_get_layout:
  * @event: a key event
  *
- * Extracts the group from a key event.
+ * Extracts the layout from a key event.
  *
- * Returns: the group of @event
+ * Returns: the layout of @event
  */
 guint
-gdk_key_event_get_group (GdkEvent *event)
+gdk_key_event_get_layout (GdkEvent *event)
 {
   g_return_val_if_fail (event->any.type == GDK_KEY_PRESS ||
                         event->any.type == GDK_KEY_RELEASE, 0);
 
-  return event->key.group;
+  return event->key.translated[0].layout;
+}
+
+/**
+ * gdk_key_event_get_consumed_modifiers:
+ * @event: a key event
+ *
+ * Extracts the consumed modifiers from a key event.
+ *
+ * Returns: the consumed modifiers or @event
+ */
+GdkModifierType
+gdk_key_event_get_consumed_modifiers (GdkEvent *event)
+{
+  g_return_val_if_fail (event->any.type == GDK_KEY_PRESS ||
+                        event->any.type == GDK_KEY_RELEASE, 0);
+
+  return event->key.translated[0].consumed;
 }
 
 /**
@@ -2111,57 +2126,6 @@ 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;
-}
-
 /**
  * gdk_event_matches:
  * @event: the #GdkEvent
@@ -2169,9 +2133,10 @@ translate_keyboard_accel_state (GdkKeymap       *keymap,
  * @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.
+ * as a keyval and modifiers. Partial matches are possible where the
+ * combination matches if the currently active group is ignored.
+ *
+ * Note that we ignore Caps Lock for matching.
  *
  * Returns: a GdkEventMatch value describing whether @event matches
  */
@@ -2183,10 +2148,8 @@ gdk_event_matches (GdkEvent        *event,
   guint keycode;
   GdkModifierType state;
   GdkModifierType mask;
-  int group;
-  GdkKeymap *keymap;
   guint ev_keyval;
-  int effective_group;
+  int layout;
   int level;
   GdkModifierType consumed_modifiers;
   GdkModifierType shift_group_mask;
@@ -2195,24 +2158,16 @@ gdk_event_matches (GdkEvent        *event,
   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));
+  keycode = event->key.keycode;
+  state = event->key.state & ~GDK_LOCK_MASK;
+  ev_keyval = event->key.translated[1].keyval;
+  layout = event->key.translated[1].layout;
+  level = event->key.translated[1].level;
+  consumed_modifiers = event->key.translated[1].consumed;
 
   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,
-                                  &ev_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
    */
@@ -2244,21 +2199,24 @@ gdk_event_matches (GdkEvent        *event,
       if (ev_keyval == key && /* exact match */
           (!group_mod_is_accel_mod ||
            (state & shift_group_mask) == (modifiers & shift_group_mask)))
-        return GDK_EVENT_MATCH_EXACT;
+        {
+          g_print ("exact match key %d\n", key);
+          return GDK_EVENT_MATCH_EXACT;
+        }
 
-      gdk_keymap_get_entries_for_keyval (keymap, keyval, &keys, &n_keys);
+      gdk_display_map_keyval (gdk_event_get_display (event), 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))
+              (!group_mod_is_accel_mod || keys[i].group == layout))
             {
               /* partial match */
               g_free (keys);
 
+              g_print ("partial match keycode %d level %d\n", keycode, level);
               return GDK_EVENT_MATCH_PARTIAL;
             }
         }
@@ -2288,8 +2246,6 @@ gdk_event_get_match (GdkEvent        *event,
 {
   GdkKeymap *keymap;
   GdkModifierType mask;
-  guint keycode;
-  guint group;
   guint key;
   guint accel_key;
   GdkModifierType accel_mods;
@@ -2303,10 +2259,9 @@ gdk_event_get_match (GdkEvent        *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);
+  accel_key = event->key.translated[1].keyval;
+  accel_mods = event->key.state;
+  consumed_modifiers = event->key.translated[1].consumed;
 
   if (accel_key == GDK_KEY_Sys_Req &&
       (accel_mods & GDK_ALT_MASK) != 0)
@@ -2319,24 +2274,17 @@ gdk_event_get_match (GdkEvent        *event,
       return TRUE;
     }
 
-  translate_keyboard_accel_state (keymap,
-                                  keycode,
-                                  accel_mods,
-                                  group,
-                                  &key, NULL, NULL, &consumed_modifiers);
-
-  accel_key = gdk_keyval_to_lower (key);
+  key = gdk_keyval_to_lower (accel_key);
 
-  if (accel_key == GDK_KEY_ISO_Left_Tab)
-    accel_key = GDK_KEY_Tab;
+  if (key == GDK_KEY_ISO_Left_Tab)
+    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;
+  *keyval = key;
   *modifiers = accel_mods;
 
   return TRUE;
diff --git a/gdk/gdkevents.h b/gdk/gdkevents.h
index 6d5fa26dbf..016186118c 100644
--- a/gdk/gdkevents.h
+++ b/gdk/gdkevents.h
@@ -363,9 +363,11 @@ guint                   gdk_key_event_get_keyval        (GdkEvent *event);
 GDK_AVAILABLE_IN_ALL
 guint                   gdk_key_event_get_keycode       (GdkEvent *event);
 GDK_AVAILABLE_IN_ALL
-guint                   gdk_key_event_get_scancode      (GdkEvent *event);
+GdkModifierType         gdk_key_event_get_consumed_modifiers (GdkEvent *event);
 GDK_AVAILABLE_IN_ALL
-guint                   gdk_key_event_get_group         (GdkEvent *event);
+guint                   gdk_key_event_get_layout        (GdkEvent *event);
+GDK_AVAILABLE_IN_ALL
+guint                   gdk_key_event_get_level         (GdkEvent *event);
 GDK_AVAILABLE_IN_ALL
 gboolean                gdk_key_event_is_modifier       (GdkEvent *event);
 GDK_AVAILABLE_IN_ALL
diff --git a/gdk/gdkeventsprivate.h b/gdk/gdkeventsprivate.h
index 6cc2aadcba..ababf6d3a9 100644
--- a/gdk/gdkeventsprivate.h
+++ b/gdk/gdkeventsprivate.h
@@ -223,6 +223,13 @@ struct _GdkEventScroll
   GdkDeviceTool *tool;
 };
 
+typedef struct {
+  guint keyval;
+  GdkModifierType consumed;
+  guint layout;
+  guint level;
+} GdkTranslatedKey;
+
 /*
  * GdkEventKey:
  * @type: the type of the event (%GDK_KEY_PRESS or %GDK_KEY_RELEASE).
@@ -232,13 +239,13 @@ struct _GdkEventScroll
  * @state: (type GdkModifierType): a bit-mask representing the state of
  *   the modifier keys (e.g. Control, Shift and Alt) and the pointer
  *   buttons. See #GdkModifierType.
+ * @keycode: the raw code of the key that was pressed or released.
  * @keyval: the key that was pressed or released. See the
- *   `gdk/gdkkeysyms.h` header file for a
- *   complete list of GDK key codes.
- * @hardware_keycode: the raw code of the key that was pressed or released.
- * @group: the keyboard group.
- * @is_modifier: a flag that indicates if @hardware_keycode is mapped to a
- *   modifier
+ *   `gdk/gdkkeysyms.h` header file for a complete list of GDK key codes.
+ * @consumed_modifiers: Modifiers that were consumed when translating
+ *    @keycode to @keyval
+ * @layout: the effective keyboard layout
+ * @level: the effective shift level
  *
  * Describes a key press or key release event.
  */
@@ -246,10 +253,8 @@ struct _GdkEventKey
 {
   GdkEventAny any;
   GdkModifierType state;
-  guint keyval;
-  guint16 hardware_keycode;
-  guint16 key_scancode;
-  guint8 group;
+  guint32 keycode;
+  GdkTranslatedKey translated[2];
 };
 
 /*
@@ -594,17 +599,16 @@ GdkEvent * gdk_event_proximity_new      (GdkEventType     type,
                                          GdkDeviceTool   *tool,
                                          guint32          time);
 
-GdkEvent * gdk_event_key_new            (GdkEventType     type,
-                                         GdkSurface      *surface,
-                                         GdkDevice       *device,
-                                         GdkDevice       *source_device,
-                                         guint32          time,
-                                         GdkModifierType  state,
-                                         guint            keyval,
-                                         guint16          keycode,
-                                         guint16          scancode,
-                                         guint8           group,
-                                         gboolean         is_modifier);
+GdkEvent * gdk_event_key_new            (GdkEventType      type,
+                                         GdkSurface       *surface,
+                                         GdkDevice        *device,
+                                         GdkDevice        *source_device,
+                                         guint32           time,
+                                         guint             keycode,
+                                         GdkModifierType   modifiers,
+                                         gboolean          is_modifier,
+                                         GdkTranslatedKey *translated,
+                                         GdkTranslatedKey *no_lock);
 
 GdkEvent * gdk_event_focus_new          (GdkSurface      *surface,
                                          GdkDevice       *device,
diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c
index 7432a9b348..9dae9a93b5 100644
--- a/gdk/gdksurface.c
+++ b/gdk/gdksurface.c
@@ -2815,17 +2815,18 @@ rewrite_event_for_toplevel (GdkEvent *event)
                                 gdk_event_get_source_device (event),
                                 gdk_focus_event_get_in (event));
   else
-    return gdk_event_key_new (gdk_event_get_event_type (event),
-                              surface,
-                              gdk_event_get_device (event),
-                              gdk_event_get_source_device (event),
-                              gdk_event_get_time (event),
-                              gdk_event_get_modifier_state (event),
-                              gdk_key_event_get_keyval (event),
-                              gdk_key_event_get_keycode (event),
-                              gdk_key_event_get_scancode (event),
-                              gdk_key_event_get_group (event),
-                              gdk_key_event_is_modifier (event));
+    {
+      return gdk_event_key_new (gdk_event_get_event_type (event),
+                                surface,
+                                gdk_event_get_device (event),
+                                gdk_event_get_source_device (event),
+                                gdk_event_get_time (event),
+                                gdk_key_event_get_keycode (event),
+                                gdk_event_get_modifier_state (event),
+                                gdk_key_event_is_modifier (event),
+                                &event->key.translated[0],
+                                &event->key.translated[1]);
+    }
 }
 
 static void
@@ -2874,13 +2875,13 @@ add_event_mark (GdkEvent *event,
     case GDK_KEY_PRESS:
     case GDK_KEY_RELEASE:
       {
-        message = g_strdup_printf ("%s {keyval=%u, state=0x%x, hardware_keycode=%u key_scancode=%u group=%u 
is_modifier=%u}",
+        message = g_strdup_printf ("%s {keyval=%u, state=0x%x, keycode=%u layout=%u level=%u 
is_modifier=%u}",
                                    kind,
                                    gdk_key_event_get_keyval (event),
                                    gdk_event_get_modifier_state (event),
                                    gdk_key_event_get_keycode (event),
-                                   gdk_key_event_get_scancode (event),
-                                   gdk_key_event_get_group (event),
+                                   gdk_key_event_get_layout (event),
+                                   gdk_key_event_get_level (event),
                                    gdk_key_event_is_modifier (event));
         break;
       }
diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c
index 18824309fe..c4fdcbcde8 100644
--- a/gdk/wayland/gdkdevice-wayland.c
+++ b/gdk/wayland/gdkdevice-wayland.c
@@ -2020,9 +2020,13 @@ deliver_key_event (GdkWaylandSeat *seat,
   struct xkb_state *xkb_state;
   struct xkb_keymap *xkb_keymap;
   GdkKeymap *keymap;
-  xkb_keysym_t sym;
   guint delay, interval, timeout;
   gint64 begin_time, now;
+  xkb_mod_mask_t consumed;
+  GdkTranslatedKey translated;
+  GdkTranslatedKey no_lock;
+  xkb_mod_mask_t modifiers;
+  xkb_mod_index_t caps_lock;
 
   begin_time = g_get_monotonic_time ();
 
@@ -2032,36 +2036,69 @@ deliver_key_event (GdkWaylandSeat *seat,
   xkb_state = _gdk_wayland_keymap_get_xkb_state (keymap);
   xkb_keymap = _gdk_wayland_keymap_get_xkb_keymap (keymap);
 
-  sym = xkb_state_key_get_one_sym (xkb_state, key);
-  if (sym == XKB_KEY_NoSymbol)
+  translated.keyval = xkb_state_key_get_one_sym (xkb_state, key);
+  modifiers = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_EFFECTIVE);
+  consumed = modifiers & ~xkb_state_mod_mask_remove_consumed (xkb_state, key, modifiers);
+  translated.consumed = gdk_wayland_keymap_get_gdk_modifiers (keymap, consumed);
+  translated.layout = xkb_state_key_get_layout (xkb_state, key);
+  translated.level = xkb_state_key_get_level (xkb_state, key, translated.layout);
+
+  if (translated.keyval == XKB_KEY_NoSymbol)
     return;
 
   seat->pointer_info.time = time_;
   seat->key_modifiers = gdk_keymap_get_modifier_state (keymap);
 
+
+  modifiers = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_EFFECTIVE);
+  caps_lock = xkb_keymap_mod_get_index (xkb_keymap, XKB_MOD_NAME_CAPS);
+  if (modifiers & (1 << caps_lock))
+    {
+      struct xkb_state *tmp_state = xkb_state_new (xkb_keymap);
+      xkb_layout_index_t layout;
+
+      modifiers &= ~(1 << caps_lock);
+      layout = xkb_state_serialize_layout (xkb_state, XKB_STATE_LAYOUT_EFFECTIVE);
+      xkb_state_update_mask (tmp_state, modifiers, 0, 0, layout, 0, 0);
+
+      no_lock.keyval = xkb_state_key_get_one_sym (tmp_state, key);
+      consumed = modifiers & ~xkb_state_mod_mask_remove_consumed (tmp_state, key, modifiers);
+      no_lock.consumed = gdk_wayland_keymap_get_gdk_modifiers (keymap, consumed);
+      no_lock.layout = xkb_state_key_get_layout (tmp_state, key);
+      no_lock.level = xkb_state_key_get_level (tmp_state, key, no_lock.layout);
+
+      xkb_state_unref (tmp_state);
+    }
+  else
+    {
+      no_lock = translated;
+    }
+
   event = gdk_event_key_new (state ? GDK_KEY_PRESS : GDK_KEY_RELEASE,
                              seat->keyboard_focus,
                              seat->master_keyboard,
                              seat->keyboard,
                              time_,
-                             device_get_modifiers (seat->master_pointer),
-                             sym,
                              key,
-                             key,
-                             0,
-                             _gdk_wayland_keymap_key_is_modifier (keymap, key));
+                             device_get_modifiers (seat->master_pointer),
+                             _gdk_wayland_keymap_key_is_modifier (keymap, key),
+                             &translated, 
+                             &no_lock);
 
   _gdk_wayland_display_deliver_event (seat->display, event);
 
   GDK_SEAT_NOTE (seat, EVENTS,
             g_message ("keyboard %s event%s, surface %p, code %d, sym %d, "
-                       "mods 0x%x",
+                       "mods 0x%x, consumed 0x%x, layout %d level %d",
                        (state ? "press" : "release"),
                        (from_key_repeat ? " (repeat)" : ""),
                        gdk_event_get_surface (event),
                        gdk_key_event_get_keycode (event),
                        gdk_key_event_get_keyval (event),
-                       gdk_event_get_modifier_state (event)));
+                       gdk_event_get_modifier_state (event),
+                       gdk_key_event_get_consumed_modifiers (event),
+                       gdk_key_event_get_layout (event),
+                       gdk_key_event_get_level (event)));
 
   if (!xkb_keymap_key_repeats (xkb_keymap, key))
     return;
diff --git a/gdk/wayland/gdkkeys-wayland.c b/gdk/wayland/gdkkeys-wayland.c
index ae5108c5dc..203e656750 100644
--- a/gdk/wayland/gdkkeys-wayland.c
+++ b/gdk/wayland/gdkkeys-wayland.c
@@ -300,6 +300,15 @@ get_gdk_modifiers (struct xkb_keymap *xkb_keymap,
   return state;
 }
 
+GdkModifierType
+gdk_wayland_keymap_get_gdk_modifiers (GdkKeymap *keymap,
+                                      guint32    mods)
+{
+  struct xkb_keymap *xkb_keymap = GDK_WAYLAND_KEYMAP (keymap)->xkb_keymap;
+
+  return get_gdk_modifiers (xkb_keymap, mods);
+}
+
 static gboolean
 gdk_wayland_keymap_translate_keyboard_state (GdkKeymap       *keymap,
                                             guint            hardware_keycode,
diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h
index 6ea1a1ae6e..13dbd221e0 100644
--- a/gdk/wayland/gdkprivate-wayland.h
+++ b/gdk/wayland/gdkprivate-wayland.h
@@ -201,5 +201,7 @@ void gdk_wayland_surface_update_scale (GdkSurface *surface);
 
 GdkSurface * create_dnd_surface (GdkDisplay *display);
 
+GdkModifierType gdk_wayland_keymap_get_gdk_modifiers (GdkKeymap *keymap,
+                                                      guint32    mods);
 
 #endif /* __GDK_PRIVATE_WAYLAND_H__ */
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index 3daa4b86bf..cb67162587 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -806,7 +806,7 @@ _gdk_win32_print_event (GdkEvent *event)
       kvname = gdk_keyval_name (gdk_key_event_get_keyval (event));
       g_print ("%#.02x group:%d %s",
                gdk_key_event_get_keycode (event),
-               gdk_key_event_get_group (event),
+               gdk_key_event_get_layout (event),
               (kvname ? kvname : "??"));
       print_event_state (gdk_event_get_modifier_state (event));
       break;
diff --git a/gdk/x11/gdkdevicemanager-xi2.c b/gdk/x11/gdkdevicemanager-xi2.c
index 6e6ba54c93..dc98e76bd9 100644
--- a/gdk/x11/gdkdevicemanager-xi2.c
+++ b/gdk/x11/gdkdevicemanager-xi2.c
@@ -1521,7 +1521,10 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
         GdkKeymap *keymap = gdk_display_get_keymap (display);
         GdkModifierType consumed, state, orig_state;
+        int layout, level;
         guint keyval;
+        GdkTranslatedKey translated;
+        GdkTranslatedKey no_lock;
 
         GDK_DISPLAY_NOTE (display, EVENTS,
                   g_message ("key %s:\twindow %ld\n"
@@ -1549,12 +1552,37 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
                                              state,
                                              xev->group.effective,
                                              &keyval,
-                                             NULL, NULL, &consumed);
+                                             &layout, &level, &consumed);
         orig_state = state;
         state &= ~consumed;
         _gdk_x11_keymap_add_virt_mods (keymap, &state);
         state |= orig_state;
 
+        translated.keyval = keyval;
+        translated.consumed = consumed;
+        translated.layout = layout;
+        translated.level = level;
+
+        if (orig_state & GDK_LOCK_MASK)
+          {
+            orig_state &= ~GDK_LOCK_MASK;
+
+            gdk_keymap_translate_keyboard_state (keymap,
+                                                 xev->detail,
+                                                 orig_state,
+                                                 xev->group.effective,
+                                                 &keyval,
+                                                 &layout, &level, &consumed);
+
+            no_lock.keyval = keyval;
+            no_lock.consumed = consumed;
+            no_lock.layout = layout;
+            no_lock.level = level;
+          }
+        else
+          {
+            no_lock = translated;
+          }
         event = gdk_event_key_new (xev->evtype == XI_KeyPress
                                      ? GDK_KEY_PRESS
                                      : GDK_KEY_RELEASE,
@@ -1562,12 +1590,11 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
                                    device,
                                    source_device,
                                    xev->time,
-                                   state,
-                                   keyval,
                                    xev->detail,
-                                   xev->detail,
-                                   xev->group.effective,
-                                   gdk_x11_keymap_key_is_modifier (keymap, xev->detail));
+                                   state,
+                                   gdk_x11_keymap_key_is_modifier (keymap, xev->detail),
+                                   &translated,
+                                   &no_lock);
 
         if (ev->evtype == XI_KeyPress)
           set_user_time (event);
diff --git a/gdk/x11/gdkdrag-x11.c b/gdk/x11/gdkdrag-x11.c
index 6aefc9466a..da0c516796 100644
--- a/gdk/x11/gdkdrag-x11.c
+++ b/gdk/x11/gdkdrag-x11.c
@@ -2214,7 +2214,7 @@ gdk_dnd_handle_key_event (GdkDrag           *drag,
 
   if (event->any.type == GDK_KEY_PRESS)
     {
-      switch (event->keyval)
+      switch (event->translated[0].keyval)
         {
         case GDK_KEY_Escape:
           gdk_drag_cancel (drag, GDK_DRAG_CANCEL_USER_CANCELLED);
diff --git a/gtk/gtkeventcontrollerkey.c b/gtk/gtkeventcontrollerkey.c
index 62614dbf79..ae7c11a8b0 100644
--- a/gtk/gtkeventcontrollerkey.c
+++ b/gtk/gtkeventcontrollerkey.c
@@ -385,5 +385,5 @@ gtk_event_controller_key_get_group (GtkEventControllerKey *controller)
   g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_KEY (controller), FALSE);
   g_return_val_if_fail (controller->current_event != NULL, FALSE);
 
-  return gdk_key_event_get_group (controller->current_event);
+  return gdk_key_event_get_layout (controller->current_event);
 }
diff --git a/gtk/gtkimcontextsimple.c b/gtk/gtkimcontextsimple.c
index b5b868c7c0..061fae5d10 100644
--- a/gtk/gtkimcontextsimple.c
+++ b/gtk/gtkimcontextsimple.c
@@ -929,18 +929,21 @@ no_sequence_matches (GtkIMContextSimple *context_simple,
       
       for (i = 0; i < n_compose - len - 1; i++)
        {
-          guint tmp_keyval = priv->compose_buffer[len + i];
+          GdkTranslatedKey translated;
+          translated.keyval = priv->compose_buffer[len + i];
+          translated.consumed = 0;
+          translated.layout = 0;
+          translated.level = 0;
           GdkEvent *tmp_event = gdk_event_key_new (GDK_KEY_PRESS,
                                                    gdk_event_get_surface (event),
                                                    gdk_event_get_device (event),
                                                    gdk_event_get_source_device (event),
                                                    gdk_event_get_time (event),
+                                                   priv->compose_buffer[len + i],
                                                    gdk_event_get_modifier_state (event),
-                                                   tmp_keyval,
-                                                   tmp_keyval,
-                                                   tmp_keyval,
-                                                   0,
-                                                   0);
+                                                   FALSE,
+                                                   &translated,
+                                                   &translated);
          
          gtk_im_context_filter_keypress (context, tmp_event);
          gdk_event_unref (tmp_event);
@@ -997,7 +1000,7 @@ canonical_hex_keyval (GdkEvent *event)
    * any other state, and return that hex keyval if so
    */
   gdk_display_map_keycode (gdk_event_get_display (event),
-                           gdk_key_event_get_scancode (event),
+                           gdk_key_event_get_keycode (event),
                            NULL,
                            &keyvals, &n_vals);
 
diff --git a/testsuite/gtk/shortcuts.c b/testsuite/gtk/shortcuts.c
index 56f3a2d286..9049842c87 100644
--- a/testsuite/gtk/shortcuts.c
+++ b/testsuite/gtk/shortcuts.c
@@ -23,23 +23,13 @@ struct _GdkEventKey
 {
   GdkEventAny any;
   GdkModifierType state;
+  guint32 keycode;
   guint keyval;
-  guint16 hardware_keycode;
-  guint16 key_scancode;
-  guint8 group;
+  GdkModifierType consumed;
+  guint layout;
+  guint level;
 };
 
-static GdkEvent * gdk_event_key_new     (GdkEventType     type,
-                                         GdkSurface      *surface,
-                                         GdkDevice       *device,
-                                         GdkDevice       *source_device,
-                                         guint32          time,
-                                         GdkModifierType  state,
-                                         guint            keyval,
-                                         guint16          keycode,
-                                         guint16          scancode,
-                                         guint8           group,
-                                         gboolean         is_modifier);
 
 static GdkEvent *
 gdk_event_key_new (GdkEventType     type,
@@ -47,11 +37,26 @@ gdk_event_key_new (GdkEventType     type,
                    GdkDevice       *device,
                    GdkDevice       *source_device,
                    guint32          time,
+                   guint            keycode,
+                   guint            keyval,
                    GdkModifierType  state,
+                   GdkModifierType  consumed,
+                   guint            layout,
+                   guint            level,
+                   gboolean         is_modifier);
+
+static GdkEvent *
+gdk_event_key_new (GdkEventType     type,
+                   GdkSurface      *surface,
+                   GdkDevice       *device,
+                   GdkDevice       *source_device,
+                   guint32          time,
+                   guint            keycode,
                    guint            keyval,
-                   guint16          keycode,
-                   guint16          scancode,
-                   guint8           group,
+                   GdkModifierType  state,
+                   GdkModifierType  consumed,
+                   guint            layout,
+                   guint            level,
                    gboolean         is_modifier)
 {
   GdkEventKey *event;
@@ -67,11 +72,12 @@ gdk_event_key_new (GdkEventType     type,
   event->any.surface = g_object_ref (surface);
   event->any.device = g_object_ref (device);
   event->any.source_device = g_object_ref (source_device);
-  event->state = state;
+  event->keycode = keycode;
   event->keyval = keyval;
-  event->hardware_keycode = keycode;
-  event->key_scancode = scancode;
-  event->group = group;
+  event->state = state;
+  event->consumed = consumed;
+  event->layout = layout;
+  event->level = level;
   event->any.key_is_modifier = is_modifier;
 
   return (GdkEvent *)event;
@@ -374,14 +380,17 @@ test_trigger_trigger (void)
                                  device,
                                  device,
                                  GDK_CURRENT_TIME,
-                                 tests[i].state,
-                                 tests[i].keyval,
-                                 keys[0].keycode,
                                  keys[0].keycode,
+                                 tests[i].keyval,
+                                 tests[i].state,
+                                 0,
                                  keys[0].group,
+                                 keys[0].level,
                                  FALSE);
       for (j = 0; j < 4; j++)
-        g_assert_cmpint (gtk_shortcut_trigger_trigger (trigger[j], event, tests[i].mnemonic), ==, 
tests[i].result[j]);
+        {
+          g_assert_cmpint (gtk_shortcut_trigger_trigger (trigger[j], event, tests[i].mnemonic), ==, 
tests[i].result[j]);
+        }
 
       gdk_event_unref (event);
     }



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