src/keymap-priv.c


Log

Author Commit Date CI Message
Pierre Le Marre dddffd51 2025-05-05T13:22:57 state: Fix virtual modifiers with non-real mod mapping Currently there are 2 issues with the handling of virtual modifiers in the keyboard state: 1. We assume that the input modifiers masks encode the indexes of all the modifiers of the keymap, but this is true only for the *real* modifiers (at least in xkbcommon and X11). Indeed, since the virtual modifiers *indexes* are implementation-specific, the input modifier masks merely *encode* the modifiers via their *mapping*. Consider the following keymap: ```c xkb_keymap { xkb_compat { virtual_modifiers M1 = 0x100; }; xkb_types { virtual_modifiers M2 = 0x200; }; }; ``` Now to illustrate, consider the following 2 implementation variants of libxkbcommon (assuming indexes 0-7 are the usual real modifiers): 1. Process `xkb_compat` then `xkb_types`. M1 and M2 have the respective indexes 8 and 9 and map to themselves (with the current assumption about mask denotation). 2. Process `xkb_types` then `xkb_compat`. M1 and M2 have the respective indexes 9 and 8 and map to each other. With the current `xkb_state_update_mask`, implementation 2 will swap M1 and M2 (compared to impl. 1) at each update! Indeed, we can see that `xkb_state_serialize_mods` doesn’t roundtrip via `xkb_state_update_mask`. 2. We assume that modifier masks use only bits denoting modifiers in the keymap, but when parsing the keymap we accept explicit virtual modifiers mapping of arbitrary values. E.g. if `M1` is the only virtual modifier and it is defined by: ```c virtual_modifiers M1 = 0x80000000; // 1 << (32 - 1) ``` then the 32th bit of a modifier mask input does *not* denote the 32th virtual modifier of the keymap, but merely the encoding of the mapping of `M1`. So when calling `xkb_state_update_mask`, we may discard some bits of the modifiers masks and end up with an incorrect state. These 2 issues may break interoperability with other implementations of XKB (e.g. kbvm) and make pure virtual modifiers handling fragile. We introduce the notion of *canonical state modifier mask*: the mask with the smallest population count that denotes all bits used to encode the modifiers in the keyboard state. It is equal to the bitwise OR of real modifiers mask and all the virtual modifiers mappings. This commit fixes the 2 issues by making *weaker* assumptions about the input modifier masks: 1. Modifiers may map to arbitrary values, not only real modifiers. 2. Input modifier masks merely encode modifiers via their *mapping*: - *real* modifiers map to themselves; - *virtual* modifiers map to the bitwise OR of their *explicit* mapping (via `virtual_modifiers`) and their *implicit* mapping (via keys’ real and virtual modmaps). - modifiers indexes are implementation-specific. Since the implementation before this commit also resolved virtual modifiers to their mappings, we continue doing so, but using only the bits that are *not* set in the canonical state modifier mask, so that we enable roundtrip of `xkb_state_serialize_mods` via `xkb_state_update_mask`. 3. Input modifier masks do not denote modifiers indexes (apart from real modifiers), so it is safe to discard only the bits that are not set in the canonical state modifier mask.
Pierre Le Marre f8148744 2025-05-06T11:26:21 Define the mapping of real modifiers explicitly When querying for a modifier mapping, we should treat all modifiers equally. So simply store real modifier mapping as we do for the virtual ones. Also fixed useless boolean conversions.
Pierre Le Marre 9e93e5e5 2025-04-13T10:25:02 symbols: Restrict the number of actions and keysyms per level In preparation to support capitalization in `xkb_state_key_get_syms()`, this commit reduces the number of supported actions and keysyms per level, going from UINT_MAX to UINT16_MAX. This is most likely still more than enough and could be even reduced further, but deemed unnecessary at the moment: alignment of `struct xkb_level` is driven by the fields `a` and `s`. - Switched the item count type from `unsigned int` to `uint16_t`. - Introduced `xkb_{action,keysym}_count_t` type for the respective item count for exact typing. - Added relevant bounds checks.
Pierre Le Marre 256be1ea 2025-03-25T08:13:21 xkbcomp: Fix merge mode for defaults actions - Keep defaults local: do not share accross includes. - Do not allocate default actions.
Pierre Le Marre 7dbd2576 2025-04-01T19:20:10 keymap: Use constants for Lock and Control indexes These indexes are fixed, so there is no need to lookup their name.
Julian Orth cb3565b1 2025-03-07T17:59:33 keymap: Fix segfault due to invalid group wrapping The modular arithmetic is incorrect for negative values, e.g. for num_groups = 1. It triggers a segfault for the following settings: - layouts count (per key or total) N: `N > 0`, and - layout index n: `n = - k * N` (`k > 0`) % returns the *remainder* of the division, not the modulus (see C11 standard 6.5.5 “Multiplicative operators”: a % b = a - (a/b)*b. While both operators return the same result for positive operands, they do not for e.g. a negative dividend: remainder may be negative (in the open interval ]-num_groups, num_groups[) while the modulus is always positive. So if the remainder is negative, we must add `num_groups` to get the modulus. Fixes: 67b03cea ("state: correctly wrap state->locked_group and ->group") Signed-off-by: Julian Orth <ju.orth@gmail.com> Co-authored-by: Julian Orth <ju.orth@gmail.com> Co-authored-by: Pierre Le Marre <dev@wismill.eu>
Pierre Le Marre 5ef19bcf 2025-02-13T17:58:21 xkbcomp: Fix incorrect memory comparison Spotted by clang-tidy: ``` ../src/keymap-priv.c:146:16: warning: comparing object representation of type 'union xkb_action' which does not have a unique object representation; consider comparing the members of the object manually [bugprone-suspicious-memory-comparison] ```` Indeed, from “EXP42-C. Do not compare padding data”[^1]: > unnamed members of objects of structure and union type do not participate > in initialization. Unnamed members of structure objects have indeterminate > representation even after initialization. Fixed by using a dedicated comparison function for `union xkb_action`. [^1]: https://wiki.sei.cmu.edu/confluence/display/c/EXP42-C.+Do+not+compare+padding+data
Pierre Le Marre e3108182 2025-02-12T09:49:25 Fix int casts related to layout index - XkbWrapGroupIntoRange - State
Ran Benita e120807b 2025-01-29T15:35:22 Update license notices to SDPX short identifiers + update LICENSE Fix #628. Signed-off-by: Ran Benita <ran@unusedvar.com>
Pierre Le Marre c85c9bdc 2025-01-27T17:15:06 symbols: Allow levels with different keysyms and actions counts Contrary to groups, there is no reason for levels to restrict the same count of keysyms and actions.
Pierre Le Marre 842497d9 2025-01-22T16:46:11 clang-tidy: Fix implicit or incorrect integer casts
Pierre Le Marre e3e44998 2025-01-16T20:23:47 Fix missing or incorrect integer literal suffixes The correct suffix is required in order to have the expected value in a portable way.
Pierre Le Marre d43bb955 2024-12-19T18:21:01 symbols: Fix key symbols/actions merge - Fixed field for defined keysyms/actions - Fixed regression introduced by fdf2c525977e7e8af4135d593110f5bc1454abd8
Pierre Le Marre 086a286a 2024-09-23T16:20:17 mods: Always use constants from xkbcommon-names.h Respect the claim that real modifiers names are built-in: - Add `XKB_MOD_NAME_MOD[1-5]` constants. - Replace modifiers names with their corresponding constants.
Pierre Le Marre fdf2c525 2024-10-08T19:43:30 actions: Add support for multiple actions per level This makes 1 keysym == 1 action holds also for multiple keysyms per level. The motivation of this new feature are: - Make multiple keysyms per level more intuitive. - Explore how to fix the issue with shortcuts in multi-layout settings (see the xkeyboard-config issue[^1]). The idea is to use e.g.: ```c key <LCTL> { symbols[1] = [ {Control_L, ISO_First_Group } ], actions[1] = [ {SetMods(modifiers=Control), SetGroup(group=-4) } ] }; ``` in order to switch temporarily to a reference layout in order to get the same shortcuts on every layout. When no action is specified, `interpret` statements are used to find an action corresponding for *each* keysym, as expected. For an interpretation matching Any keysym, we may get the same interpretation for multiple keysyms. This may result in unwanted duplicate actions. So set this interpretation only if no previous keysym was matched with this interpret at this level, else set the default interpretation. For now, at most one action of each following categories is allowed per level: - modifier actions: `SetMods`, `LatchMods`, `LockMods`; - group actions: `SetGroup`, `LatchGroup`, `LockGroup`. Some examples: - `SetMods` + `SetGroup`: ok - `SetMods` + `SetMods`: error - `SetMods` + `LockMods`: error - `SetMods` + `LockGroup`: ok [^1]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/issues/416
Pierre Le Marre 772ac0c4 2024-09-23T11:02:35 keymap: Rename keysyms field in xkb_level The current field `u` (short for “union”) is not very descriptive. Next commit will add multiple actions per level, so let’s rename the keysym field to `s` (short for “symmbols”).
Ran Benita 40aab05e 2019-12-27T13:03:20 build: include config.h manually Previously we included it with an `-include` compiler directive. But that's not portable. And it's better to be explicit anyway. Every .c file should have `include "config.h"` first thing. Signed-off-by: Ran Benita <ran@unusedvar.com>
Daniel Stone 5440aaa5 2017-06-26T21:52:27 Fix signed vs. unsigned confusion in name sanitisation Don't try to divide through a signed char when indexing an array, lest ye try to index off the start of it. Signed-off-by: Daniel Stone <daniels@collabora.com>
Ran Benita 39082082 2016-02-28T00:33:19 keymap: share LevelsSameSyms() The function is generic enough. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 787faf36 2014-04-22T12:23:36 keymap: don't use darray in xkb_mod_set Instead just statically allocate the mods array (of size MAX_MOD_SIZE = 32). The limit is not going anywhere, and static allocations are nicer (nicer code, no OOM, etc.). It's also small and dense enough. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 6b1cdee1 2014-04-22T11:47:23 keymap: add and use xkb_mods_{foreach,enumerate}() To iterate over an xkb_mod_set. Slightly nicer interface and makes transitioning from darray easier. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 0f6bca2b 2014-04-22T11:33:47 keymap: rename xkb_foreach_key to xkb_keys_foreach We'll use the format xkb_foos_foreach and xkb_foos_enumerate for the various iterators. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 95aabeec 2013-02-09T19:10:56 symbols: use xkb_mod_set instead of entire keymap The keymap is not removed entirely from the Info (just constified), since it is still needed in AddKeySymbols() for looking up aliases. This dependency will be removed in the future. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita edc0aef5 2013-02-08T13:21:27 text: take xkb_mod_set instead of the entire keymap The modifier printing functions only need the modifier information, they don't care about keys or leds, etc. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita ca3170ad 2013-02-08T13:09:33 Add struct xkb_mod_set The only thing that the compilation phase needs the keymap for currently is for access to the modifier information (it also modifies it in place!). We want to only pass along the neccessary information, to make it more tractable and testable, so instead of passing the entire keymap we add a new 'mod_set' object and pass a (const) reference to that. The new object is just the old array of 'struct xkb_mod'. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 51a1df2f 2014-04-19T15:56:27 keymap: move ModNameToIndex from text.c and use it in keymap.c Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita fa87cdb8 2014-02-07T19:39:42 darray: cleanup We have quite diverged from the upstream file, so let's make it at least easier to look at. Remove some unused macros and rename some for consistency. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 7210497c 2014-01-13T17:07:41 keymap: split private functions to keymap-priv.c This makes it easier to share the private functions in other DSOs without relying (too much) on dead code elimination, exported symbols, etc. Signed-off-by: Ran Benita <ran234@gmail.com>