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/>.
24 #include <systemd/sd-bus.h>
25 #include <systemd/sd-event.h>
26 #include <xkbcommon/xkbcommon.h>
27 #include <xkbcommon/xkbcommon-compose.h>
31 #include "idev-internal.h"
33 #include "term-internal.h"
36 typedef struct kbdtbl kbdtbl;
37 typedef struct kbdmap kbdmap;
38 typedef struct kbdctx kbdctx;
39 typedef struct idev_keyboard idev_keyboard;
43 struct xkb_compose_table *xkb_compose_table;
48 struct xkb_keymap *xkb_keymap;
49 xkb_mod_index_t modmap[IDEV_KBDMOD_CNT];
50 xkb_led_index_t ledmap[IDEV_KBDLED_CNT];
55 idev_context *context;
56 struct xkb_context *xkb_context;
57 struct kbdmap *kbdmap;
58 struct kbdtbl *kbdtbl;
60 sd_bus_slot *slot_locale_props_changed;
61 sd_bus_slot *slot_locale_get_all;
64 char *locale_x11_model;
65 char *locale_x11_layout;
66 char *locale_x11_variant;
67 char *locale_x11_options;
69 char *last_x11_layout;
70 char *last_x11_variant;
71 char *last_x11_options;
74 struct idev_keyboard {
80 struct xkb_state *xkb_state;
81 struct xkb_compose_state *xkb_compose;
85 sd_event_source *repeat_timer;
90 uint32_t *compose_res;
95 #define keyboard_from_device(_d) container_of((_d), idev_keyboard, device)
97 #define KBDCTX_KEY "keyboard.context" /* hashmap key for global kbdctx */
98 #define KBDXKB_SHIFT (8) /* xkb shifts evdev key-codes by 8 */
99 #define KBDKEY_UP (0) /* KEY UP event value */
100 #define KBDKEY_DOWN (1) /* KEY DOWN event value */
101 #define KBDKEY_REPEAT (2) /* KEY REPEAT event value */
103 static const idev_device_vtable keyboard_vtable;
105 static int keyboard_update_kbdmap(idev_keyboard *k);
106 static int keyboard_update_kbdtbl(idev_keyboard *k);
109 * Keyboard Compose Tables
112 static kbdtbl *kbdtbl_ref(kbdtbl *kt) {
114 assert_return(kt->ref > 0, NULL);
121 static kbdtbl *kbdtbl_unref(kbdtbl *kt) {
125 assert_return(kt->ref > 0, NULL);
130 xkb_compose_table_unref(kt->xkb_compose_table);
136 DEFINE_TRIVIAL_CLEANUP_FUNC(kbdtbl*, kbdtbl_unref);
138 static int kbdtbl_new_from_locale(kbdtbl **out, kbdctx *kc, const char *locale) {
139 _cleanup_(kbdtbl_unrefp) kbdtbl *kt = NULL;
141 assert_return(out, -EINVAL);
142 assert_return(locale, -EINVAL);
144 kt = new0(kbdtbl, 1);
150 kt->xkb_compose_table = xkb_compose_table_new_from_locale(kc->xkb_context,
152 XKB_COMPOSE_COMPILE_NO_FLAGS);
153 if (!kt->xkb_compose_table)
154 return errno > 0 ? -errno : -EFAULT;
165 static const char * const kbdmap_modmap[IDEV_KBDMOD_CNT] = {
166 [IDEV_KBDMOD_IDX_SHIFT] = XKB_MOD_NAME_SHIFT,
167 [IDEV_KBDMOD_IDX_CTRL] = XKB_MOD_NAME_CTRL,
168 [IDEV_KBDMOD_IDX_ALT] = XKB_MOD_NAME_ALT,
169 [IDEV_KBDMOD_IDX_LINUX] = XKB_MOD_NAME_LOGO,
170 [IDEV_KBDMOD_IDX_CAPS] = XKB_MOD_NAME_CAPS,
173 static const char * const kbdmap_ledmap[IDEV_KBDLED_CNT] = {
174 [IDEV_KBDLED_IDX_NUM] = XKB_LED_NAME_NUM,
175 [IDEV_KBDLED_IDX_CAPS] = XKB_LED_NAME_CAPS,
176 [IDEV_KBDLED_IDX_SCROLL] = XKB_LED_NAME_SCROLL,
179 static kbdmap *kbdmap_ref(kbdmap *km) {
180 assert_return(km, NULL);
181 assert_return(km->ref > 0, NULL);
187 static kbdmap *kbdmap_unref(kbdmap *km) {
191 assert_return(km->ref > 0, NULL);
196 xkb_keymap_unref(km->xkb_keymap);
202 DEFINE_TRIVIAL_CLEANUP_FUNC(kbdmap*, kbdmap_unref);
204 static int kbdmap_new_from_names(kbdmap **out,
209 const char *options) {
210 _cleanup_(kbdmap_unrefp) kbdmap *km = NULL;
211 struct xkb_rule_names rmlvo = { };
214 assert_return(out, -EINVAL);
216 km = new0(kbdmap, 1);
222 rmlvo.rules = "evdev";
224 rmlvo.layout = layout;
225 rmlvo.variant = variant;
226 rmlvo.options = options;
229 km->xkb_keymap = xkb_keymap_new_from_names(kc->xkb_context, &rmlvo, 0);
231 return errno > 0 ? -errno : -EFAULT;
233 for (i = 0; i < IDEV_KBDMOD_CNT; ++i) {
234 const char *t = kbdmap_modmap[i];
237 km->modmap[i] = xkb_keymap_mod_get_index(km->xkb_keymap, t);
239 km->modmap[i] = XKB_MOD_INVALID;
242 for (i = 0; i < IDEV_KBDLED_CNT; ++i) {
243 const char *t = kbdmap_ledmap[i];
246 km->ledmap[i] = xkb_keymap_led_get_index(km->xkb_keymap, t);
248 km->ledmap[i] = XKB_LED_INVALID;
260 static int kbdctx_refresh_compose_table(kbdctx *kc, const char *lang) {
270 if (streq_ptr(kc->locale_lang, lang))
273 r = free_and_strdup(&kc->locale_lang, lang);
277 log_debug("idev-keyboard: new default compose table: [ %s ]", lang);
279 r = kbdtbl_new_from_locale(&kt, kc, lang);
281 /* TODO: We need to catch the case where no compose-file is
282 * available. xkb doesn't tell us so far.. so we must not treat
283 * it as a hard-failure but just continue. Preferably, we want
284 * xkb to tell us exactly whether compilation failed or whether
285 * there is no compose file available for this locale. */
286 log_debug_errno(r, "idev-keyboard: cannot load compose-table for '%s': %m",
292 kbdtbl_unref(kc->kbdtbl);
295 HASHMAP_FOREACH(s, kc->context->session_map, i)
296 HASHMAP_FOREACH(d, s->device_map, j)
297 if (idev_is_keyboard(d))
298 keyboard_update_kbdtbl(keyboard_from_device(d));
303 static void move_str(char **dest, char **src) {
309 static int kbdctx_refresh_keymap(kbdctx *kc) {
317 streq_ptr(kc->locale_x11_model, kc->last_x11_model) &&
318 streq_ptr(kc->locale_x11_layout, kc->last_x11_layout) &&
319 streq_ptr(kc->locale_x11_variant, kc->last_x11_variant) &&
320 streq_ptr(kc->locale_x11_options, kc->last_x11_options))
323 move_str(&kc->last_x11_model, &kc->locale_x11_model);
324 move_str(&kc->last_x11_layout, &kc->locale_x11_layout);
325 move_str(&kc->last_x11_variant, &kc->locale_x11_variant);
326 move_str(&kc->last_x11_options, &kc->locale_x11_options);
328 log_debug("idev-keyboard: new default keymap: [%s / %s / %s / %s]",
329 kc->last_x11_model, kc->last_x11_layout, kc->last_x11_variant, kc->last_x11_options);
331 /* TODO: add a fallback keymap that's compiled-in */
332 r = kbdmap_new_from_names(&km, kc, kc->last_x11_model, kc->last_x11_layout,
333 kc->last_x11_variant, kc->last_x11_options);
335 return log_debug_errno(r, "idev-keyboard: cannot create keymap from locale1: %m");
337 kbdmap_unref(kc->kbdmap);
340 HASHMAP_FOREACH(s, kc->context->session_map, i)
341 HASHMAP_FOREACH(d, s->device_map, j)
342 if (idev_is_keyboard(d))
343 keyboard_update_kbdmap(keyboard_from_device(d));
348 static int kbdctx_set_locale(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
349 kbdctx *kc = userdata;
350 const char *s, *ctype = NULL, *lang = NULL;
353 r = sd_bus_message_enter_container(m, 'a', "s");
357 while ((r = sd_bus_message_read(m, "s", &s)) > 0) {
359 ctype = startswith(s, "LC_CTYPE=");
361 lang = startswith(s, "LANG=");
367 r = sd_bus_message_exit_container(m);
371 kbdctx_refresh_compose_table(kc, ctype ? : lang);
376 log_debug_errno(r, "idev-keyboard: cannot parse locale property from locale1: %m");
381 static const struct bus_properties_map kbdctx_locale_map[] = {
382 { "Locale", "as", kbdctx_set_locale, 0 },
383 { "X11Model", "s", NULL, offsetof(kbdctx, locale_x11_model) },
384 { "X11Layout", "s", NULL, offsetof(kbdctx, locale_x11_layout) },
385 { "X11Variant", "s", NULL, offsetof(kbdctx, locale_x11_variant) },
386 { "X11Options", "s", NULL, offsetof(kbdctx, locale_x11_options) },
389 static int kbdctx_locale_get_all_fn(sd_bus *bus,
392 sd_bus_error *ret_err) {
393 kbdctx *kc = userdata;
396 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
398 if (sd_bus_message_is_method_error(m, NULL)) {
399 const sd_bus_error *error = sd_bus_message_get_error(m);
401 log_debug("idev-keyboard: GetAll() on locale1 failed: %s: %s",
402 error->name, error->message);
406 r = bus_message_map_all_properties(bus, m, kbdctx_locale_map, kc);
408 log_debug("idev-keyboard: erroneous GetAll() reply from locale1");
412 kbdctx_refresh_keymap(kc);
416 static int kbdctx_query_locale(kbdctx *kc) {
417 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
420 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
422 r = sd_bus_message_new_method_call(kc->context->sysbus,
424 "org.freedesktop.locale1",
425 "/org/freedesktop/locale1",
426 "org.freedesktop.DBus.Properties",
431 r = sd_bus_message_append(m, "s", "org.freedesktop.locale1");
435 r = sd_bus_call_async(kc->context->sysbus,
436 &kc->slot_locale_get_all,
438 kbdctx_locale_get_all_fn,
447 return log_debug_errno(r, "idev-keyboard: cannot send GetAll to locale1: %m");
450 static int kbdctx_locale_props_changed_fn(sd_bus *bus,
451 sd_bus_message *signal,
453 sd_bus_error *ret_err) {
454 kbdctx *kc = userdata;
457 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
459 /* skip interface name */
460 r = sd_bus_message_skip(signal, "s");
464 r = bus_message_map_properties_changed(bus, signal, kbdctx_locale_map, kc);
469 r = kbdctx_query_locale(kc);
474 kbdctx_refresh_keymap(kc);
478 return log_debug_errno(r, "idev-keyboard: cannot handle PropertiesChanged from locale1: %m");
481 static int kbdctx_setup_bus(kbdctx *kc) {
484 r = sd_bus_add_match(kc->context->sysbus,
485 &kc->slot_locale_props_changed,
487 "sender='org.freedesktop.locale1',"
488 "interface='org.freedesktop.DBus.Properties',"
489 "member='PropertiesChanged',"
490 "path='/org/freedesktop/locale1'",
491 kbdctx_locale_props_changed_fn,
494 return log_debug_errno(r, "idev-keyboard: cannot setup locale1 link: %m");
496 return kbdctx_query_locale(kc);
499 static void kbdctx_log_fn(struct xkb_context *ctx, enum xkb_log_level lvl, const char *format, va_list args) {
503 if (lvl >= XKB_LOG_LEVEL_DEBUG)
505 else if (lvl >= XKB_LOG_LEVEL_INFO)
507 else if (lvl >= XKB_LOG_LEVEL_WARNING)
508 sd_lvl = LOG_INFO; /* most XKB warnings really are informational */
510 /* XKB_LOG_LEVEL_ERROR and worse */
513 snprintf(buf, sizeof(buf), "idev-xkb: %s", format);
514 log_internalv(sd_lvl, 0, __FILE__, __LINE__, __func__, buf, args);
517 static kbdctx *kbdctx_ref(kbdctx *kc) {
518 assert_return(kc, NULL);
519 assert_return(kc->ref > 0, NULL);
525 static kbdctx *kbdctx_unref(kbdctx *kc) {
529 assert_return(kc->ref > 0, NULL);
534 free(kc->last_x11_options);
535 free(kc->last_x11_variant);
536 free(kc->last_x11_layout);
537 free(kc->last_x11_model);
538 free(kc->locale_x11_options);
539 free(kc->locale_x11_variant);
540 free(kc->locale_x11_layout);
541 free(kc->locale_x11_model);
542 free(kc->locale_lang);
543 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
544 kc->slot_locale_props_changed = sd_bus_slot_unref(kc->slot_locale_props_changed);
545 kc->kbdtbl = kbdtbl_unref(kc->kbdtbl);
546 kc->kbdmap = kbdmap_unref(kc->kbdmap);
547 xkb_context_unref(kc->xkb_context);
548 hashmap_remove_value(kc->context->data_map, KBDCTX_KEY, kc);
554 DEFINE_TRIVIAL_CLEANUP_FUNC(kbdctx*, kbdctx_unref);
556 static int kbdctx_new(kbdctx **out, idev_context *c) {
557 _cleanup_(kbdctx_unrefp) kbdctx *kc = NULL;
560 assert_return(out, -EINVAL);
561 assert_return(c, -EINVAL);
563 kc = new0(kbdctx, 1);
571 kc->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
572 if (!kc->xkb_context)
573 return errno > 0 ? -errno : -EFAULT;
575 xkb_context_set_log_fn(kc->xkb_context, kbdctx_log_fn);
576 xkb_context_set_log_level(kc->xkb_context, XKB_LOG_LEVEL_DEBUG);
578 r = kbdctx_refresh_keymap(kc);
582 r = kbdctx_refresh_compose_table(kc, NULL);
587 r = kbdctx_setup_bus(kc);
592 r = hashmap_put(c->data_map, KBDCTX_KEY, kc);
601 static int get_kbdctx(idev_context *c, kbdctx **out) {
604 assert_return(c, -EINVAL);
605 assert_return(out, -EINVAL);
607 kc = hashmap_get(c->data_map, KBDCTX_KEY);
609 *out = kbdctx_ref(kc);
613 return kbdctx_new(out, c);
620 bool idev_is_keyboard(idev_device *d) {
621 return d && d->vtable == &keyboard_vtable;
624 idev_device *idev_find_keyboard(idev_session *s, const char *name) {
627 assert_return(s, NULL);
628 assert_return(name, NULL);
630 kname = strjoina("keyboard/", name);
631 return hashmap_get(s->device_map, kname);
634 static int keyboard_raise_data(idev_keyboard *k, idev_data *data) {
635 idev_device *d = &k->device;
638 r = idev_session_raise_device_data(d->session, d, data);
640 log_debug_errno(r, "idev-keyboard: %s/%s: error while raising data event: %m",
641 d->session->name, d->name);
646 static int keyboard_resize_bufs(idev_keyboard *k, uint32_t n_syms) {
649 if (n_syms <= k->n_syms)
652 t = realloc(k->compose_res, sizeof(*t) * n_syms);
657 t = realloc(k->evdata.keyboard.keysyms, sizeof(*t) * n_syms);
660 k->evdata.keyboard.keysyms = t;
662 t = realloc(k->evdata.keyboard.codepoints, sizeof(*t) * n_syms);
665 k->evdata.keyboard.codepoints = t;
667 t = realloc(k->repdata.keyboard.keysyms, sizeof(*t) * n_syms);
670 k->repdata.keyboard.keysyms = t;
672 t = realloc(k->repdata.keyboard.codepoints, sizeof(*t) * n_syms);
675 k->repdata.keyboard.codepoints = t;
681 static unsigned int keyboard_read_compose(idev_keyboard *k, const xkb_keysym_t **out) {
682 _cleanup_free_ char *t = NULL;
688 r = xkb_compose_state_get_utf8(k->xkb_compose, buf, sizeof(buf));
689 if (r >= (int)sizeof(buf)) {
694 xkb_compose_state_get_utf8(k->xkb_compose, t, r + 1);
700 for (i = 0; i < r; ++i) {
704 len = term_utf8_decode(&u8, &ucs, p[i]);
706 r = keyboard_resize_bufs(k, flen + len);
710 for (j = 0; j < len; ++j)
711 k->compose_res[flen++] = ucs[j];
715 *out = k->compose_res;
719 static void keyboard_arm(idev_keyboard *k, usec_t usecs) {
723 usecs += now(CLOCK_MONOTONIC);
724 r = sd_event_source_set_time(k->repeat_timer, usecs);
726 sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_ONESHOT);
728 sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
732 static int keyboard_repeat_timer_fn(sd_event_source *source, uint64_t usec, void *userdata) {
733 idev_keyboard *k = userdata;
735 /* never feed REPEAT keys into COMPOSE */
737 keyboard_arm(k, k->repeat_rate);
738 return keyboard_raise_data(k, &k->repdata);
741 int idev_keyboard_new(idev_device **out, idev_session *s, const char *name) {
742 _cleanup_(idev_device_freep) idev_device *d = NULL;
747 assert_return(out, -EINVAL);
748 assert_return(s, -EINVAL);
749 assert_return(name, -EINVAL);
751 k = new0(idev_keyboard, 1);
756 k->device = IDEV_DEVICE_INIT(&keyboard_vtable, s);
757 k->repeat_delay = 250 * USEC_PER_MSEC;
758 k->repeat_rate = 30 * USEC_PER_MSEC;
760 /* TODO: add key-repeat configuration */
762 r = get_kbdctx(s->context, &k->kbdctx);
766 r = keyboard_update_kbdmap(k);
770 r = keyboard_update_kbdtbl(k);
774 r = keyboard_resize_bufs(k, 8);
778 r = sd_event_add_time(s->context->event,
783 keyboard_repeat_timer_fn,
788 r = sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
792 kname = strjoina("keyboard/", name);
793 r = idev_device_add(d, kname);
803 static void keyboard_free(idev_device *d) {
804 idev_keyboard *k = keyboard_from_device(d);
806 xkb_compose_state_unref(k->xkb_compose);
807 xkb_state_unref(k->xkb_state);
808 free(k->repdata.keyboard.codepoints);
809 free(k->repdata.keyboard.keysyms);
810 free(k->evdata.keyboard.codepoints);
811 free(k->evdata.keyboard.keysyms);
812 free(k->compose_res);
813 k->repeat_timer = sd_event_source_unref(k->repeat_timer);
814 k->kbdtbl = kbdtbl_unref(k->kbdtbl);
815 k->kbdmap = kbdmap_unref(k->kbdmap);
816 k->kbdctx = kbdctx_unref(k->kbdctx);
820 static int8_t guess_ascii(struct xkb_state *state, uint32_t code, uint32_t n_syms, const uint32_t *syms) {
821 xkb_layout_index_t n_lo, lo;
822 xkb_level_index_t lv;
823 struct xkb_keymap *keymap;
824 const xkb_keysym_t *s;
827 if (n_syms == 1 && syms[0] < 128 && syms[0] > 0)
830 keymap = xkb_state_get_keymap(state);
831 n_lo = xkb_keymap_num_layouts_for_key(keymap, code + KBDXKB_SHIFT);
833 for (lo = 0; lo < n_lo; ++lo) {
834 lv = xkb_state_key_get_level(state, code + KBDXKB_SHIFT, lo);
835 num = xkb_keymap_key_get_syms_by_level(keymap, code + KBDXKB_SHIFT, lo, lv, &s);
836 if (num == 1 && s[0] < 128 && s[0] > 0)
843 static int keyboard_fill(idev_keyboard *k,
849 const uint32_t *keysyms) {
850 idev_data_keyboard *kev;
854 assert(dst == &k->evdata || dst == &k->repdata);
856 r = keyboard_resize_bufs(k, n_syms);
860 dst->type = IDEV_DATA_KEYBOARD;
861 dst->resync = resync;
862 kev = &dst->keyboard;
863 kev->ascii = guess_ascii(k->xkb_state, code, n_syms, keysyms);
867 kev->consumed_mods = 0;
868 kev->n_syms = n_syms;
869 memcpy(kev->keysyms, keysyms, sizeof(*keysyms) * n_syms);
871 for (i = 0; i < n_syms; ++i) {
872 kev->codepoints[i] = xkb_keysym_to_utf32(keysyms[i]);
873 if (!kev->codepoints[i])
874 kev->codepoints[i] = 0xffffffffUL;
877 for (i = 0; i < IDEV_KBDMOD_CNT; ++i) {
878 if (k->kbdmap->modmap[i] == XKB_MOD_INVALID)
881 r = xkb_state_mod_index_is_active(k->xkb_state, k->kbdmap->modmap[i], XKB_STATE_MODS_EFFECTIVE);
885 r = xkb_state_mod_index_is_consumed(k->xkb_state, code + KBDXKB_SHIFT, k->kbdmap->modmap[i]);
887 kev->consumed_mods |= 1 << i;
893 static void keyboard_repeat(idev_keyboard *k) {
894 idev_data *evdata = &k->evdata;
895 idev_data *repdata = &k->repdata;
896 idev_data_keyboard *evkbd = &evdata->keyboard;
897 idev_data_keyboard *repkbd = &repdata->keyboard;
898 const xkb_keysym_t *keysyms;
899 idev_device *d = &k->device;
903 if (evdata->resync) {
905 * We received a re-sync event. During re-sync, any number of
906 * key-events may have been lost and sync-events may be
907 * re-ordered. Always disable key-repeat for those events. Any
908 * following event will trigger it again.
911 k->repeating = false;
916 repeats = xkb_keymap_key_repeats(k->kbdmap->xkb_keymap, evkbd->keycode + KBDXKB_SHIFT);
918 if (k->repeating && repkbd->keycode == evkbd->keycode) {
920 * We received an event for the key we currently repeat. If it
921 * was released, stop key-repeat. Otherwise, ignore the event.
924 if (evkbd->value == KBDKEY_UP) {
925 k->repeating = false;
928 } else if (evkbd->value == KBDKEY_DOWN && repeats) {
930 * We received a key-down event for a key that repeats. The
931 * previous condition caught keys we already repeat, so we know
932 * this is a different key or no key-repeat is running. Start
937 num = xkb_state_key_get_syms(k->xkb_state, evkbd->keycode + KBDXKB_SHIFT, &keysyms);
939 r = errno > 0 ? errno : -EFAULT;
941 r = keyboard_fill(k, repdata, false, evkbd->keycode, KBDKEY_REPEAT, num, keysyms);
944 log_debug_errno(r, "idev-keyboard: %s/%s: cannot set key-repeat: %m",
945 d->session->name, d->name);
946 k->repeating = false;
950 keyboard_arm(k, k->repeat_delay);
952 } else if (k->repeating && !repeats) {
954 * We received an event for a key that does not repeat, but we
955 * currently repeat a previously received key. The new key is
956 * usually a modifier, but might be any kind of key. In this
957 * case, we continue repeating the old key, but update the
958 * symbols according to the new state.
962 num = xkb_state_key_get_syms(k->xkb_state, repkbd->keycode + KBDXKB_SHIFT, &keysyms);
964 r = errno > 0 ? errno : -EFAULT;
966 r = keyboard_fill(k, repdata, false, repkbd->keycode, KBDKEY_REPEAT, num, keysyms);
969 log_debug_errno(r, "idev-keyboard: %s/%s: cannot update key-repeat: %m",
970 d->session->name, d->name);
971 k->repeating = false;
977 static int keyboard_feed_evdev(idev_keyboard *k, idev_data *data) {
978 struct input_event *ev = &data->evdev.event;
979 enum xkb_state_component compch;
980 enum xkb_compose_status cstatus;
981 const xkb_keysym_t *keysyms;
982 idev_device *d = &k->device;
985 if (ev->type != EV_KEY || ev->value > KBDKEY_DOWN)
988 /* TODO: We should audit xkb-actions, whether they need @resync as
989 * flag. Most actions should just be executed, however, there might
990 * be actions that depend on modifier-orders. Those should be
993 num = xkb_state_key_get_syms(k->xkb_state, ev->code + KBDXKB_SHIFT, &keysyms);
994 compch = xkb_state_update_key(k->xkb_state, ev->code + KBDXKB_SHIFT, ev->value);
996 if (compch & XKB_STATE_LEDS) {
997 /* TODO: update LEDs */
1005 if (k->xkb_compose && ev->value == KBDKEY_DOWN) {
1006 if (num == 1 && !data->resync) {
1007 xkb_compose_state_feed(k->xkb_compose, keysyms[0]);
1008 cstatus = xkb_compose_state_get_status(k->xkb_compose);
1010 cstatus = XKB_COMPOSE_CANCELLED;
1014 case XKB_COMPOSE_NOTHING:
1015 /* keep produced keysyms and forward unchanged */
1017 case XKB_COMPOSE_COMPOSING:
1018 /* consumed by compose-state, drop keysym */
1022 case XKB_COMPOSE_COMPOSED:
1023 /* compose-state produced sth, replace keysym */
1024 num = keyboard_read_compose(k, &keysyms);
1025 xkb_compose_state_reset(k->xkb_compose);
1027 case XKB_COMPOSE_CANCELLED:
1028 /* canceled compose, reset, forward cancellation sym */
1029 xkb_compose_state_reset(k->xkb_compose);
1032 } else if (k->xkb_compose &&
1034 keysyms[0] == XKB_KEY_Multi_key &&
1036 ev->value == KBDKEY_UP) {
1037 /* Reset compose state on Multi-Key UP events. This effectively
1038 * requires you to hold the key during the whole sequence. I
1039 * think it's pretty handy to avoid accidental
1040 * Compose-sequences, but this may break Compose for disabled
1041 * people. We really need to make this opional! (TODO) */
1042 xkb_compose_state_reset(k->xkb_compose);
1045 if (ev->value == KBDKEY_UP) {
1046 /* never produce keysyms for UP */
1051 r = keyboard_fill(k, &k->evdata, data->resync, ev->code, ev->value, num, keysyms);
1056 return keyboard_raise_data(k, &k->evdata);
1059 log_debug_errno(r, "idev-keyboard: %s/%s: cannot handle event: %m",
1060 d->session->name, d->name);
1061 k->repeating = false;
1066 static int keyboard_feed(idev_device *d, idev_data *data) {
1067 idev_keyboard *k = keyboard_from_device(d);
1069 switch (data->type) {
1070 case IDEV_DATA_RESYNC:
1072 * If the underlying device is re-synced, key-events might be
1073 * sent re-ordered. Thus, we don't know which key was pressed
1074 * last. Key-repeat might get confused, hence, disable it
1075 * during re-syncs. The first following event will enable it
1079 k->repeating = false;
1082 case IDEV_DATA_EVDEV:
1083 return keyboard_feed_evdev(k, data);
1089 static int keyboard_update_kbdmap(idev_keyboard *k) {
1090 idev_device *d = &k->device;
1091 struct xkb_state *state;
1097 km = k->kbdctx->kbdmap;
1098 if (km == k->kbdmap)
1102 state = xkb_state_new(km->xkb_keymap);
1104 r = errno > 0 ? -errno : -EFAULT;
1108 kbdmap_unref(k->kbdmap);
1109 k->kbdmap = kbdmap_ref(km);
1110 xkb_state_unref(k->xkb_state);
1111 k->xkb_state = state;
1113 /* TODO: On state-change, we should trigger a resync so the whole
1114 * event-state is flushed into the new xkb-state. libevdev currently
1115 * does not support that, though. */
1120 return log_debug_errno(r, "idev-keyboard: %s/%s: cannot adopt new keymap: %m",
1121 d->session->name, d->name);
1124 static int keyboard_update_kbdtbl(idev_keyboard *k) {
1125 idev_device *d = &k->device;
1126 struct xkb_compose_state *compose = NULL;
1132 kt = k->kbdctx->kbdtbl;
1133 if (kt == k->kbdtbl)
1138 compose = xkb_compose_state_new(kt->xkb_compose_table, XKB_COMPOSE_STATE_NO_FLAGS);
1140 r = errno > 0 ? -errno : -EFAULT;
1145 kbdtbl_unref(k->kbdtbl);
1146 k->kbdtbl = kbdtbl_ref(kt);
1147 xkb_compose_state_unref(k->xkb_compose);
1148 k->xkb_compose = compose;
1153 return log_debug_errno(r, "idev-keyboard: %s/%s: cannot adopt new compose table: %m",
1154 d->session->name, d->name);
1157 static const idev_device_vtable keyboard_vtable = {
1158 .free = keyboard_free,
1159 .feed = keyboard_feed,