chiark / gitweb /
treewide: more log_*_errno() conversions, multiline calls
[elogind.git] / src / libsystemd-terminal / idev-keyboard.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com>
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <inttypes.h>
23 #include <stdbool.h>
24 #include <stdlib.h>
25 #include <systemd/sd-bus.h>
26 #include <systemd/sd-event.h>
27 #include <xkbcommon/xkbcommon.h>
28 #include <xkbcommon/xkbcommon-compose.h>
29 #include "bus-util.h"
30 #include "hashmap.h"
31 #include "idev.h"
32 #include "idev-internal.h"
33 #include "macro.h"
34 #include "term-internal.h"
35 #include "util.h"
36
37 typedef struct kbdtbl kbdtbl;
38 typedef struct kbdmap kbdmap;
39 typedef struct kbdctx kbdctx;
40 typedef struct idev_keyboard idev_keyboard;
41
42 struct kbdtbl {
43         unsigned long ref;
44         struct xkb_compose_table *xkb_compose_table;
45 };
46
47 struct kbdmap {
48         unsigned long ref;
49         struct xkb_keymap *xkb_keymap;
50         xkb_mod_index_t modmap[IDEV_KBDMOD_CNT];
51         xkb_led_index_t ledmap[IDEV_KBDLED_CNT];
52 };
53
54 struct kbdctx {
55         unsigned long ref;
56         idev_context *context;
57         struct xkb_context *xkb_context;
58         struct kbdmap *kbdmap;
59         struct kbdtbl *kbdtbl;
60
61         sd_bus_slot *slot_locale_props_changed;
62         sd_bus_slot *slot_locale_get_all;
63
64         char *locale_lang;
65         char *locale_x11_model;
66         char *locale_x11_layout;
67         char *locale_x11_variant;
68         char *locale_x11_options;
69         char *last_x11_model;
70         char *last_x11_layout;
71         char *last_x11_variant;
72         char *last_x11_options;
73 };
74
75 struct idev_keyboard {
76         idev_device device;
77         kbdctx *kbdctx;
78         kbdmap *kbdmap;
79         kbdtbl *kbdtbl;
80
81         struct xkb_state *xkb_state;
82         struct xkb_compose_state *xkb_compose;
83
84         usec_t repeat_delay;
85         usec_t repeat_rate;
86         sd_event_source *repeat_timer;
87
88         uint32_t n_syms;
89         idev_data evdata;
90         idev_data repdata;
91         uint32_t *compose_res;
92
93         bool repeating : 1;
94 };
95
96 #define keyboard_from_device(_d) container_of((_d), idev_keyboard, device)
97
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 */
103
104 static const idev_device_vtable keyboard_vtable;
105
106 static int keyboard_update_kbdmap(idev_keyboard *k);
107 static int keyboard_update_kbdtbl(idev_keyboard *k);
108
109 /*
110  * Keyboard Compose Tables
111  */
112
113 static kbdtbl *kbdtbl_ref(kbdtbl *kt) {
114         if (kt) {
115                 assert_return(kt->ref > 0, NULL);
116                 ++kt->ref;
117         }
118
119         return kt;
120 }
121
122 static kbdtbl *kbdtbl_unref(kbdtbl *kt) {
123         if (!kt)
124                 return NULL;
125
126         assert_return(kt->ref > 0, NULL);
127
128         if (--kt->ref > 0)
129                 return NULL;
130
131         xkb_compose_table_unref(kt->xkb_compose_table);
132         free(kt);
133
134         return 0;
135 }
136
137 DEFINE_TRIVIAL_CLEANUP_FUNC(kbdtbl*, kbdtbl_unref);
138
139 static int kbdtbl_new_from_locale(kbdtbl **out, kbdctx *kc, const char *locale) {
140         _cleanup_(kbdtbl_unrefp) kbdtbl *kt = NULL;
141
142         assert_return(out, -EINVAL);
143         assert_return(locale, -EINVAL);
144
145         kt = new0(kbdtbl, 1);
146         if (!kt)
147                 return -ENOMEM;
148
149         kt->ref = 1;
150
151         kt->xkb_compose_table = xkb_compose_table_new_from_locale(kc->xkb_context,
152                                                                   locale,
153                                                                   XKB_COMPOSE_COMPILE_NO_FLAGS);
154         if (!kt->xkb_compose_table)
155                 return errno > 0 ? -errno : -EFAULT;
156
157         *out = kt;
158         kt = NULL;
159         return 0;
160 }
161
162 /*
163  * Keyboard Keymaps
164  */
165
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,
172 };
173
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,
178 };
179
180 static kbdmap *kbdmap_ref(kbdmap *km) {
181         assert_return(km, NULL);
182         assert_return(km->ref > 0, NULL);
183
184         ++km->ref;
185         return km;
186 }
187
188 static kbdmap *kbdmap_unref(kbdmap *km) {
189         if (!km)
190                 return NULL;
191
192         assert_return(km->ref > 0, NULL);
193
194         if (--km->ref > 0)
195                 return NULL;
196
197         xkb_keymap_unref(km->xkb_keymap);
198         free(km);
199
200         return 0;
201 }
202
203 DEFINE_TRIVIAL_CLEANUP_FUNC(kbdmap*, kbdmap_unref);
204
205 static int kbdmap_new_from_names(kbdmap **out,
206                                  kbdctx *kc,
207                                  const char *model,
208                                  const char *layout,
209                                  const char *variant,
210                                  const char *options) {
211         _cleanup_(kbdmap_unrefp) kbdmap *km = NULL;
212         struct xkb_rule_names rmlvo = { };
213         unsigned int i;
214
215         assert_return(out, -EINVAL);
216
217         km = new0(kbdmap, 1);
218         if (!km)
219                 return -ENOMEM;
220
221         km->ref = 1;
222
223         rmlvo.rules = "evdev";
224         rmlvo.model = model;
225         rmlvo.layout = layout;
226         rmlvo.variant = variant;
227         rmlvo.options = options;
228
229         errno = 0;
230         km->xkb_keymap = xkb_keymap_new_from_names(kc->xkb_context, &rmlvo, 0);
231         if (!km->xkb_keymap)
232                 return errno > 0 ? -errno : -EFAULT;
233
234         for (i = 0; i < IDEV_KBDMOD_CNT; ++i) {
235                 const char *t = kbdmap_modmap[i];
236
237                 if (t)
238                         km->modmap[i] = xkb_keymap_mod_get_index(km->xkb_keymap, t);
239                 else
240                         km->modmap[i] = XKB_MOD_INVALID;
241         }
242
243         for (i = 0; i < IDEV_KBDLED_CNT; ++i) {
244                 const char *t = kbdmap_ledmap[i];
245
246                 if (t)
247                         km->ledmap[i] = xkb_keymap_led_get_index(km->xkb_keymap, t);
248                 else
249                         km->ledmap[i] = XKB_LED_INVALID;
250         }
251
252         *out = km;
253         km = NULL;
254         return 0;
255 }
256
257 /*
258  * Keyboard Context
259  */
260
261 static int kbdctx_refresh_compose_table(kbdctx *kc, const char *lang) {
262         kbdtbl *kt;
263         idev_session *s;
264         idev_device *d;
265         Iterator i, j;
266         int r;
267
268         if (!lang)
269                 lang = "C";
270
271         if (streq_ptr(kc->locale_lang, lang))
272                 return 0;
273
274         r = free_and_strdup(&kc->locale_lang, lang);
275         if (r < 0)
276                 return r;
277
278         log_debug("idev-keyboard: new default compose table: [ %s ]", lang);
279
280         r = kbdtbl_new_from_locale(&kt, kc, lang);
281         if (r < 0) {
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",
288                                 lang);
289                 r = 0;
290                 kt = NULL;
291         }
292
293         kbdtbl_unref(kc->kbdtbl);
294         kc->kbdtbl = kt;
295
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));
300
301         return 0;
302 }
303
304 static void move_str(char **dest, char **src) {
305         free(*dest);
306         *dest = *src;
307         *src = NULL;
308 }
309
310 static int kbdctx_refresh_keymap(kbdctx *kc) {
311         idev_session *s;
312         idev_device *d;
313         Iterator i, j;
314         kbdmap *km;
315         int r;
316
317         if (kc->kbdmap &&
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))
322                 return 0 ;
323
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);
328
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);
331
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);
335         if (r < 0) {
336                 log_debug_errno(r, "idev-keyboard: cannot create keymap from locale1: %m");
337                 return r;
338         }
339
340         kbdmap_unref(kc->kbdmap);
341         kc->kbdmap = km;
342
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));
347
348         return 0;
349 }
350
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;
354         int r;
355
356         r = sd_bus_message_enter_container(m, 'a', "s");
357         if (r < 0)
358                 goto error;
359
360         while ((r = sd_bus_message_read(m, "s", &s)) > 0) {
361                 if (!ctype)
362                         ctype = startswith(s, "LC_CTYPE=");
363                 if (!lang)
364                         lang = startswith(s, "LANG=");
365         }
366
367         if (r < 0)
368                 goto error;
369
370         r = sd_bus_message_exit_container(m);
371         if (r < 0)
372                 goto error;
373
374         kbdctx_refresh_compose_table(kc, ctype ? : lang);
375         r = 0;
376
377 error:
378         if (r < 0)
379                 log_debug_errno(r, "idev-keyboard: cannot parse locale property from locale1: %m");
380
381         return r;
382 }
383
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) },
390 };
391
392 static int kbdctx_locale_get_all_fn(sd_bus *bus,
393                                     sd_bus_message *m,
394                                     void *userdata,
395                                     sd_bus_error *ret_err) {
396         kbdctx *kc = userdata;
397         int r;
398
399         kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
400
401         if (sd_bus_message_is_method_error(m, NULL)) {
402                 const sd_bus_error *error = sd_bus_message_get_error(m);
403
404                 log_debug("idev-keyboard: GetAll() on locale1 failed: %s: %s",
405                           error->name, error->message);
406                 return 0;
407         }
408
409         r = bus_message_map_all_properties(bus, m, kbdctx_locale_map, kc);
410         if (r < 0) {
411                 log_debug("idev-keyboard: erroneous GetAll() reply from locale1");
412                 return 0;
413         }
414
415         kbdctx_refresh_keymap(kc);
416         return 0;
417 }
418
419 static int kbdctx_query_locale(kbdctx *kc) {
420         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
421         int r;
422
423         kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
424
425         r = sd_bus_message_new_method_call(kc->context->sysbus,
426                                            &m,
427                                            "org.freedesktop.locale1",
428                                            "/org/freedesktop/locale1",
429                                            "org.freedesktop.DBus.Properties",
430                                            "GetAll");
431         if (r < 0)
432                 goto error;
433
434         r = sd_bus_message_append(m, "s", "org.freedesktop.locale1");
435         if (r < 0)
436                 goto error;
437
438         r = sd_bus_call_async(kc->context->sysbus,
439                               &kc->slot_locale_get_all,
440                               m,
441                               kbdctx_locale_get_all_fn,
442                               kc,
443                               0);
444         if (r < 0)
445                 goto error;
446
447         return 0;
448
449 error:
450         log_debug_errno(r, "idev-keyboard: cannot send GetAll to locale1: %m");
451         return r;
452 }
453
454 static int kbdctx_locale_props_changed_fn(sd_bus *bus,
455                                           sd_bus_message *signal,
456                                           void *userdata,
457                                           sd_bus_error *ret_err) {
458         kbdctx *kc = userdata;
459         int r;
460
461         kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
462
463         /* skip interface name */
464         r = sd_bus_message_skip(signal, "s");
465         if (r < 0)
466                 goto error;
467
468         r = bus_message_map_properties_changed(bus, signal, kbdctx_locale_map, kc);
469         if (r < 0)
470                 goto error;
471
472         if (r > 0) {
473                 r = kbdctx_query_locale(kc);
474                 if (r < 0)
475                         return r;
476         }
477
478         kbdctx_refresh_keymap(kc);
479         return 0;
480
481 error:
482         log_debug_errno(r, "idev-keyboard: cannot handle PropertiesChanged from locale1: %m");
483         return r;
484 }
485
486 static int kbdctx_setup_bus(kbdctx *kc) {
487         int r;
488
489         r = sd_bus_add_match(kc->context->sysbus,
490                              &kc->slot_locale_props_changed,
491                              "type='signal',"
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,
497                              kc);
498         if (r < 0) {
499                 log_debug_errno(r, "idev-keyboard: cannot setup locale1 link: %m");
500                 return r;
501         }
502
503         return kbdctx_query_locale(kc);
504 }
505
506 static void kbdctx_log_fn(struct xkb_context *ctx, enum xkb_log_level lvl, const char *format, va_list args) {
507         char buf[LINE_MAX];
508         int sd_lvl;
509
510         if (lvl >= XKB_LOG_LEVEL_DEBUG)
511                 sd_lvl = LOG_DEBUG;
512         else if (lvl >= XKB_LOG_LEVEL_INFO)
513                 sd_lvl = LOG_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)
517                 sd_lvl = LOG_ERR;
518         else if (lvl >= XKB_LOG_LEVEL_CRITICAL)
519                 sd_lvl = LOG_CRIT;
520         else
521                 sd_lvl = LOG_CRIT;
522
523         snprintf(buf, sizeof(buf), "idev-xkb: %s", format);
524         log_internalv(sd_lvl, 0, __FILE__, __LINE__, __func__, buf, args);
525 }
526
527 static kbdctx *kbdctx_ref(kbdctx *kc) {
528         assert_return(kc, NULL);
529         assert_return(kc->ref > 0, NULL);
530
531         ++kc->ref;
532         return kc;
533 }
534
535 static kbdctx *kbdctx_unref(kbdctx *kc) {
536         if (!kc)
537                 return NULL;
538
539         assert_return(kc->ref > 0, NULL);
540
541         if (--kc->ref > 0)
542                 return NULL;
543
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);
559         free(kc);
560
561         return NULL;
562 }
563
564 DEFINE_TRIVIAL_CLEANUP_FUNC(kbdctx*, kbdctx_unref);
565
566 static int kbdctx_new(kbdctx **out, idev_context *c) {
567         _cleanup_(kbdctx_unrefp) kbdctx *kc = NULL;
568         int r;
569
570         assert_return(out, -EINVAL);
571         assert_return(c, -EINVAL);
572
573         kc = new0(kbdctx, 1);
574         if (!kc)
575                 return -ENOMEM;
576
577         kc->ref = 1;
578         kc->context = c;
579
580         errno = 0;
581         kc->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
582         if (!kc->xkb_context)
583                 return errno > 0 ? -errno : -EFAULT;
584
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);
587
588         r = kbdctx_refresh_keymap(kc);
589         if (r < 0)
590                 return r;
591
592         r = kbdctx_refresh_compose_table(kc, NULL);
593         if (r < 0)
594                 return r;
595
596         if (c->sysbus) {
597                 r = kbdctx_setup_bus(kc);
598                 if (r < 0)
599                         return r;
600         }
601
602         r = hashmap_put(c->data_map, KBDCTX_KEY, kc);
603         if (r < 0)
604                 return r;
605
606         *out = kc;
607         kc = NULL;
608         return 0;
609 }
610
611 static int get_kbdctx(idev_context *c, kbdctx **out) {
612         kbdctx *kc;
613
614         assert_return(c, -EINVAL);
615         assert_return(out, -EINVAL);
616
617         kc = hashmap_get(c->data_map, KBDCTX_KEY);
618         if (kc) {
619                 *out = kbdctx_ref(kc);
620                 return 0;
621         }
622
623         return kbdctx_new(out, c);
624 }
625
626 /*
627  * Keyboard Devices
628  */
629
630 bool idev_is_keyboard(idev_device *d) {
631         return d && d->vtable == &keyboard_vtable;
632 }
633
634 idev_device *idev_find_keyboard(idev_session *s, const char *name) {
635         char *kname;
636
637         assert_return(s, NULL);
638         assert_return(name, NULL);
639
640         kname = strappenda("keyboard/", name);
641         return hashmap_get(s->device_map, kname);
642 }
643
644 static int keyboard_raise_data(idev_keyboard *k, idev_data *data) {
645         idev_device *d = &k->device;
646         int r;
647
648         r = idev_session_raise_device_data(d->session, d, data);
649         if (r < 0)
650                 log_debug_errno(r, "idev-keyboard: %s/%s: error while raising data event: %m",
651                                 d->session->name, d->name);
652
653         return r;
654 }
655
656 static int keyboard_resize_bufs(idev_keyboard *k, uint32_t n_syms) {
657         uint32_t *t;
658
659         if (n_syms <= k->n_syms)
660                 return 0;
661
662         t = realloc(k->compose_res, sizeof(*t) * n_syms);
663         if (!t)
664                 return -ENOMEM;
665         k->compose_res = t;
666
667         t = realloc(k->evdata.keyboard.keysyms, sizeof(*t) * n_syms);
668         if (!t)
669                 return -ENOMEM;
670         k->evdata.keyboard.keysyms = t;
671
672         t = realloc(k->evdata.keyboard.codepoints, sizeof(*t) * n_syms);
673         if (!t)
674                 return -ENOMEM;
675         k->evdata.keyboard.codepoints = t;
676
677         t = realloc(k->repdata.keyboard.keysyms, sizeof(*t) * n_syms);
678         if (!t)
679                 return -ENOMEM;
680         k->repdata.keyboard.keysyms = t;
681
682         t = realloc(k->repdata.keyboard.codepoints, sizeof(*t) * n_syms);
683         if (!t)
684                 return -ENOMEM;
685         k->repdata.keyboard.codepoints = t;
686
687         k->n_syms = n_syms;
688         return 0;
689 }
690
691 static unsigned int keyboard_read_compose(idev_keyboard *k, const xkb_keysym_t **out) {
692         _cleanup_free_ char *t = NULL;
693         term_utf8 u8 = { };
694         char buf[256], *p;
695         size_t flen = 0;
696         int i, r;
697
698         r = xkb_compose_state_get_utf8(k->xkb_compose, buf, sizeof(buf));
699         if (r >= (int)sizeof(buf)) {
700                 t = malloc(r + 1);
701                 if (!t)
702                         return 0;
703
704                 xkb_compose_state_get_utf8(k->xkb_compose, t, r + 1);
705                 p = t;
706         } else {
707                 p = buf;
708         }
709
710         for (i = 0; i < r; ++i) {
711                 uint32_t *ucs;
712                 size_t len, j;
713
714                 len = term_utf8_decode(&u8, &ucs, p[i]);
715                 if (len > 0) {
716                         r = keyboard_resize_bufs(k, flen + len);
717                         if (r < 0)
718                                 return 0;
719
720                         for (j = 0; j < len; ++j)
721                                 k->compose_res[flen++] = ucs[j];
722                 }
723         }
724
725         *out = k->compose_res;
726         return flen;
727 }
728
729 static void keyboard_arm(idev_keyboard *k, usec_t usecs) {
730         int r;
731
732         if (usecs != 0) {
733                 usecs += now(CLOCK_MONOTONIC);
734                 r = sd_event_source_set_time(k->repeat_timer, usecs);
735                 if (r >= 0)
736                         sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_ONESHOT);
737         } else {
738                 sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
739         }
740 }
741
742 static int keyboard_repeat_timer_fn(sd_event_source *source, uint64_t usec, void *userdata) {
743         idev_keyboard *k = userdata;
744
745         /* never feed REPEAT keys into COMPOSE */
746
747         keyboard_arm(k, k->repeat_rate);
748         return keyboard_raise_data(k, &k->repdata);
749 }
750
751 int idev_keyboard_new(idev_device **out, idev_session *s, const char *name) {
752         _cleanup_(idev_device_freep) idev_device *d = NULL;
753         idev_keyboard *k;
754         char *kname;
755         int r;
756
757         assert_return(out, -EINVAL);
758         assert_return(s, -EINVAL);
759         assert_return(name, -EINVAL);
760
761         k = new0(idev_keyboard, 1);
762         if (!k)
763                 return -ENOMEM;
764
765         d = &k->device;
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;
769
770         /* TODO: add key-repeat configuration */
771
772         r = get_kbdctx(s->context, &k->kbdctx);
773         if (r < 0)
774                 return r;
775
776         r = keyboard_update_kbdmap(k);
777         if (r < 0)
778                 return r;
779
780         r = keyboard_update_kbdtbl(k);
781         if (r < 0)
782                 return r;
783
784         r = keyboard_resize_bufs(k, 8);
785         if (r < 0)
786                 return r;
787
788         r = sd_event_add_time(s->context->event,
789                               &k->repeat_timer,
790                               CLOCK_MONOTONIC,
791                               0,
792                               10 * USEC_PER_MSEC,
793                               keyboard_repeat_timer_fn,
794                               k);
795         if (r < 0)
796                 return r;
797
798         r = sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
799         if (r < 0)
800                 return r;
801
802         kname = strappenda("keyboard/", name);
803         r = idev_device_add(d, kname);
804         if (r < 0)
805                 return r;
806
807         if (out)
808                 *out = d;
809         d = NULL;
810         return 0;
811 }
812
813 static void keyboard_free(idev_device *d) {
814         idev_keyboard *k = keyboard_from_device(d);
815
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);
827         free(k);
828 }
829
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;
835         int num;
836
837         if (n_syms == 1 && syms[0] < 128 && syms[0] > 0)
838                 return syms[0];
839
840         keymap = xkb_state_get_keymap(state);
841         n_lo = xkb_keymap_num_layouts_for_key(keymap, code + KBDXKB_SHIFT);
842
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)
847                         return s[0];
848         }
849
850         return -1;
851 }
852
853 static int keyboard_fill(idev_keyboard *k,
854                          idev_data *dst,
855                          bool resync,
856                          uint16_t code,
857                          uint32_t value,
858                          uint32_t n_syms,
859                          const uint32_t *keysyms) {
860         idev_data_keyboard *kev;
861         uint32_t i;
862         int r;
863
864         assert(dst == &k->evdata || dst == &k->repdata);
865
866         r = keyboard_resize_bufs(k, n_syms);
867         if (r < 0)
868                 return r;
869
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);
874         kev->value = value;
875         kev->keycode = code;
876         kev->mods = 0;
877         kev->consumed_mods = 0;
878         kev->n_syms = n_syms;
879         memcpy(kev->keysyms, keysyms, sizeof(*keysyms) * n_syms);
880
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;
885         }
886
887         for (i = 0; i < IDEV_KBDMOD_CNT; ++i) {
888                 if (k->kbdmap->modmap[i] == XKB_MOD_INVALID)
889                         continue;
890
891                 r = xkb_state_mod_index_is_active(k->xkb_state, k->kbdmap->modmap[i], XKB_STATE_MODS_EFFECTIVE);
892                 if (r > 0)
893                         kev->mods |= 1 << i;
894
895                 r = xkb_state_mod_index_is_consumed(k->xkb_state, code + KBDXKB_SHIFT, k->kbdmap->modmap[i]);
896                 if (r > 0)
897                         kev->consumed_mods |= 1 << i;
898         }
899
900         return 0;
901 }
902
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;
910         bool repeats;
911         int r, num;
912
913         if (evdata->resync) {
914                 /*
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.
919                  */
920
921                 k->repeating = false;
922                 keyboard_arm(k, 0);
923                 return;
924         }
925
926         repeats = xkb_keymap_key_repeats(k->kbdmap->xkb_keymap, evkbd->keycode + KBDXKB_SHIFT);
927
928         if (k->repeating && repkbd->keycode == evkbd->keycode) {
929                 /*
930                  * We received an event for the key we currently repeat. If it
931                  * was released, stop key-repeat. Otherwise, ignore the event.
932                  */
933
934                 if (evkbd->value == KBDKEY_UP) {
935                         k->repeating = false;
936                         keyboard_arm(k, 0);
937                 }
938         } else if (evkbd->value == KBDKEY_DOWN && repeats) {
939                 /*
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
943                  * new key-repeat.
944                  */
945
946                 errno = 0;
947                 num = xkb_state_key_get_syms(k->xkb_state, evkbd->keycode + KBDXKB_SHIFT, &keysyms);
948                 if (num < 0)
949                         r = errno > 0 ? errno : -EFAULT;
950                 else
951                         r = keyboard_fill(k, repdata, false, evkbd->keycode, KBDKEY_REPEAT, num, keysyms);
952
953                 if (r < 0) {
954                         log_debug_errno(r, "idev-keyboard: %s/%s: cannot set key-repeat: %m",
955                                         d->session->name, d->name);
956                         k->repeating = false;
957                         keyboard_arm(k, 0);
958                 } else {
959                         k->repeating = true;
960                         keyboard_arm(k, k->repeat_delay);
961                 }
962         } else if (k->repeating && !repeats) {
963                 /*
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.
969                  */
970
971                 errno = 0;
972                 num = xkb_state_key_get_syms(k->xkb_state, repkbd->keycode + KBDXKB_SHIFT, &keysyms);
973                 if (num < 0)
974                         r = errno > 0 ? errno : -EFAULT;
975                 else
976                         r = keyboard_fill(k, repdata, false, repkbd->keycode, KBDKEY_REPEAT, num, keysyms);
977
978                 if (r < 0) {
979                         log_debug_errno(r, "idev-keyboard: %s/%s: cannot update key-repeat: %m",
980                                         d->session->name, d->name);
981                         k->repeating = false;
982                         keyboard_arm(k, 0);
983                 }
984         }
985 }
986
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;
993         int num, r;
994
995         if (ev->type != EV_KEY || ev->value > KBDKEY_DOWN)
996                 return 0;
997
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
1001          * suppressed. */
1002
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);
1005
1006         if (compch & XKB_STATE_LEDS) {
1007                 /* TODO: update LEDs */
1008         }
1009
1010         if (num < 0) {
1011                 r = num;
1012                 goto error;
1013         }
1014
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);
1019                 } else {
1020                         cstatus = XKB_COMPOSE_CANCELLED;
1021                 }
1022
1023                 switch (cstatus) {
1024                 case XKB_COMPOSE_NOTHING:
1025                         /* keep produced keysyms and forward unchanged */
1026                         break;
1027                 case XKB_COMPOSE_COMPOSING:
1028                         /* consumed by compose-state, drop keysym */
1029                         keysyms = NULL;
1030                         num = 0;
1031                         break;
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);
1036                         break;
1037                 case XKB_COMPOSE_CANCELLED:
1038                         /* canceled compose, reset, forward cancellation sym */
1039                         xkb_compose_state_reset(k->xkb_compose);
1040                         break;
1041                 }
1042         } else if (k->xkb_compose &&
1043                    num == 1 &&
1044                    keysyms[0] == XKB_KEY_Multi_key &&
1045                    !data->resync &&
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);
1053         }
1054
1055         if (ev->value == KBDKEY_UP) {
1056                 /* never produce keysyms for UP */
1057                 keysyms = NULL;
1058                 num = 0;
1059         }
1060
1061         r = keyboard_fill(k, &k->evdata, data->resync, ev->code, ev->value, num, keysyms);
1062         if (r < 0)
1063                 goto error;
1064
1065         keyboard_repeat(k);
1066         return keyboard_raise_data(k, &k->evdata);
1067
1068 error:
1069         log_debug_errno(r, "idev-keyboard: %s/%s: cannot handle event: %m",
1070                         d->session->name, d->name);
1071         k->repeating = false;
1072         keyboard_arm(k, 0);
1073         return 0;
1074 }
1075
1076 static int keyboard_feed(idev_device *d, idev_data *data) {
1077         idev_keyboard *k = keyboard_from_device(d);
1078
1079         switch (data->type) {
1080         case IDEV_DATA_RESYNC:
1081                 /*
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
1086                  * again.
1087                  */
1088
1089                 k->repeating = false;
1090                 keyboard_arm(k, 0);
1091                 return 0;
1092         case IDEV_DATA_EVDEV:
1093                 return keyboard_feed_evdev(k, data);
1094         default:
1095                 return 0;
1096         }
1097 }
1098
1099 static int keyboard_update_kbdmap(idev_keyboard *k) {
1100         idev_device *d = &k->device;
1101         struct xkb_state *state;
1102         kbdmap *km;
1103         int r;
1104
1105         assert(k);
1106
1107         km = k->kbdctx->kbdmap;
1108         if (km == k->kbdmap)
1109                 return 0;
1110
1111         errno = 0;
1112         state = xkb_state_new(km->xkb_keymap);
1113         if (!state) {
1114                 r = errno > 0 ? -errno : -EFAULT;
1115                 goto error;
1116         }
1117
1118         kbdmap_unref(k->kbdmap);
1119         k->kbdmap = kbdmap_ref(km);
1120         xkb_state_unref(k->xkb_state);
1121         k->xkb_state = state;
1122
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. */
1126
1127         return 0;
1128
1129 error:
1130         log_debug_errno(r, "idev-keyboard: %s/%s: cannot adopt new keymap: %m",
1131                         d->session->name, d->name);
1132         return r;
1133 }
1134
1135 static int keyboard_update_kbdtbl(idev_keyboard *k) {
1136         idev_device *d = &k->device;
1137         struct xkb_compose_state *compose = NULL;
1138         kbdtbl *kt;
1139         int r;
1140
1141         assert(k);
1142
1143         kt = k->kbdctx->kbdtbl;
1144         if (kt == k->kbdtbl)
1145                 return 0;
1146
1147         if (kt) {
1148                 errno = 0;
1149                 compose = xkb_compose_state_new(kt->xkb_compose_table, XKB_COMPOSE_STATE_NO_FLAGS);
1150                 if (!compose) {
1151                         r = errno > 0 ? -errno : -EFAULT;
1152                         goto error;
1153                 }
1154         }
1155
1156         kbdtbl_unref(k->kbdtbl);
1157         k->kbdtbl = kbdtbl_ref(kt);
1158         xkb_compose_state_unref(k->xkb_compose);
1159         k->xkb_compose = compose;
1160
1161         return 0;
1162
1163 error:
1164         log_debug_errno(r, "idev-keyboard: %s/%s: cannot adopt new compose table: %m",
1165                         d->session->name, d->name);
1166         return r;
1167 }
1168
1169 static const idev_device_vtable keyboard_vtable = {
1170         .free                   = keyboard_free,
1171         .feed                   = keyboard_feed,
1172 };