|
53d9881e
|
2024-03-05T10:28:11
|
|
keysyms: Fix inconsistent case-insensitive name lookup
`xkb_keysym_from_name` has inconsistent behavior when used with the flag
`XKB_KEYSYM_CASE_INSENSITIVE`:
```c
xkb_keysym_from_name("a", XKB_KEYSYM_CASE_INSENSITIVE) == XKB_KEY_a;
xkb_keysym_from_name("A", XKB_KEYSYM_CASE_INSENSITIVE) == XKB_KEY_a;
xkb_keysym_from_name("dead_a", XKB_KEYSYM_CASE_INSENSITIVE) == XKB_KEY_dead_A;
xkb_keysym_from_name("dead_A", XKB_KEYSYM_CASE_INSENSITIVE) == XKB_KEY_dead_A;
xkb_keysym_from_name("dead_o", XKB_KEYSYM_CASE_INSENSITIVE) == XKB_KEY_dead_o;
xkb_keysym_from_name("dead_O", XKB_KEYSYM_CASE_INSENSITIVE) == XKB_KEY_dead_o;
xkb_keysym_from_name("KANA_tsu", XKB_KEYSYM_CASE_INSENSITIVE) == XKB_KEY_kana_tsu;
xkb_keysym_from_name("KANA_TSU", XKB_KEYSYM_CASE_INSENSITIVE) == XKB_KEY_kana_tsu;
xkb_keysym_from_name("KANA_ya", XKB_KEYSYM_CASE_INSENSITIVE) == XKB_KEY_kana_YA;
xkb_keysym_from_name("KANA_YA", XKB_KEYSYM_CASE_INSENSITIVE) == XKB_KEY_kana_YA;
xkb_keysym_from_name("XF86Screensaver", XKB_KEYSYM_CASE_INSENSITIVE) == XKB_KEY_XF86ScreenSaver;
xkb_keysym_from_name("XF86ScreenSaver", XKB_KEYSYM_CASE_INSENSITIVE) == XKB_KEY_XF86ScreenSaver;
```
So currently, if two keysym names differ only by case, then the
lower-case *keysym* is returned, not the keysym corresponding to the
lower-case keysym *name*. Indeed, `xkb_keysym_from_name` uses
`xkb_keysym_is_lower` to test if a keysym is a lower-case keysym.
Let’s look at the example for keysyms `a` and `A`: we get the keysym `a`
not because its name is lower case, but because `xkb_keysym_is_lower(XKB_KEY_a)`
returns true and `xkb_keysym_is_lower(XKB_KEY_A)` returns false.
So the results are correct according to the doc:
- Katakana is not a bicameral script, so e.g. `kana_ya` is *not* the lower
case of `kana_YA`.
- As for the `dead_*` keysyms, they are not cased either because they do
not correspond to characters.
- `XF86ScreenSaver` and `XF86Screensaver` are two different keysyms.
But this is also very counter-intuitive: `xkb_keysym_is_lower` is not
the right function to use in this case, because one would expect to check
only the name, not the corresponding character case:
```c
xkb_keysym_from_name("KANA_YA", XKB_KEYSYM_CASE_INSENSITIVE) == XKB_KEY_kana_ya;
xkb_keysym_from_name("XF86ScreenSaver", XKB_KEYSYM_CASE_INSENSITIVE) == XKB_KEY_XF86Screensaver;
```
Fixed by making the order of the keysyms names consistent in `src/ks_tables.h`:
1. Sort by the casefolded name: e.g. `kana_ya` < `kana_YO`.
2. If same casefolded name, then sort by cased name, i.e for
ASCII: upper before lower: e.g `kana_YA` < `kana_ya`.
Thus we now have e.g. `kana_YA` < `kana_ya` < `kana_YO` < `kana_yo`.
The lookup logic has also been simplified.
Added exhaustive test for ambiguous case-insensitive names.
|