From e06cc7b07465369fb7c01c9778b84cf82c82fdcf Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 27 Aug 2014 18:34:55 +0200 Subject: terminal: add xkb-based keyboard devices to idev The idev-keyboard object provides keyboard devices to the idev interface. It uses libxkbcommon to provide proper keymap support. So far, the keyboard implementation is pretty straightforward with one keyboard device per matching evdev element. We feed everything into the system keymap and provide proper high-level keyboard events to the application. Compose-features and IM need to be added later. --- src/libsystemd-terminal/idev.c | 62 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) (limited to 'src/libsystemd-terminal/idev.c') diff --git a/src/libsystemd-terminal/idev.c b/src/libsystemd-terminal/idev.c index 2316a66529..0ed518cded 100644 --- a/src/libsystemd-terminal/idev.c +++ b/src/libsystemd-terminal/idev.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "hashmap.h" #include "idev.h" #include "idev-internal.h" @@ -525,10 +526,40 @@ void idev_session_disable(idev_session *s) { } } +static int add_link(idev_element *e, idev_device *d) { + idev_link *l; + + assert(e); + assert(d); + + l = new0(idev_link, 1); + if (!l) + return -ENOMEM; + + l->element = e; + l->device = d; + LIST_PREPEND(links_by_element, e->links, l); + LIST_PREPEND(links_by_device, d->links, l); + device_attach(d, l); + + return 0; +} + +static int guess_type(struct udev_device *d) { + const char *id_key; + + id_key = udev_device_get_property_value(d, "ID_INPUT_KEY"); + if (streq_ptr(id_key, "1")) + return IDEV_DEVICE_KEYBOARD; + + return IDEV_DEVICE_CNT; +} + int idev_session_add_evdev(idev_session *s, struct udev_device *ud) { idev_element *e; + idev_device *d; dev_t devnum; - int r; + int r, type; assert_return(s, -EINVAL); assert_return(ud, -EINVAL); @@ -549,7 +580,34 @@ int idev_session_add_evdev(idev_session *s, struct udev_device *ud) { if (r != 0) return r; - return 0; + type = guess_type(ud); + if (type < 0) + return type; + + switch (type) { + case IDEV_DEVICE_KEYBOARD: + d = idev_find_keyboard(s, e->name); + if (d) { + log_debug("idev: %s: keyboard for new evdev element '%s' already available", + s->name, e->name); + return 0; + } + + r = idev_keyboard_new(&d, s, e->name); + if (r < 0) + return r; + + r = add_link(e, d); + if (r < 0) { + idev_device_free(d); + return r; + } + + return session_add_device(s, d); + default: + /* unknown elements are silently ignored */ + return 0; + } } int idev_session_remove_evdev(idev_session *s, struct udev_device *ud) { -- cgit v1.2.3-54-g00ecf