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_errno(r, "idev-keyboard: cannot load compose-table for '%s': %m",
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_errno(r, "idev-keyboard: cannot create keymap from locale1: %m");
340 kbdmap_unref(kc->kbdmap);
343 HASHMAP_FOREACH(s, kc->context->session_map, i)
344 HASHMAP_FOREACH(d, s->device_map, j)
345 if (idev_is_keyboard(d))
346 keyboard_update_kbdmap(keyboard_from_device(d));
351 static int kbdctx_set_locale(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
352 kbdctx *kc = userdata;
353 const char *s, *ctype = NULL, *lang = NULL;
356 r = sd_bus_message_enter_container(m, 'a', "s");
360 while ((r = sd_bus_message_read(m, "s", &s)) > 0) {
362 ctype = startswith(s, "LC_CTYPE=");
364 lang = startswith(s, "LANG=");
370 r = sd_bus_message_exit_container(m);
374 kbdctx_refresh_compose_table(kc, ctype ? : lang);
379 log_debug_errno(r, "idev-keyboard: cannot parse locale property from locale1: %m");
384 static const struct bus_properties_map kbdctx_locale_map[] = {
385 { "Locale", "as", kbdctx_set_locale, 0 },
386 { "X11Model", "s", NULL, offsetof(kbdctx, locale_x11_model) },
387 { "X11Layout", "s", NULL, offsetof(kbdctx, locale_x11_layout) },
388 { "X11Variant", "s", NULL, offsetof(kbdctx, locale_x11_variant) },
389 { "X11Options", "s", NULL, offsetof(kbdctx, locale_x11_options) },
392 static int kbdctx_locale_get_all_fn(sd_bus *bus,
395 sd_bus_error *ret_err) {
396 kbdctx *kc = userdata;
399 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
401 if (sd_bus_message_is_method_error(m, NULL)) {
402 const sd_bus_error *error = sd_bus_message_get_error(m);
404 log_debug("idev-keyboard: GetAll() on locale1 failed: %s: %s",
405 error->name, error->message);
409 r = bus_message_map_all_properties(bus, m, kbdctx_locale_map, kc);
411 log_debug("idev-keyboard: erroneous GetAll() reply from locale1");
415 kbdctx_refresh_keymap(kc);
419 static int kbdctx_query_locale(kbdctx *kc) {
420 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
423 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
425 r = sd_bus_message_new_method_call(kc->context->sysbus,
427 "org.freedesktop.locale1",
428 "/org/freedesktop/locale1",
429 "org.freedesktop.DBus.Properties",
434 r = sd_bus_message_append(m, "s", "org.freedesktop.locale1");
438 r = sd_bus_call_async(kc->context->sysbus,
439 &kc->slot_locale_get_all,
441 kbdctx_locale_get_all_fn,
450 log_debug_errno(r, "idev-keyboard: cannot send GetAll to locale1: %m");
454 static int kbdctx_locale_props_changed_fn(sd_bus *bus,
455 sd_bus_message *signal,
457 sd_bus_error *ret_err) {
458 kbdctx *kc = userdata;
461 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
463 /* skip interface name */
464 r = sd_bus_message_skip(signal, "s");
468 r = bus_message_map_properties_changed(bus, signal, kbdctx_locale_map, kc);
473 r = kbdctx_query_locale(kc);
478 kbdctx_refresh_keymap(kc);
482 log_debug_errno(r, "idev-keyboard: cannot handle PropertiesChanged from locale1: %m");
486 static int kbdctx_setup_bus(kbdctx *kc) {
489 r = sd_bus_add_match(kc->context->sysbus,
490 &kc->slot_locale_props_changed,
492 "sender='org.freedesktop.locale1',"
493 "interface='org.freedesktop.DBus.Properties',"
494 "member='PropertiesChanged',"
495 "path='/org/freedesktop/locale1'",
496 kbdctx_locale_props_changed_fn,
499 log_debug_errno(r, "idev-keyboard: cannot setup locale1 link: %m");
503 return kbdctx_query_locale(kc);
506 static void kbdctx_log_fn(struct xkb_context *ctx, enum xkb_log_level lvl, const char *format, va_list args) {
510 if (lvl >= XKB_LOG_LEVEL_DEBUG)
512 else if (lvl >= XKB_LOG_LEVEL_INFO)
514 else if (lvl >= XKB_LOG_LEVEL_WARNING)
515 sd_lvl = LOG_INFO; /* most XKB warnings really are informational */
516 else if (lvl >= XKB_LOG_LEVEL_ERROR)
518 else if (lvl >= XKB_LOG_LEVEL_CRITICAL)
523 snprintf(buf, sizeof(buf), "idev-xkb: %s", format);
524 log_internalv(sd_lvl, 0, __FILE__, __LINE__, __func__, buf, args);
527 static kbdctx *kbdctx_ref(kbdctx *kc) {
528 assert_return(kc, NULL);
529 assert_return(kc->ref > 0, NULL);
535 static kbdctx *kbdctx_unref(kbdctx *kc) {
539 assert_return(kc->ref > 0, NULL);
544 free(kc->last_x11_options);
545 free(kc->last_x11_variant);
546 free(kc->last_x11_layout);
547 free(kc->last_x11_model);
548 free(kc->locale_x11_options);
549 free(kc->locale_x11_variant);
550 free(kc->locale_x11_layout);
551 free(kc->locale_x11_model);
552 free(kc->locale_lang);
553 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
554 kc->slot_locale_props_changed = sd_bus_slot_unref(kc->slot_locale_props_changed);
555 kc->kbdtbl = kbdtbl_unref(kc->kbdtbl);
556 kc->kbdmap = kbdmap_unref(kc->kbdmap);
557 xkb_context_unref(kc->xkb_context);
558 hashmap_remove_value(kc->context->data_map, KBDCTX_KEY, kc);
564 DEFINE_TRIVIAL_CLEANUP_FUNC(kbdctx*, kbdctx_unref);
566 static int kbdctx_new(kbdctx **out, idev_context *c) {
567 _cleanup_(kbdctx_unrefp) kbdctx *kc = NULL;
570 assert_return(out, -EINVAL);
571 assert_return(c, -EINVAL);
573 kc = new0(kbdctx, 1);
581 kc->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
582 if (!kc->xkb_context)
583 return errno > 0 ? -errno : -EFAULT;
585 xkb_context_set_log_fn(kc->xkb_context, kbdctx_log_fn);
586 xkb_context_set_log_level(kc->xkb_context, XKB_LOG_LEVEL_DEBUG);
588 r = kbdctx_refresh_keymap(kc);
592 r = kbdctx_refresh_compose_table(kc, NULL);
597 r = kbdctx_setup_bus(kc);
602 r = hashmap_put(c->data_map, KBDCTX_KEY, kc);
611 static int get_kbdctx(idev_context *c, kbdctx **out) {
614 assert_return(c, -EINVAL);
615 assert_return(out, -EINVAL);
617 kc = hashmap_get(c->data_map, KBDCTX_KEY);
619 *out = kbdctx_ref(kc);
623 return kbdctx_new(out, c);
630 bool idev_is_keyboard(idev_device *d) {
631 return d && d->vtable == &keyboard_vtable;
634 idev_device *idev_find_keyboard(idev_session *s, const char *name) {
637 assert_return(s, NULL);
638 assert_return(name, NULL);
640 kname = strappenda("keyboard/", name);
641 return hashmap_get(s->device_map, kname);
644 static int keyboard_raise_data(idev_keyboard *k, idev_data *data) {
645 idev_device *d = &k->device;
648 r = idev_session_raise_device_data(d->session, d, data);
650 log_debug_errno(r, "idev-keyboard: %s/%s: error while raising data event: %m",
651 d->session->name, d->name);
656 static int keyboard_resize_bufs(idev_keyboard *k, uint32_t n_syms) {
659 if (n_syms <= k->n_syms)
662 t = realloc(k->compose_res, sizeof(*t) * n_syms);
667 t = realloc(k->evdata.keyboard.keysyms, sizeof(*t) * n_syms);
670 k->evdata.keyboard.keysyms = t;
672 t = realloc(k->evdata.keyboard.codepoints, sizeof(*t) * n_syms);
675 k->evdata.keyboard.codepoints = t;
677 t = realloc(k->repdata.keyboard.keysyms, sizeof(*t) * n_syms);
680 k->repdata.keyboard.keysyms = t;
682 t = realloc(k->repdata.keyboard.codepoints, sizeof(*t) * n_syms);
685 k->repdata.keyboard.codepoints = t;
691 static unsigned int keyboard_read_compose(idev_keyboard *k, const xkb_keysym_t **out) {
692 _cleanup_free_ char *t = NULL;
698 r = xkb_compose_state_get_utf8(k->xkb_compose, buf, sizeof(buf));
699 if (r >= (int)sizeof(buf)) {
704 xkb_compose_state_get_utf8(k->xkb_compose, t, r + 1);
710 for (i = 0; i < r; ++i) {
714 len = term_utf8_decode(&u8, &ucs, p[i]);
716 r = keyboard_resize_bufs(k, flen + len);
720 for (j = 0; j < len; ++j)
721 k->compose_res[flen++] = ucs[j];
725 *out = k->compose_res;
729 static void keyboard_arm(idev_keyboard *k, usec_t usecs) {
733 usecs += now(CLOCK_MONOTONIC);
734 r = sd_event_source_set_time(k->repeat_timer, usecs);
736 sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_ONESHOT);
738 sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
742 static int keyboard_repeat_timer_fn(sd_event_source *source, uint64_t usec, void *userdata) {
743 idev_keyboard *k = userdata;
745 /* never feed REPEAT keys into COMPOSE */
747 keyboard_arm(k, k->repeat_rate);
748 return keyboard_raise_data(k, &k->repdata);
751 int idev_keyboard_new(idev_device **out, idev_session *s, const char *name) {
752 _cleanup_(idev_device_freep) idev_device *d = NULL;
757 assert_return(out, -EINVAL);
758 assert_return(s, -EINVAL);
759 assert_return(name, -EINVAL);
761 k = new0(idev_keyboard, 1);
766 k->device = IDEV_DEVICE_INIT(&keyboard_vtable, s);
767 k->repeat_delay = 250 * USEC_PER_MSEC;
768 k->repeat_rate = 30 * USEC_PER_MSEC;
770 /* TODO: add key-repeat configuration */
772 r = get_kbdctx(s->context, &k->kbdctx);
776 r = keyboard_update_kbdmap(k);
780 r = keyboard_update_kbdtbl(k);
784 r = keyboard_resize_bufs(k, 8);
788 r = sd_event_add_time(s->context->event,
793 keyboard_repeat_timer_fn,
798 r = sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
802 kname = strappenda("keyboard/", name);
803 r = idev_device_add(d, kname);
813 static void keyboard_free(idev_device *d) {
814 idev_keyboard *k = keyboard_from_device(d);
816 xkb_compose_state_unref(k->xkb_compose);
817 xkb_state_unref(k->xkb_state);
818 free(k->repdata.keyboard.codepoints);
819 free(k->repdata.keyboard.keysyms);
820 free(k->evdata.keyboard.codepoints);
821 free(k->evdata.keyboard.keysyms);
822 free(k->compose_res);
823 k->repeat_timer = sd_event_source_unref(k->repeat_timer);
824 k->kbdtbl = kbdtbl_unref(k->kbdtbl);
825 k->kbdmap = kbdmap_unref(k->kbdmap);
826 k->kbdctx = kbdctx_unref(k->kbdctx);
830 static int8_t guess_ascii(struct xkb_state *state, uint32_t code, uint32_t n_syms, const uint32_t *syms) {
831 xkb_layout_index_t n_lo, lo;
832 xkb_level_index_t lv;
833 struct xkb_keymap *keymap;
834 const xkb_keysym_t *s;
837 if (n_syms == 1 && syms[0] < 128 && syms[0] > 0)
840 keymap = xkb_state_get_keymap(state);
841 n_lo = xkb_keymap_num_layouts_for_key(keymap, code + KBDXKB_SHIFT);
843 for (lo = 0; lo < n_lo; ++lo) {
844 lv = xkb_state_key_get_level(state, code + KBDXKB_SHIFT, lo);
845 num = xkb_keymap_key_get_syms_by_level(keymap, code + KBDXKB_SHIFT, lo, lv, &s);
846 if (num == 1 && s[0] < 128 && s[0] > 0)
853 static int keyboard_fill(idev_keyboard *k,
859 const uint32_t *keysyms) {
860 idev_data_keyboard *kev;
864 assert(dst == &k->evdata || dst == &k->repdata);
866 r = keyboard_resize_bufs(k, n_syms);
870 dst->type = IDEV_DATA_KEYBOARD;
871 dst->resync = resync;
872 kev = &dst->keyboard;
873 kev->ascii = guess_ascii(k->xkb_state, code, n_syms, keysyms);
877 kev->consumed_mods = 0;
878 kev->n_syms = n_syms;
879 memcpy(kev->keysyms, keysyms, sizeof(*keysyms) * n_syms);
881 for (i = 0; i < n_syms; ++i) {
882 kev->codepoints[i] = xkb_keysym_to_utf32(keysyms[i]);
883 if (!kev->codepoints[i])
884 kev->codepoints[i] = 0xffffffffUL;
887 for (i = 0; i < IDEV_KBDMOD_CNT; ++i) {
888 if (k->kbdmap->modmap[i] == XKB_MOD_INVALID)
891 r = xkb_state_mod_index_is_active(k->xkb_state, k->kbdmap->modmap[i], XKB_STATE_MODS_EFFECTIVE);
895 r = xkb_state_mod_index_is_consumed(k->xkb_state, code + KBDXKB_SHIFT, k->kbdmap->modmap[i]);
897 kev->consumed_mods |= 1 << i;
903 static void keyboard_repeat(idev_keyboard *k) {
904 idev_data *evdata = &k->evdata;
905 idev_data *repdata = &k->repdata;
906 idev_data_keyboard *evkbd = &evdata->keyboard;
907 idev_data_keyboard *repkbd = &repdata->keyboard;
908 const xkb_keysym_t *keysyms;
909 idev_device *d = &k->device;
913 if (evdata->resync) {
915 * We received a re-sync event. During re-sync, any number of
916 * key-events may have been lost and sync-events may be
917 * re-ordered. Always disable key-repeat for those events. Any
918 * following event will trigger it again.
921 k->repeating = false;
926 repeats = xkb_keymap_key_repeats(k->kbdmap->xkb_keymap, evkbd->keycode + KBDXKB_SHIFT);
928 if (k->repeating && repkbd->keycode == evkbd->keycode) {
930 * We received an event for the key we currently repeat. If it
931 * was released, stop key-repeat. Otherwise, ignore the event.
934 if (evkbd->value == KBDKEY_UP) {
935 k->repeating = false;
938 } else if (evkbd->value == KBDKEY_DOWN && repeats) {
940 * We received a key-down event for a key that repeats. The
941 * previous condition caught keys we already repeat, so we know
942 * this is a different key or no key-repeat is running. Start
947 num = xkb_state_key_get_syms(k->xkb_state, evkbd->keycode + KBDXKB_SHIFT, &keysyms);
949 r = errno > 0 ? errno : -EFAULT;
951 r = keyboard_fill(k, repdata, false, evkbd->keycode, KBDKEY_REPEAT, num, keysyms);
954 log_debug_errno(r, "idev-keyboard: %s/%s: cannot set key-repeat: %m",
955 d->session->name, d->name);
956 k->repeating = false;
960 keyboard_arm(k, k->repeat_delay);
962 } else if (k->repeating && !repeats) {
964 * We received an event for a key that does not repeat, but we
965 * currently repeat a previously received key. The new key is
966 * usually a modifier, but might be any kind of key. In this
967 * case, we continue repeating the old key, but update the
968 * symbols according to the new state.
972 num = xkb_state_key_get_syms(k->xkb_state, repkbd->keycode + KBDXKB_SHIFT, &keysyms);
974 r = errno > 0 ? errno : -EFAULT;
976 r = keyboard_fill(k, repdata, false, repkbd->keycode, KBDKEY_REPEAT, num, keysyms);
979 log_debug_errno(r, "idev-keyboard: %s/%s: cannot update key-repeat: %m",
980 d->session->name, d->name);
981 k->repeating = false;
987 static int keyboard_feed_evdev(idev_keyboard *k, idev_data *data) {
988 struct input_event *ev = &data->evdev.event;
989 enum xkb_state_component compch;
990 enum xkb_compose_status cstatus;
991 const xkb_keysym_t *keysyms;
992 idev_device *d = &k->device;
995 if (ev->type != EV_KEY || ev->value > KBDKEY_DOWN)
998 /* TODO: We should audit xkb-actions, whether they need @resync as
999 * flag. Most actions should just be executed, however, there might
1000 * be actions that depend on modifier-orders. Those should be
1003 num = xkb_state_key_get_syms(k->xkb_state, ev->code + KBDXKB_SHIFT, &keysyms);
1004 compch = xkb_state_update_key(k->xkb_state, ev->code + KBDXKB_SHIFT, ev->value);
1006 if (compch & XKB_STATE_LEDS) {
1007 /* TODO: update LEDs */
1015 if (k->xkb_compose && ev->value == KBDKEY_DOWN) {
1016 if (num == 1 && !data->resync) {
1017 xkb_compose_state_feed(k->xkb_compose, keysyms[0]);
1018 cstatus = xkb_compose_state_get_status(k->xkb_compose);
1020 cstatus = XKB_COMPOSE_CANCELLED;
1024 case XKB_COMPOSE_NOTHING:
1025 /* keep produced keysyms and forward unchanged */
1027 case XKB_COMPOSE_COMPOSING:
1028 /* consumed by compose-state, drop keysym */
1032 case XKB_COMPOSE_COMPOSED:
1033 /* compose-state produced sth, replace keysym */
1034 num = keyboard_read_compose(k, &keysyms);
1035 xkb_compose_state_reset(k->xkb_compose);
1037 case XKB_COMPOSE_CANCELLED:
1038 /* canceled compose, reset, forward cancellation sym */
1039 xkb_compose_state_reset(k->xkb_compose);
1042 } else if (k->xkb_compose &&
1044 keysyms[0] == XKB_KEY_Multi_key &&
1046 ev->value == KBDKEY_UP) {
1047 /* Reset compose state on Multi-Key UP events. This effectively
1048 * requires you to hold the key during the whole sequence. I
1049 * think it's pretty handy to avoid accidental
1050 * Compose-sequences, but this may break Compose for disabled
1051 * people. We really need to make this opional! (TODO) */
1052 xkb_compose_state_reset(k->xkb_compose);
1055 if (ev->value == KBDKEY_UP) {
1056 /* never produce keysyms for UP */
1061 r = keyboard_fill(k, &k->evdata, data->resync, ev->code, ev->value, num, keysyms);
1066 return keyboard_raise_data(k, &k->evdata);
1069 log_debug_errno(r, "idev-keyboard: %s/%s: cannot handle event: %m",
1070 d->session->name, d->name);
1071 k->repeating = false;
1076 static int keyboard_feed(idev_device *d, idev_data *data) {
1077 idev_keyboard *k = keyboard_from_device(d);
1079 switch (data->type) {
1080 case IDEV_DATA_RESYNC:
1082 * If the underlying device is re-synced, key-events might be
1083 * sent re-ordered. Thus, we don't know which key was pressed
1084 * last. Key-repeat might get confused, hence, disable it
1085 * during re-syncs. The first following event will enable it
1089 k->repeating = false;
1092 case IDEV_DATA_EVDEV:
1093 return keyboard_feed_evdev(k, data);
1099 static int keyboard_update_kbdmap(idev_keyboard *k) {
1100 idev_device *d = &k->device;
1101 struct xkb_state *state;
1107 km = k->kbdctx->kbdmap;
1108 if (km == k->kbdmap)
1112 state = xkb_state_new(km->xkb_keymap);
1114 r = errno > 0 ? -errno : -EFAULT;
1118 kbdmap_unref(k->kbdmap);
1119 k->kbdmap = kbdmap_ref(km);
1120 xkb_state_unref(k->xkb_state);
1121 k->xkb_state = state;
1123 /* TODO: On state-change, we should trigger a resync so the whole
1124 * event-state is flushed into the new xkb-state. libevdev currently
1125 * does not support that, though. */
1130 log_debug_errno(r, "idev-keyboard: %s/%s: cannot adopt new keymap: %m",
1131 d->session->name, d->name);
1135 static int keyboard_update_kbdtbl(idev_keyboard *k) {
1136 idev_device *d = &k->device;
1137 struct xkb_compose_state *compose = NULL;
1143 kt = k->kbdctx->kbdtbl;
1144 if (kt == k->kbdtbl)
1149 compose = xkb_compose_state_new(kt->xkb_compose_table, XKB_COMPOSE_STATE_NO_FLAGS);
1151 r = errno > 0 ? -errno : -EFAULT;
1156 kbdtbl_unref(k->kbdtbl);
1157 k->kbdtbl = kbdtbl_ref(kt);
1158 xkb_compose_state_unref(k->xkb_compose);
1159 k->xkb_compose = compose;
1164 log_debug_errno(r, "idev-keyboard: %s/%s: cannot adopt new compose table: %m",
1165 d->session->name, d->name);
1169 static const idev_device_vtable keyboard_vtable = {
1170 .free = keyboard_free,
1171 .feed = keyboard_feed,