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 return log_debug_errno(r, "idev-keyboard: cannot create keymap from locale1: %m");
338 kbdmap_unref(kc->kbdmap);
341 HASHMAP_FOREACH(s, kc->context->session_map, i)
342 HASHMAP_FOREACH(d, s->device_map, j)
343 if (idev_is_keyboard(d))
344 keyboard_update_kbdmap(keyboard_from_device(d));
349 static int kbdctx_set_locale(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
350 kbdctx *kc = userdata;
351 const char *s, *ctype = NULL, *lang = NULL;
354 r = sd_bus_message_enter_container(m, 'a', "s");
358 while ((r = sd_bus_message_read(m, "s", &s)) > 0) {
360 ctype = startswith(s, "LC_CTYPE=");
362 lang = startswith(s, "LANG=");
368 r = sd_bus_message_exit_container(m);
372 kbdctx_refresh_compose_table(kc, ctype ? : lang);
377 log_debug_errno(r, "idev-keyboard: cannot parse locale property from locale1: %m");
382 static const struct bus_properties_map kbdctx_locale_map[] = {
383 { "Locale", "as", kbdctx_set_locale, 0 },
384 { "X11Model", "s", NULL, offsetof(kbdctx, locale_x11_model) },
385 { "X11Layout", "s", NULL, offsetof(kbdctx, locale_x11_layout) },
386 { "X11Variant", "s", NULL, offsetof(kbdctx, locale_x11_variant) },
387 { "X11Options", "s", NULL, offsetof(kbdctx, locale_x11_options) },
390 static int kbdctx_locale_get_all_fn(sd_bus *bus,
393 sd_bus_error *ret_err) {
394 kbdctx *kc = userdata;
397 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
399 if (sd_bus_message_is_method_error(m, NULL)) {
400 const sd_bus_error *error = sd_bus_message_get_error(m);
402 log_debug("idev-keyboard: GetAll() on locale1 failed: %s: %s",
403 error->name, error->message);
407 r = bus_message_map_all_properties(bus, m, kbdctx_locale_map, kc);
409 log_debug("idev-keyboard: erroneous GetAll() reply from locale1");
413 kbdctx_refresh_keymap(kc);
417 static int kbdctx_query_locale(kbdctx *kc) {
418 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
421 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
423 r = sd_bus_message_new_method_call(kc->context->sysbus,
425 "org.freedesktop.locale1",
426 "/org/freedesktop/locale1",
427 "org.freedesktop.DBus.Properties",
432 r = sd_bus_message_append(m, "s", "org.freedesktop.locale1");
436 r = sd_bus_call_async(kc->context->sysbus,
437 &kc->slot_locale_get_all,
439 kbdctx_locale_get_all_fn,
448 log_debug_errno(r, "idev-keyboard: cannot send GetAll to locale1: %m");
452 static int kbdctx_locale_props_changed_fn(sd_bus *bus,
453 sd_bus_message *signal,
455 sd_bus_error *ret_err) {
456 kbdctx *kc = userdata;
459 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
461 /* skip interface name */
462 r = sd_bus_message_skip(signal, "s");
466 r = bus_message_map_properties_changed(bus, signal, kbdctx_locale_map, kc);
471 r = kbdctx_query_locale(kc);
476 kbdctx_refresh_keymap(kc);
480 log_debug_errno(r, "idev-keyboard: cannot handle PropertiesChanged from locale1: %m");
484 static int kbdctx_setup_bus(kbdctx *kc) {
487 r = sd_bus_add_match(kc->context->sysbus,
488 &kc->slot_locale_props_changed,
490 "sender='org.freedesktop.locale1',"
491 "interface='org.freedesktop.DBus.Properties',"
492 "member='PropertiesChanged',"
493 "path='/org/freedesktop/locale1'",
494 kbdctx_locale_props_changed_fn,
497 log_debug_errno(r, "idev-keyboard: cannot setup locale1 link: %m");
501 return kbdctx_query_locale(kc);
504 static void kbdctx_log_fn(struct xkb_context *ctx, enum xkb_log_level lvl, const char *format, va_list args) {
508 if (lvl >= XKB_LOG_LEVEL_DEBUG)
510 else if (lvl >= XKB_LOG_LEVEL_INFO)
512 else if (lvl >= XKB_LOG_LEVEL_WARNING)
513 sd_lvl = LOG_INFO; /* most XKB warnings really are informational */
514 else if (lvl >= XKB_LOG_LEVEL_ERROR)
516 else if (lvl >= XKB_LOG_LEVEL_CRITICAL)
521 snprintf(buf, sizeof(buf), "idev-xkb: %s", format);
522 log_internalv(sd_lvl, 0, __FILE__, __LINE__, __func__, buf, args);
525 static kbdctx *kbdctx_ref(kbdctx *kc) {
526 assert_return(kc, NULL);
527 assert_return(kc->ref > 0, NULL);
533 static kbdctx *kbdctx_unref(kbdctx *kc) {
537 assert_return(kc->ref > 0, NULL);
542 free(kc->last_x11_options);
543 free(kc->last_x11_variant);
544 free(kc->last_x11_layout);
545 free(kc->last_x11_model);
546 free(kc->locale_x11_options);
547 free(kc->locale_x11_variant);
548 free(kc->locale_x11_layout);
549 free(kc->locale_x11_model);
550 free(kc->locale_lang);
551 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
552 kc->slot_locale_props_changed = sd_bus_slot_unref(kc->slot_locale_props_changed);
553 kc->kbdtbl = kbdtbl_unref(kc->kbdtbl);
554 kc->kbdmap = kbdmap_unref(kc->kbdmap);
555 xkb_context_unref(kc->xkb_context);
556 hashmap_remove_value(kc->context->data_map, KBDCTX_KEY, kc);
562 DEFINE_TRIVIAL_CLEANUP_FUNC(kbdctx*, kbdctx_unref);
564 static int kbdctx_new(kbdctx **out, idev_context *c) {
565 _cleanup_(kbdctx_unrefp) kbdctx *kc = NULL;
568 assert_return(out, -EINVAL);
569 assert_return(c, -EINVAL);
571 kc = new0(kbdctx, 1);
579 kc->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
580 if (!kc->xkb_context)
581 return errno > 0 ? -errno : -EFAULT;
583 xkb_context_set_log_fn(kc->xkb_context, kbdctx_log_fn);
584 xkb_context_set_log_level(kc->xkb_context, XKB_LOG_LEVEL_DEBUG);
586 r = kbdctx_refresh_keymap(kc);
590 r = kbdctx_refresh_compose_table(kc, NULL);
595 r = kbdctx_setup_bus(kc);
600 r = hashmap_put(c->data_map, KBDCTX_KEY, kc);
609 static int get_kbdctx(idev_context *c, kbdctx **out) {
612 assert_return(c, -EINVAL);
613 assert_return(out, -EINVAL);
615 kc = hashmap_get(c->data_map, KBDCTX_KEY);
617 *out = kbdctx_ref(kc);
621 return kbdctx_new(out, c);
628 bool idev_is_keyboard(idev_device *d) {
629 return d && d->vtable == &keyboard_vtable;
632 idev_device *idev_find_keyboard(idev_session *s, const char *name) {
635 assert_return(s, NULL);
636 assert_return(name, NULL);
638 kname = strappenda("keyboard/", name);
639 return hashmap_get(s->device_map, kname);
642 static int keyboard_raise_data(idev_keyboard *k, idev_data *data) {
643 idev_device *d = &k->device;
646 r = idev_session_raise_device_data(d->session, d, data);
648 log_debug_errno(r, "idev-keyboard: %s/%s: error while raising data event: %m",
649 d->session->name, d->name);
654 static int keyboard_resize_bufs(idev_keyboard *k, uint32_t n_syms) {
657 if (n_syms <= k->n_syms)
660 t = realloc(k->compose_res, sizeof(*t) * n_syms);
665 t = realloc(k->evdata.keyboard.keysyms, sizeof(*t) * n_syms);
668 k->evdata.keyboard.keysyms = t;
670 t = realloc(k->evdata.keyboard.codepoints, sizeof(*t) * n_syms);
673 k->evdata.keyboard.codepoints = t;
675 t = realloc(k->repdata.keyboard.keysyms, sizeof(*t) * n_syms);
678 k->repdata.keyboard.keysyms = t;
680 t = realloc(k->repdata.keyboard.codepoints, sizeof(*t) * n_syms);
683 k->repdata.keyboard.codepoints = t;
689 static unsigned int keyboard_read_compose(idev_keyboard *k, const xkb_keysym_t **out) {
690 _cleanup_free_ char *t = NULL;
696 r = xkb_compose_state_get_utf8(k->xkb_compose, buf, sizeof(buf));
697 if (r >= (int)sizeof(buf)) {
702 xkb_compose_state_get_utf8(k->xkb_compose, t, r + 1);
708 for (i = 0; i < r; ++i) {
712 len = term_utf8_decode(&u8, &ucs, p[i]);
714 r = keyboard_resize_bufs(k, flen + len);
718 for (j = 0; j < len; ++j)
719 k->compose_res[flen++] = ucs[j];
723 *out = k->compose_res;
727 static void keyboard_arm(idev_keyboard *k, usec_t usecs) {
731 usecs += now(CLOCK_MONOTONIC);
732 r = sd_event_source_set_time(k->repeat_timer, usecs);
734 sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_ONESHOT);
736 sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
740 static int keyboard_repeat_timer_fn(sd_event_source *source, uint64_t usec, void *userdata) {
741 idev_keyboard *k = userdata;
743 /* never feed REPEAT keys into COMPOSE */
745 keyboard_arm(k, k->repeat_rate);
746 return keyboard_raise_data(k, &k->repdata);
749 int idev_keyboard_new(idev_device **out, idev_session *s, const char *name) {
750 _cleanup_(idev_device_freep) idev_device *d = NULL;
755 assert_return(out, -EINVAL);
756 assert_return(s, -EINVAL);
757 assert_return(name, -EINVAL);
759 k = new0(idev_keyboard, 1);
764 k->device = IDEV_DEVICE_INIT(&keyboard_vtable, s);
765 k->repeat_delay = 250 * USEC_PER_MSEC;
766 k->repeat_rate = 30 * USEC_PER_MSEC;
768 /* TODO: add key-repeat configuration */
770 r = get_kbdctx(s->context, &k->kbdctx);
774 r = keyboard_update_kbdmap(k);
778 r = keyboard_update_kbdtbl(k);
782 r = keyboard_resize_bufs(k, 8);
786 r = sd_event_add_time(s->context->event,
791 keyboard_repeat_timer_fn,
796 r = sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
800 kname = strappenda("keyboard/", name);
801 r = idev_device_add(d, kname);
811 static void keyboard_free(idev_device *d) {
812 idev_keyboard *k = keyboard_from_device(d);
814 xkb_compose_state_unref(k->xkb_compose);
815 xkb_state_unref(k->xkb_state);
816 free(k->repdata.keyboard.codepoints);
817 free(k->repdata.keyboard.keysyms);
818 free(k->evdata.keyboard.codepoints);
819 free(k->evdata.keyboard.keysyms);
820 free(k->compose_res);
821 k->repeat_timer = sd_event_source_unref(k->repeat_timer);
822 k->kbdtbl = kbdtbl_unref(k->kbdtbl);
823 k->kbdmap = kbdmap_unref(k->kbdmap);
824 k->kbdctx = kbdctx_unref(k->kbdctx);
828 static int8_t guess_ascii(struct xkb_state *state, uint32_t code, uint32_t n_syms, const uint32_t *syms) {
829 xkb_layout_index_t n_lo, lo;
830 xkb_level_index_t lv;
831 struct xkb_keymap *keymap;
832 const xkb_keysym_t *s;
835 if (n_syms == 1 && syms[0] < 128 && syms[0] > 0)
838 keymap = xkb_state_get_keymap(state);
839 n_lo = xkb_keymap_num_layouts_for_key(keymap, code + KBDXKB_SHIFT);
841 for (lo = 0; lo < n_lo; ++lo) {
842 lv = xkb_state_key_get_level(state, code + KBDXKB_SHIFT, lo);
843 num = xkb_keymap_key_get_syms_by_level(keymap, code + KBDXKB_SHIFT, lo, lv, &s);
844 if (num == 1 && s[0] < 128 && s[0] > 0)
851 static int keyboard_fill(idev_keyboard *k,
857 const uint32_t *keysyms) {
858 idev_data_keyboard *kev;
862 assert(dst == &k->evdata || dst == &k->repdata);
864 r = keyboard_resize_bufs(k, n_syms);
868 dst->type = IDEV_DATA_KEYBOARD;
869 dst->resync = resync;
870 kev = &dst->keyboard;
871 kev->ascii = guess_ascii(k->xkb_state, code, n_syms, keysyms);
875 kev->consumed_mods = 0;
876 kev->n_syms = n_syms;
877 memcpy(kev->keysyms, keysyms, sizeof(*keysyms) * n_syms);
879 for (i = 0; i < n_syms; ++i) {
880 kev->codepoints[i] = xkb_keysym_to_utf32(keysyms[i]);
881 if (!kev->codepoints[i])
882 kev->codepoints[i] = 0xffffffffUL;
885 for (i = 0; i < IDEV_KBDMOD_CNT; ++i) {
886 if (k->kbdmap->modmap[i] == XKB_MOD_INVALID)
889 r = xkb_state_mod_index_is_active(k->xkb_state, k->kbdmap->modmap[i], XKB_STATE_MODS_EFFECTIVE);
893 r = xkb_state_mod_index_is_consumed(k->xkb_state, code + KBDXKB_SHIFT, k->kbdmap->modmap[i]);
895 kev->consumed_mods |= 1 << i;
901 static void keyboard_repeat(idev_keyboard *k) {
902 idev_data *evdata = &k->evdata;
903 idev_data *repdata = &k->repdata;
904 idev_data_keyboard *evkbd = &evdata->keyboard;
905 idev_data_keyboard *repkbd = &repdata->keyboard;
906 const xkb_keysym_t *keysyms;
907 idev_device *d = &k->device;
911 if (evdata->resync) {
913 * We received a re-sync event. During re-sync, any number of
914 * key-events may have been lost and sync-events may be
915 * re-ordered. Always disable key-repeat for those events. Any
916 * following event will trigger it again.
919 k->repeating = false;
924 repeats = xkb_keymap_key_repeats(k->kbdmap->xkb_keymap, evkbd->keycode + KBDXKB_SHIFT);
926 if (k->repeating && repkbd->keycode == evkbd->keycode) {
928 * We received an event for the key we currently repeat. If it
929 * was released, stop key-repeat. Otherwise, ignore the event.
932 if (evkbd->value == KBDKEY_UP) {
933 k->repeating = false;
936 } else if (evkbd->value == KBDKEY_DOWN && repeats) {
938 * We received a key-down event for a key that repeats. The
939 * previous condition caught keys we already repeat, so we know
940 * this is a different key or no key-repeat is running. Start
945 num = xkb_state_key_get_syms(k->xkb_state, evkbd->keycode + KBDXKB_SHIFT, &keysyms);
947 r = errno > 0 ? errno : -EFAULT;
949 r = keyboard_fill(k, repdata, false, evkbd->keycode, KBDKEY_REPEAT, num, keysyms);
952 log_debug_errno(r, "idev-keyboard: %s/%s: cannot set key-repeat: %m",
953 d->session->name, d->name);
954 k->repeating = false;
958 keyboard_arm(k, k->repeat_delay);
960 } else if (k->repeating && !repeats) {
962 * We received an event for a key that does not repeat, but we
963 * currently repeat a previously received key. The new key is
964 * usually a modifier, but might be any kind of key. In this
965 * case, we continue repeating the old key, but update the
966 * symbols according to the new state.
970 num = xkb_state_key_get_syms(k->xkb_state, repkbd->keycode + KBDXKB_SHIFT, &keysyms);
972 r = errno > 0 ? errno : -EFAULT;
974 r = keyboard_fill(k, repdata, false, repkbd->keycode, KBDKEY_REPEAT, num, keysyms);
977 log_debug_errno(r, "idev-keyboard: %s/%s: cannot update key-repeat: %m",
978 d->session->name, d->name);
979 k->repeating = false;
985 static int keyboard_feed_evdev(idev_keyboard *k, idev_data *data) {
986 struct input_event *ev = &data->evdev.event;
987 enum xkb_state_component compch;
988 enum xkb_compose_status cstatus;
989 const xkb_keysym_t *keysyms;
990 idev_device *d = &k->device;
993 if (ev->type != EV_KEY || ev->value > KBDKEY_DOWN)
996 /* TODO: We should audit xkb-actions, whether they need @resync as
997 * flag. Most actions should just be executed, however, there might
998 * be actions that depend on modifier-orders. Those should be
1001 num = xkb_state_key_get_syms(k->xkb_state, ev->code + KBDXKB_SHIFT, &keysyms);
1002 compch = xkb_state_update_key(k->xkb_state, ev->code + KBDXKB_SHIFT, ev->value);
1004 if (compch & XKB_STATE_LEDS) {
1005 /* TODO: update LEDs */
1013 if (k->xkb_compose && ev->value == KBDKEY_DOWN) {
1014 if (num == 1 && !data->resync) {
1015 xkb_compose_state_feed(k->xkb_compose, keysyms[0]);
1016 cstatus = xkb_compose_state_get_status(k->xkb_compose);
1018 cstatus = XKB_COMPOSE_CANCELLED;
1022 case XKB_COMPOSE_NOTHING:
1023 /* keep produced keysyms and forward unchanged */
1025 case XKB_COMPOSE_COMPOSING:
1026 /* consumed by compose-state, drop keysym */
1030 case XKB_COMPOSE_COMPOSED:
1031 /* compose-state produced sth, replace keysym */
1032 num = keyboard_read_compose(k, &keysyms);
1033 xkb_compose_state_reset(k->xkb_compose);
1035 case XKB_COMPOSE_CANCELLED:
1036 /* canceled compose, reset, forward cancellation sym */
1037 xkb_compose_state_reset(k->xkb_compose);
1040 } else if (k->xkb_compose &&
1042 keysyms[0] == XKB_KEY_Multi_key &&
1044 ev->value == KBDKEY_UP) {
1045 /* Reset compose state on Multi-Key UP events. This effectively
1046 * requires you to hold the key during the whole sequence. I
1047 * think it's pretty handy to avoid accidental
1048 * Compose-sequences, but this may break Compose for disabled
1049 * people. We really need to make this opional! (TODO) */
1050 xkb_compose_state_reset(k->xkb_compose);
1053 if (ev->value == KBDKEY_UP) {
1054 /* never produce keysyms for UP */
1059 r = keyboard_fill(k, &k->evdata, data->resync, ev->code, ev->value, num, keysyms);
1064 return keyboard_raise_data(k, &k->evdata);
1067 log_debug_errno(r, "idev-keyboard: %s/%s: cannot handle event: %m",
1068 d->session->name, d->name);
1069 k->repeating = false;
1074 static int keyboard_feed(idev_device *d, idev_data *data) {
1075 idev_keyboard *k = keyboard_from_device(d);
1077 switch (data->type) {
1078 case IDEV_DATA_RESYNC:
1080 * If the underlying device is re-synced, key-events might be
1081 * sent re-ordered. Thus, we don't know which key was pressed
1082 * last. Key-repeat might get confused, hence, disable it
1083 * during re-syncs. The first following event will enable it
1087 k->repeating = false;
1090 case IDEV_DATA_EVDEV:
1091 return keyboard_feed_evdev(k, data);
1097 static int keyboard_update_kbdmap(idev_keyboard *k) {
1098 idev_device *d = &k->device;
1099 struct xkb_state *state;
1105 km = k->kbdctx->kbdmap;
1106 if (km == k->kbdmap)
1110 state = xkb_state_new(km->xkb_keymap);
1112 r = errno > 0 ? -errno : -EFAULT;
1116 kbdmap_unref(k->kbdmap);
1117 k->kbdmap = kbdmap_ref(km);
1118 xkb_state_unref(k->xkb_state);
1119 k->xkb_state = state;
1121 /* TODO: On state-change, we should trigger a resync so the whole
1122 * event-state is flushed into the new xkb-state. libevdev currently
1123 * does not support that, though. */
1128 log_debug_errno(r, "idev-keyboard: %s/%s: cannot adopt new keymap: %m",
1129 d->session->name, d->name);
1133 static int keyboard_update_kbdtbl(idev_keyboard *k) {
1134 idev_device *d = &k->device;
1135 struct xkb_compose_state *compose = NULL;
1141 kt = k->kbdctx->kbdtbl;
1142 if (kt == k->kbdtbl)
1147 compose = xkb_compose_state_new(kt->xkb_compose_table, XKB_COMPOSE_STATE_NO_FLAGS);
1149 r = errno > 0 ? -errno : -EFAULT;
1154 kbdtbl_unref(k->kbdtbl);
1155 k->kbdtbl = kbdtbl_ref(kt);
1156 xkb_compose_state_unref(k->xkb_compose);
1157 k->xkb_compose = compose;
1162 return log_debug_errno(r, "idev-keyboard: %s/%s: cannot adopt new compose table: %m",
1163 d->session->name, d->name);
1166 static const idev_device_vtable keyboard_vtable = {
1167 .free = keyboard_free,
1168 .feed = keyboard_feed,