From b8706be540a1c6cab13477f36503800e762d412d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 17 Dec 2022 13:02:41 +0200 Subject: [PATCH] WIP: state: add API for updating latched and locked mods & layout in server state 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`[0], 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. [0] https://www.x.org/releases/X11R7.7/doc/kbproto/xkbproto.html#Querying_and_Changing_Keyboard_State Fixes: https://github.com/xkbcommon/libxkbcommon/issues/310 Signed-off-by: Ran Benita --- include/xkbcommon/xkbcommon.h | 60 +++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/include/xkbcommon/xkbcommon.h b/include/xkbcommon/xkbcommon.h index a7148f35b..82d1090d5 100644 --- a/include/xkbcommon/xkbcommon.h +++ b/include/xkbcommon/xkbcommon.h @@ -81,9 +81,10 @@ #ifndef _XKBCOMMON_H_ #define _XKBCOMMON_H_ +#include +#include #include #include -#include #include #include @@ -1441,12 +1442,67 @@ enum xkb_state_component xkb_state_update_key(struct xkb_state *state, xkb_keycode_t key, enum xkb_key_direction direction); +/** + * Update the keyboard state to change the latched and locked state of + * the modifiers and layout. + * + * This entry point is intended for *server* applications and should not be used + * by *client* applications; see @ref server-client-state for details. + * + * Use this function to update the latched and locked state according to + * "out of band" (non-device) inputs, such as UI layout switchers. + * + * @par Layout out of range + * @parblock + * + * If the effective layout, after taking into account the depressed, latched and + * locked layout, is out of range (negative or greater than the maximum layout), + * it is brought into range. Currently, the layout is wrapped using integer + * modulus (with negative values wrapping from the end). The wrapping behavior + * may be made configurable in the future. + * + * @endparblock + * + * @param affect_latched_mods + * @param latched_mods + * Modifiers to set as latched or unlatched. Only modifiers in + * `affect_latched_mods` are considered. + * @param affect_latched_layout + * @param latched_layout + * Layout to latch. Only considered if `affect_latched_layout` is true. + * Maybe be out of range (including negative) -- see note above. + * @param affect_locked_mods + * @param locked_mods + * Modifiers to set as locked or unlocked. Only modifiers in + * `affect_locked_mods` are considered. + * @param affect_locked_layout + * @param locked_layout + * Layout to lock. Only considered if `affect_locked_layout` is true. + * Maybe be out of range (including negative) -- see note above. + * + * @returns A mask of state components that have changed as a result of + * the update. If nothing in the state has changed, returns 0. + * + * @memberof xkb_state + * + * @sa xkb_state_update_mask() + */ +enum xkb_state_component +xkb_state_update_latched_locked(xkb_mod_mask_t affect_latched_mods, + xkb_mod_mask_t latched_mods, + bool affect_latched_layout, + int32_t latched_layout, + xkb_mod_mask_t affect_locked_mods, + xkb_mod_mask_t locked_mods, + bool affect_locked_layout, + int32_t locked_layout); + /** * Update a keyboard state from a set of explicit masks. * * This entry point is intended for *client* applications; see @ref * server-client-state for details. *Server* applications should use - * xkb_state_update_key() instead. + * xkb_state_update_key() and xkb_state_update_latched_locked() instead. * * All parameters must always be passed, or the resulting state may be * incoherent.