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 <daniel@fooishbar.org>
master
Daniel Stone 2012-03-22 14:32:53 +00:00
parent b6c79ad0d8
commit 3d672fcfea
4 changed files with 185 additions and 12 deletions

View File

@ -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

View File

@ -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.
*/

View File

@ -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);
}

View File

@ -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);