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 kbdctx *kbdctx_ref(kbdctx *kc) {
508 assert_return(kc, NULL);
509 assert_return(kc->ref > 0, NULL);
515 static kbdctx *kbdctx_unref(kbdctx *kc) {
519 assert_return(kc->ref > 0, NULL);
524 free(kc->last_x11_options);
525 free(kc->last_x11_variant);
526 free(kc->last_x11_layout);
527 free(kc->last_x11_model);
528 free(kc->locale_x11_options);
529 free(kc->locale_x11_variant);
530 free(kc->locale_x11_layout);
531 free(kc->locale_x11_model);
532 free(kc->locale_lang);
533 kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
534 kc->slot_locale_props_changed = sd_bus_slot_unref(kc->slot_locale_props_changed);
535 kc->kbdtbl = kbdtbl_unref(kc->kbdtbl);
536 kc->kbdmap = kbdmap_unref(kc->kbdmap);
537 xkb_context_unref(kc->xkb_context);
538 hashmap_remove_value(kc->context->data_map, KBDCTX_KEY, kc);
544 DEFINE_TRIVIAL_CLEANUP_FUNC(kbdctx*, kbdctx_unref);
546 static int kbdctx_new(kbdctx **out, idev_context *c) {
547 _cleanup_(kbdctx_unrefp) kbdctx *kc = NULL;
550 assert_return(out, -EINVAL);
551 assert_return(c, -EINVAL);
553 kc = new0(kbdctx, 1);
561 kc->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
562 if (!kc->xkb_context)
563 return errno > 0 ? -errno : -EFAULT;
565 r = kbdctx_refresh_keymap(kc);
569 r = kbdctx_refresh_compose_table(kc, NULL);
574 r = kbdctx_setup_bus(kc);
579 r = hashmap_put(c->data_map, KBDCTX_KEY, kc);
588 static int get_kbdctx(idev_context *c, kbdctx **out) {
591 assert_return(c, -EINVAL);
592 assert_return(out, -EINVAL);
594 kc = hashmap_get(c->data_map, KBDCTX_KEY);
596 *out = kbdctx_ref(kc);
600 return kbdctx_new(out, c);
607 bool idev_is_keyboard(idev_device *d) {
608 return d && d->vtable == &keyboard_vtable;
611 idev_device *idev_find_keyboard(idev_session *s, const char *name) {
614 assert_return(s, NULL);
615 assert_return(name, NULL);
617 kname = strappenda("keyboard/", name);
618 return hashmap_get(s->device_map, kname);
621 static int keyboard_raise_data(idev_keyboard *k, idev_data *data) {
622 idev_device *d = &k->device;
625 r = idev_session_raise_device_data(d->session, d, data);
627 log_debug("idev-keyboard: %s/%s: error while raising data event: %s",
628 d->session->name, d->name, strerror(-r));
633 static int keyboard_resize_bufs(idev_keyboard *k, uint32_t n_syms) {
636 if (n_syms <= k->n_syms)
639 t = realloc(k->compose_res, sizeof(*t) * n_syms);
644 t = realloc(k->evdata.keyboard.keysyms, sizeof(*t) * n_syms);
647 k->evdata.keyboard.keysyms = t;
649 t = realloc(k->evdata.keyboard.codepoints, sizeof(*t) * n_syms);
652 k->evdata.keyboard.codepoints = t;
654 t = realloc(k->repdata.keyboard.keysyms, sizeof(*t) * n_syms);
657 k->repdata.keyboard.keysyms = t;
659 t = realloc(k->repdata.keyboard.codepoints, sizeof(*t) * n_syms);
662 k->repdata.keyboard.codepoints = t;
668 static unsigned int keyboard_read_compose(idev_keyboard *k, const xkb_keysym_t **out) {
669 _cleanup_free_ char *t = NULL;
675 r = xkb_compose_state_get_utf8(k->xkb_compose, buf, sizeof(buf));
676 if (r >= (int)sizeof(buf)) {
681 xkb_compose_state_get_utf8(k->xkb_compose, t, r + 1);
687 for (i = 0; i < r; ++i) {
691 len = term_utf8_decode(&u8, &ucs, p[i]);
693 r = keyboard_resize_bufs(k, flen + len);
697 for (j = 0; j < len; ++j)
698 k->compose_res[flen++] = ucs[j];
702 *out = k->compose_res;
706 static void keyboard_arm(idev_keyboard *k, usec_t usecs) {
710 usecs += now(CLOCK_MONOTONIC);
711 r = sd_event_source_set_time(k->repeat_timer, usecs);
713 sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_ONESHOT);
715 sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
719 static int keyboard_repeat_timer_fn(sd_event_source *source, uint64_t usec, void *userdata) {
720 idev_keyboard *k = userdata;
722 /* never feed REPEAT keys into COMPOSE */
724 keyboard_arm(k, k->repeat_rate);
725 return keyboard_raise_data(k, &k->repdata);
728 int idev_keyboard_new(idev_device **out, idev_session *s, const char *name) {
729 _cleanup_(idev_device_freep) idev_device *d = NULL;
734 assert_return(out, -EINVAL);
735 assert_return(s, -EINVAL);
736 assert_return(name, -EINVAL);
738 k = new0(idev_keyboard, 1);
743 k->device = IDEV_DEVICE_INIT(&keyboard_vtable, s);
744 k->repeat_delay = 250 * USEC_PER_MSEC;
745 k->repeat_rate = 30 * USEC_PER_MSEC;
747 /* TODO: add key-repeat configuration */
749 r = get_kbdctx(s->context, &k->kbdctx);
753 r = keyboard_update_kbdmap(k);
757 r = keyboard_update_kbdtbl(k);
761 r = keyboard_resize_bufs(k, 8);
765 r = sd_event_add_time(s->context->event,
770 keyboard_repeat_timer_fn,
775 r = sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
779 kname = strappenda("keyboard/", name);
780 r = idev_device_add(d, kname);
790 static void keyboard_free(idev_device *d) {
791 idev_keyboard *k = keyboard_from_device(d);
793 xkb_compose_state_unref(k->xkb_compose);
794 xkb_state_unref(k->xkb_state);
795 free(k->repdata.keyboard.codepoints);
796 free(k->repdata.keyboard.keysyms);
797 free(k->evdata.keyboard.codepoints);
798 free(k->evdata.keyboard.keysyms);
799 free(k->compose_res);
800 k->repeat_timer = sd_event_source_unref(k->repeat_timer);
801 k->kbdtbl = kbdtbl_unref(k->kbdtbl);
802 k->kbdmap = kbdmap_unref(k->kbdmap);
803 k->kbdctx = kbdctx_unref(k->kbdctx);
807 static int8_t guess_ascii(struct xkb_state *state, uint32_t code, uint32_t n_syms, const uint32_t *syms) {
808 xkb_layout_index_t n_lo, lo;
809 xkb_level_index_t lv;
810 struct xkb_keymap *keymap;
811 const xkb_keysym_t *s;
814 if (n_syms == 1 && syms[0] < 128 && syms[0] > 0)
817 keymap = xkb_state_get_keymap(state);
818 n_lo = xkb_keymap_num_layouts_for_key(keymap, code + KBDXKB_SHIFT);
820 for (lo = 0; lo < n_lo; ++lo) {
821 lv = xkb_state_key_get_level(state, code + KBDXKB_SHIFT, lo);
822 num = xkb_keymap_key_get_syms_by_level(keymap, code + KBDXKB_SHIFT, lo, lv, &s);
823 if (num == 1 && s[0] < 128 && s[0] > 0)
830 static int keyboard_fill(idev_keyboard *k,
836 const uint32_t *keysyms) {
837 idev_data_keyboard *kev;
841 assert(dst == &k->evdata || dst == &k->repdata);
843 r = keyboard_resize_bufs(k, n_syms);
847 dst->type = IDEV_DATA_KEYBOARD;
848 dst->resync = resync;
849 kev = &dst->keyboard;
850 kev->ascii = guess_ascii(k->xkb_state, code, n_syms, keysyms);
854 kev->consumed_mods = 0;
855 kev->n_syms = n_syms;
856 memcpy(kev->keysyms, keysyms, sizeof(*keysyms) * n_syms);
858 for (i = 0; i < n_syms; ++i) {
859 kev->codepoints[i] = xkb_keysym_to_utf32(keysyms[i]);
860 if (!kev->codepoints[i])
861 kev->codepoints[i] = 0xffffffffUL;
864 for (i = 0; i < IDEV_KBDMOD_CNT; ++i) {
865 if (k->kbdmap->modmap[i] == XKB_MOD_INVALID)
868 r = xkb_state_mod_index_is_active(k->xkb_state, k->kbdmap->modmap[i], XKB_STATE_MODS_EFFECTIVE);
872 r = xkb_state_mod_index_is_consumed(k->xkb_state, code + KBDXKB_SHIFT, k->kbdmap->modmap[i]);
874 kev->consumed_mods |= 1 << i;
880 static void keyboard_repeat(idev_keyboard *k) {
881 idev_data *evdata = &k->evdata;
882 idev_data *repdata = &k->repdata;
883 idev_data_keyboard *evkbd = &evdata->keyboard;
884 idev_data_keyboard *repkbd = &repdata->keyboard;
885 const xkb_keysym_t *keysyms;
886 idev_device *d = &k->device;
890 if (evdata->resync) {
892 * We received a re-sync event. During re-sync, any number of
893 * key-events may have been lost and sync-events may be
894 * re-ordered. Always disable key-repeat for those events. Any
895 * following event will trigger it again.
898 k->repeating = false;
903 repeats = xkb_keymap_key_repeats(k->kbdmap->xkb_keymap, evkbd->keycode + KBDXKB_SHIFT);
905 if (k->repeating && repkbd->keycode == evkbd->keycode) {
907 * We received an event for the key we currently repeat. If it
908 * was released, stop key-repeat. Otherwise, ignore the event.
911 if (evkbd->value == KBDKEY_UP) {
912 k->repeating = false;
915 } else if (evkbd->value == KBDKEY_DOWN && repeats) {
917 * We received a key-down event for a key that repeats. The
918 * previous condition caught keys we already repeat, so we know
919 * this is a different key or no key-repeat is running. Start
924 num = xkb_state_key_get_syms(k->xkb_state, evkbd->keycode + KBDXKB_SHIFT, &keysyms);
926 r = errno > 0 ? errno : -EFAULT;
928 r = keyboard_fill(k, repdata, false, evkbd->keycode, KBDKEY_REPEAT, num, keysyms);
931 log_debug("idev-keyboard: %s/%s: cannot set key-repeat: %s",
932 d->session->name, d->name, strerror(-r));
933 k->repeating = false;
937 keyboard_arm(k, k->repeat_delay);
939 } else if (k->repeating && !repeats) {
941 * We received an event for a key that does not repeat, but we
942 * currently repeat a previously received key. The new key is
943 * usually a modifier, but might be any kind of key. In this
944 * case, we continue repeating the old key, but update the
945 * symbols according to the new state.
949 num = xkb_state_key_get_syms(k->xkb_state, repkbd->keycode + KBDXKB_SHIFT, &keysyms);
951 r = errno > 0 ? errno : -EFAULT;
953 r = keyboard_fill(k, repdata, false, repkbd->keycode, KBDKEY_REPEAT, num, keysyms);
956 log_debug("idev-keyboard: %s/%s: cannot update key-repeat: %s",
957 d->session->name, d->name, strerror(-r));
958 k->repeating = false;
964 static int keyboard_feed_evdev(idev_keyboard *k, idev_data *data) {
965 struct input_event *ev = &data->evdev.event;
966 enum xkb_state_component compch;
967 enum xkb_compose_status cstatus;
968 const xkb_keysym_t *keysyms;
969 idev_device *d = &k->device;
972 if (ev->type != EV_KEY || ev->value > KBDKEY_DOWN)
975 /* TODO: We should audit xkb-actions, whether they need @resync as
976 * flag. Most actions should just be executed, however, there might
977 * be actions that depend on modifier-orders. Those should be
980 num = xkb_state_key_get_syms(k->xkb_state, ev->code + KBDXKB_SHIFT, &keysyms);
981 compch = xkb_state_update_key(k->xkb_state, ev->code + KBDXKB_SHIFT, ev->value);
983 if (compch & XKB_STATE_LEDS) {
984 /* TODO: update LEDs */
992 if (k->xkb_compose && ev->value == KBDKEY_DOWN) {
993 if (num == 1 && !data->resync) {
994 xkb_compose_state_feed(k->xkb_compose, keysyms[0]);
995 cstatus = xkb_compose_state_get_status(k->xkb_compose);
997 cstatus = XKB_COMPOSE_CANCELLED;
1001 case XKB_COMPOSE_NOTHING:
1002 /* keep produced keysyms and forward unchanged */
1004 case XKB_COMPOSE_COMPOSING:
1005 /* consumed by compose-state, drop keysym */
1009 case XKB_COMPOSE_COMPOSED:
1010 /* compose-state produced sth, replace keysym */
1011 num = keyboard_read_compose(k, &keysyms);
1012 xkb_compose_state_reset(k->xkb_compose);
1014 case XKB_COMPOSE_CANCELLED:
1015 /* canceled compose, reset, forward cancellation sym */
1016 xkb_compose_state_reset(k->xkb_compose);
1019 } else if (k->xkb_compose &&
1021 keysyms[0] == XKB_KEY_Multi_key &&
1023 ev->value == KBDKEY_UP) {
1024 /* Reset compose state on Multi-Key UP events. This effectively
1025 * requires you to hold the key during the whole sequence. I
1026 * think it's pretty handy to avoid accidental
1027 * Compose-sequences, but this may break Compose for disabled
1028 * people. We really need to make this opional! (TODO) */
1029 xkb_compose_state_reset(k->xkb_compose);
1032 if (ev->value == KBDKEY_UP) {
1033 /* never produce keysyms for UP */
1038 r = keyboard_fill(k, &k->evdata, data->resync, ev->code, ev->value, num, keysyms);
1043 return keyboard_raise_data(k, &k->evdata);
1046 log_debug("idev-keyboard: %s/%s: cannot handle event: %s",
1047 d->session->name, d->name, strerror(-r));
1048 k->repeating = false;
1053 static int keyboard_feed(idev_device *d, idev_data *data) {
1054 idev_keyboard *k = keyboard_from_device(d);
1056 switch (data->type) {
1057 case IDEV_DATA_RESYNC:
1059 * If the underlying device is re-synced, key-events might be
1060 * sent re-ordered. Thus, we don't know which key was pressed
1061 * last. Key-repeat might get confused, hence, disable it
1062 * during re-syncs. The first following event will enable it
1066 k->repeating = false;
1069 case IDEV_DATA_EVDEV:
1070 return keyboard_feed_evdev(k, data);
1076 static int keyboard_update_kbdmap(idev_keyboard *k) {
1077 idev_device *d = &k->device;
1078 struct xkb_state *state;
1084 km = k->kbdctx->kbdmap;
1085 if (km == k->kbdmap)
1089 state = xkb_state_new(km->xkb_keymap);
1091 r = errno > 0 ? -errno : -EFAULT;
1095 kbdmap_unref(k->kbdmap);
1096 k->kbdmap = kbdmap_ref(km);
1097 xkb_state_unref(k->xkb_state);
1098 k->xkb_state = state;
1100 /* TODO: On state-change, we should trigger a resync so the whole
1101 * event-state is flushed into the new xkb-state. libevdev currently
1102 * does not support that, though. */
1107 log_debug("idev-keyboard: %s/%s: cannot adopt new keymap: %s",
1108 d->session->name, d->name, strerror(-r));
1112 static int keyboard_update_kbdtbl(idev_keyboard *k) {
1113 idev_device *d = &k->device;
1114 struct xkb_compose_state *compose = NULL;
1120 kt = k->kbdctx->kbdtbl;
1121 if (kt == k->kbdtbl)
1126 compose = xkb_compose_state_new(kt->xkb_compose_table, XKB_COMPOSE_STATE_NO_FLAGS);
1128 r = errno > 0 ? -errno : -EFAULT;
1133 kbdtbl_unref(k->kbdtbl);
1134 k->kbdtbl = kbdtbl_ref(kt);
1135 xkb_compose_state_unref(k->xkb_compose);
1136 k->xkb_compose = compose;
1141 log_debug("idev-keyboard: %s/%s: cannot adopt new compose table: %s",
1142 d->session->name, d->name, strerror(-r));
1146 static const idev_device_vtable keyboard_vtable = {
1147 .free = keyboard_free,
1148 .feed = keyboard_feed,