1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include <systemd/sd-bus.h>
26 #include <systemd/sd-event.h>
27 #include <xkbcommon/xkbcommon.h>
28 #include <xkbcommon/xkbcommon-compose.h>
32 #include "idev-internal.h"
34 #include "term-internal.h"
37 typedef struct kbdtbl kbdtbl;
38 typedef struct kbdmap kbdmap;
39 typedef struct kbdctx kbdctx;
40 typedef struct idev_keyboard idev_keyboard;
44 struct xkb_compose_table *xkb_compose_table;
49 struct xkb_keymap *xkb_keymap;
50 xkb_mod_index_t modmap[IDEV_KBDMOD_CNT];
51 xkb_led_index_t ledmap[IDEV_KBDLED_CNT];
56 idev_context *context;
57 struct xkb_context *xkb_context;
58 struct kbdmap *kbdmap;
59 struct kbdtbl *kbdtbl;
61 sd_bus_slot *slot_locale_props_changed;
62 sd_bus_slot *slot_locale_get_all;
65 char *locale_x11_model;
66 char *locale_x11_layout;
67 char *locale_x11_variant;
68 char *locale_x11_options;
70 char *last_x11_layout;
71 char *last_x11_variant;
72 char *last_x11_options;
75 struct idev_keyboard {
81 struct xkb_state *xkb_state;
82 struct xkb_compose_state *xkb_compose;
86 sd_event_source *repeat_timer;
91 uint32_t *compose_res;
96 #define keyboard_from_device(_d) container_of((_d), idev_keyboard, device)
98 #define KBDCTX_KEY "keyboard.context" /* hashmap key for global kbdctx */
99 #define KBDXKB_SHIFT (8) /* xkb shifts evdev key-codes by 8 */
100 #define KBDKEY_UP (0) /* KEY UP event value */
101 #define KBDKEY_DOWN (1) /* KEY DOWN event value */
102 #define KBDKEY_REPEAT (2) /* KEY REPEAT event value */
104 static const idev_device_vtable keyboard_vtable;
106 static int keyboard_update_kbdmap(idev_keyboard *k);
107 static int keyboard_update_kbdtbl(idev_keyboard *k);
110 * Keyboard Compose Tables
113 static kbdtbl *kbdtbl_ref(kbdtbl *kt) {
115 assert_return(kt->ref > 0, NULL);
122 static kbdtbl *kbdtbl_unref(kbdtbl *kt) {
126 assert_return(kt->ref > 0, NULL);
131 xkb_compose_table_unref(kt->xkb_compose_table);
137 DEFINE_TRIVIAL_CLEANUP_FUNC(kbdtbl*, kbdtbl_unref);
139 static int kbdtbl_new_from_locale(kbdtbl **out, kbdctx *kc, const char *locale) {
140 _cleanup_(kbdtbl_unrefp) kbdtbl *kt = NULL;
142 assert_return(out, -EINVAL);
143 assert_return(locale, -EINVAL);
145 kt = new0(kbdtbl, 1);
151 kt->xkb_compose_table = xkb_compose_table_new_from_locale(kc->xkb_context,
153 XKB_COMPOSE_COMPILE_NO_FLAGS);
154 if (!kt->xkb_compose_table)
155 return errno > 0 ? -errno : -EFAULT;
166 static const char * const kbdmap_modmap[IDEV_KBDMOD_CNT] = {
167 [IDEV_KBDMOD_IDX_SHIFT] = XKB_MOD_NAME_SHIFT,
168 [IDEV_KBDMOD_IDX_CTRL] = XKB_MOD_NAME_CTRL,
169 [IDEV_KBDMOD_IDX_ALT] = XKB_MOD_NAME_ALT,
170 [IDEV_KBDMOD_IDX_LINUX] = XKB_MOD_NAME_LOGO,
171 [IDEV_KBDMOD_IDX_CAPS] = XKB_MOD_NAME_CAPS,
174 static const char * const kbdmap_ledmap[IDEV_KBDLED_CNT] = {
175 [IDEV_KBDLED_IDX_NUM] = XKB_LED_NAME_NUM,
176 [IDEV_KBDLED_IDX_CAPS] = XKB_LED_NAME_CAPS,
177 [IDEV_KBDLED_IDX_SCROLL] = XKB_LED_NAME_SCROLL,
180 static kbdmap *kbdmap_ref(kbdmap *km) {
181 assert_return(km, NULL);
182 assert_return(km->ref > 0, NULL);
188 static kbdmap *kbdmap_unref(kbdmap *km) {
192 assert_return(km->ref > 0, NULL);
197 xkb_keymap_unref(km->xkb_keymap);
203 DEFINE_TRIVIAL_CLEANUP_FUNC(kbdmap*, kbdmap_unref);
205 static int kbdmap_new_from_names(kbdmap **out,
210 const char *options) {
211 _cleanup_(kbdmap_unrefp) kbdmap *km = NULL;
212 struct xkb_rule_names rmlvo = { };
215 assert_return(out, -EINVAL);
217 km = new0(kbdmap, 1);
223 rmlvo.rules = "evdev";
225 rmlvo.layout = layout;
226 rmlvo.variant = variant;
227 rmlvo.options = options;
230 km->xkb_keymap = xkb_keymap_new_from_names(kc->xkb_context, &rmlvo, 0);
232 return errno > 0 ? -errno : -EFAULT;
234 for (i = 0; i < IDEV_KBDMOD_CNT; ++i) {
235 const char *t = kbdmap_modmap[i];
238 km->modmap[i] = xkb_keymap_mod_get_index(km->xkb_keymap, t);
240 km->modmap[i] = XKB_MOD_INVALID;
243 for (i = 0; i < IDEV_KBDLED_CNT; ++i) {
244 const char *t = kbdmap_ledmap[i];
247 km->ledmap[i] = xkb_keymap_led_get_index(km->xkb_keymap, t);
249 km->ledmap[i] = XKB_LED_INVALID;
261 static int kbdctx_refresh_compose_table(kbdctx *kc, const char *lang) {
271 if (streq_ptr(kc->locale_lang, lang))
274 r = free_and_strdup(&kc->locale_lang, lang);
278 log_debug("idev-keyboard: new default compose table: [ %s ]", lang);
280 r = kbdtbl_new_from_locale(&kt, kc, lang);
282 /* TODO: We need to catch the case where no compose-file is
283 * available. xkb doesn't tell us so far.. so we must not treat
284 * it as a hard-failure but just continue. Preferably, we want
285 * xkb to tell us exactly whether compilation failed or whether
286 * there is no compose file available for this locale. */
287 log_debug("idev-keyboard: cannot load compose-table for '%s': %s",
293 kbdtbl_unref(kc->kbdtbl);
296 HASHMAP_FOREACH(s, kc->context->session_map, i)
297 HASHMAP_FOREACH(d, s->device_map, j)
298 if (idev_is_keyboard(d))
299 keyboard_update_kbdtbl(keyboard_from_device(d));
304 static void move_str(char **dest, char **src) {
310 static int kbdctx_refresh_keymap(kbdctx *kc) {
318 streq_ptr(kc->locale_x11_model, kc->last_x11_model) &&
319 streq_ptr(kc->locale_x11_layout, kc->last_x11_layout) &&
320 streq_ptr(kc->locale_x11_variant, kc->last_x11_variant) &&
321 streq_ptr(kc->locale_x11_options, kc->last_x11_options))
324 move_str(&kc->last_x11_model, &kc->locale_x11_model);
325 move_str(&kc->last_x11_layout, &kc->locale_x11_layout);
326 move_str(&kc->last_x11_variant, &kc->locale_x11_variant);
327 move_str(&kc->last_x11_options, &kc->locale_x11_options);
329 log_debug("idev-keyboard: new default keymap: [%s / %s / %s / %s]",
330 kc->last_x11_model, kc->last_x11_layout, kc->last_x11_variant, kc->last_x11_options);
332 /* TODO: add a fallback keymap that's compiled-in */
333 r = kbdmap_new_from_names(&km, kc, kc->last_x11_model, kc->last_x11_layout,
334 kc->last_x11_variant, kc->last_x11_options);
336 log_debug("idev-keyboard: cannot create keymap from locale1: %s",
341 kbdmap_unref(kc->kbdmap);
344 HASHMAP_FOREACH(s, kc->context->session_map, i)
345 HASHMAP_FOREACH(d, s->device_map, j)
346 if (idev_is_keyboard(d))
347 keyboard_update_kbdmap(keyboard_from_device(d));
352 static int kbdctx_set_locale(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
353 kbdctx *kc = userdata;
354 const char *s, *ctype = NULL, *lang = NULL;
357 r = sd_bus_message_enter_container(m, 'a', "s");
361 while ((r = sd_bus_message_read(m, "s", &s)) > 0) {
363 ctype = startswith(s, "LC_CTYPE=");
365 lang = startswith(s, "LANG=");
371 r = sd_bus_message_exit_container(m);
375 kbdctx_refresh_compose_table(kc, ctype ? : lang);
380 log_debug("idev-keyboard: cannot parse locale property from locale1: %s", strerror(-r));
385 static const struct bus_properties_map kbdctx_locale_map[] = {
386 { "Locale", "as", kbdctx_set_locale, 0 },
387 { "X11Model", "s", NULL, offsetof(kbdctx, locale_x11_model) },
388 { "X11Layout", "s", NULL, offsetof(kbdctx, locale_x11_layout) },
389 { "X11Variant", "s", NULL, offsetof(kbdctx, locale_x11_variant) },
390 { "X11Options", "s", NULL, offsetof(kbdctx, locale_x11_options) },
393 static int kbdctx_locale_get_all_fn(sd_bus *bus,
396 sd_bus_error *ret_err) {
397 kbdctx *kc = userdata;
400 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
402 if (sd_bus_message_is_method_error(m, NULL)) {
403 const sd_bus_error *error = sd_bus_message_get_error(m);
405 log_debug("idev-keyboard: GetAll() on locale1 failed: %s: %s",
406 error->name, error->message);
410 r = bus_message_map_all_properties(bus, m, kbdctx_locale_map, kc);
412 log_debug("idev-keyboard: erroneous GetAll() reply from locale1");
416 kbdctx_refresh_keymap(kc);
420 static int kbdctx_query_locale(kbdctx *kc) {
421 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
424 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
426 r = sd_bus_message_new_method_call(kc->context->sysbus,
428 "org.freedesktop.locale1",
429 "/org/freedesktop/locale1",
430 "org.freedesktop.DBus.Properties",
435 r = sd_bus_message_append(m, "s", "org.freedesktop.locale1");
439 r = sd_bus_call_async(kc->context->sysbus,
440 &kc->slot_locale_get_all,
442 kbdctx_locale_get_all_fn,
451 log_debug("idev-keyboard: cannot send GetAll to locale1: %s", strerror(-r));
455 static int kbdctx_locale_props_changed_fn(sd_bus *bus,
456 sd_bus_message *signal,
458 sd_bus_error *ret_err) {
459 kbdctx *kc = userdata;
462 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
464 /* skip interface name */
465 r = sd_bus_message_skip(signal, "s");
469 r = bus_message_map_properties_changed(bus, signal, kbdctx_locale_map, kc);
474 r = kbdctx_query_locale(kc);
479 kbdctx_refresh_keymap(kc);
483 log_debug("idev-keyboard: cannot handle PropertiesChanged from locale1: %s", strerror(-r));
487 static int kbdctx_setup_bus(kbdctx *kc) {
490 r = sd_bus_add_match(kc->context->sysbus,
491 &kc->slot_locale_props_changed,
493 "sender='org.freedesktop.locale1',"
494 "interface='org.freedesktop.DBus.Properties',"
495 "member='PropertiesChanged',"
496 "path='/org/freedesktop/locale1'",
497 kbdctx_locale_props_changed_fn,
500 log_debug("idev-keyboard: cannot setup locale1 link: %s", strerror(-r));
504 return kbdctx_query_locale(kc);
507 static void kbdctx_log_fn(struct xkb_context *ctx, enum xkb_log_level lvl, const char *format, va_list args) {
511 if (lvl >= XKB_LOG_LEVEL_DEBUG)
513 else if (lvl >= XKB_LOG_LEVEL_INFO)
515 else if (lvl >= XKB_LOG_LEVEL_WARNING)
516 sd_lvl = LOG_INFO; /* most XKB warnings really are informational */
517 else if (lvl >= XKB_LOG_LEVEL_ERROR)
519 else if (lvl >= XKB_LOG_LEVEL_CRITICAL)
524 snprintf(buf, sizeof(buf), "idev-xkb: %s", format);
525 log_internalv(sd_lvl, 0, __FILE__, __LINE__, __func__, buf, args);
528 static kbdctx *kbdctx_ref(kbdctx *kc) {
529 assert_return(kc, NULL);
530 assert_return(kc->ref > 0, NULL);
536 static kbdctx *kbdctx_unref(kbdctx *kc) {
540 assert_return(kc->ref > 0, NULL);
545 free(kc->last_x11_options);
546 free(kc->last_x11_variant);
547 free(kc->last_x11_layout);
548 free(kc->last_x11_model);
549 free(kc->locale_x11_options);
550 free(kc->locale_x11_variant);
551 free(kc->locale_x11_layout);
552 free(kc->locale_x11_model);
553 free(kc->locale_lang);
554 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
555 kc->slot_locale_props_changed = sd_bus_slot_unref(kc->slot_locale_props_changed);
556 kc->kbdtbl = kbdtbl_unref(kc->kbdtbl);
557 kc->kbdmap = kbdmap_unref(kc->kbdmap);
558 xkb_context_unref(kc->xkb_context);
559 hashmap_remove_value(kc->context->data_map, KBDCTX_KEY, kc);
565 DEFINE_TRIVIAL_CLEANUP_FUNC(kbdctx*, kbdctx_unref);
567 static int kbdctx_new(kbdctx **out, idev_context *c) {
568 _cleanup_(kbdctx_unrefp) kbdctx *kc = NULL;
571 assert_return(out, -EINVAL);
572 assert_return(c, -EINVAL);
574 kc = new0(kbdctx, 1);
582 kc->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
583 if (!kc->xkb_context)
584 return errno > 0 ? -errno : -EFAULT;
586 xkb_context_set_log_fn(kc->xkb_context, kbdctx_log_fn);
587 xkb_context_set_log_level(kc->xkb_context, XKB_LOG_LEVEL_DEBUG);
589 r = kbdctx_refresh_keymap(kc);
593 r = kbdctx_refresh_compose_table(kc, NULL);
598 r = kbdctx_setup_bus(kc);
603 r = hashmap_put(c->data_map, KBDCTX_KEY, kc);
612 static int get_kbdctx(idev_context *c, kbdctx **out) {
615 assert_return(c, -EINVAL);
616 assert_return(out, -EINVAL);
618 kc = hashmap_get(c->data_map, KBDCTX_KEY);
620 *out = kbdctx_ref(kc);
624 return kbdctx_new(out, c);
631 bool idev_is_keyboard(idev_device *d) {
632 return d && d->vtable == &keyboard_vtable;
635 idev_device *idev_find_keyboard(idev_session *s, const char *name) {
638 assert_return(s, NULL);
639 assert_return(name, NULL);
641 kname = strappenda("keyboard/", name);
642 return hashmap_get(s->device_map, kname);
645 static int keyboard_raise_data(idev_keyboard *k, idev_data *data) {
646 idev_device *d = &k->device;
649 r = idev_session_raise_device_data(d->session, d, data);
651 log_debug("idev-keyboard: %s/%s: error while raising data event: %s",
652 d->session->name, d->name, strerror(-r));
657 static int keyboard_resize_bufs(idev_keyboard *k, uint32_t n_syms) {
660 if (n_syms <= k->n_syms)
663 t = realloc(k->compose_res, sizeof(*t) * n_syms);
668 t = realloc(k->evdata.keyboard.keysyms, sizeof(*t) * n_syms);
671 k->evdata.keyboard.keysyms = t;
673 t = realloc(k->evdata.keyboard.codepoints, sizeof(*t) * n_syms);
676 k->evdata.keyboard.codepoints = t;
678 t = realloc(k->repdata.keyboard.keysyms, sizeof(*t) * n_syms);
681 k->repdata.keyboard.keysyms = t;
683 t = realloc(k->repdata.keyboard.codepoints, sizeof(*t) * n_syms);
686 k->repdata.keyboard.codepoints = t;
692 static unsigned int keyboard_read_compose(idev_keyboard *k, const xkb_keysym_t **out) {
693 _cleanup_free_ char *t = NULL;
699 r = xkb_compose_state_get_utf8(k->xkb_compose, buf, sizeof(buf));
700 if (r >= (int)sizeof(buf)) {
705 xkb_compose_state_get_utf8(k->xkb_compose, t, r + 1);
711 for (i = 0; i < r; ++i) {
715 len = term_utf8_decode(&u8, &ucs, p[i]);
717 r = keyboard_resize_bufs(k, flen + len);
721 for (j = 0; j < len; ++j)
722 k->compose_res[flen++] = ucs[j];
726 *out = k->compose_res;
730 static void keyboard_arm(idev_keyboard *k, usec_t usecs) {
734 usecs += now(CLOCK_MONOTONIC);
735 r = sd_event_source_set_time(k->repeat_timer, usecs);
737 sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_ONESHOT);
739 sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
743 static int keyboard_repeat_timer_fn(sd_event_source *source, uint64_t usec, void *userdata) {
744 idev_keyboard *k = userdata;
746 /* never feed REPEAT keys into COMPOSE */
748 keyboard_arm(k, k->repeat_rate);
749 return keyboard_raise_data(k, &k->repdata);
752 int idev_keyboard_new(idev_device **out, idev_session *s, const char *name) {
753 _cleanup_(idev_device_freep) idev_device *d = NULL;
758 assert_return(out, -EINVAL);
759 assert_return(s, -EINVAL);
760 assert_return(name, -EINVAL);
762 k = new0(idev_keyboard, 1);
767 k->device = IDEV_DEVICE_INIT(&keyboard_vtable, s);
768 k->repeat_delay = 250 * USEC_PER_MSEC;
769 k->repeat_rate = 30 * USEC_PER_MSEC;
771 /* TODO: add key-repeat configuration */
773 r = get_kbdctx(s->context, &k->kbdctx);
777 r = keyboard_update_kbdmap(k);
781 r = keyboard_update_kbdtbl(k);
785 r = keyboard_resize_bufs(k, 8);
789 r = sd_event_add_time(s->context->event,
794 keyboard_repeat_timer_fn,
799 r = sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
803 kname = strappenda("keyboard/", name);
804 r = idev_device_add(d, kname);
814 static void keyboard_free(idev_device *d) {
815 idev_keyboard *k = keyboard_from_device(d);
817 xkb_compose_state_unref(k->xkb_compose);
818 xkb_state_unref(k->xkb_state);
819 free(k->repdata.keyboard.codepoints);
820 free(k->repdata.keyboard.keysyms);
821 free(k->evdata.keyboard.codepoints);
822 free(k->evdata.keyboard.keysyms);
823 free(k->compose_res);
824 k->repeat_timer = sd_event_source_unref(k->repeat_timer);
825 k->kbdtbl = kbdtbl_unref(k->kbdtbl);
826 k->kbdmap = kbdmap_unref(k->kbdmap);
827 k->kbdctx = kbdctx_unref(k->kbdctx);
831 static int8_t guess_ascii(struct xkb_state *state, uint32_t code, uint32_t n_syms, const uint32_t *syms) {
832 xkb_layout_index_t n_lo, lo;
833 xkb_level_index_t lv;
834 struct xkb_keymap *keymap;
835 const xkb_keysym_t *s;
838 if (n_syms == 1 && syms[0] < 128 && syms[0] > 0)
841 keymap = xkb_state_get_keymap(state);
842 n_lo = xkb_keymap_num_layouts_for_key(keymap, code + KBDXKB_SHIFT);
844 for (lo = 0; lo < n_lo; ++lo) {
845 lv = xkb_state_key_get_level(state, code + KBDXKB_SHIFT, lo);
846 num = xkb_keymap_key_get_syms_by_level(keymap, code + KBDXKB_SHIFT, lo, lv, &s);
847 if (num == 1 && s[0] < 128 && s[0] > 0)
854 static int keyboard_fill(idev_keyboard *k,
860 const uint32_t *keysyms) {
861 idev_data_keyboard *kev;
865 assert(dst == &k->evdata || dst == &k->repdata);
867 r = keyboard_resize_bufs(k, n_syms);
871 dst->type = IDEV_DATA_KEYBOARD;
872 dst->resync = resync;
873 kev = &dst->keyboard;
874 kev->ascii = guess_ascii(k->xkb_state, code, n_syms, keysyms);
878 kev->consumed_mods = 0;
879 kev->n_syms = n_syms;
880 memcpy(kev->keysyms, keysyms, sizeof(*keysyms) * n_syms);
882 for (i = 0; i < n_syms; ++i) {
883 kev->codepoints[i] = xkb_keysym_to_utf32(keysyms[i]);
884 if (!kev->codepoints[i])
885 kev->codepoints[i] = 0xffffffffUL;
888 for (i = 0; i < IDEV_KBDMOD_CNT; ++i) {
889 if (k->kbdmap->modmap[i] == XKB_MOD_INVALID)
892 r = xkb_state_mod_index_is_active(k->xkb_state, k->kbdmap->modmap[i], XKB_STATE_MODS_EFFECTIVE);
896 r = xkb_state_mod_index_is_consumed(k->xkb_state, code + KBDXKB_SHIFT, k->kbdmap->modmap[i]);
898 kev->consumed_mods |= 1 << i;
904 static void keyboard_repeat(idev_keyboard *k) {
905 idev_data *evdata = &k->evdata;
906 idev_data *repdata = &k->repdata;
907 idev_data_keyboard *evkbd = &evdata->keyboard;
908 idev_data_keyboard *repkbd = &repdata->keyboard;
909 const xkb_keysym_t *keysyms;
910 idev_device *d = &k->device;
914 if (evdata->resync) {
916 * We received a re-sync event. During re-sync, any number of
917 * key-events may have been lost and sync-events may be
918 * re-ordered. Always disable key-repeat for those events. Any
919 * following event will trigger it again.
922 k->repeating = false;
927 repeats = xkb_keymap_key_repeats(k->kbdmap->xkb_keymap, evkbd->keycode + KBDXKB_SHIFT);
929 if (k->repeating && repkbd->keycode == evkbd->keycode) {
931 * We received an event for the key we currently repeat. If it
932 * was released, stop key-repeat. Otherwise, ignore the event.
935 if (evkbd->value == KBDKEY_UP) {
936 k->repeating = false;
939 } else if (evkbd->value == KBDKEY_DOWN && repeats) {
941 * We received a key-down event for a key that repeats. The
942 * previous condition caught keys we already repeat, so we know
943 * this is a different key or no key-repeat is running. Start
948 num = xkb_state_key_get_syms(k->xkb_state, evkbd->keycode + KBDXKB_SHIFT, &keysyms);
950 r = errno > 0 ? errno : -EFAULT;
952 r = keyboard_fill(k, repdata, false, evkbd->keycode, KBDKEY_REPEAT, num, keysyms);
955 log_debug("idev-keyboard: %s/%s: cannot set key-repeat: %s",
956 d->session->name, d->name, strerror(-r));
957 k->repeating = false;
961 keyboard_arm(k, k->repeat_delay);
963 } else if (k->repeating && !repeats) {
965 * We received an event for a key that does not repeat, but we
966 * currently repeat a previously received key. The new key is
967 * usually a modifier, but might be any kind of key. In this
968 * case, we continue repeating the old key, but update the
969 * symbols according to the new state.
973 num = xkb_state_key_get_syms(k->xkb_state, repkbd->keycode + KBDXKB_SHIFT, &keysyms);
975 r = errno > 0 ? errno : -EFAULT;
977 r = keyboard_fill(k, repdata, false, repkbd->keycode, KBDKEY_REPEAT, num, keysyms);
980 log_debug("idev-keyboard: %s/%s: cannot update key-repeat: %s",
981 d->session->name, d->name, strerror(-r));
982 k->repeating = false;
988 static int keyboard_feed_evdev(idev_keyboard *k, idev_data *data) {
989 struct input_event *ev = &data->evdev.event;
990 enum xkb_state_component compch;
991 enum xkb_compose_status cstatus;
992 const xkb_keysym_t *keysyms;
993 idev_device *d = &k->device;
996 if (ev->type != EV_KEY || ev->value > KBDKEY_DOWN)
999 /* TODO: We should audit xkb-actions, whether they need @resync as
1000 * flag. Most actions should just be executed, however, there might
1001 * be actions that depend on modifier-orders. Those should be
1004 num = xkb_state_key_get_syms(k->xkb_state, ev->code + KBDXKB_SHIFT, &keysyms);
1005 compch = xkb_state_update_key(k->xkb_state, ev->code + KBDXKB_SHIFT, ev->value);
1007 if (compch & XKB_STATE_LEDS) {
1008 /* TODO: update LEDs */
1016 if (k->xkb_compose && ev->value == KBDKEY_DOWN) {
1017 if (num == 1 && !data->resync) {
1018 xkb_compose_state_feed(k->xkb_compose, keysyms[0]);
1019 cstatus = xkb_compose_state_get_status(k->xkb_compose);
1021 cstatus = XKB_COMPOSE_CANCELLED;
1025 case XKB_COMPOSE_NOTHING:
1026 /* keep produced keysyms and forward unchanged */
1028 case XKB_COMPOSE_COMPOSING:
1029 /* consumed by compose-state, drop keysym */
1033 case XKB_COMPOSE_COMPOSED:
1034 /* compose-state produced sth, replace keysym */
1035 num = keyboard_read_compose(k, &keysyms);
1036 xkb_compose_state_reset(k->xkb_compose);
1038 case XKB_COMPOSE_CANCELLED:
1039 /* canceled compose, reset, forward cancellation sym */
1040 xkb_compose_state_reset(k->xkb_compose);
1043 } else if (k->xkb_compose &&
1045 keysyms[0] == XKB_KEY_Multi_key &&
1047 ev->value == KBDKEY_UP) {
1048 /* Reset compose state on Multi-Key UP events. This effectively
1049 * requires you to hold the key during the whole sequence. I
1050 * think it's pretty handy to avoid accidental
1051 * Compose-sequences, but this may break Compose for disabled
1052 * people. We really need to make this opional! (TODO) */
1053 xkb_compose_state_reset(k->xkb_compose);
1056 if (ev->value == KBDKEY_UP) {
1057 /* never produce keysyms for UP */
1062 r = keyboard_fill(k, &k->evdata, data->resync, ev->code, ev->value, num, keysyms);
1067 return keyboard_raise_data(k, &k->evdata);
1070 log_debug("idev-keyboard: %s/%s: cannot handle event: %s",
1071 d->session->name, d->name, strerror(-r));
1072 k->repeating = false;
1077 static int keyboard_feed(idev_device *d, idev_data *data) {
1078 idev_keyboard *k = keyboard_from_device(d);
1080 switch (data->type) {
1081 case IDEV_DATA_RESYNC:
1083 * If the underlying device is re-synced, key-events might be
1084 * sent re-ordered. Thus, we don't know which key was pressed
1085 * last. Key-repeat might get confused, hence, disable it
1086 * during re-syncs. The first following event will enable it
1090 k->repeating = false;
1093 case IDEV_DATA_EVDEV:
1094 return keyboard_feed_evdev(k, data);
1100 static int keyboard_update_kbdmap(idev_keyboard *k) {
1101 idev_device *d = &k->device;
1102 struct xkb_state *state;
1108 km = k->kbdctx->kbdmap;
1109 if (km == k->kbdmap)
1113 state = xkb_state_new(km->xkb_keymap);
1115 r = errno > 0 ? -errno : -EFAULT;
1119 kbdmap_unref(k->kbdmap);
1120 k->kbdmap = kbdmap_ref(km);
1121 xkb_state_unref(k->xkb_state);
1122 k->xkb_state = state;
1124 /* TODO: On state-change, we should trigger a resync so the whole
1125 * event-state is flushed into the new xkb-state. libevdev currently
1126 * does not support that, though. */
1131 log_debug("idev-keyboard: %s/%s: cannot adopt new keymap: %s",
1132 d->session->name, d->name, strerror(-r));
1136 static int keyboard_update_kbdtbl(idev_keyboard *k) {
1137 idev_device *d = &k->device;
1138 struct xkb_compose_state *compose = NULL;
1144 kt = k->kbdctx->kbdtbl;
1145 if (kt == k->kbdtbl)
1150 compose = xkb_compose_state_new(kt->xkb_compose_table, XKB_COMPOSE_STATE_NO_FLAGS);
1152 r = errno > 0 ? -errno : -EFAULT;
1157 kbdtbl_unref(k->kbdtbl);
1158 k->kbdtbl = kbdtbl_ref(kt);
1159 xkb_compose_state_unref(k->xkb_compose);
1160 k->xkb_compose = compose;
1165 log_debug("idev-keyboard: %s/%s: cannot adopt new compose table: %s",
1166 d->session->name, d->name, strerror(-r));
1170 static const idev_device_vtable keyboard_vtable = {
1171 .free = keyboard_free,
1172 .feed = keyboard_feed,