src/state.c


Log

Author Commit Date CI Message
Pierre Le Marre 10457563 2025-05-12T06:41:28 keymap: Ensure proper type for actions count
Pierre Le Marre 903c16da 2025-05-12T07:42:32 keymap: Ensure proper type for key types counts
Pierre Le Marre b4c89600 2025-05-09T15:15:10 actions: Add VoidAction(), mirroring NoSymbol/VoidSymbol. Added `VoidAction()` action to match the keysym pair `NoSymbol` / `VoidSymbol`. It enables overriding a previous action and breaks latches. This is a libxkbcommon extension. When serializing it will be converted to `LockControls(controls=none,affect=neither)` for backward compatibility. We cannot serialize it to `NoAction()`, as it would be dropped in e.g. the context of multiple actions.
Pierre Le Marre 551cca2a 2024-12-03T10:12:03 state: Add server API for updating latched and locked mods & layout Up to now, the “server state” `xkb_state` API only offered one entry point to update the server state – `xkb_state_update_key`, which reflects the direct keyboard keys state. But some updates come out-of-band from keyboard input events stream, for example, a GUI layout switcher. The X11 XKB protocol has a request which allows for such updates, `XkbLatchLockState`[^1], but xkbcommon does not have similar functionality. So server applications ended up using `xkb_state_update_state` for this, but that’s a function intended for client applications, not servers. Add support for updating the latched & locked state of the mods and layout. Note that the depressed states cannot be updated in this way -- XKB does not expect them to be updated out of band. [^1]: https://www.x.org/releases/X11R7.7/doc/kbproto/xkbproto.html#Querying_and_Changing_Keyboard_State Fixes: #310 Signed-off-by: Ran Benita <ran@unusedvar.com> Co-authored-by: Ran Benita <ran@unusedvar.com> Co-authored-by: Pierre Le Marre <dev@wismill.eu>
Pierre Le Marre 662ce937 2024-12-03T10:09:10 state: Avoid keycode lookup when key ref is available
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 e1aca42e 2025-05-05T12:06:18 state: Minor refactor - Move variable declaration close to their use. - Make them constant whenever possible.
Pierre Le Marre 8bc60ee3 2025-05-05T13:20:45 modifiers: Minor optimization It has low impact, but it also adds better semantics.
Pierre Le Marre 9ede705b 2025-04-13T09:50:18 state: Capitalization transformation in xkb_state_key_get_syms Previously `xkb_state_key_get_syms()` did not perform capitalization tranformation, while `xkb_state_key_get_one_sym()` does perform it. This is unfortunate if we want to promote the use of multiple keysyms per levels. The API make it difficult to change now though: we return a pointer to an immutable array rather than filling a buffer. While we could use an internal buffer in `xkb_state`, this option would limit the API to *sequential* calls of `xkb_state_key_get_syms()` or require some buffer handling (e.g. rotation). Instead we now store the capitalization directly in `xkb_level`. We modified `xkb_level` like so (see below for discussion about the size): ```diff struct xkb_level { - unsigned int num_syms; + uint16_t num_syms; - unsigned int num_actions; + uint16_t num_actions; + union { + /** num_syms == 1: Upper keysym */ + xkb_keysym_t upper; + /** num_syms > 1: Indicate if `syms` contains the upper case + * keysyms after the lower ones. */ + bool has_upper; + }; union { xkb_keysym_t sym; /* num_syms == 1 */ xkb_keysym_t *syms; /* num_syms > 1 */ } s; union { union xkb_action action; /* num_actions == 1 */ union xkb_action *actions; /* num_actions > 1 */ } a; }; ``` - When `level.num_syms` <= 1, we store the upper keysym in `level.upper`. - Else if there no cased syms, we set `level.has_upper` to false. - Else if there are some cased syms, we set `level.has_upper`` to `true` and we double the original size of `level.s.syms`, but *without* modifying `level.num_syms`. We then append the transformed keysyms right after the original ones, so that we can access them by a simple pointer operation: `level.s.syms + level.num_syms`. The memory footprint is *unchanged*, thanks to the reduced fields for actions and keysyms counts.
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.
Pierre Le Marre e3108182 2025-02-12T09:49:25 Fix int casts related to layout index - XkbWrapGroupIntoRange - State
Ran Benita a380ba52 2025-01-25T07:00:43 Move XKB_EXPORT to headers The Windows dllexport annotation wants to be on the declarations, not the definitions. Signed-off-by: Ran Benita <ran@unusedvar.com>
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 af5704dc 2025-01-25T11:01:03 state: Fix empty level not breaking latches In essence empty levels are levels with just a `NoSymbol` keysym and a `NoAction()`, which breaks latches. Fixed regression introduced in fdf2c525977e7e8af4135d593110f5bc1454abd8. Added tests also for the case where the keycode is unknown.
Pierre Le Marre 842497d9 2025-01-22T16:46:11 clang-tidy: Fix implicit or incorrect integer casts
Pierre Le Marre c7fdf506 2025-01-16T20:23:28 Use portable integer literal suffixes
Jules Bertholet 3fdd822d 2025-01-16T02:21:29 state: Fix mods not being independently cleared (#584) The modifiers filters should ensure minimal interaction between them, but currently the Latch mod filters are overzealous and mess with the mods from other filters set to be cleared, resulting in some modifiers permanently set. Fixed by clearing mods properly with `OR` rather than direct setting of `state::clear_mods`. While we are at it, `state::set_mods` should be `OR`ed as well. This should not have any impact for now, but this is more future-proof. Fixes #583 Co-authored-by: Jules Bertholet <julesbertholet@quoi.xyz> Co-authored-by: Pierre Le Marre <dev@wismill.eu>
Pierre Le Marre 6c6dbf32 2025-01-07T11:19:30 state: Fix LatchGroup action with latchToLock disabled A `LatchGroup` action with the `latchToLock`` option disabled can apply its latch effect multiple times.
Pierre Le Marre 325ba10e 2025-01-07T16:27:50 state: Fix LEDs driven by the group state When the indicator field `whichGroupState` is set to `Base` or `Latched`, the group masks should be considered only as boolean values as per the XKB specification.
Pierre Le Marre e0130e30 2024-11-18T20:08:56 state: Add vmod support for xkb_state_mod_mask_remove_consumed
Pierre Le Marre 5fbc0ec7 2024-10-14T16:05:52 state: Support querying whether virtual mods are consumed Previously it was not possible to query the status of virtual modifiers with the following functions: - `xkb_state_mod_index_is_consumed` - `xkb_state_mod_index_is_consumed2` Note that it may *overmatch* if some modifier mappings overlap. For example, the default “us” PC layout maps both “Alt” and “Meta” to the real modifier “Mod1”; thus “Mod1”, “Alt” and “Meta” modifiers will return the same result with these functions.
Pierre Le Marre 31a841ae 2024-10-14T16:05:35 state: support querying whether virtual modifiers are active Previously it was not possible to query the status of virtual modifiers with the following functions: - `xkb_state_mod_index_is_active` - `xkb_state_mod_indices_are_active` - `xkb_state_mod_name_is_active` - `xkb_state_mod_names_are_active` Note that it may *overmatch* if some modifier mappings overlap. For example, the default “us” PC layout maps both “Alt” and “Meta” to the real modifier “Mod1”; thus “Mod1”, “Alt” and “Meta” modifiers will return the same result with these functions.
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 8b45556d 2024-09-24T21:51:14 logging: Make log_err_func* use a message ID
Pierre Le Marre e9bd7de4 2024-07-04T16:22:13 state: Add support for group latch action Surprisingly, the latch group action was not yet implemented. Added tests to ensure we get the tricky bits right.
Pierre Le Marre addf73c5 2024-07-12T09:17:34 keysyms: Require only 5 bytes for UTF-8 encoding Require only 5 bytes for the buffer of `xkb_keysym_to_utf8`, as UTF-8 encodes code points on up to 4 bytes + 1 byte for the NULL-terminating byte. Previous standard [RFC 2279] (1998) required up to 6 bytes per code point, but has been superseded by [RFC 3629] (2003). [RFC 2279]: https://datatracker.ietf.org/doc/html/rfc2279 [RFC 3629]: https://datatracker.ietf.org/doc/html/rfc3629
Pierre Le Marre 7185b023 2023-09-24T09:40:08 Add documentation to XkbToControl While some transformations are defined in the section “Interpreting the Control Modifier” of the XKB protocol, a lot are not. Documentation is scarce about the topic, so write down some context using the following sources: - https://en.wikipedia.org/wiki/Caret_notation#Use_in_software - https://www.vt100.net/shuford/terminal/dec_keyboards_news.txt - https://misc.openbsd.narkive.com/NvSWf6ax/which-key-shortcuts-are-safe-to-bind-and-some-q-s-about-history-and-os-diffs-re-ctrl-4-means - https://vt100.net/docs/vt220-rm/chapter3.html#T3-5
Sam James fed96378 2023-11-05T22:06:40 state: fix -Walloc-size GCC 14 introduces a new -Walloc-size included in -Wextra which gives: ``` src/state.c:589:9: warning: allocation of insufficient size ‘1’ for type ‘struct xkb_state’ with size ‘128’ [-Walloc-size] ``` The calloc prototype is: ``` void *calloc(size_t nmemb, size_t size); ``` So, just swap the number of members and size arguments to match the prototype, as we're initialising 1 struct of size `sizeof(struct xkb_state)`. GCC then sees we're not doing anything wrong. Signed-off-by: Sam James <sam@gentoo.org>
Jaroslaw Kubik d92a248c 2020-02-05T17:42:06 API to query modifier set required to type a keysym The new API is useful to implement features like auto-type and desktop automation. Since the inputs for these features is usually specified in terms of the symbols that need to be typed, the implementation needs to be able to invert the keycode->keysym transformation and produce a sequence of keycodes that can be used to type the requested character(s).
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>
Michael Forney 9d58bbd4 2019-06-04T14:01:02 Use bitwise test instead of popcount to check if one bit is set We don't need to determine the total number of bits set to determine if exactly one is set. Additionally, on x86_64 without any -march=* flag, __builtin_popcount will get compiled to a function call to the compiler runtime (on gcc), or a long sequence of bit operations (on clang). Signed-off-by: Michael Forney <mforney@mforney.org>
Ran Benita 767fa86d 2017-12-21T14:18:07 Convert http:// -> https:// where possible Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 6b57344c 2017-04-27T20:06:21 state: cure boolean blindness in the filter functions' result Makes it a little easier to understand the filters. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 927fd8f8 2017-04-27T19:17:53 state: remove unneeded NULL check xkb_filter_new() cannot return NULL. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita d44c3ab2 2017-04-27T19:14:56 state: reorder new() functions before the set() functions in the code So that they may be read more naturally in chronological order. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 327364d2 2016-11-14T17:37:35 utils: rename popcount to avoid conflict in NetBSD Resolves https://github.com/xkbcommon/libxkbcommon/issues/41 Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita babc9e0c 2016-02-27T22:31:16 state: add GTK consumed modifiers mode This is more or less what is implemented here: https://git.gnome.org/browse/gtk+/tree/gdk/x11/gdkkeys-x11.c?h=3.19.10#n1131 The implementation here is more technically correct but should provide the same results. Try it out with ./test/interactive-evdev -g (modifiers prefixed with "-" are consumed). https://bugzilla.gnome.org/show_bug.cgi?id=754110 https://github.com/xkbcommon/libxkbcommon/issues/17 Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita a0a41332 2016-02-27T19:06:14 state: allow different modes for calculating consumed modifiers The current functions dealing with consumed modifiers use the traditional XKB definition of consumed modifiers (see description in the added documentation). However, for several users of the library (e.g. GTK) this definition is unsuitable or too eager. This is exacerbated by some less-than-ideal xkeyboard-config type definitions (CTRL+ALT seems to cause most grief...). So, because we - want to enable alternative interpretations, but - don't want to expose too much internal details, and - want to keep things simple for all library users, we add a high-level "mode" parameter which selects the desired interpretation. New ones can be added as long as they make some sense. All of the old consumed-modifiers functions keep using the traditional ("XKB") mode. I mark xkb_state_mod_mask_remove_consumed() and as deprecated without adding a *2 variant because I don't it is very useful (or used) in practice. Alternative modes are added in subsequent commits (this commit only adds a mode for the existing behavior). https://github.com/xkbcommon/libxkbcommon/issues/17 Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita c8e6996f 2016-06-09T15:30:21 src/state: match_mod_masks can return bool instead of int Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita c8a25645 2016-02-28T00:02:05 state: factor out get_entry_for_mods() Will be useful later. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 9f5139b5 2016-02-27T19:43:07 state: factor out entry_is_active() check Makes the code slightly cleaner and I plan to use the function in another place. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 13d23259 2015-09-07T14:45:09 state: reduce scope of fake action Also rename to "dummy" as I think it is a nicer name. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita c03834a1 2014-10-23T21:00:20 Reduce variable scopes Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 30e7445d 2014-10-17T00:41:05 state: correctly infer inactive type entries The current test is incorrect, since 'map[None]' is entirely valid. In most cases this doesn't cause any problems, since the default fallback is Level1, and it's almost always 'map[None] = Level1' anyway. But in one case in xkeyboard-config it isn't, in types/numpad(mac): type "KEYPAD" { modifiers = None; map[None] = Level2; level_name[Level2] = "Number"; }; So before checking if no modifiers were mapped, make sure there *were* any modifiers at all. https://bugs.freedesktop.org/show_bug.cgi?id=85092 Reported-by: Gatis Paeglis <gatis.paeglis@digia.com> Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita a1f0595a 2014-08-18T20:27:07 state: make sure the mods are fully resolved after xkb_state_update_mask() Virtual modifiers can have "mappings" to real modifiers, e.g. NumLock may also set Mod2. In a normal turn of events, the various components (depressed, latched, locked, and consequently effective) include the mapped mods, because the masks are pre-resolved everywhere. However, xkb_state_update_mask() accepts arbitrary mod masks, which may not be resolved (if it comes from somewhere other than xkb_state_serialize_mods()). So let's always resolve them ourselves. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 99184f16 2012-11-24T13:29:54 Make the effective mod mask calculation available to other files We will want to use that function in state.c as well. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 80ae8e61 2014-08-18T20:08:25 state: no need for loop in xkb_state_update_mask() Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 9014cf8c 2014-04-22T13:15:21 keymap, keycodes, compat: don't use darray for LEDs Use a static array of size XKB_MAX_LEDS instead, as in xkb_mod_set. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 3d7aff5f 2014-04-19T16:15:05 keymap: rename wrap_group_into_range -> XkbWrapGroupIntoRange It better fits with the naming convention in keymap.h. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 54174409 2014-03-27T17:42:20 state: fix consumed modifier calculation The current calculation is in short: entry ? (entry->mask & ~entry->preserve) : 0 This changes it be type->mask & ~(entry ? entry->preserve : 0) This is what Xlib does. While less intuitive, it is actually more correct, if you follow this deduction: - The key group's type->mask defines which modifiers the key even cares about. The others are completely irrelevant (and in fact they are masked out from all sided in the level calculation). Example: NumLock for an alphabetic key. - The type->mask, the mods which are not masked out, are *all* relevant (and in fact in the level calculation they must match *exactly* to the state). These mods affect which level is chosen for the key, whether they are active or not. - Because the type->mask mods are all relevant, they must be considered as consumed by the calculation *even if they are not active*. Therefore we use type->mask instead of entry->mask. The second change is what happens when no entry is found: return 0 or just take preserve to be 0? Let's consider an example, the basic type type "ALPHABETIC" { modifiers = Shift+Lock; map[Shift] = Level2; map[Lock] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Caps"; }; Suppose Shift+Lock is active - it doesn't match any entry, thus it gets to level 0. The first interpretation would take them both to be unconsumed, the second (new one) would take them both to be consumed. This seems much better: Caps is active, and Shift disables it, they both do something. This change also fixes a pretty lousy bug (since 0.3.2), where Shift appears to apparently *not* disable Caps. What actually happens is that Caps is not consumed (see above) but active, thus the implicit capitalization in get_one_sym() kicks in and capitalizes it anyway. Reported-by: Davinder Pal Singh Bhamra Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 3cfa7fda 2014-03-21T23:00:37 state: apply control transformation on utf8/utf32 keysym strings This is required by the specification: http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier and clients expect this to happen. https://bugs.freedesktop.org/show_bug.cgi?id=75892 Reported-by: Gatis Paeglis <gatis.paeglis@digia.com> Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita b973d71e 2014-03-21T23:00:17 state: add xkb_state_key_get_{utf8,utf32}() API functions These functions generally have the same effect as xkb_state_key_get_syms() + xkb_keysym_to_utf{8,32}(). So why add them? - They provide a slightly nicer interface, especially if the string is the only interest. - It makes the handling of multiple-keysyms-to-utf8 transparent. For the designated use-case of multiple-keysyms (unicode combining characters), this is a must. We also validate the UTF-8, which the user might not otherwise do. - We will need to apply some transformation on the resulting string which depend on the xkb_state. This is not possible with the xkb_keysym_* functions. With these functions, the existing xkb_keysym_to_utf{8,32}() are not expected to be used by a typical user; they are "raw" functions. Signed-off-by: Ran Benita <ran234@gmail.com>
Jasper St. Pierre 4fb7b06b 2014-02-21T18:09:00 state: Add xkb_state_key_get_consumed_mods This retrieves the mask of consumed modifiers for a given key and state, which is helpful for toolkits without having them to do it one modifier at a time, or pass in 0xFFFFFFFF to xkb_state_remove_consumed_mods to "reverse-engineer" the consumed mods.
Ran Benita e89516e9 2014-02-09T13:51:38 state: check wrap_group_into_range() return value It returns XKB_LAYOUT_INVALID in case num_groups == 0. So we shouldn't just save it in the state. Note, though, that this condition is generally impossible. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 04bacf87 2014-02-08T15:53:50 state: optimize xkb_state_led_update_all() Before: ran@ran:~/src/libxkbcommon$ ./test/bench-key-proc ran 20000000 iterations in 6.623018074s After: ran@ran:~/src/libxkbcommon$ ./test/bench-key-proc ran 20000000 iterations in 4.762291091s Not that anyone needs to process millions of keys per second... Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 769b91c5 2014-02-08T15:30:05 Use (1u << idx) instead of (1 << idx) where appropriate It doesn't matter (I think), since the implicit conversion doesn't have any effect (e.g. sign-extension). But it's better to be aware of the type. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 623b10f8 2014-02-08T00:27:54 Fix sign-compare warnings Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 2abff2a0 2014-02-07T17:29:34 state: use the XKB_MOD_MASK constant Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 31430670 2014-01-11T16:40:42 Fix some cppcheck warnings Someone was nice enough to run this for us: ftp://ftp.sunet.se/pub/Linux/distributions/Debian/debian/pool/main/libx/libxkbcommon/libxkbcommon_0.3.1.orig.tar.gz [libxkbcommon-0.3.1/src/keymap.c:86]: (style) The scope of the variable 'j' can be reduced. [libxkbcommon-0.3.1/src/keymap.c:87]: (style) The scope of the variable 'key' can be reduced. [libxkbcommon-0.3.1/src/keysym-utf.c:843]: (style) The scope of the variable 'mid' can be reduced. [libxkbcommon-0.3.1/src/state.c:992]: (style) The scope of the variable 'str' can be reduced. [libxkbcommon-0.3.1/src/xkbcomp/action.c:467]: (style) The scope of the variable 'absolute' can be reduced. [libxkbcommon-0.3.1/src/xkbcomp/rules.c:468]: (style) The scope of the variable 'consumed' can be reduced. [libxkbcommon-0.3.1/src/xkbcomp/rules.c:862]: (style) The scope of the variable 'mlvo' can be reduced. [libxkbcommon-0.3.1/src/xkbcomp/rules.c:863]: (style) The scope of the variable 'kccgst' can be reduced. [libxkbcommon-0.3.1/src/xkbcomp/rules.c:865]: (style) The scope of the variable 'match_type' can be reduced. [libxkbcommon-0.3.1/src/xkbcomp/symbols.c:753]: (style) The scope of the variable 'toAct' can be reduced. [libxkbcommon-0.3.1/src/xkbcomp/symbols.c:1573]: (style) The scope of the variable 'key' can be reduced. [libxkbcommon-0.3.1/test/common.c:80]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [libxkbcommon-0.3.1/test/interactive.c:358]: (style) The scope of the variable 'nevs' can be reduced. [libxkbcommon-0.3.1/test/interactive.c:236]: (style) Checking if unsigned variable 'nsyms' is less than zero. [libxkbcommon-0.3.1/test/interactive.c:226]: (style) Unused variable: unicode Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 2a2a8d7d 2013-08-13T18:57:43 state: apply capitalization transformation on keysyms The xkbproto spec says: http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier If the Lock modifier is not consumed by the symbol lookup process, routines that determine the symbol and string that correspond to an event should capitalize the result. This was not an issue until now, because most xkeyboard-config keymaps do not utilize this "feature", and specify the keysyms for the Lock modifier explicitly instead. However, some keymaps do depend on it, e.g. ch(fr) for eacute and others. The spec goes on to describe two options for doing this transformation: locale-sensitive and locale-insensitive. We opt for the latter; it is less desirable but we don't want *that* headache. Also, only xkb_state_key_get_one_sym() is changed; xkb_state_key_get_syms() is left as-is, and always reports the untransformed keysyms. This is for the following reasons: - The API doesn't allow it, since we return a const pointer directly to the keymap keysyms table and we can't transform that. - The transformation doesn't make sense for multiple-keysyms. - It can be useful for an application to get the "raw" keysyms if it wants to (e.g. maybe it wants to do the transformation itself). Finally, note that xkb_state_mod_index_is_consumed() does *not* report Lock as consumed even if it was used in the transformation. This is what Xlib does. This definitely doesn't fall under the "hard to misuse" API rule but it's the best we can do. https://bugs.freedesktop.org/show_bug.cgi?id=67167 Reported-By: Gatis Paeglis <gatis.paeglis@digia.com> Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita be38862b 2013-07-26T00:50:26 keymap: remove struct xkb_key_redirect_action The file src/xkbcomp/action.c already doesn't handle this action type and fails if it encounters it. So lets not pretend to do something with it, and ignore it rather than failing. If we/someone wants this we can consider implementing it. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 9f75e0ab 2013-03-07T01:15:21 state: use stdbool in filters Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 57bfde3a 2013-03-04T18:41:13 keymap: rename xkb_kt_map_entry to xkb_key_type_entry That's a better name and fits more nicely. Also change type->map to type->entries. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita cd6a71fc 2013-03-04T02:12:00 state: small style fix Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 8cee7490 2013-02-17T22:18:57 Change 'indicator' to 'led' everywhere possible The code currently uses the two names interchangeably. Settle on 'led', because it is shorter, more recognizable, and what we use in our API (though of course the parser still uses 'indicator'). In camel case we make it 'Led'. We change 'xkb_indicator_map' to just 'xkb_led' and the variables of this type are 'led'. This mimics 'xkb_key' and 'key'. IndicatorNameInfo and LEDInfo are changed to 'LedNameInfo' and 'LedInfo', and the variables are 'ledi' (like 'keyi' etc.). This is instead of 'ii' and 'im'. This might make a few places a bit confusing, but less than before I think. It's also shorter. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 089c3a18 2013-02-17T14:59:50 state: fix unbound virtual modifier bug Recent xkeyboard-config introduced the following line in symbols/level3: vmods = LevelThree, However, the XKM format which xkbcomp produces for the X server can't handle explicit virtual modifiers such as this: https://bugs.freedesktop.org/show_bug.cgi?id=4927 So by doing the following, for example: setxkbmap -layout de (or another 3-level layouts) xkbcomp $DISPLAY out.xkb xkbcomp out.xkb $DISPLAY The modifier is lost and can't be used for switching to Level3 (see the included test). We, however, are affected worse by this bug when we load the out.xkb keymap. First, the FOUR_LEVEL_ALPHABETIC key type has these entries: map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; [...] Now, because the LevelThree virtual modifier is not bound to anything, the effective mask of the "map[LevelThree]" entry is just 0. So when the modifier state is empty (initial state), this entry is chosen, and we get Level3, instead of failing to match any entry and getting the default Level1. The difference in behavior from the xserver stems from this commit: acdad6058d52dc8a3e724dc95448300850d474f2 Which removed the entry->active field. Without bugs, this would be correct; however, it seems in this case we should just follow the server's behavior. The server sets the entry->active field like so in XKBMisc.c: /* entry is active if vmods are bound */ entry->active = (mask != 0); The xkblib spec explains this field, but does not specify how to initialize it. This commit does the same as above but more directly. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita f1598469 2012-11-11T16:14:30 state: rename state->cur to state->components 'cur' doesn't make sense anymore. 'components' is a bit long for this, but not too bad, and nothing better comes to mind. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 7372c9f1 2012-11-11T16:06:54 state: don't keep the previous state components in xkb_state There is really no need to keep this in the struct, we can just allocate it on the stack when we need to. Don't know why I did it this way. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 60bd9202 2012-11-11T00:22:46 keymap: wrap the layout parameter if it is out of range for the key The functions num_levels_for_key() and get_syms_by_level() have a 'layout' parameter. Currently it is expected that this value is always legal for the key, as determined by num_layouts_for_key(). However, there are legitimate use cases for passing an out-of-range layout there, most probably passing the effective layout, and expecting to get the keysyms/levels for just this layout. So we wrap it just as we do in the xkb_state_* functions. This is also useful for stuff like this: http://developer.gnome.org/gdk/stable/gdk-Keyboard-Handling.html#gdk-keymap-lookup-key If this behavior is not desired, the user has the option to check against num_layouts_for_key herself. https://bugs.freedesktop.org/show_bug.cgi?id=56866 Reported-by: Gatis Paeglis <gatis.paeglis@digia.com> Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 7261f404 2012-10-29T01:00:27 state, context: allow passing NULL to *_unref() For error handling code, it's nice to be able to pass NULL to these function without worrying about segfaults ensuing. free() sets the precedent here. Also document this fact. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita a51ee704 2012-10-26T16:24:11 state: don't use xkb_keymap_num_layouts internally Clearer and more greppable this way. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita ee6f3f28 2012-10-26T16:12:28 state: don't use xkb_state_serialize_* internally The code in these cases is clearer when done directly. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 6f093ad5 2012-10-24T23:09:26 state: fix possible index-out-of-bounds in action dispatch table The current code assumes that action->type always falls in the range of the xkb_action_type enum. But keymaps can also have Private actions, which are allowed to set their own type number. So with a default xkeyboard-config keymap, keycode 86 at level 4, which triggers such an action, causes us to crash. Fix it by always checking the bounds. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 867992cd 2012-10-23T17:17:18 state: fix typo in state component copying Gladly no-one should have been fast enough to hit this. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 4b81c9f3 2012-10-22T21:00:57 Report which components of the state have changed We add a return value to the xkb_state_update_key and xkb_state_update_mask, which reports to the caller which of the state components have changed as a result. This restores the XKB functionality of the XkbStateNotify and XkbIndicatorsStateNotify events. See: http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Events It is quite useful in some situations. For example, it allows an application to avoid doing some work if nothing of relevance in the state has changed. Say, a keyboard layout applet. Also useful for debugging. The deltas themselves are not provided, because I can't see a use case. If needed, it should be possible to add some API for that. In xkbcommon, keymaps are immutable, so all of the other *Notify events from XKB are irrelevant. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 550cb24d 2012-10-22T19:19:43 state: add struct state_components This holds all of the state component fields in the state in one struct. We will later want to keep the previous state components after updates, so this will allow us to do it without duplicating the fields. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 6a94b122 2012-10-22T20:49:44 Split the mods, layout, leds parts of xkb_state_components Note first: This commits breaks the ABI somewhat. If an application is run against this commit without recompiling against the updated header, these break: - xkb_state_layout_*_is_active always retuns false. - xkb_state_serialize_mods always returns 0. So it might break layout switching in some applications. However, xkbcommon-compat.h provides the necessary fixes, so recompiling should work (though updating the application is even better). Split the enum to its individual components, which enables us to refer to them individually. We will use that later for reporting which components of the state have changed after update. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita f43b33c0 2012-10-13T13:13:55 state: make mod_index_is_consumed() return -1 on invalid input Like all the other functions. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 9197eb0f 2012-10-10T19:08:01 Remove the XKB_NUM_INDICATORS limit Use a darray instead of a static array of size 32. We still enforce XKB_MAX_LEDS because of the size of xkb_led_mask_t. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 2f4db8a9 2012-10-10T09:47:31 keymap, state: don't assume led index < xkb_keymap_num_leds xkb_keymap_num_leds() returns the number of leds that have any possibility of being set. Even if a led is defined but can not be set in any way, it is not counted. In a few places currently we assume that led indexes are smaller than this number, which is wrong both for the above reason and for the fact that the xkb format actually allows explicitly setting the indicator index, which means that the indexes might be non-consecutive. We don't really have good API to iterate on leds, now, because xkb_keymap_num_leds is pretty useless. To work around that we use sizeof(xkb_led_mask_t) * 8. This makes the "Group 2" led work (try switching to a layout other than the first in test/interactive). Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita b65980cc 2012-10-05T15:10:41 state: don't needlessly fetch the xkb_key It's a leftover. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita e5b6055b 2012-10-03T20:16:09 state: don't ignore type argument in xkb_state_mod_*_are_active Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 1a6b1e07 2012-10-03T19:41:22 state: fix bad EFFECTIVE check in *_is_active() This is a regression introduced in ed78fbcb30888cbfc6cd00. XKB_STATE_EFFECTIVE is just a OR of the other states, so using & here is completely wrong. So test/state shows for example: dumping state for LCtrl down: group English (US) (0): effective depressed latched locked mod Control (2): depressed latched locked dumping state for LCtrl + RAlt down: group English (US) (0): effective depressed latched locked mod Control (2): depressed latched locked mod Mod1 (3): depressed latched locked dumping state for RAlt down: group English (US) (0): effective depressed latched locked mod Mod1 (3): depressed latched locked dumping state for Caps Lock: group English (US) (0): effective depressed latched locked mod Lock (1): depressed latched locked led Caps Lock (0): active dumping state for Alt-Shift-+ group English (US) (0): effective depressed latched locked mod Shift (0): depressed latched locked mod Mod1 (3): depressed latched locked which is bogus. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita fe1faa14 2012-10-03T20:08:13 Use our types instead of int/uint32_t in a few places Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 8016c6f4 2012-10-03T20:21:05 state: simplify xkb_state_mod_index_is_active Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 11df0632 2012-09-27T21:11:11 state: add missing const in get_one_sym Signed-off-by: Ran Benita <ran234@gmail.com>
Daniel Stone 5aaf65b7 2012-09-27T23:27:49 Add xkb_state_key_get_one_sym The trivial wrapper around xkb_state_key_get_syms that every user to date has implemented. Signed-off-by: Daniel Stone <daniel@fooishbar.org>
Ran Benita 5d265926 2012-09-24T14:57:30 keymap: remove some more unneeded macros It clearer to just access the needed data directly. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita c955f8e2 2012-09-24T14:41:09 keymap: store a pointer to the type in xkb_group instead of index Gets rid of some more unneeded indirection, including the XkbKeyType macro. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 01b00d75 2012-09-24T12:11:31 keymap, symbols: improve xkb_key memory layout Add struct xkb_group and xkb_level for use in xkb_key, to mirror how it's done in KeyInfo, GroupInfo, LevelInfo in symbols.c. This corresponds more nicely to the logical data layout (i.e. a key has groups which have levels), and also removes a lot of copying and ugly code due to the index indirections and separate arrays which were used before. This uses more memory in some places (e.g. we alloc an action for every level even if the key doesn't have any) but less in other places (e.g. we no longer have to pad each group to ->width levels). The numbers say we use less overall. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 419a4975 2012-09-21T21:16:20 state: missing XKB_EXPORT on xkb_state_key_get_level And some error handling. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 7d1db12d 2012-09-21T15:39:32 state: separate group wrapping/clamping to a function We'll need this function for wrapping our global effective group as well. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita ed78fbcb 2012-09-21T12:45:58 state: special case effective group in layout_is_active Currently, xkb_state_layout_{index,name}_is_active may report multiple groups as effective, because at looks at base,latched,locked separately. But there can only be one effective group, which is computed from the other three. So if XKB_STATE_EFFECTIVE is requested, just compare to the effective group we have computed. We also modify mod_{index,name}_is_active similarly, just for symmetry (there the effective mask is just an OR of the other three so the current test is correct). Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita bbaa11c6 2012-09-21T14:58:31 Rename map.{c,h} to keymap.{c,h} Seeing as we don't like "map" anymore. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita 7dca986e 2012-09-21T14:55:46 state, map: check XkbKey != NULL where missing Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita debd62b5 2012-09-21T13:30:42 Move xkb_state functions from map.c to state.c Seems more appropriate. Only change is to turn some xkb_state_get_map functions to direct state->keymap. Signed-off-by: Ran Benita <ran234@gmail.com>
Ran Benita fcd20290 2012-09-21T14:44:17 Don't use xkbcommon-compat names in internal code Signed-off-by: Ran Benita <ran234@gmail.com>
Daniel Stone bf194080 2012-09-19T16:19:57 Promote keymap enumeration API to public Rename the functions to get keysyms by key/layout/level to fit with the recent public API renames, and expose them. Signed-off-by: Daniel Stone <daniel@fooishbar.org>
Ran Benita 67b03cea 2012-09-21T16:30:01 state: correctly wrap state->locked_group and ->group These values weren't wrapped before, which caused group_index_is_active to stop working after a few group switches. Also, the current group-wrapping function didn't take into consideration actions such as LockGroup=-1, which need to wrap around, etc. xkb_layout_index_t is unsigned, but it was used to hold possibly negative values (e.g. locked_group is 0 and gets a -1 action). This group wrapping function should now act like the XkbAdjustGroup function from xserver, and at least ./test/interactive doesn't bring up any problems with group switching any more. Signed-off-by: Ran Benita <ran234@gmail.com>