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
parent
b6c79ad0d8
commit
3d672fcfea
|
@ -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
|
||||
|
|
47
src/map.c
47
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.
|
||||
*/
|
||||
|
|
75
src/state.c
75
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);
|
||||
}
|
||||
|
|
39
test/state.c
39
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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue