[gtk/gtk-3-24: 4/6] gdkkeys-win32: Fix handling of SGCAPS




commit 4e9ddaf086fe315169a655db6e70a80bcd23e57b
Author: Philip Zander <philip zander gmail com>
Date:   Sun Jan 9 11:33:40 2022 +0100

    gdkkeys-win32: Fix handling of SGCAPS
    
    Contrary to what you can read on the internet, SGCAPS keys don't work
    by having capslock toggle the KBDCTRL bit, they actually have two
    consecutive table entries, the first of which is for the normal
    version and the second of which is for the capslocked version.
    
    Background: SGCAPS is short for Swiss German caps because Swiss German
    was the first layout to use this feature. For keys with the SGCAPS flag,
    capslock has a different effect than pressing shift. For example:
    Shift + ü = è,  CapsLock + ü = Ü,  CapsLock + Shift + ü = È

 gdk/win32/gdkkeys-win32-impl.c | 23 +++++++++++++++--------
 gdk/win32/gdkkeys-win32.c      | 11 -----------
 gdk/win32/gdkprivate-win32.h   |  1 -
 3 files changed, 15 insertions(+), 20 deletions(-)
---
diff --git a/gdk/win32/gdkkeys-win32-impl.c b/gdk/win32/gdkkeys-win32-impl.c
index 4539989c13..368f3f6506 100644
--- a/gdk/win32/gdkkeys-win32-impl.c
+++ b/gdk/win32/gdkkeys-win32-impl.c
@@ -291,6 +291,7 @@ vk_to_char_fuzzy (GdkWin32KeymapLayoutInfo *info,
 
   if (entry->VirtualKey == vk)
     {
+      gboolean have_sgcaps    = FALSE;
       WCHAR    best_char      = WCH_NONE;
       BYTE     best_modifiers = 0;
       int      best_score     = -1;
@@ -316,10 +317,11 @@ vk_to_char_fuzzy (GdkWin32KeymapLayoutInfo *info,
         mod_bits ^= KBDSHIFT;
 
       /* In the Swiss German layout, CapsLock + key is different from Shift + key
-       * for some keys. For such keys, Capslock toggles the KBDCTRL bit. */
+       * for some keys. For such keys, the characters for active capslock are
+       * in the next entry. */
       if ((entry->Attributes & SGCAPS) &&
           (lock_bits & CAPLOK))
-        mod_bits ^= KBDCTRL;
+        have_sgcaps = TRUE;
 
       /* I'm not totally sure how kanalok behaves, for now I assume that there
        * aren't any special cases. */
@@ -336,12 +338,12 @@ vk_to_char_fuzzy (GdkWin32KeymapLayoutInfo *info,
           int      score;
 
           if (candidate_modbits & ~mod_bits)
-              continue;
+            continue;
 
           c = entry->wch[level];
-          if (c == WCH_DEAD)
+          if (c == WCH_DEAD || have_sgcaps)
             {
-              /* Next entry contains the undead keys */
+              /* Next entry contains the undead/capslocked keys */
               PVK_TO_WCHARS next_entry;
               next_entry = (PVK_TO_WCHARS) ((PBYTE) wch_table->pVkToWchars.ptr
                                             + entry_size * (entry_index + 1));
@@ -458,8 +460,13 @@ init_vk_lookup_table (GdkWin32KeymapLayoutInfo *info)
 
           /* Lookup table to find entry for a VK in O(1). */
 
-          info->vk_lookup_table[entry->VirtualKey].table = table_idx;
-          info->vk_lookup_table[entry->VirtualKey].index = entry_idx;
+          /* Only add the first entry, as some layouts (Swiss German) contain
+           * multiple successive entries for the same VK (SGCAPS). */
+          if (info->vk_lookup_table[entry->VirtualKey].table < 0)
+            {
+              info->vk_lookup_table[entry->VirtualKey].table = table_idx;
+              info->vk_lookup_table[entry->VirtualKey].index = entry_idx;
+            }
 
           /* Create reverse lookup entries to find a VK+modifier combinations
            * that results in a given character. */
@@ -497,7 +504,7 @@ init_vk_lookup_table (GdkWin32KeymapLayoutInfo *info)
               g_hash_table_insert (info->reverse_lookup_table,
                                    GINT_TO_POINTER (c),
                                    GINT_TO_POINTER (inserted_idx));
-          }
+            }
         }
     }
 }
diff --git a/gdk/win32/gdkkeys-win32.c b/gdk/win32/gdkkeys-win32.c
index d835b44c67..4cb1e176a1 100644
--- a/gdk/win32/gdkkeys-win32.c
+++ b/gdk/win32/gdkkeys-win32.c
@@ -620,17 +620,6 @@ _gdk_win32_keymap_set_active_layout (GdkWin32Keymap *keymap,
     }
 }
 
-gboolean
-_gdk_win32_keymap_has_altgr (GdkWin32Keymap *keymap)
-{
-  /* We just return FALSE, since it doesn't really matter because AltGr
-   * is the same as Ctrl + Alt. Hence, we will never get a GDK_MOD2_MASK, 
-   * rather we will just get GDK_CONTROL_MASK | GDK_MOD1_MASK. I don't 
-   * think there is any clean way to distinguish <Ctrl + Alt> from 
-   * <AltGr> on Windows. */
-  return FALSE;
-}
-
 guint8
 _gdk_win32_keymap_get_active_group (GdkWin32Keymap *keymap)
 {
diff --git a/gdk/win32/gdkprivate-win32.h b/gdk/win32/gdkprivate-win32.h
index e06aafc820..5173cf6af3 100644
--- a/gdk/win32/gdkprivate-win32.h
+++ b/gdk/win32/gdkprivate-win32.h
@@ -446,7 +446,6 @@ gint      _gdk_win32_display_text_property_to_utf8_list (GdkDisplay    *display,
                                                         gchar       ***list);
 gchar     *_gdk_win32_display_utf8_to_string_target (GdkDisplay *display, const gchar *str);
 
-gboolean   _gdk_win32_keymap_has_altgr           (GdkWin32Keymap *keymap);
 guint8     _gdk_win32_keymap_get_active_group    (GdkWin32Keymap *keymap);
 guint8     _gdk_win32_keymap_get_rshift_scancode (GdkWin32Keymap *keymap);
 void       _gdk_win32_keymap_set_active_layout   (GdkWin32Keymap *keymap,


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