chiark / gitweb /
treewide: simplify log_*_errno(r,...) immediately followed by "return r"
[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                 return log_debug_errno(r, "idev-keyboard: cannot create keymap from locale1: %m");
337
338         kbdmap_unref(kc->kbdmap);
339         kc->kbdmap = km;
340
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));
345
346         return 0;
347 }
348
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;
352         int r;
353
354         r = sd_bus_message_enter_container(m, 'a', "s");
355         if (r < 0)
356                 goto error;
357
358         while ((r = sd_bus_message_read(m, "s", &s)) > 0) {
359                 if (!ctype)
360                         ctype = startswith(s, "LC_CTYPE=");
361                 if (!lang)
362                         lang = startswith(s, "LANG=");
363         }
364
365         if (r < 0)
366                 goto error;
367
368         r = sd_bus_message_exit_container(m);
369         if (r < 0)
370                 goto error;
371
372         kbdctx_refresh_compose_table(kc, ctype ? : lang);
373         r = 0;
374
375 error:
376         if (r < 0)
377                 log_debug_errno(r, "idev-keyboard: cannot parse locale property from locale1: %m");
378
379         return r;
380 }
381
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) },
388 };
389
390 static int kbdctx_locale_get_all_fn(sd_bus *bus,
391                                     sd_bus_message *m,
392                                     void *userdata,
393                                     sd_bus_error *ret_err) {
394         kbdctx *kc = userdata;
395         int r;
396
397         kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
398
399         if (sd_bus_message_is_method_error(m, NULL)) {
400                 const sd_bus_error *error = sd_bus_message_get_error(m);
401
402                 log_debug("idev-keyboard: GetAll() on locale1 failed: %s: %s",
403                           error->name, error->message);
404                 return 0;
405         }
406
407         r = bus_message_map_all_properties(bus, m, kbdctx_locale_map, kc);
408         if (r < 0) {
409                 log_debug("idev-keyboard: erroneous GetAll() reply from locale1");
410                 return 0;
411         }
412
413         kbdctx_refresh_keymap(kc);
414         return 0;
415 }
416
417 static int kbdctx_query_locale(kbdctx *kc) {
418         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
419         int r;
420
421         kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
422
423         r = sd_bus_message_new_method_call(kc->context->sysbus,
424                                            &m,
425                                            "org.freedesktop.locale1",
426                                            "/org/freedesktop/locale1",
427                                            "org.freedesktop.DBus.Properties",
428                                            "GetAll");
429         if (r < 0)
430                 goto error;
431
432         r = sd_bus_message_append(m, "s", "org.freedesktop.locale1");
433         if (r < 0)
434                 goto error;
435
436         r = sd_bus_call_async(kc->context->sysbus,
437                               &kc->slot_locale_get_all,
438                               m,
439                               kbdctx_locale_get_all_fn,
440                               kc,
441                               0);
442         if (r < 0)
443                 goto error;
444
445         return 0;
446
447 error:
448         log_debug_errno(r, "idev-keyboard: cannot send GetAll to locale1: %m");
449         return r;
450 }
451
452 static int kbdctx_locale_props_changed_fn(sd_bus *bus,
453                                           sd_bus_message *signal,
454                                           void *userdata,
455                                           sd_bus_error *ret_err) {
456         kbdctx *kc = userdata;
457         int r;
458
459         kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
460
461         /* skip interface name */
462         r = sd_bus_message_skip(signal, "s");
463         if (r < 0)
464                 goto error;
465
466         r = bus_message_map_properties_changed(bus, signal, kbdctx_locale_map, kc);
467         if (r < 0)
468                 goto error;
469
470         if (r > 0) {
471                 r = kbdctx_query_locale(kc);
472                 if (r < 0)
473                         return r;
474         }
475
476         kbdctx_refresh_keymap(kc);
477         return 0;
478
479 error:
480         log_debug_errno(r, "idev-keyboard: cannot handle PropertiesChanged from locale1: %m");
481         return r;
482 }
483
484 static int kbdctx_setup_bus(kbdctx *kc) {
485         int r;
486
487         r = sd_bus_add_match(kc->context->sysbus,
488                              &kc->slot_locale_props_changed,
489                              "type='signal',"
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,
495                              kc);
496         if (r < 0) {
497                 log_debug_errno(r, "idev-keyboard: cannot setup locale1 link: %m");
498                 return r;
499         }
500
501         return kbdctx_query_locale(kc);
502 }
503
504 static void kbdctx_log_fn(struct xkb_context *ctx, enum xkb_log_level lvl, const char *format, va_list args) {
505         char buf[LINE_MAX];
506         int sd_lvl;
507
508         if (lvl >= XKB_LOG_LEVEL_DEBUG)
509                 sd_lvl = LOG_DEBUG;
510         else if (lvl >= XKB_LOG_LEVEL_INFO)
511                 sd_lvl = LOG_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)
515                 sd_lvl = LOG_ERR;
516         else if (lvl >= XKB_LOG_LEVEL_CRITICAL)
517                 sd_lvl = LOG_CRIT;
518         else
519                 sd_lvl = LOG_CRIT;
520
521         snprintf(buf, sizeof(buf), "idev-xkb: %s", format);
522         log_internalv(sd_lvl, 0, __FILE__, __LINE__, __func__, buf, args);
523 }
524
525 static kbdctx *kbdctx_ref(kbdctx *kc) {
526         assert_return(kc, NULL);
527         assert_return(kc->ref > 0, NULL);
528
529         ++kc->ref;
530         return kc;
531 }
532
533 static kbdctx *kbdctx_unref(kbdctx *kc) {
534         if (!kc)
535                 return NULL;
536
537         assert_return(kc->ref > 0, NULL);
538
539         if (--kc->ref > 0)
540                 return NULL;
541
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);
557         free(kc);
558
559         return NULL;
560 }
561
562 DEFINE_TRIVIAL_CLEANUP_FUNC(kbdctx*, kbdctx_unref);
563
564 static int kbdctx_new(kbdctx **out, idev_context *c) {
565         _cleanup_(kbdctx_unrefp) kbdctx *kc = NULL;
566         int r;
567
568         assert_return(out, -EINVAL);
569         assert_return(c, -EINVAL);
570
571         kc = new0(kbdctx, 1);
572         if (!kc)
573                 return -ENOMEM;
574
575         kc->ref = 1;
576         kc->context = c;
577
578         errno = 0;
579         kc->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
580         if (!kc->xkb_context)
581                 return errno > 0 ? -errno : -EFAULT;
582
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);
585
586         r = kbdctx_refresh_keymap(kc);
587         if (r < 0)
588                 return r;
589
590         r = kbdctx_refresh_compose_table(kc, NULL);
591         if (r < 0)
592                 return r;
593
594         if (c->sysbus) {
595                 r = kbdctx_setup_bus(kc);
596                 if (r < 0)
597                         return r;
598         }
599
600         r = hashmap_put(c->data_map, KBDCTX_KEY, kc);
601         if (r < 0)
602                 return r;
603
604         *out = kc;
605         kc = NULL;
606         return 0;
607 }
608
609 static int get_kbdctx(idev_context *c, kbdctx **out) {
610         kbdctx *kc;
611
612         assert_return(c, -EINVAL);
613         assert_return(out, -EINVAL);
614
615         kc = hashmap_get(c->data_map, KBDCTX_KEY);
616         if (kc) {
617                 *out = kbdctx_ref(kc);
618                 return 0;
619         }
620
621         return kbdctx_new(out, c);
622 }
623
624 /*
625  * Keyboard Devices
626  */
627
628 bool idev_is_keyboard(idev_device *d) {
629         return d && d->vtable == &keyboard_vtable;
630 }
631
632 idev_device *idev_find_keyboard(idev_session *s, const char *name) {
633         char *kname;
634
635         assert_return(s, NULL);
636         assert_return(name, NULL);
637
638         kname = strappenda("keyboard/", name);
639         return hashmap_get(s->device_map, kname);
640 }
641
642 static int keyboard_raise_data(idev_keyboard *k, idev_data *data) {
643         idev_device *d = &k->device;
644         int r;
645
646         r = idev_session_raise_device_data(d->session, d, data);
647         if (r < 0)
648                 log_debug_errno(r, "idev-keyboard: %s/%s: error while raising data event: %m",
649                                 d->session->name, d->name);
650
651         return r;
652 }
653
654 static int keyboard_resize_bufs(idev_keyboard *k, uint32_t n_syms) {
655         uint32_t *t;
656
657         if (n_syms <= k->n_syms)
658                 return 0;
659
660         t = realloc(k->compose_res, sizeof(*t) * n_syms);
661         if (!t)
662                 return -ENOMEM;
663         k->compose_res = t;
664
665         t = realloc(k->evdata.keyboard.keysyms, sizeof(*t) * n_syms);
666         if (!t)
667                 return -ENOMEM;
668         k->evdata.keyboard.keysyms = t;
669
670         t = realloc(k->evdata.keyboard.codepoints, sizeof(*t) * n_syms);
671         if (!t)
672                 return -ENOMEM;
673         k->evdata.keyboard.codepoints = t;
674
675         t = realloc(k->repdata.keyboard.keysyms, sizeof(*t) * n_syms);
676         if (!t)
677                 return -ENOMEM;
678         k->repdata.keyboard.keysyms = t;
679
680         t = realloc(k->repdata.keyboard.codepoints, sizeof(*t) * n_syms);
681         if (!t)
682                 return -ENOMEM;
683         k->repdata.keyboard.codepoints = t;
684
685         k->n_syms = n_syms;
686         return 0;
687 }
688
689 static unsigned int keyboard_read_compose(idev_keyboard *k, const xkb_keysym_t **out) {
690         _cleanup_free_ char *t = NULL;
691         term_utf8 u8 = { };
692         char buf[256], *p;
693         size_t flen = 0;
694         int i, r;
695
696         r = xkb_compose_state_get_utf8(k->xkb_compose, buf, sizeof(buf));
697         if (r >= (int)sizeof(buf)) {
698                 t = malloc(r + 1);
699                 if (!t)
700                         return 0;
701
702                 xkb_compose_state_get_utf8(k->xkb_compose, t, r + 1);
703                 p = t;
704         } else {
705                 p = buf;
706         }
707
708         for (i = 0; i < r; ++i) {
709                 uint32_t *ucs;
710                 size_t len, j;
711
712                 len = term_utf8_decode(&u8, &ucs, p[i]);
713                 if (len > 0) {
714                         r = keyboard_resize_bufs(k, flen + len);
715                         if (r < 0)
716                                 return 0;
717
718                         for (j = 0; j < len; ++j)
719                                 k->compose_res[flen++] = ucs[j];
720                 }
721         }
722
723         *out = k->compose_res;
724         return flen;
725 }
726
727 static void keyboard_arm(idev_keyboard *k, usec_t usecs) {
728         int r;
729
730         if (usecs != 0) {
731                 usecs += now(CLOCK_MONOTONIC);
732                 r = sd_event_source_set_time(k->repeat_timer, usecs);
733                 if (r >= 0)
734                         sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_ONESHOT);
735         } else {
736                 sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
737         }
738 }
739
740 static int keyboard_repeat_timer_fn(sd_event_source *source, uint64_t usec, void *userdata) {
741         idev_keyboard *k = userdata;
742
743         /* never feed REPEAT keys into COMPOSE */
744
745         keyboard_arm(k, k->repeat_rate);
746         return keyboard_raise_data(k, &k->repdata);
747 }
748
749 int idev_keyboard_new(idev_device **out, idev_session *s, const char *name) {
750         _cleanup_(idev_device_freep) idev_device *d = NULL;
751         idev_keyboard *k;
752         char *kname;
753         int r;
754
755         assert_return(out, -EINVAL);
756         assert_return(s, -EINVAL);
757         assert_return(name, -EINVAL);
758
759         k = new0(idev_keyboard, 1);
760         if (!k)
761                 return -ENOMEM;
762
763         d = &k->device;
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;
767
768         /* TODO: add key-repeat configuration */
769
770         r = get_kbdctx(s->context, &k->kbdctx);
771         if (r < 0)
772                 return r;
773
774         r = keyboard_update_kbdmap(k);
775         if (r < 0)
776                 return r;
777
778         r = keyboard_update_kbdtbl(k);
779         if (r < 0)
780                 return r;
781
782         r = keyboard_resize_bufs(k, 8);
783         if (r < 0)
784                 return r;
785
786         r = sd_event_add_time(s->context->event,
787                               &k->repeat_timer,
788                               CLOCK_MONOTONIC,
789                               0,
790                               10 * USEC_PER_MSEC,
791                               keyboard_repeat_timer_fn,
792                               k);
793         if (r < 0)
794                 return r;
795
796         r = sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
797         if (r < 0)
798                 return r;
799
800         kname = strappenda("keyboard/", name);
801         r = idev_device_add(d, kname);
802         if (r < 0)
803                 return r;
804
805         if (out)
806                 *out = d;
807         d = NULL;
808         return 0;
809 }
810
811 static void keyboard_free(idev_device *d) {
812         idev_keyboard *k = keyboard_from_device(d);
813
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);
825         free(k);
826 }
827
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;
833         int num;
834
835         if (n_syms == 1 && syms[0] < 128 && syms[0] > 0)
836                 return syms[0];
837
838         keymap = xkb_state_get_keymap(state);
839         n_lo = xkb_keymap_num_layouts_for_key(keymap, code + KBDXKB_SHIFT);
840
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)
845                         return s[0];
846         }
847
848         return -1;
849 }
850
851 static int keyboard_fill(idev_keyboard *k,
852                          idev_data *dst,
853                          bool resync,
854                          uint16_t code,
855                          uint32_t value,
856                          uint32_t n_syms,
857                          const uint32_t *keysyms) {
858         idev_data_keyboard *kev;
859         uint32_t i;
860         int r;
861
862         assert(dst == &k->evdata || dst == &k->repdata);
863
864         r = keyboard_resize_bufs(k, n_syms);
865         if (r < 0)
866                 return r;
867
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);
872         kev->value = value;
873         kev->keycode = code;
874         kev->mods = 0;
875         kev->consumed_mods = 0;
876         kev->n_syms = n_syms;
877         memcpy(kev->keysyms, keysyms, sizeof(*keysyms) * n_syms);
878
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;
883         }
884
885         for (i = 0; i < IDEV_KBDMOD_CNT; ++i) {
886                 if (k->kbdmap->modmap[i] == XKB_MOD_INVALID)
887                         continue;
888
889                 r = xkb_state_mod_index_is_active(k->xkb_state, k->kbdmap->modmap[i], XKB_STATE_MODS_EFFECTIVE);
890                 if (r > 0)
891                         kev->mods |= 1 << i;
892
893                 r = xkb_state_mod_index_is_consumed(k->xkb_state, code + KBDXKB_SHIFT, k->kbdmap->modmap[i]);
894                 if (r > 0)
895                         kev->consumed_mods |= 1 << i;
896         }
897
898         return 0;
899 }
900
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;
908         bool repeats;
909         int r, num;
910
911         if (evdata->resync) {
912                 /*
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.
917                  */
918
919                 k->repeating = false;
920                 keyboard_arm(k, 0);
921                 return;
922         }
923
924         repeats = xkb_keymap_key_repeats(k->kbdmap->xkb_keymap, evkbd->keycode + KBDXKB_SHIFT);
925
926         if (k->repeating && repkbd->keycode == evkbd->keycode) {
927                 /*
928                  * We received an event for the key we currently repeat. If it
929                  * was released, stop key-repeat. Otherwise, ignore the event.
930                  */
931
932                 if (evkbd->value == KBDKEY_UP) {
933                         k->repeating = false;
934                         keyboard_arm(k, 0);
935                 }
936         } else if (evkbd->value == KBDKEY_DOWN && repeats) {
937                 /*
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
941                  * new key-repeat.
942                  */
943
944                 errno = 0;
945                 num = xkb_state_key_get_syms(k->xkb_state, evkbd->keycode + KBDXKB_SHIFT, &keysyms);
946                 if (num < 0)
947                         r = errno > 0 ? errno : -EFAULT;
948                 else
949                         r = keyboard_fill(k, repdata, false, evkbd->keycode, KBDKEY_REPEAT, num, keysyms);
950
951                 if (r < 0) {
952                         log_debug_errno(r, "idev-keyboard: %s/%s: cannot set key-repeat: %m",
953                                         d->session->name, d->name);
954                         k->repeating = false;
955                         keyboard_arm(k, 0);
956                 } else {
957                         k->repeating = true;
958                         keyboard_arm(k, k->repeat_delay);
959                 }
960         } else if (k->repeating && !repeats) {
961                 /*
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.
967                  */
968
969                 errno = 0;
970                 num = xkb_state_key_get_syms(k->xkb_state, repkbd->keycode + KBDXKB_SHIFT, &keysyms);
971                 if (num < 0)
972                         r = errno > 0 ? errno : -EFAULT;
973                 else
974                         r = keyboard_fill(k, repdata, false, repkbd->keycode, KBDKEY_REPEAT, num, keysyms);
975
976                 if (r < 0) {
977                         log_debug_errno(r, "idev-keyboard: %s/%s: cannot update key-repeat: %m",
978                                         d->session->name, d->name);
979                         k->repeating = false;
980                         keyboard_arm(k, 0);
981                 }
982         }
983 }
984
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;
991         int num, r;
992
993         if (ev->type != EV_KEY || ev->value > KBDKEY_DOWN)
994                 return 0;
995
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
999          * suppressed. */
1000
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);
1003
1004         if (compch & XKB_STATE_LEDS) {
1005                 /* TODO: update LEDs */
1006         }
1007
1008         if (num < 0) {
1009                 r = num;
1010                 goto error;
1011         }
1012
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);
1017                 } else {
1018                         cstatus = XKB_COMPOSE_CANCELLED;
1019                 }
1020
1021                 switch (cstatus) {
1022                 case XKB_COMPOSE_NOTHING:
1023                         /* keep produced keysyms and forward unchanged */
1024                         break;
1025                 case XKB_COMPOSE_COMPOSING:
1026                         /* consumed by compose-state, drop keysym */
1027                         keysyms = NULL;
1028                         num = 0;
1029                         break;
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);
1034                         break;
1035                 case XKB_COMPOSE_CANCELLED:
1036                         /* canceled compose, reset, forward cancellation sym */
1037                         xkb_compose_state_reset(k->xkb_compose);
1038                         break;
1039                 }
1040         } else if (k->xkb_compose &&
1041                    num == 1 &&
1042                    keysyms[0] == XKB_KEY_Multi_key &&
1043                    !data->resync &&
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);
1051         }
1052
1053         if (ev->value == KBDKEY_UP) {
1054                 /* never produce keysyms for UP */
1055                 keysyms = NULL;
1056                 num = 0;
1057         }
1058
1059         r = keyboard_fill(k, &k->evdata, data->resync, ev->code, ev->value, num, keysyms);
1060         if (r < 0)
1061                 goto error;
1062
1063         keyboard_repeat(k);
1064         return keyboard_raise_data(k, &k->evdata);
1065
1066 error:
1067         log_debug_errno(r, "idev-keyboard: %s/%s: cannot handle event: %m",
1068                         d->session->name, d->name);
1069         k->repeating = false;
1070         keyboard_arm(k, 0);
1071         return 0;
1072 }
1073
1074 static int keyboard_feed(idev_device *d, idev_data *data) {
1075         idev_keyboard *k = keyboard_from_device(d);
1076
1077         switch (data->type) {
1078         case IDEV_DATA_RESYNC:
1079                 /*
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
1084                  * again.
1085                  */
1086
1087                 k->repeating = false;
1088                 keyboard_arm(k, 0);
1089                 return 0;
1090         case IDEV_DATA_EVDEV:
1091                 return keyboard_feed_evdev(k, data);
1092         default:
1093                 return 0;
1094         }
1095 }
1096
1097 static int keyboard_update_kbdmap(idev_keyboard *k) {
1098         idev_device *d = &k->device;
1099         struct xkb_state *state;
1100         kbdmap *km;
1101         int r;
1102
1103         assert(k);
1104
1105         km = k->kbdctx->kbdmap;
1106         if (km == k->kbdmap)
1107                 return 0;
1108
1109         errno = 0;
1110         state = xkb_state_new(km->xkb_keymap);
1111         if (!state) {
1112                 r = errno > 0 ? -errno : -EFAULT;
1113                 goto error;
1114         }
1115
1116         kbdmap_unref(k->kbdmap);
1117         k->kbdmap = kbdmap_ref(km);
1118         xkb_state_unref(k->xkb_state);
1119         k->xkb_state = state;
1120
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. */
1124
1125         return 0;
1126
1127 error:
1128         log_debug_errno(r, "idev-keyboard: %s/%s: cannot adopt new keymap: %m",
1129                         d->session->name, d->name);
1130         return r;
1131 }
1132
1133 static int keyboard_update_kbdtbl(idev_keyboard *k) {
1134         idev_device *d = &k->device;
1135         struct xkb_compose_state *compose = NULL;
1136         kbdtbl *kt;
1137         int r;
1138
1139         assert(k);
1140
1141         kt = k->kbdctx->kbdtbl;
1142         if (kt == k->kbdtbl)
1143                 return 0;
1144
1145         if (kt) {
1146                 errno = 0;
1147                 compose = xkb_compose_state_new(kt->xkb_compose_table, XKB_COMPOSE_STATE_NO_FLAGS);
1148                 if (!compose) {
1149                         r = errno > 0 ? -errno : -EFAULT;
1150                         goto error;
1151                 }
1152         }
1153
1154         kbdtbl_unref(k->kbdtbl);
1155         k->kbdtbl = kbdtbl_ref(kt);
1156         xkb_compose_state_unref(k->xkb_compose);
1157         k->xkb_compose = compose;
1158
1159         return 0;
1160
1161 error:
1162         return log_debug_errno(r, "idev-keyboard: %s/%s: cannot adopt new compose table: %m",
1163                                d->session->name, d->name);
1164 }
1165
1166 static const idev_device_vtable keyboard_vtable = {
1167         .free                   = keyboard_free,
1168         .feed                   = keyboard_feed,
1169 };