1 /************************************************************
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 ********************************************************/
28 * Copyright © 2012 Intel Corporation
30 * Permission is hereby granted, free of charge, to any person obtaining a
31 * copy of this software and associated documentation files (the "Software"),
32 * to deal in the Software without restriction, including without limitation
33 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
34 * and/or sell copies of the Software, and to permit persons to whom the
35 * Software is furnished to do so, subject to the following conditions:
37 * The above copyright notice and this permission notice (including the next
38 * paragraph) shall be included in all copies or substantial portions of the
41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
46 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
47 * DEALINGS IN THE SOFTWARE.
49 * Author: Daniel Stone <daniel@fooishbar.org>
53 * This is a bastardised version of xkbActions.c from the X server which
54 * does not support, for the moment:
55 * - AccessX sticky/debounce/etc (will come later)
56 * - pointer keys (may come later)
57 * - key redirects (unlikely)
58 * - messages (very unlikely)
67 #include "xkbcommon/xkbcommon.h"
68 #include "XKBcommonint.h"
71 struct xkb_state *state;
72 union xkb_action action;
73 xkb_keycode_t keycode;
75 int (*func)(struct xkb_filter *filter, xkb_keycode_t key,
76 enum xkb_key_direction direction);
78 struct xkb_filter *next;
81 static union xkb_action *
82 xkb_key_get_action(struct xkb_state *state, xkb_keycode_t key)
86 if (!XkbKeyHasActions(state->xkb, key) ||
87 !XkbKeycodeInRange(state->xkb, key)) {
88 static union xkb_action fake;
89 memset(&fake, 0, sizeof(fake));
90 fake.type = XkbSA_NoAction;
94 group = xkb_key_get_group(state, key);
95 level = xkb_key_get_level(state, key, group);
97 return XkbKeyActionEntry(state->xkb, key, level, group);
100 static struct xkb_filter *
101 xkb_filter_new(struct xkb_state *state)
104 int old_size = state->num_filters;
105 struct xkb_filter *filters = state->filters;
107 for (i = 0; i < state->num_filters; i++) {
110 filters[i].state = state;
111 filters[i].refcnt = 1;
115 if (state->num_filters > 0)
116 state->num_filters *= 2;
118 state->num_filters = 4;
119 filters = realloc(filters, state->num_filters * sizeof(*filters));
120 if (!filters) { /* WSGO */
121 state->num_filters = old_size;
124 state->filters = filters;
125 memset(&filters[old_size], 0,
126 (state->num_filters - old_size) * sizeof(*filters));
128 filters[old_size].state = state;
129 filters[old_size].refcnt = 1;
131 return &filters[old_size];
134 /***====================================================================***/
137 xkb_filter_group_set_func(struct xkb_filter *filter, xkb_keycode_t keycode,
138 enum xkb_key_direction direction)
140 if (keycode != filter->keycode) {
141 filter->action.group.flags &= ~XkbSA_ClearLocks;
145 if (direction == XKB_KEY_DOWN) {
149 else if (--filter->refcnt > 0) {
153 if (filter->action.group.flags & XkbSA_GroupAbsolute)
154 filter->state->base_group = filter->action.group.group;
156 filter->state->base_group = -filter->action.group.group;
157 if (filter->action.group.flags & XkbSA_ClearLocks)
158 filter->state->locked_group = 0;
166 xkb_filter_group_set_new(struct xkb_state *state, xkb_keycode_t keycode,
167 union xkb_action *action)
169 struct xkb_filter *filter = xkb_filter_new(state);
171 if (!filter) /* WSGO */
173 filter->keycode = keycode;
174 filter->func = xkb_filter_group_set_func;
175 filter->action = *action;
177 if (action->group.flags & XkbSA_GroupAbsolute) {
178 filter->action.group.group = filter->state->base_group;
179 filter->state->base_group = action->group.group;
182 filter->state->base_group += action->group.group;
189 xkb_filter_group_lock_func(struct xkb_filter *filter, xkb_keycode_t keycode,
190 enum xkb_key_direction direction)
192 if (keycode != filter->keycode)
195 if (direction == XKB_KEY_DOWN) {
199 if (--filter->refcnt > 0)
207 xkb_filter_group_lock_new(struct xkb_state *state, xkb_keycode_t keycode,
208 union xkb_action *action)
210 struct xkb_filter *filter = xkb_filter_new(state);
215 filter->keycode = keycode;
216 filter->func = xkb_filter_group_lock_func;
217 filter->action = *action;
219 if (action->group.flags & XkbSA_GroupAbsolute)
220 filter->state->locked_group = action->group.group;
222 filter->state->locked_group += action->group.group;
228 xkb_filter_mod_set_func(struct xkb_filter *filter, xkb_keycode_t keycode,
229 enum xkb_key_direction direction)
231 if (keycode != filter->keycode) {
232 filter->action.mods.flags &= ~XkbSA_ClearLocks;
236 if (direction == XKB_KEY_DOWN) {
240 else if (--filter->refcnt > 0) {
244 filter->state->base_mods &= ~(filter->action.mods.mask);
245 if (filter->action.mods.flags & XkbSA_ClearLocks)
246 filter->state->locked_mods &= ~filter->action.mods.mask;
254 xkb_filter_mod_set_new(struct xkb_state *state, xkb_keycode_t keycode,
255 union xkb_action *action)
257 struct xkb_filter *filter = xkb_filter_new(state);
259 if (!filter) /* WSGO */
261 filter->keycode = keycode;
262 filter->func = xkb_filter_mod_set_func;
263 filter->action = *action;
265 filter->state->base_mods |= action->mods.mask;
271 xkb_filter_mod_lock_func(struct xkb_filter *filter, xkb_keycode_t keycode,
272 enum xkb_key_direction direction)
274 if (keycode != filter->keycode)
277 if (direction == XKB_KEY_DOWN) {
281 if (--filter->refcnt > 0)
284 filter->state->locked_mods &= ~filter->priv;
290 xkb_filter_mod_lock_new(struct xkb_state *state, xkb_keycode_t keycode,
291 union xkb_action *action)
293 struct xkb_filter *filter = xkb_filter_new(state);
295 if (!filter) /* WSGO */
298 filter->keycode = keycode;
299 filter->func = xkb_filter_mod_lock_func;
300 filter->action = *action;
301 filter->priv = state->locked_mods & action->mods.mask;
302 state->locked_mods |= action->mods.mask;
307 enum xkb_key_latch_state {
314 xkb_filter_mod_latch_func(struct xkb_filter *filter, xkb_keycode_t keycode,
315 enum xkb_key_direction direction)
317 enum xkb_key_latch_state latch = filter->priv;
319 if (direction == XKB_KEY_DOWN && latch == LATCH_PENDING) {
320 /* If this is a new keypress and we're awaiting our single latched
321 * keypress, then either break the latch if any random key is pressed,
322 * or promote it to a lock or plain base set if it's the same
324 union xkb_action *action = xkb_key_get_action(filter->state, keycode);
325 if (action->type == XkbSA_LatchMods &&
326 action->mods.flags == filter->action.mods.flags &&
327 action->mods.mask == filter->action.mods.mask) {
328 filter->action = *action;
329 if (filter->action.mods.flags & XkbSA_LatchToLock) {
330 filter->action.type = XkbSA_LockMods;
331 filter->func = xkb_filter_mod_lock_func;
332 filter->state->locked_mods |= filter->action.mods.mask;
335 filter->action.type = XkbSA_SetMods;
336 filter->func = xkb_filter_mod_set_func;
337 filter->state->base_mods |= filter->action.mods.mask;
339 filter->keycode = keycode;
340 filter->state->latched_mods &= ~filter->action.mods.mask;
344 else if (((1 << action->type) & XkbSA_BreakLatch)) {
345 /* XXX: This may be totally broken, we might need to break the
346 * latch in the next run after this press? */
347 filter->state->latched_mods &= ~filter->action.mods.mask;
352 else if (direction == XKB_KEY_UP && keycode == filter->keycode) {
353 /* Our key got released. If we've set it to clear locks, and we
354 * currently have the same modifiers locked, then release them and
355 * don't actually latch. Else we've actually hit the latching
356 * stage, so set PENDING and move our modifier from base to
358 if (latch == NO_LATCH ||
359 ((filter->action.mods.flags & XkbSA_ClearLocks) &&
360 (filter->state->locked_mods & filter->action.mods.mask) ==
361 filter->action.mods.mask)) {
362 /* XXX: We might be a bit overenthusiastic about clearing
363 * mods other filters have set here? */
364 if (latch == LATCH_PENDING)
365 filter->state->latched_mods &= ~filter->action.mods.mask;
367 filter->state->base_mods &= ~filter->action.mods.mask;
368 filter->state->locked_mods &= ~filter->action.mods.mask;
372 latch = LATCH_PENDING;
373 filter->state->base_mods &= ~filter->action.mods.mask;
374 filter->state->latched_mods |= filter->action.mods.mask;
378 else if (direction == XKB_KEY_DOWN && latch == LATCH_KEY_DOWN) {
379 /* Someone's pressed another key while we've still got the latching
380 * key held down, so keep the base modifier state active (from
381 * xkb_filter_mod_latch_new), but don't trip the latch, just clear
382 * it as soon as the modifier gets released. */
386 filter->priv = latch;
392 xkb_filter_mod_latch_new(struct xkb_state *state, xkb_keycode_t keycode,
393 union xkb_action *action)
395 struct xkb_filter *filter = xkb_filter_new(state);
396 enum xkb_key_latch_state latch = LATCH_KEY_DOWN;
398 if (!filter) /* WSGO */
400 filter->keycode = keycode;
401 filter->priv = latch;
402 filter->func = xkb_filter_mod_latch_func;
403 filter->action = *action;
405 filter->state->base_mods |= action->mods.mask;
411 * Applies any relevant filters to the key, first from the list of filters
412 * that are currently active, then if no filter has claimed the key, possibly
413 * apply a new filter from the key action.
416 xkb_filter_apply_all(struct xkb_state *state, xkb_keycode_t key,
417 enum xkb_key_direction direction)
419 struct xkb_filter *filters = state->filters;
420 union xkb_action *act = NULL;
424 /* First run through all the currently active filters and see if any of
425 * them have claimed this event. */
426 for (i = 0; i < state->num_filters; i++) {
427 if (!filters[i].func)
429 send &= (*filters[i].func)(&filters[i], key, direction);
432 if (!send || direction == XKB_KEY_UP)
435 act = xkb_key_get_action(state, key);
438 send = xkb_filter_mod_set_new(state, key, act);
440 case XkbSA_LatchMods:
441 send = xkb_filter_mod_latch_new(state, key, act);
444 send = xkb_filter_mod_lock_new(state, key, act);
447 send = xkb_filter_group_set_new(state, key, act);
450 case XkbSA_LatchGroup:
451 send = xkb_filter_mod_latch_new(state, key, act);
454 case XkbSA_LockGroup:
455 send = xkb_filter_group_lock_new(state, key, act);
463 xkb_state_new(struct xkb_keymap *xkb)
465 struct xkb_state *ret;
470 ret = calloc(sizeof(*ret), 1);
475 ret->xkb = xkb_map_ref(xkb);
481 xkb_state_ref(struct xkb_state *state)
488 xkb_state_unref(struct xkb_state *state)
491 assert(state->refcnt >= 0);
492 if (state->refcnt > 0)
495 xkb_map_unref(state->xkb);
496 free(state->filters);
501 * Update the LED state to match the rest of the xkb_state.
504 xkb_state_led_update_all(struct xkb_state *state)
510 for (led = 0; led < XkbNumIndicators; led++) {
511 struct xkb_indicator_map *map = &state->xkb->indicators->maps[led];
512 uint32_t mod_mask = 0;
513 uint32_t group_mask = 0;
515 if (!map->which_mods && !map->which_groups && !map->ctrls)
518 if (map->which_mods) {
519 if (map->which_mods & XkbIM_UseBase)
520 mod_mask |= state->base_mods;
521 if (map->which_mods & XkbIM_UseLatched)
522 mod_mask |= state->latched_mods;
523 if (map->which_mods & XkbIM_UseLocked)
524 mod_mask |= state->locked_mods;
525 if (map->which_mods & XkbIM_UseEffective)
526 mod_mask |= state->mods;
527 if ((map->mods.mask & mod_mask))
528 state->leds |= (1 << led);
530 else if (map->which_groups) {
531 if (map->which_mods & XkbIM_UseBase)
532 group_mask |= (1 << state->base_group);
533 if (map->which_mods & XkbIM_UseLatched)
534 group_mask |= (1 << state->latched_group);
535 if (map->which_mods & XkbIM_UseLocked)
536 group_mask |= (1 << state->locked_group);
537 if (map->which_mods & XkbIM_UseEffective)
538 group_mask |= (1 << state->group);
539 if ((map->groups & group_mask))
540 state->leds |= (1 << led);
542 else if (map->ctrls) {
543 if ((map->ctrls & state->xkb->ctrls->enabled_ctrls))
544 state->leds |= (1 << led);
550 * Calculates the derived state (effective mods/group and LEDs) from an
551 * up-to-date xkb_state.
554 xkb_state_update_derived(struct xkb_state *state)
556 state->mods = (state->base_mods | state->latched_mods | state->locked_mods);
557 /* FIXME: Clamp/wrap locked_group */
558 state->group = state->locked_group + state->base_group +
559 state->latched_group;
560 /* FIXME: Clamp/wrap effective group */
562 xkb_state_led_update_all(state);
566 * Given a particular key event, updates the state structure to reflect the
570 xkb_state_update_key(struct xkb_state *state, xkb_keycode_t key,
571 enum xkb_key_direction direction)
573 xkb_filter_apply_all(state, key, direction);
574 xkb_state_update_derived(state);
578 * Updates the state from a set of explicit masks as gained from
579 * xkb_state_serialise_mods and xkb_state_serialise_groups. As noted in the
580 * documentation for these functions in xkbcommon.h, this round-trip is
581 * lossy, and should only be used to update a slave state mirroring the
582 * master, e.g. in a client/server window system.
585 xkb_state_update_mask(struct xkb_state *state,
586 xkb_mod_mask_t base_mods,
587 xkb_mod_mask_t latched_mods,
588 xkb_mod_mask_t locked_mods,
589 xkb_group_index_t base_group,
590 xkb_group_index_t latched_group,
591 xkb_group_index_t locked_group)
595 state->base_mods = 0;
596 state->latched_mods = 0;
597 state->locked_mods = 0;
598 for (mod = 0; mod < xkb_map_num_mods(state->xkb); mod++) {
599 xkb_mod_mask_t idx = (1 << mod);
601 state->base_mods |= idx;
602 if (latched_mods & idx)
603 state->latched_mods |= idx;
604 if (locked_mods & idx)
605 state->locked_mods |= idx;
608 state->base_group = base_group;
609 state->latched_group = latched_group;
610 state->locked_group = locked_group;
612 xkb_state_update_derived(state);
616 * Serialises the requested modifier state into an xkb_mod_mask_t, with all
617 * the same disclaimers as in xkb_state_update_mask.
620 xkb_state_serialise_mods(struct xkb_state *state,
621 enum xkb_state_component type)
623 xkb_mod_mask_t ret = 0;
625 if (type == XKB_STATE_EFFECTIVE)
628 if (type & XKB_STATE_DEPRESSED)
629 ret |= state->base_mods;
630 if (type & XKB_STATE_LATCHED)
631 ret |= state->latched_mods;
632 if (type & XKB_STATE_LOCKED)
633 ret |= state->locked_mods;
639 * Serialises the requested group state, with all the same disclaimers as
640 * in xkb_state_update_mask.
643 xkb_state_serialise_group(struct xkb_state *state,
644 enum xkb_state_component type)
646 xkb_group_index_t ret = 0;
648 if (type == XKB_STATE_EFFECTIVE)
651 if (type & XKB_STATE_DEPRESSED)
652 ret += state->base_group;
653 if (type & XKB_STATE_LATCHED)
654 ret += state->latched_group;
655 if (type & XKB_STATE_LOCKED)
656 ret += state->locked_group;
662 * Returns 1 if the given modifier is active with the specified type(s), 0 if
663 * not, or -1 if the modifier is invalid.
666 xkb_state_mod_index_is_active(struct xkb_state *state,
668 enum xkb_state_component type)
672 if (idx >= xkb_map_num_mods(state->xkb))
675 if (type & XKB_STATE_DEPRESSED)
676 ret |= (state->base_mods & (1 << idx));
677 if (type & XKB_STATE_LATCHED)
678 ret |= (state->latched_mods & (1 << idx));
679 if (type & XKB_STATE_LOCKED)
680 ret |= (state->locked_mods & (1 << idx));
686 * Returns 1 if the given modifier is active with the specified type(s), 0 if
687 * not, or -1 if the modifier is invalid.
690 xkb_state_mod_name_is_active(struct xkb_state *state, const char *name,
691 enum xkb_state_component type)
693 xkb_mod_index_t idx = xkb_map_mod_get_index(state->xkb, name);
695 if (idx == XKB_MOD_INVALID)
698 return xkb_state_mod_index_is_active(state, idx, type);
702 * Returns 1 if the given group is active with the specified type(s), 0 if
703 * not, or -1 if the group is invalid.
706 xkb_state_group_index_is_active(struct xkb_state *state,
707 xkb_group_index_t idx,
708 enum xkb_state_component type)
712 if (idx >= xkb_map_num_groups(state->xkb))
715 if (type & XKB_STATE_DEPRESSED)
716 ret |= (state->base_group == idx);
717 if (type & XKB_STATE_LATCHED)
718 ret |= (state->latched_group == idx);
719 if (type & XKB_STATE_LOCKED)
720 ret |= (state->locked_group == idx);
726 * Returns 1 if the given modifier is active with the specified type(s), 0 if
727 * not, or -1 if the modifier is invalid.
730 xkb_state_group_name_is_active(struct xkb_state *state, const char *name,
731 enum xkb_state_component type)
733 xkb_group_index_t idx = xkb_map_group_get_index(state->xkb, name);
735 if (idx == XKB_GROUP_INVALID)
738 return xkb_state_group_index_is_active(state, idx, type);
742 * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
745 xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx)
747 if (idx >= xkb_map_num_leds(state->xkb))
750 return !!(state->leds & (1 << idx));
754 * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
757 xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
759 xkb_led_index_t idx = xkb_map_led_get_index(state->xkb, name);
761 if (idx == XKB_LED_INVALID)
764 return xkb_state_led_index_is_active(state, idx);