From 3d672fcfea6b823db4793b9ad1c3aadc4b547a08 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Thu, 22 Mar 2012 14:32:53 +0000 Subject: [PATCH] Add LED state API And also convert state.c to use the state API for mods and groups, rather than testing the state members directly. Signed-off-by: Daniel Stone --- include/xkbcommon/xkbcommon.h | 36 +++++++++++++++++ src/map.c | 47 ++++++++++++++++++++++ src/state.c | 75 ++++++++++++++++++++++++++++++++++- test/state.c | 39 +++++++++++++----- 4 files changed, 185 insertions(+), 12 deletions(-) diff --git a/include/xkbcommon/xkbcommon.h b/include/xkbcommon/xkbcommon.h index 98e8049..fe72a74 100644 --- a/include/xkbcommon/xkbcommon.h +++ b/include/xkbcommon/xkbcommon.h @@ -64,10 +64,12 @@ typedef uint32_t xkb_keycode_t; typedef uint32_t xkb_keysym_t; typedef uint32_t xkb_mod_index_t; typedef uint32_t xkb_group_index_t; +typedef uint32_t xkb_led_index_t; #define XKB_MOD_INVALID (0xffffffff) #define XKB_GROUP_INVALID (0xffffffff) #define XKB_KEYCODE_INVALID (0xffffffff) +#define XKB_LED_INVALID (0xffffffff) #define XKB_KEYCODE_MAX (0xffffffff - 1) #define xkb_keycode_is_legal_ext(kc) (kc <= XKB_KEYCODE_MAX) @@ -497,6 +499,8 @@ struct xkb_state { unsigned short ptr_buttons; /* core pointer buttons */ + uint32_t leds; + int refcnt; void *filters; int num_filters; @@ -615,6 +619,24 @@ xkb_map_group_get_index(struct xkb_desc *xkb, const char *name); _X_EXPORT xkb_group_index_t xkb_key_num_groups(struct xkb_desc *xkb, xkb_keycode_t key); +/** + * Returns the number of LEDs in the given map. + */ +_X_EXPORT xkb_led_index_t +xkb_map_num_leds(struct xkb_desc *xkb); + +/** + * Returns the name of the LED specified by 'idx', or NULL if invalid. + */ +_X_EXPORT const char * +xkb_map_led_get_name(struct xkb_desc *xkb, xkb_led_index_t idx); + +/** + * Returns the index of the LED specified by 'name', or XKB_LED_INVALID. + */ +_X_EXPORT xkb_led_index_t +xkb_map_led_get_index(struct xkb_desc *xkb, const char *name); + /** @} */ /** @@ -706,6 +728,20 @@ _X_EXPORT int xkb_state_group_index_is_active(struct xkb_state *state, xkb_group_index_t idx, enum xkb_state_component type); +/** + * Returns 1 if the LED specified by 'name' is active, 0 if it is unset, or + * -1 if the LED does not exist in the current map. + */ +_X_EXPORT int +xkb_state_led_name_is_active(struct xkb_state *state, const char *name); + +/** + * Returns 1 if the LED specified by 'idx' is active, 0 if it is unset, or + * -1 if the LED does not exist in the current map. + */ +_X_EXPORT int +xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx); + /** @} */ _XFUNCPROTOEND diff --git a/src/map.c b/src/map.c index 6af6d28..7f1d85a 100644 --- a/src/map.c +++ b/src/map.c @@ -197,6 +197,53 @@ xkb_key_num_groups(struct xkb_desc *xkb, xkb_keycode_t key) return XkbKeyNumGroups(xkb, key); } +/** + * Return the total number of active LEDs in the keymap. + */ +xkb_led_index_t +xkb_map_num_leds(struct xkb_desc *xkb) +{ + xkb_led_index_t ret = 0; + xkb_led_index_t i; + + for (i = 0; i < XkbNumIndicators; i++) + if (xkb->indicators->maps[i].which_groups || + xkb->indicators->maps[i].which_mods || + xkb->indicators->maps[i].ctrls) + ret++; + + return ret; +} + +/** + * Returns the name for a given group. + */ +const char * +xkb_map_led_get_name(struct xkb_desc *xkb, xkb_led_index_t idx) +{ + if (idx >= xkb_map_num_leds(xkb)) + return NULL; + + return xkb->names->indicators[idx]; +} + +/** + * Returns the index for a named group. + */ +xkb_group_index_t +xkb_map_led_get_index(struct xkb_desc *xkb, const char *name) +{ + xkb_led_index_t num_leds = xkb_map_num_leds(xkb); + xkb_led_index_t i; + + for (i = 0; i < num_leds; i++) { + if (strcasecmp(xkb->names->indicators[i], name) == 0) + return i; + } + + return XKB_LED_INVALID; +} + /** * Returns the level to use for the given key and state, or -1 if invalid. */ diff --git a/src/state.c b/src/state.c index 1802f84..e5dce5c 100644 --- a/src/state.c +++ b/src/state.c @@ -444,6 +444,55 @@ xkb_state_unref(struct xkb_state *state) free(state); } +/** + * Update the LED state to match the rest of the xkb_state. + */ +static void +xkb_state_led_update_all(struct xkb_state *state) +{ + xkb_led_index_t led; + + state->leds = 0; + + for (led = 0; led < XkbNumIndicators; led++) { + struct xkb_indicator_map *map = &state->xkb->indicators->maps[led]; + uint32_t mod_mask = 0; + uint32_t group_mask = 0; + + if (!map->which_mods && !map->which_groups && !map->ctrls) + continue; + + if (map->which_mods) { + if (map->which_mods & XkbIM_UseBase) + mod_mask |= state->base_mods; + if (map->which_mods & XkbIM_UseLatched) + mod_mask |= state->latched_mods; + if (map->which_mods & XkbIM_UseLocked) + mod_mask |= state->locked_mods; + if (map->which_mods & XkbIM_UseEffective) + mod_mask |= state->mods; + if ((map->mods.mask & mod_mask)) + state->leds |= (1 << led); + } + else if (map->which_groups) { + if (map->which_mods & XkbIM_UseBase) + group_mask |= (1 << state->base_group); + if (map->which_mods & XkbIM_UseLatched) + group_mask |= (1 << state->latched_group); + if (map->which_mods & XkbIM_UseLocked) + group_mask |= (1 << state->locked_group); + if (map->which_mods & XkbIM_UseEffective) + group_mask |= (1 << state->group); + if ((map->groups & group_mask)) + state->leds |= (1 << led); + } + else if (map->ctrls) { + if ((map->ctrls & state->xkb->ctrls->enabled_ctrls)) + state->leds |= (1 << led); + } + } +} + /** * Given a particular key event, updates the state structure to reflect the * new modifiers. @@ -459,7 +508,7 @@ xkb_state_update_key(struct xkb_state *state, xkb_keycode_t key, int down) state->latched_group; /* FIXME: Clamp/wrap effective group */ - /* FIXME: Update LED state. */ + xkb_state_led_update_all(state); } /** @@ -537,3 +586,27 @@ int xkb_state_group_name_is_active(struct xkb_state *state, const char *name, return xkb_state_group_index_is_active(state, idx, type); } + +/** + * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid. + */ +int xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx) +{ + if (idx >= xkb_map_num_leds(state->xkb)) + return -1; + + return !!(state->leds & (1 << idx)); +} + +/** + * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid. + */ +int xkb_state_led_name_is_active(struct xkb_state *state, const char *name) +{ + xkb_led_index_t idx = xkb_map_led_get_index(state->xkb, name); + + if (idx == XKB_LED_INVALID) + return -1; + + return xkb_state_led_index_is_active(state, idx); +} diff --git a/test/state.c b/test/state.c index 6048ee7..eea5b59 100644 --- a/test/state.c +++ b/test/state.c @@ -43,34 +43,49 @@ print_state(struct xkb_state *state) { xkb_group_index_t group; xkb_mod_index_t mod; + xkb_led_index_t led; - if (!state->group && !state->mods) { + if (!state->group && !state->mods && !state->leds) { fprintf(stderr, "\tno state\n"); return; } for (group = 0; group < xkb_map_num_groups(state->xkb); group++) { - if (group != state->group && group != state->base_group && - group != state->latched_group && group != state->locked_group) + if (!xkb_state_group_index_is_active(state, group, XKB_STATE_EFFECTIVE)) continue; fprintf(stderr, "\tgroup %s (%d): %s%s%s%s\n", xkb_map_group_get_name(state->xkb, group), group, - (state->group == group) ? "effective " : "", - (state->base_group == group) ? "depressed " : "", - (state->latched_group == group) ? "latched " : "", - (state->locked_group == group) ? "locked " : ""); + xkb_state_group_index_is_active(state, group, XKB_STATE_EFFECTIVE) ? + "effective " : "", + xkb_state_group_index_is_active(state, group, XKB_STATE_DEPRESSED) ? + "depressed " : "", + xkb_state_group_index_is_active(state, group, XKB_STATE_LATCHED) ? + "latched " : "", + xkb_state_group_index_is_active(state, group, XKB_STATE_LOCKED) ? + "locked " : ""); } for (mod = 0; mod < xkb_map_num_mods(state->xkb); mod++) { - if (!(state->mods & (1 << mod))) + if (!xkb_state_mod_index_is_active(state, mod, XKB_STATE_EFFECTIVE)) continue; fprintf(stderr, "\tmod %s (%d): %s%s%s\n", xkb_map_mod_get_name(state->xkb, mod), mod, - (state->base_mods & (1 << mod)) ? "depressed " : "", - (state->latched_mods & (1 << mod)) ? "latched " : "", - (state->locked_mods & (1 << mod)) ? "locked " : ""); + xkb_state_mod_index_is_active(state, mod, XKB_STATE_DEPRESSED) ? + "depressed " : "", + xkb_state_mod_index_is_active(state, mod, XKB_STATE_LATCHED) ? + "latched " : "", + xkb_state_mod_index_is_active(state, mod, XKB_STATE_LOCKED) ? + "locked " : ""); + } + + for (led = 0; led < xkb_map_num_leds(state->xkb); led++) { + if (!xkb_state_led_index_is_active(state, led)) + continue; + fprintf(stderr, "\tled %s (%d): active\n", + xkb_map_led_get_name(state->xkb, led), + led); } } @@ -135,6 +150,7 @@ main(int argc, char *argv[]) print_state(state); assert(xkb_state_mod_name_is_active(state, "Caps Lock", XKB_STATE_LOCKED)); + assert(xkb_state_led_name_is_active(state, "Caps Lock")); num_syms = xkb_key_get_syms(state, KEY_Q + EVDEV_OFFSET, &syms); assert(num_syms == 1 && syms[0] == XK_Q); @@ -143,6 +159,7 @@ main(int argc, char *argv[]) xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, 0); assert(!xkb_state_mod_name_is_active(state, "Caps Lock", XKB_STATE_EFFECTIVE)); + assert(!xkb_state_led_name_is_active(state, "Caps Lock")); num_syms = xkb_key_get_syms(state, KEY_Q + EVDEV_OFFSET, &syms); assert(num_syms == 1 && syms[0] == XK_q); -- 2.34.1