116f513dea1a8ac99c83bef1fcdbb028d761badc
[platform/upstream/libxkbcommon.git] / src / state.c
1 /************************************************************
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
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.
15
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.
24
25 ********************************************************/
26
27 /*
28  * Copyright © 2012 Intel Corporation
29  *
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:
36  *
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
39  * Software.
40  *
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.
48  *
49  * Author: Daniel Stone <daniel@fooishbar.org>
50  */
51
52 /*
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)
59  */
60
61 #ifdef HAVE_CONFIG_H
62 #include <config.h>
63 #endif
64
65 #include <assert.h>
66
67 #include "xkbcommon/xkbcommon.h"
68 #include "XKBcommonint.h"
69
70 struct xkb_filter {
71     struct xkb_state *state;
72     union xkb_action action;
73     xkb_keycode_t keycode;
74     uint32_t priv;
75     int (*func)(struct xkb_filter *filter, xkb_keycode_t key, int down);
76     int refcnt;
77     struct xkb_filter *next;
78 };
79
80 static union xkb_action *
81 xkb_key_get_action(struct xkb_state *state, xkb_keycode_t key)
82 {
83     int group, level;
84
85     if (!XkbKeyHasActions(state->xkb, key) ||
86         !XkbKeycodeInRange(state->xkb, key)) {
87         static union xkb_action fake;
88         memset(&fake, 0, sizeof(fake));
89         fake.type = XkbSA_NoAction;
90         return &fake;
91     }
92
93     group = xkb_key_get_group(state, key);
94     level = xkb_key_get_level(state, key, group);
95
96     return XkbKeyActionEntry(state->xkb, key, level, group);
97 }
98
99 static struct xkb_filter *
100 xkb_filter_new(struct xkb_state *state)
101 {
102     int i;
103     int old_size = state->num_filters;
104     struct xkb_filter *filters = state->filters;
105
106     for (i = 0; i < state->num_filters; i++) {
107         if (filters[i].func)
108             continue;
109         filters[i].state = state;
110         filters[i].refcnt = 1;
111         return &filters[i];
112     }
113
114     if (state->num_filters > 0)
115         state->num_filters *= 2;
116     else
117         state->num_filters = 4;
118     filters = realloc(filters, state->num_filters * sizeof(*filters));
119     if (!filters) { /* WSGO */
120         state->num_filters = old_size;
121         return NULL;
122     }
123     state->filters = filters;
124     memset(&filters[old_size], 0,
125            (state->num_filters - old_size) * sizeof(*filters));
126
127     filters[old_size].state = state;
128     filters[old_size].refcnt = 1;
129
130     return &filters[old_size];
131 }
132
133 /***====================================================================***/
134
135 static int
136 xkb_filter_group_set_func(struct xkb_filter *filter, xkb_keycode_t keycode,
137                           int down)
138 {
139     if (keycode != filter->keycode) {
140         filter->action.group.flags &= ~XkbSA_ClearLocks;
141         return 1;
142     }
143
144     if (down) {
145         filter->refcnt++;
146         return 0;
147     }
148     else if (--filter->refcnt > 0) {
149         return 0;
150     }
151
152     if (filter->action.group.flags & XkbSA_GroupAbsolute)
153         filter->state->base_group = filter->action.group.group;
154     else
155         filter->state->base_group = -filter->action.group.group;
156     if (filter->action.group.flags & XkbSA_ClearLocks)
157         filter->state->locked_group = 0;
158
159     filter->func = NULL;
160
161     return 1;
162 }
163
164 static int
165 xkb_filter_group_set_new(struct xkb_state *state, xkb_keycode_t keycode,
166                          union xkb_action *action)
167 {
168     struct xkb_filter *filter = xkb_filter_new(state);
169
170     if (!filter) /* WSGO */
171         return -1;
172     filter->keycode = keycode;
173     filter->func = xkb_filter_group_set_func;
174     filter->action = *action;
175
176     if (action->group.flags & XkbSA_GroupAbsolute) {
177         filter->action.group.group = filter->state->base_group;
178         filter->state->base_group = action->group.group;
179     }
180     else {
181         filter->state->base_group += action->group.group;
182     }
183
184     return 1;
185 }
186
187 static int
188 xkb_filter_mod_set_func(struct xkb_filter *filter, xkb_keycode_t keycode,
189                         int down)
190 {
191     if (keycode != filter->keycode) {
192         filter->action.mods.flags &= ~XkbSA_ClearLocks;
193         return 1;
194     }
195
196     if (down) {
197         filter->refcnt++;
198         return 0;
199     }
200     else if (--filter->refcnt > 0) {
201         return 0;
202     }
203
204     filter->state->base_mods &= ~(filter->action.mods.mask);
205     if (filter->action.mods.flags & XkbSA_ClearLocks)
206         filter->state->locked_mods &= ~filter->action.mods.mask;
207
208     filter->func = NULL;
209
210     return 1;
211 }
212
213 static int
214 xkb_filter_mod_set_new(struct xkb_state *state, xkb_keycode_t keycode,
215                        union xkb_action *action)
216 {
217     struct xkb_filter *filter = xkb_filter_new(state);
218
219     if (!filter) /* WSGO */
220         return -1;
221     filter->keycode = keycode;
222     filter->func = xkb_filter_mod_set_func;
223     filter->action = *action;
224
225     filter->state->base_mods |= action->mods.mask;
226
227     return 1;
228 }
229
230 static int
231 xkb_filter_mod_lock_func(struct xkb_filter *filter, xkb_keycode_t keycode,
232                          int down)
233 {
234     if (keycode != filter->keycode)
235         return 1;
236
237     if (down) {
238         filter->refcnt++;
239         return 0;
240     }
241     if (--filter->refcnt > 0)
242         return 0;
243
244     filter->state->locked_mods &= ~filter->priv;
245     filter->func = NULL;
246     return 1;
247 }
248
249 static int
250 xkb_filter_mod_lock_new(struct xkb_state *state, xkb_keycode_t keycode,
251                         union xkb_action *action)
252 {
253     struct xkb_filter *filter = xkb_filter_new(state);
254
255     if (!filter) /* WSGO */
256         return 0;
257
258     filter->keycode = keycode;
259     filter->func = xkb_filter_mod_lock_func;
260     filter->action = *action;
261     filter->priv = state->locked_mods & action->mods.mask;
262     state->locked_mods |= action->mods.mask;
263
264     return 1;
265 }
266
267 enum xkb_key_latch_state {
268     NO_LATCH,
269     LATCH_KEY_DOWN,
270     LATCH_PENDING,
271 };
272
273 static int
274 xkb_filter_mod_latch_func(struct xkb_filter *filter, xkb_keycode_t keycode,
275                           int down)
276 {
277     enum xkb_key_latch_state latch = filter->priv;
278
279     if (down && latch == LATCH_PENDING) {
280         /* If this is a new keypress and we're awaiting our single latched
281          * keypress, then either break the latch if any random key is pressed,
282          * or promote it to a lock or plain base set if it's the same
283          * modifier. */
284         union xkb_action *action = xkb_key_get_action(filter->state, keycode);
285         if (action->type == XkbSA_LatchMods &&
286             action->mods.flags == filter->action.mods.flags &&
287             action->mods.mask == filter->action.mods.mask) {
288             filter->action = *action;
289             if (filter->action.mods.flags & XkbSA_LatchToLock) {
290                 filter->action.type = XkbSA_LockMods;
291                 filter->func = xkb_filter_mod_lock_func;
292                 filter->state->locked_mods |= filter->action.mods.mask;
293             }
294             else {
295                 filter->action.type = XkbSA_SetMods;
296                 filter->func = xkb_filter_mod_set_func;
297                 filter->state->base_mods |= filter->action.mods.mask;
298             }
299             filter->keycode = keycode;
300             filter->state->latched_mods &= ~filter->action.mods.mask;
301             /* XXX beep beep! */
302             return 0;
303         }
304         else if (((1 << action->type) & XkbSA_BreakLatch)) {
305             /* XXX: This may be totally broken, we might need to break the
306              *      latch in the next run after this press? */
307             filter->state->latched_mods &= ~filter->action.mods.mask;
308             filter->func = NULL;
309             return 1;
310         }
311     }
312     else if (!down && keycode == filter->keycode) {
313         /* Our key got released.  If we've set it to clear locks, and we
314          * currently have the same modifiers locked, then release them and
315          * don't actually latch.  Else we've actually hit the latching
316          * stage, so set PENDING and move our modifier from base to
317          * latched. */
318         if (latch == NO_LATCH ||
319             ((filter->action.mods.flags & XkbSA_ClearLocks) &&
320              (filter->state->locked_mods & filter->action.mods.mask) ==
321              filter->action.mods.mask)) {
322             /* XXX: We might be a bit overenthusiastic about clearing
323              *      mods other filters have set here? */
324             if (latch == LATCH_PENDING)
325                 filter->state->latched_mods &= ~filter->action.mods.mask;
326             else
327                 filter->state->base_mods &= ~filter->action.mods.mask;
328             filter->state->locked_mods &= ~filter->action.mods.mask;
329             filter->func = NULL;
330         }
331         else {
332             latch = LATCH_PENDING;
333             filter->state->base_mods &= ~filter->action.mods.mask;
334             filter->state->latched_mods |= filter->action.mods.mask;
335             /* XXX beep beep! */
336         }
337     }
338     else if (down && latch == LATCH_KEY_DOWN) {
339         /* Someone's pressed another key while we've still got the latching
340          * key held down, so keep the base modifier state active (from
341          * xkb_filter_mod_latch_new), but don't trip the latch, just clear
342          * it as soon as the modifier gets released. */
343         latch = NO_LATCH;
344     }
345
346     filter->priv = latch;
347
348     return 1;
349 }
350
351 static int
352 xkb_filter_mod_latch_new(struct xkb_state *state, xkb_keycode_t keycode,
353                          union xkb_action *action)
354 {
355     struct xkb_filter *filter = xkb_filter_new(state);
356     enum xkb_key_latch_state latch = LATCH_KEY_DOWN;
357
358     if (!filter) /* WSGO */
359         return -1;
360     filter->keycode = keycode;
361     filter->priv = latch;
362     filter->func = xkb_filter_mod_latch_func;
363     filter->action = *action;
364
365     filter->state->base_mods |= action->mods.mask;
366
367     return 1;
368 }
369
370 /**
371  * Applies any relevant filters to the key, first from the list of filters
372  * that are currently active, then if no filter has claimed the key, possibly
373  * apply a new filter from the key action.
374  */
375 static void
376 xkb_filter_apply_all(struct xkb_state *state, xkb_keycode_t key, int down)
377 {
378     struct xkb_filter *filters = state->filters;
379     union xkb_action *act = NULL;
380     int send = 1;
381     int i;
382
383     /* First run through all the currently active filters and see if any of
384      * them have claimed this event. */
385     for (i = 0; i < state->num_filters; i++) {
386         if (!filters[i].func)
387             continue;
388         send &= (*filters[i].func)(&filters[i], key, down);
389     }
390
391     if (!send || !down)
392         return;
393
394     act = xkb_key_get_action(state, key);
395     switch (act->type) {
396     case XkbSA_SetMods:
397         send = xkb_filter_mod_set_new(state, key, act);
398         break;
399     case XkbSA_LatchMods:
400         send = xkb_filter_mod_latch_new(state, key, act);
401         break;
402     case XkbSA_LockMods:
403         send = xkb_filter_mod_lock_new(state, key, act);
404         break;
405     case XkbSA_SetGroup:
406         send = xkb_filter_group_set_new(state, key, act);
407         break;
408 #if 0
409     case XkbSA_LatchGroup:
410         send = xkb_filter_mod_latch_new(state, key, act);
411         break;
412     case XkbSA_LockGroup:
413         send = xkb_filter_group_lock_new(state, key, act);
414         break;
415 #endif
416     }
417
418     return;
419 }
420
421 struct xkb_state *
422 xkb_state_new(struct xkb_desc *xkb)
423 {
424     struct xkb_state *ret;
425
426     if (!xkb)
427         return NULL;
428
429     ret = calloc(sizeof(*ret), 1);
430     if (!ret)
431         return NULL;
432
433     ret->refcnt = 1;
434     ret->xkb = xkb;
435     xkb_map_ref(xkb);
436
437     return ret;
438 }
439
440 void
441 xkb_state_unref(struct xkb_state *state)
442 {
443     state->refcnt--;
444     assert(state->refcnt >= 0);
445     if (state->refcnt == 0)
446         return;
447
448     xkb_map_unref(state->xkb);
449     free(state);
450 }
451
452 /**
453  * Update the LED state to match the rest of the xkb_state.
454  */
455 static void
456 xkb_state_led_update_all(struct xkb_state *state)
457 {
458     xkb_led_index_t led;
459
460     state->leds = 0;
461
462     for (led = 0; led < XkbNumIndicators; led++) {
463         struct xkb_indicator_map *map = &state->xkb->indicators->maps[led];
464         uint32_t mod_mask = 0;
465         uint32_t group_mask = 0;
466
467         if (!map->which_mods && !map->which_groups && !map->ctrls)
468             continue;
469
470         if (map->which_mods) {
471             if (map->which_mods & XkbIM_UseBase)
472                 mod_mask |= state->base_mods;
473             if (map->which_mods & XkbIM_UseLatched)
474                 mod_mask |= state->latched_mods;
475             if (map->which_mods & XkbIM_UseLocked)
476                 mod_mask |= state->locked_mods;
477             if (map->which_mods & XkbIM_UseEffective)
478                 mod_mask |= state->mods;
479             if ((map->mods.mask & mod_mask))
480                 state->leds |= (1 << led);
481         }
482         else if (map->which_groups) {
483             if (map->which_mods & XkbIM_UseBase)
484                 group_mask |= (1 << state->base_group);
485             if (map->which_mods & XkbIM_UseLatched)
486                 group_mask |= (1 << state->latched_group);
487             if (map->which_mods & XkbIM_UseLocked)
488                 group_mask |= (1 << state->locked_group);
489             if (map->which_mods & XkbIM_UseEffective)
490                 group_mask |= (1 << state->group);
491             if ((map->groups & group_mask))
492                 state->leds |= (1 << led);
493         }
494         else if (map->ctrls) {
495             if ((map->ctrls & state->xkb->ctrls->enabled_ctrls))
496                 state->leds |= (1 << led);
497         }
498     }
499 }
500
501 /**
502  * Given a particular key event, updates the state structure to reflect the
503  * new modifiers.
504  */
505 void
506 xkb_state_update_key(struct xkb_state *state, xkb_keycode_t key, int down)
507 {
508     xkb_filter_apply_all(state, key, down);
509
510     state->mods = (state->base_mods | state->latched_mods | state->locked_mods);
511     /* FIXME: Clamp/wrap locked_group */
512     state->group = state->locked_group + state->base_group +
513                    state->latched_group;
514     /* FIXME: Clamp/wrap effective group */
515
516     xkb_state_led_update_all(state);
517 }
518
519 /**
520  * Returns 1 if the given modifier is active with the specified type(s), 0 if
521  * not, or -1 if the modifier is invalid.
522  */
523 int xkb_state_mod_index_is_active(struct xkb_state *state,
524                                   xkb_mod_index_t idx,
525                                   enum xkb_state_component type)
526 {
527     int ret = 0;
528
529     if (idx >= xkb_map_num_mods(state->xkb))
530         return -1;
531
532     if (type & XKB_STATE_DEPRESSED)
533         ret |= (state->base_mods & (1 << idx));
534     if (type & XKB_STATE_LATCHED)
535         ret |= (state->latched_mods & (1 << idx));
536     if (type & XKB_STATE_LOCKED)
537         ret |= (state->locked_mods & (1 << idx));
538
539     return ret;
540 }
541
542 /**
543  * Returns 1 if the given modifier is active with the specified type(s), 0 if
544  * not, or -1 if the modifier is invalid.
545  */
546 int xkb_state_mod_name_is_active(struct xkb_state *state, const char *name,
547                                  enum xkb_state_component type)
548 {
549     xkb_mod_index_t idx = xkb_map_mod_get_index(state->xkb, name);
550
551     if (idx == XKB_MOD_INVALID)
552         return -1;
553
554     return xkb_state_mod_index_is_active(state, idx, type);
555 }
556
557 /**
558  * Returns 1 if the given group is active with the specified type(s), 0 if
559  * not, or -1 if the group is invalid.
560  */
561 int xkb_state_group_index_is_active(struct xkb_state *state,
562                                     xkb_group_index_t idx,
563                                     enum xkb_state_component type)
564 {
565     int ret = 0;
566
567     if (idx >= xkb_map_num_groups(state->xkb))
568         return -1;
569
570     if (type & XKB_STATE_DEPRESSED)
571         ret |= (state->base_group == idx);
572     if (type & XKB_STATE_LATCHED)
573         ret |= (state->latched_group == idx);
574     if (type & XKB_STATE_LOCKED)
575         ret |= (state->locked_group == idx);
576
577     return ret;
578 }
579
580 /**
581  * Returns 1 if the given modifier is active with the specified type(s), 0 if
582  * not, or -1 if the modifier is invalid.
583  */
584 int xkb_state_group_name_is_active(struct xkb_state *state, const char *name,
585                                  enum xkb_state_component type)
586 {
587     xkb_group_index_t idx = xkb_map_group_get_index(state->xkb, name);
588
589     if (idx == XKB_GROUP_INVALID)
590         return -1;
591
592     return xkb_state_group_index_is_active(state, idx, type);
593 }
594
595 /**
596  * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
597  */
598 int xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx)
599 {
600     if (idx >= xkb_map_num_leds(state->xkb))
601         return -1;
602
603     return !!(state->leds & (1 << idx));
604 }
605
606 /**
607  * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
608  */
609 int xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
610 {
611     xkb_led_index_t idx = xkb_map_led_get_index(state->xkb, name);
612
613     if (idx == XKB_LED_INVALID)
614         return -1;
615
616     return xkb_state_led_index_is_active(state, idx);
617 }