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_mod_set_func(struct xkb_filter *filter, xkb_keycode_t keycode,
190 enum xkb_key_direction direction)
192 if (keycode != filter->keycode) {
193 filter->action.mods.flags &= ~XkbSA_ClearLocks;
197 if (direction == XKB_KEY_DOWN) {
201 else if (--filter->refcnt > 0) {
205 filter->state->base_mods &= ~(filter->action.mods.mask);
206 if (filter->action.mods.flags & XkbSA_ClearLocks)
207 filter->state->locked_mods &= ~filter->action.mods.mask;
215 xkb_filter_mod_set_new(struct xkb_state *state, xkb_keycode_t keycode,
216 union xkb_action *action)
218 struct xkb_filter *filter = xkb_filter_new(state);
220 if (!filter) /* WSGO */
222 filter->keycode = keycode;
223 filter->func = xkb_filter_mod_set_func;
224 filter->action = *action;
226 filter->state->base_mods |= action->mods.mask;
232 xkb_filter_mod_lock_func(struct xkb_filter *filter, xkb_keycode_t keycode,
233 enum xkb_key_direction direction)
235 if (keycode != filter->keycode)
238 if (direction == XKB_KEY_DOWN) {
242 if (--filter->refcnt > 0)
245 filter->state->locked_mods &= ~filter->priv;
251 xkb_filter_mod_lock_new(struct xkb_state *state, xkb_keycode_t keycode,
252 union xkb_action *action)
254 struct xkb_filter *filter = xkb_filter_new(state);
256 if (!filter) /* WSGO */
259 filter->keycode = keycode;
260 filter->func = xkb_filter_mod_lock_func;
261 filter->action = *action;
262 filter->priv = state->locked_mods & action->mods.mask;
263 state->locked_mods |= action->mods.mask;
268 enum xkb_key_latch_state {
275 xkb_filter_mod_latch_func(struct xkb_filter *filter, xkb_keycode_t keycode,
276 enum xkb_key_direction direction)
278 enum xkb_key_latch_state latch = filter->priv;
280 if (direction == XKB_KEY_DOWN && latch == LATCH_PENDING) {
281 /* If this is a new keypress and we're awaiting our single latched
282 * keypress, then either break the latch if any random key is pressed,
283 * or promote it to a lock or plain base set if it's the same
285 union xkb_action *action = xkb_key_get_action(filter->state, keycode);
286 if (action->type == XkbSA_LatchMods &&
287 action->mods.flags == filter->action.mods.flags &&
288 action->mods.mask == filter->action.mods.mask) {
289 filter->action = *action;
290 if (filter->action.mods.flags & XkbSA_LatchToLock) {
291 filter->action.type = XkbSA_LockMods;
292 filter->func = xkb_filter_mod_lock_func;
293 filter->state->locked_mods |= filter->action.mods.mask;
296 filter->action.type = XkbSA_SetMods;
297 filter->func = xkb_filter_mod_set_func;
298 filter->state->base_mods |= filter->action.mods.mask;
300 filter->keycode = keycode;
301 filter->state->latched_mods &= ~filter->action.mods.mask;
305 else if (((1 << action->type) & XkbSA_BreakLatch)) {
306 /* XXX: This may be totally broken, we might need to break the
307 * latch in the next run after this press? */
308 filter->state->latched_mods &= ~filter->action.mods.mask;
313 else if (direction == XKB_KEY_UP && keycode == filter->keycode) {
314 /* Our key got released. If we've set it to clear locks, and we
315 * currently have the same modifiers locked, then release them and
316 * don't actually latch. Else we've actually hit the latching
317 * stage, so set PENDING and move our modifier from base to
319 if (latch == NO_LATCH ||
320 ((filter->action.mods.flags & XkbSA_ClearLocks) &&
321 (filter->state->locked_mods & filter->action.mods.mask) ==
322 filter->action.mods.mask)) {
323 /* XXX: We might be a bit overenthusiastic about clearing
324 * mods other filters have set here? */
325 if (latch == LATCH_PENDING)
326 filter->state->latched_mods &= ~filter->action.mods.mask;
328 filter->state->base_mods &= ~filter->action.mods.mask;
329 filter->state->locked_mods &= ~filter->action.mods.mask;
333 latch = LATCH_PENDING;
334 filter->state->base_mods &= ~filter->action.mods.mask;
335 filter->state->latched_mods |= filter->action.mods.mask;
339 else if (direction == XKB_KEY_DOWN && latch == LATCH_KEY_DOWN) {
340 /* Someone's pressed another key while we've still got the latching
341 * key held down, so keep the base modifier state active (from
342 * xkb_filter_mod_latch_new), but don't trip the latch, just clear
343 * it as soon as the modifier gets released. */
347 filter->priv = latch;
353 xkb_filter_mod_latch_new(struct xkb_state *state, xkb_keycode_t keycode,
354 union xkb_action *action)
356 struct xkb_filter *filter = xkb_filter_new(state);
357 enum xkb_key_latch_state latch = LATCH_KEY_DOWN;
359 if (!filter) /* WSGO */
361 filter->keycode = keycode;
362 filter->priv = latch;
363 filter->func = xkb_filter_mod_latch_func;
364 filter->action = *action;
366 filter->state->base_mods |= action->mods.mask;
372 * Applies any relevant filters to the key, first from the list of filters
373 * that are currently active, then if no filter has claimed the key, possibly
374 * apply a new filter from the key action.
377 xkb_filter_apply_all(struct xkb_state *state, xkb_keycode_t key,
378 enum xkb_key_direction direction)
380 struct xkb_filter *filters = state->filters;
381 union xkb_action *act = NULL;
385 /* First run through all the currently active filters and see if any of
386 * them have claimed this event. */
387 for (i = 0; i < state->num_filters; i++) {
388 if (!filters[i].func)
390 send &= (*filters[i].func)(&filters[i], key, direction);
393 if (!send || direction == XKB_KEY_UP)
396 act = xkb_key_get_action(state, key);
399 send = xkb_filter_mod_set_new(state, key, act);
401 case XkbSA_LatchMods:
402 send = xkb_filter_mod_latch_new(state, key, act);
405 send = xkb_filter_mod_lock_new(state, key, act);
408 send = xkb_filter_group_set_new(state, key, act);
411 case XkbSA_LatchGroup:
412 send = xkb_filter_mod_latch_new(state, key, act);
414 case XkbSA_LockGroup:
415 send = xkb_filter_group_lock_new(state, key, act);
424 xkb_state_new(struct xkb_desc *xkb)
426 struct xkb_state *ret;
431 ret = calloc(sizeof(*ret), 1);
443 xkb_state_unref(struct xkb_state *state)
446 assert(state->refcnt >= 0);
447 if (state->refcnt > 0)
450 xkb_map_unref(state->xkb);
451 free(state->filters);
456 * Update the LED state to match the rest of the xkb_state.
459 xkb_state_led_update_all(struct xkb_state *state)
465 for (led = 0; led < XkbNumIndicators; led++) {
466 struct xkb_indicator_map *map = &state->xkb->indicators->maps[led];
467 uint32_t mod_mask = 0;
468 uint32_t group_mask = 0;
470 if (!map->which_mods && !map->which_groups && !map->ctrls)
473 if (map->which_mods) {
474 if (map->which_mods & XkbIM_UseBase)
475 mod_mask |= state->base_mods;
476 if (map->which_mods & XkbIM_UseLatched)
477 mod_mask |= state->latched_mods;
478 if (map->which_mods & XkbIM_UseLocked)
479 mod_mask |= state->locked_mods;
480 if (map->which_mods & XkbIM_UseEffective)
481 mod_mask |= state->mods;
482 if ((map->mods.mask & mod_mask))
483 state->leds |= (1 << led);
485 else if (map->which_groups) {
486 if (map->which_mods & XkbIM_UseBase)
487 group_mask |= (1 << state->base_group);
488 if (map->which_mods & XkbIM_UseLatched)
489 group_mask |= (1 << state->latched_group);
490 if (map->which_mods & XkbIM_UseLocked)
491 group_mask |= (1 << state->locked_group);
492 if (map->which_mods & XkbIM_UseEffective)
493 group_mask |= (1 << state->group);
494 if ((map->groups & group_mask))
495 state->leds |= (1 << led);
497 else if (map->ctrls) {
498 if ((map->ctrls & state->xkb->ctrls->enabled_ctrls))
499 state->leds |= (1 << led);
505 * Calculates the derived state (effective mods/group and LEDs) from an
506 * up-to-date xkb_state.
509 xkb_state_update_derived(struct xkb_state *state)
511 state->mods = (state->base_mods | state->latched_mods | state->locked_mods);
512 /* FIXME: Clamp/wrap locked_group */
513 state->group = state->locked_group + state->base_group +
514 state->latched_group;
515 /* FIXME: Clamp/wrap effective group */
517 xkb_state_led_update_all(state);
521 * Given a particular key event, updates the state structure to reflect the
525 xkb_state_update_key(struct xkb_state *state, xkb_keycode_t key,
526 enum xkb_key_direction direction)
528 xkb_filter_apply_all(state, key, direction);
529 xkb_state_update_derived(state);
533 * Updates the state from a set of explicit masks as gained from
534 * xkb_state_serialise_mods and xkb_state_serialise_groups. As noted in the
535 * documentation for these functions in xkbcommon.h, this round-trip is
536 * lossy, and should only be used to update a slave state mirroring the
537 * master, e.g. in a client/server window system.
540 xkb_state_update_mask(struct xkb_state *state,
541 xkb_mod_mask_t base_mods,
542 xkb_mod_mask_t latched_mods,
543 xkb_mod_mask_t locked_mods,
544 xkb_group_index_t base_group,
545 xkb_group_index_t latched_group,
546 xkb_group_index_t locked_group)
550 state->base_mods = 0;
551 state->latched_mods = 0;
552 state->locked_mods = 0;
553 for (mod = 0; mod < xkb_map_num_mods(state->xkb); mod++) {
554 xkb_mod_mask_t idx = (1 << mod);
556 state->base_mods |= idx;
557 if (latched_mods & idx)
558 state->latched_mods |= idx;
559 if (locked_mods & idx)
560 state->locked_mods |= idx;
563 state->base_group = base_group;
564 state->latched_group = latched_group;
565 state->locked_group = locked_group;
567 xkb_state_update_derived(state);
571 * Serialises the requested modifier state into an xkb_mod_mask_t, with all
572 * the same disclaimers as in xkb_state_update_mask.
575 xkb_state_serialise_mods(struct xkb_state *state,
576 enum xkb_state_component type)
578 xkb_mod_mask_t ret = 0;
580 if (type == XKB_STATE_EFFECTIVE)
583 if (type & XKB_STATE_DEPRESSED)
584 ret |= state->base_mods;
585 if (type & XKB_STATE_LATCHED)
586 ret |= state->latched_mods;
587 if (type & XKB_STATE_LOCKED)
588 ret |= state->locked_mods;
594 * Serialises the requested group state, with all the same disclaimers as
595 * in xkb_state_update_mask.
598 xkb_state_serialise_group(struct xkb_state *state,
599 enum xkb_state_component type)
601 xkb_group_index_t ret = 0;
603 if (type == XKB_STATE_EFFECTIVE)
606 if (type & XKB_STATE_DEPRESSED)
607 ret += state->base_group;
608 if (type & XKB_STATE_LATCHED)
609 ret += state->latched_group;
610 if (type & XKB_STATE_LOCKED)
611 ret += state->locked_group;
617 * Returns 1 if the given modifier is active with the specified type(s), 0 if
618 * not, or -1 if the modifier is invalid.
621 xkb_state_mod_index_is_active(struct xkb_state *state,
623 enum xkb_state_component type)
627 if (idx >= xkb_map_num_mods(state->xkb))
630 if (type & XKB_STATE_DEPRESSED)
631 ret |= (state->base_mods & (1 << idx));
632 if (type & XKB_STATE_LATCHED)
633 ret |= (state->latched_mods & (1 << idx));
634 if (type & XKB_STATE_LOCKED)
635 ret |= (state->locked_mods & (1 << idx));
641 * Returns 1 if the given modifier is active with the specified type(s), 0 if
642 * not, or -1 if the modifier is invalid.
645 xkb_state_mod_name_is_active(struct xkb_state *state, const char *name,
646 enum xkb_state_component type)
648 xkb_mod_index_t idx = xkb_map_mod_get_index(state->xkb, name);
650 if (idx == XKB_MOD_INVALID)
653 return xkb_state_mod_index_is_active(state, idx, type);
657 * Returns 1 if the given group is active with the specified type(s), 0 if
658 * not, or -1 if the group is invalid.
661 xkb_state_group_index_is_active(struct xkb_state *state,
662 xkb_group_index_t idx,
663 enum xkb_state_component type)
667 if (idx >= xkb_map_num_groups(state->xkb))
670 if (type & XKB_STATE_DEPRESSED)
671 ret |= (state->base_group == idx);
672 if (type & XKB_STATE_LATCHED)
673 ret |= (state->latched_group == idx);
674 if (type & XKB_STATE_LOCKED)
675 ret |= (state->locked_group == idx);
681 * Returns 1 if the given modifier is active with the specified type(s), 0 if
682 * not, or -1 if the modifier is invalid.
685 xkb_state_group_name_is_active(struct xkb_state *state, const char *name,
686 enum xkb_state_component type)
688 xkb_group_index_t idx = xkb_map_group_get_index(state->xkb, name);
690 if (idx == XKB_GROUP_INVALID)
693 return xkb_state_group_index_is_active(state, idx, type);
697 * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
700 xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx)
702 if (idx >= xkb_map_num_leds(state->xkb))
705 return !!(state->leds & (1 << idx));
709 * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
712 xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
714 xkb_led_index_t idx = xkb_map_led_get_index(state->xkb, name);
716 if (idx == XKB_LED_INVALID)
719 return xkb_state_led_index_is_active(state, idx);