chiark / gitweb /
util: rework strappenda(), and rename it strjoina()
[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         return log_debug_errno(r, "idev-keyboard: cannot send GetAll to locale1: %m");
449 }
450
451 static int kbdctx_locale_props_changed_fn(sd_bus *bus,
452                                           sd_bus_message *signal,
453                                           void *userdata,
454                                           sd_bus_error *ret_err) {
455         kbdctx *kc = userdata;
456         int r;
457
458         kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
459
460         /* skip interface name */
461         r = sd_bus_message_skip(signal, "s");
462         if (r < 0)
463                 goto error;
464
465         r = bus_message_map_properties_changed(bus, signal, kbdctx_locale_map, kc);
466         if (r < 0)
467                 goto error;
468
469         if (r > 0) {
470                 r = kbdctx_query_locale(kc);
471                 if (r < 0)
472                         return r;
473         }
474
475         kbdctx_refresh_keymap(kc);
476         return 0;
477
478 error:
479         return log_debug_errno(r, "idev-keyboard: cannot handle PropertiesChanged from locale1: %m");
480 }
481
482 static int kbdctx_setup_bus(kbdctx *kc) {
483         int r;
484
485         r = sd_bus_add_match(kc->context->sysbus,
486                              &kc->slot_locale_props_changed,
487                              "type='signal',"
488                              "sender='org.freedesktop.locale1',"
489                              "interface='org.freedesktop.DBus.Properties',"
490                              "member='PropertiesChanged',"
491                              "path='/org/freedesktop/locale1'",
492                              kbdctx_locale_props_changed_fn,
493                              kc);
494         if (r < 0)
495                 return log_debug_errno(r, "idev-keyboard: cannot setup locale1 link: %m");
496
497         return kbdctx_query_locale(kc);
498 }
499
500 static void kbdctx_log_fn(struct xkb_context *ctx, enum xkb_log_level lvl, const char *format, va_list args) {
501         char buf[LINE_MAX];
502         int sd_lvl;
503
504         if (lvl >= XKB_LOG_LEVEL_DEBUG)
505                 sd_lvl = LOG_DEBUG;
506         else if (lvl >= XKB_LOG_LEVEL_INFO)
507                 sd_lvl = LOG_INFO;
508         else if (lvl >= XKB_LOG_LEVEL_WARNING)
509                 sd_lvl = LOG_INFO; /* most XKB warnings really are informational */
510         else if (lvl >= XKB_LOG_LEVEL_ERROR)
511                 sd_lvl = LOG_ERR;
512         else if (lvl >= XKB_LOG_LEVEL_CRITICAL)
513                 sd_lvl = LOG_CRIT;
514         else
515                 sd_lvl = LOG_CRIT;
516
517         snprintf(buf, sizeof(buf), "idev-xkb: %s", format);
518         log_internalv(sd_lvl, 0, __FILE__, __LINE__, __func__, buf, args);
519 }
520
521 static kbdctx *kbdctx_ref(kbdctx *kc) {
522         assert_return(kc, NULL);
523         assert_return(kc->ref > 0, NULL);
524
525         ++kc->ref;
526         return kc;
527 }
528
529 static kbdctx *kbdctx_unref(kbdctx *kc) {
530         if (!kc)
531                 return NULL;
532
533         assert_return(kc->ref > 0, NULL);
534
535         if (--kc->ref > 0)
536                 return NULL;
537
538         free(kc->last_x11_options);
539         free(kc->last_x11_variant);
540         free(kc->last_x11_layout);
541         free(kc->last_x11_model);
542         free(kc->locale_x11_options);
543         free(kc->locale_x11_variant);
544         free(kc->locale_x11_layout);
545         free(kc->locale_x11_model);
546         free(kc->locale_lang);
547         kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all);
548         kc->slot_locale_props_changed = sd_bus_slot_unref(kc->slot_locale_props_changed);
549         kc->kbdtbl = kbdtbl_unref(kc->kbdtbl);
550         kc->kbdmap = kbdmap_unref(kc->kbdmap);
551         xkb_context_unref(kc->xkb_context);
552         hashmap_remove_value(kc->context->data_map, KBDCTX_KEY, kc);
553         free(kc);
554
555         return NULL;
556 }
557
558 DEFINE_TRIVIAL_CLEANUP_FUNC(kbdctx*, kbdctx_unref);
559
560 static int kbdctx_new(kbdctx **out, idev_context *c) {
561         _cleanup_(kbdctx_unrefp) kbdctx *kc = NULL;
562         int r;
563
564         assert_return(out, -EINVAL);
565         assert_return(c, -EINVAL);
566
567         kc = new0(kbdctx, 1);
568         if (!kc)
569                 return -ENOMEM;
570
571         kc->ref = 1;
572         kc->context = c;
573
574         errno = 0;
575         kc->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
576         if (!kc->xkb_context)
577                 return errno > 0 ? -errno : -EFAULT;
578
579         xkb_context_set_log_fn(kc->xkb_context, kbdctx_log_fn);
580         xkb_context_set_log_level(kc->xkb_context, XKB_LOG_LEVEL_DEBUG);
581
582         r = kbdctx_refresh_keymap(kc);
583         if (r < 0)
584                 return r;
585
586         r = kbdctx_refresh_compose_table(kc, NULL);
587         if (r < 0)
588                 return r;
589
590         if (c->sysbus) {
591                 r = kbdctx_setup_bus(kc);
592                 if (r < 0)
593                         return r;
594         }
595
596         r = hashmap_put(c->data_map, KBDCTX_KEY, kc);
597         if (r < 0)
598                 return r;
599
600         *out = kc;
601         kc = NULL;
602         return 0;
603 }
604
605 static int get_kbdctx(idev_context *c, kbdctx **out) {
606         kbdctx *kc;
607
608         assert_return(c, -EINVAL);
609         assert_return(out, -EINVAL);
610
611         kc = hashmap_get(c->data_map, KBDCTX_KEY);
612         if (kc) {
613                 *out = kbdctx_ref(kc);
614                 return 0;
615         }
616
617         return kbdctx_new(out, c);
618 }
619
620 /*
621  * Keyboard Devices
622  */
623
624 bool idev_is_keyboard(idev_device *d) {
625         return d && d->vtable == &keyboard_vtable;
626 }
627
628 idev_device *idev_find_keyboard(idev_session *s, const char *name) {
629         char *kname;
630
631         assert_return(s, NULL);
632         assert_return(name, NULL);
633
634         kname = strjoina("keyboard/", name);
635         return hashmap_get(s->device_map, kname);
636 }
637
638 static int keyboard_raise_data(idev_keyboard *k, idev_data *data) {
639         idev_device *d = &k->device;
640         int r;
641
642         r = idev_session_raise_device_data(d->session, d, data);
643         if (r < 0)
644                 log_debug_errno(r, "idev-keyboard: %s/%s: error while raising data event: %m",
645                                 d->session->name, d->name);
646
647         return r;
648 }
649
650 static int keyboard_resize_bufs(idev_keyboard *k, uint32_t n_syms) {
651         uint32_t *t;
652
653         if (n_syms <= k->n_syms)
654                 return 0;
655
656         t = realloc(k->compose_res, sizeof(*t) * n_syms);
657         if (!t)
658                 return -ENOMEM;
659         k->compose_res = t;
660
661         t = realloc(k->evdata.keyboard.keysyms, sizeof(*t) * n_syms);
662         if (!t)
663                 return -ENOMEM;
664         k->evdata.keyboard.keysyms = t;
665
666         t = realloc(k->evdata.keyboard.codepoints, sizeof(*t) * n_syms);
667         if (!t)
668                 return -ENOMEM;
669         k->evdata.keyboard.codepoints = t;
670
671         t = realloc(k->repdata.keyboard.keysyms, sizeof(*t) * n_syms);
672         if (!t)
673                 return -ENOMEM;
674         k->repdata.keyboard.keysyms = t;
675
676         t = realloc(k->repdata.keyboard.codepoints, sizeof(*t) * n_syms);
677         if (!t)
678                 return -ENOMEM;
679         k->repdata.keyboard.codepoints = t;
680
681         k->n_syms = n_syms;
682         return 0;
683 }
684
685 static unsigned int keyboard_read_compose(idev_keyboard *k, const xkb_keysym_t **out) {
686         _cleanup_free_ char *t = NULL;
687         term_utf8 u8 = { };
688         char buf[256], *p;
689         size_t flen = 0;
690         int i, r;
691
692         r = xkb_compose_state_get_utf8(k->xkb_compose, buf, sizeof(buf));
693         if (r >= (int)sizeof(buf)) {
694                 t = malloc(r + 1);
695                 if (!t)
696                         return 0;
697
698                 xkb_compose_state_get_utf8(k->xkb_compose, t, r + 1);
699                 p = t;
700         } else {
701                 p = buf;
702         }
703
704         for (i = 0; i < r; ++i) {
705                 uint32_t *ucs;
706                 size_t len, j;
707
708                 len = term_utf8_decode(&u8, &ucs, p[i]);
709                 if (len > 0) {
710                         r = keyboard_resize_bufs(k, flen + len);
711                         if (r < 0)
712                                 return 0;
713
714                         for (j = 0; j < len; ++j)
715                                 k->compose_res[flen++] = ucs[j];
716                 }
717         }
718
719         *out = k->compose_res;
720         return flen;
721 }
722
723 static void keyboard_arm(idev_keyboard *k, usec_t usecs) {
724         int r;
725
726         if (usecs != 0) {
727                 usecs += now(CLOCK_MONOTONIC);
728                 r = sd_event_source_set_time(k->repeat_timer, usecs);
729                 if (r >= 0)
730                         sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_ONESHOT);
731         } else {
732                 sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
733         }
734 }
735
736 static int keyboard_repeat_timer_fn(sd_event_source *source, uint64_t usec, void *userdata) {
737         idev_keyboard *k = userdata;
738
739         /* never feed REPEAT keys into COMPOSE */
740
741         keyboard_arm(k, k->repeat_rate);
742         return keyboard_raise_data(k, &k->repdata);
743 }
744
745 int idev_keyboard_new(idev_device **out, idev_session *s, const char *name) {
746         _cleanup_(idev_device_freep) idev_device *d = NULL;
747         idev_keyboard *k;
748         char *kname;
749         int r;
750
751         assert_return(out, -EINVAL);
752         assert_return(s, -EINVAL);
753         assert_return(name, -EINVAL);
754
755         k = new0(idev_keyboard, 1);
756         if (!k)
757                 return -ENOMEM;
758
759         d = &k->device;
760         k->device = IDEV_DEVICE_INIT(&keyboard_vtable, s);
761         k->repeat_delay = 250 * USEC_PER_MSEC;
762         k->repeat_rate = 30 * USEC_PER_MSEC;
763
764         /* TODO: add key-repeat configuration */
765
766         r = get_kbdctx(s->context, &k->kbdctx);
767         if (r < 0)
768                 return r;
769
770         r = keyboard_update_kbdmap(k);
771         if (r < 0)
772                 return r;
773
774         r = keyboard_update_kbdtbl(k);
775         if (r < 0)
776                 return r;
777
778         r = keyboard_resize_bufs(k, 8);
779         if (r < 0)
780                 return r;
781
782         r = sd_event_add_time(s->context->event,
783                               &k->repeat_timer,
784                               CLOCK_MONOTONIC,
785                               0,
786                               10 * USEC_PER_MSEC,
787                               keyboard_repeat_timer_fn,
788                               k);
789         if (r < 0)
790                 return r;
791
792         r = sd_event_source_set_enabled(k->repeat_timer, SD_EVENT_OFF);
793         if (r < 0)
794                 return r;
795
796         kname = strjoina("keyboard/", name);
797         r = idev_device_add(d, kname);
798         if (r < 0)
799                 return r;
800
801         if (out)
802                 *out = d;
803         d = NULL;
804         return 0;
805 }
806
807 static void keyboard_free(idev_device *d) {
808         idev_keyboard *k = keyboard_from_device(d);
809
810         xkb_compose_state_unref(k->xkb_compose);
811         xkb_state_unref(k->xkb_state);
812         free(k->repdata.keyboard.codepoints);
813         free(k->repdata.keyboard.keysyms);
814         free(k->evdata.keyboard.codepoints);
815         free(k->evdata.keyboard.keysyms);
816         free(k->compose_res);
817         k->repeat_timer = sd_event_source_unref(k->repeat_timer);
818         k->kbdtbl = kbdtbl_unref(k->kbdtbl);
819         k->kbdmap = kbdmap_unref(k->kbdmap);
820         k->kbdctx = kbdctx_unref(k->kbdctx);
821         free(k);
822 }
823
824 static int8_t guess_ascii(struct xkb_state *state, uint32_t code, uint32_t n_syms, const uint32_t *syms) {
825         xkb_layout_index_t n_lo, lo;
826         xkb_level_index_t lv;
827         struct xkb_keymap *keymap;
828         const xkb_keysym_t *s;
829         int num;
830
831         if (n_syms == 1 && syms[0] < 128 && syms[0] > 0)
832                 return syms[0];
833
834         keymap = xkb_state_get_keymap(state);
835         n_lo = xkb_keymap_num_layouts_for_key(keymap, code + KBDXKB_SHIFT);
836
837         for (lo = 0; lo < n_lo; ++lo) {
838                 lv = xkb_state_key_get_level(state, code + KBDXKB_SHIFT, lo);
839                 num = xkb_keymap_key_get_syms_by_level(keymap, code + KBDXKB_SHIFT, lo, lv, &s);
840                 if (num == 1 && s[0] < 128 && s[0] > 0)
841                         return s[0];
842         }
843
844         return -1;
845 }
846
847 static int keyboard_fill(idev_keyboard *k,
848                          idev_data *dst,
849                          bool resync,
850                          uint16_t code,
851                          uint32_t value,
852                          uint32_t n_syms,
853                          const uint32_t *keysyms) {
854         idev_data_keyboard *kev;
855         uint32_t i;
856         int r;
857
858         assert(dst == &k->evdata || dst == &k->repdata);
859
860         r = keyboard_resize_bufs(k, n_syms);
861         if (r < 0)
862                 return r;
863
864         dst->type = IDEV_DATA_KEYBOARD;
865         dst->resync = resync;
866         kev = &dst->keyboard;
867         kev->ascii = guess_ascii(k->xkb_state, code, n_syms, keysyms);
868         kev->value = value;
869         kev->keycode = code;
870         kev->mods = 0;
871         kev->consumed_mods = 0;
872         kev->n_syms = n_syms;
873         memcpy(kev->keysyms, keysyms, sizeof(*keysyms) * n_syms);
874
875         for (i = 0; i < n_syms; ++i) {
876                 kev->codepoints[i] = xkb_keysym_to_utf32(keysyms[i]);
877                 if (!kev->codepoints[i])
878                         kev->codepoints[i] = 0xffffffffUL;
879         }
880
881         for (i = 0; i < IDEV_KBDMOD_CNT; ++i) {
882                 if (k->kbdmap->modmap[i] == XKB_MOD_INVALID)
883                         continue;
884
885                 r = xkb_state_mod_index_is_active(k->xkb_state, k->kbdmap->modmap[i], XKB_STATE_MODS_EFFECTIVE);
886                 if (r > 0)
887                         kev->mods |= 1 << i;
888
889                 r = xkb_state_mod_index_is_consumed(k->xkb_state, code + KBDXKB_SHIFT, k->kbdmap->modmap[i]);
890                 if (r > 0)
891                         kev->consumed_mods |= 1 << i;
892         }
893
894         return 0;
895 }
896
897 static void keyboard_repeat(idev_keyboard *k) {
898         idev_data *evdata = &k->evdata;
899         idev_data *repdata = &k->repdata;
900         idev_data_keyboard *evkbd = &evdata->keyboard;
901         idev_data_keyboard *repkbd = &repdata->keyboard;
902         const xkb_keysym_t *keysyms;
903         idev_device *d = &k->device;
904         bool repeats;
905         int r, num;
906
907         if (evdata->resync) {
908                 /*
909                  * We received a re-sync event. During re-sync, any number of
910                  * key-events may have been lost and sync-events may be
911                  * re-ordered. Always disable key-repeat for those events. Any
912                  * following event will trigger it again.
913                  */
914
915                 k->repeating = false;
916                 keyboard_arm(k, 0);
917                 return;
918         }
919
920         repeats = xkb_keymap_key_repeats(k->kbdmap->xkb_keymap, evkbd->keycode + KBDXKB_SHIFT);
921
922         if (k->repeating && repkbd->keycode == evkbd->keycode) {
923                 /*
924                  * We received an event for the key we currently repeat. If it
925                  * was released, stop key-repeat. Otherwise, ignore the event.
926                  */
927
928                 if (evkbd->value == KBDKEY_UP) {
929                         k->repeating = false;
930                         keyboard_arm(k, 0);
931                 }
932         } else if (evkbd->value == KBDKEY_DOWN && repeats) {
933                 /*
934                  * We received a key-down event for a key that repeats. The
935                  * previous condition caught keys we already repeat, so we know
936                  * this is a different key or no key-repeat is running. Start
937                  * new key-repeat.
938                  */
939
940                 errno = 0;
941                 num = xkb_state_key_get_syms(k->xkb_state, evkbd->keycode + KBDXKB_SHIFT, &keysyms);
942                 if (num < 0)
943                         r = errno > 0 ? errno : -EFAULT;
944                 else
945                         r = keyboard_fill(k, repdata, false, evkbd->keycode, KBDKEY_REPEAT, num, keysyms);
946
947                 if (r < 0) {
948                         log_debug_errno(r, "idev-keyboard: %s/%s: cannot set key-repeat: %m",
949                                         d->session->name, d->name);
950                         k->repeating = false;
951                         keyboard_arm(k, 0);
952                 } else {
953                         k->repeating = true;
954                         keyboard_arm(k, k->repeat_delay);
955                 }
956         } else if (k->repeating && !repeats) {
957                 /*
958                  * We received an event for a key that does not repeat, but we
959                  * currently repeat a previously received key. The new key is
960                  * usually a modifier, but might be any kind of key. In this
961                  * case, we continue repeating the old key, but update the
962                  * symbols according to the new state.
963                  */
964
965                 errno = 0;
966                 num = xkb_state_key_get_syms(k->xkb_state, repkbd->keycode + KBDXKB_SHIFT, &keysyms);
967                 if (num < 0)
968                         r = errno > 0 ? errno : -EFAULT;
969                 else
970                         r = keyboard_fill(k, repdata, false, repkbd->keycode, KBDKEY_REPEAT, num, keysyms);
971
972                 if (r < 0) {
973                         log_debug_errno(r, "idev-keyboard: %s/%s: cannot update key-repeat: %m",
974                                         d->session->name, d->name);
975                         k->repeating = false;
976                         keyboard_arm(k, 0);
977                 }
978         }
979 }
980
981 static int keyboard_feed_evdev(idev_keyboard *k, idev_data *data) {
982         struct input_event *ev = &data->evdev.event;
983         enum xkb_state_component compch;
984         enum xkb_compose_status cstatus;
985         const xkb_keysym_t *keysyms;
986         idev_device *d = &k->device;
987         int num, r;
988
989         if (ev->type != EV_KEY || ev->value > KBDKEY_DOWN)
990                 return 0;
991
992         /* TODO: We should audit xkb-actions, whether they need @resync as
993          * flag. Most actions should just be executed, however, there might
994          * be actions that depend on modifier-orders. Those should be
995          * suppressed. */
996
997         num = xkb_state_key_get_syms(k->xkb_state, ev->code + KBDXKB_SHIFT, &keysyms);
998         compch = xkb_state_update_key(k->xkb_state, ev->code + KBDXKB_SHIFT, ev->value);
999
1000         if (compch & XKB_STATE_LEDS) {
1001                 /* TODO: update LEDs */
1002         }
1003
1004         if (num < 0) {
1005                 r = num;
1006                 goto error;
1007         }
1008
1009         if (k->xkb_compose && ev->value == KBDKEY_DOWN) {
1010                 if (num == 1 && !data->resync) {
1011                         xkb_compose_state_feed(k->xkb_compose, keysyms[0]);
1012                         cstatus = xkb_compose_state_get_status(k->xkb_compose);
1013                 } else {
1014                         cstatus = XKB_COMPOSE_CANCELLED;
1015                 }
1016
1017                 switch (cstatus) {
1018                 case XKB_COMPOSE_NOTHING:
1019                         /* keep produced keysyms and forward unchanged */
1020                         break;
1021                 case XKB_COMPOSE_COMPOSING:
1022                         /* consumed by compose-state, drop keysym */
1023                         keysyms = NULL;
1024                         num = 0;
1025                         break;
1026                 case XKB_COMPOSE_COMPOSED:
1027                         /* compose-state produced sth, replace keysym */
1028                         num = keyboard_read_compose(k, &keysyms);
1029                         xkb_compose_state_reset(k->xkb_compose);
1030                         break;
1031                 case XKB_COMPOSE_CANCELLED:
1032                         /* canceled compose, reset, forward cancellation sym */
1033                         xkb_compose_state_reset(k->xkb_compose);
1034                         break;
1035                 }
1036         } else if (k->xkb_compose &&
1037                    num == 1 &&
1038                    keysyms[0] == XKB_KEY_Multi_key &&
1039                    !data->resync &&
1040                    ev->value == KBDKEY_UP) {
1041                 /* Reset compose state on Multi-Key UP events. This effectively
1042                  * requires you to hold the key during the whole sequence. I
1043                  * think it's pretty handy to avoid accidental
1044                  * Compose-sequences, but this may break Compose for disabled
1045                  * people. We really need to make this opional! (TODO) */
1046                 xkb_compose_state_reset(k->xkb_compose);
1047         }
1048
1049         if (ev->value == KBDKEY_UP) {
1050                 /* never produce keysyms for UP */
1051                 keysyms = NULL;
1052                 num = 0;
1053         }
1054
1055         r = keyboard_fill(k, &k->evdata, data->resync, ev->code, ev->value, num, keysyms);
1056         if (r < 0)
1057                 goto error;
1058
1059         keyboard_repeat(k);
1060         return keyboard_raise_data(k, &k->evdata);
1061
1062 error:
1063         log_debug_errno(r, "idev-keyboard: %s/%s: cannot handle event: %m",
1064                         d->session->name, d->name);
1065         k->repeating = false;
1066         keyboard_arm(k, 0);
1067         return 0;
1068 }
1069
1070 static int keyboard_feed(idev_device *d, idev_data *data) {
1071         idev_keyboard *k = keyboard_from_device(d);
1072
1073         switch (data->type) {
1074         case IDEV_DATA_RESYNC:
1075                 /*
1076                  * If the underlying device is re-synced, key-events might be
1077                  * sent re-ordered. Thus, we don't know which key was pressed
1078                  * last. Key-repeat might get confused, hence, disable it
1079                  * during re-syncs. The first following event will enable it
1080                  * again.
1081                  */
1082
1083                 k->repeating = false;
1084                 keyboard_arm(k, 0);
1085                 return 0;
1086         case IDEV_DATA_EVDEV:
1087                 return keyboard_feed_evdev(k, data);
1088         default:
1089                 return 0;
1090         }
1091 }
1092
1093 static int keyboard_update_kbdmap(idev_keyboard *k) {
1094         idev_device *d = &k->device;
1095         struct xkb_state *state;
1096         kbdmap *km;
1097         int r;
1098
1099         assert(k);
1100
1101         km = k->kbdctx->kbdmap;
1102         if (km == k->kbdmap)
1103                 return 0;
1104
1105         errno = 0;
1106         state = xkb_state_new(km->xkb_keymap);
1107         if (!state) {
1108                 r = errno > 0 ? -errno : -EFAULT;
1109                 goto error;
1110         }
1111
1112         kbdmap_unref(k->kbdmap);
1113         k->kbdmap = kbdmap_ref(km);
1114         xkb_state_unref(k->xkb_state);
1115         k->xkb_state = state;
1116
1117         /* TODO: On state-change, we should trigger a resync so the whole
1118          * event-state is flushed into the new xkb-state. libevdev currently
1119          * does not support that, though. */
1120
1121         return 0;
1122
1123 error:
1124         return log_debug_errno(r, "idev-keyboard: %s/%s: cannot adopt new keymap: %m",
1125                                d->session->name, d->name);
1126 }
1127
1128 static int keyboard_update_kbdtbl(idev_keyboard *k) {
1129         idev_device *d = &k->device;
1130         struct xkb_compose_state *compose = NULL;
1131         kbdtbl *kt;
1132         int r;
1133
1134         assert(k);
1135
1136         kt = k->kbdctx->kbdtbl;
1137         if (kt == k->kbdtbl)
1138                 return 0;
1139
1140         if (kt) {
1141                 errno = 0;
1142                 compose = xkb_compose_state_new(kt->xkb_compose_table, XKB_COMPOSE_STATE_NO_FLAGS);
1143                 if (!compose) {
1144                         r = errno > 0 ? -errno : -EFAULT;
1145                         goto error;
1146                 }
1147         }
1148
1149         kbdtbl_unref(k->kbdtbl);
1150         k->kbdtbl = kbdtbl_ref(kt);
1151         xkb_compose_state_unref(k->xkb_compose);
1152         k->xkb_compose = compose;
1153
1154         return 0;
1155
1156 error:
1157         return log_debug_errno(r, "idev-keyboard: %s/%s: cannot adopt new compose table: %m",
1158                                d->session->name, d->name);
1159 }
1160
1161 static const idev_device_vtable keyboard_vtable = {
1162         .free                   = keyboard_free,
1163         .feed                   = keyboard_feed,
1164 };