diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2014-08-27 18:34:55 +0200 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2014-08-27 18:42:28 +0200 |
commit | e06cc7b07465369fb7c01c9778b84cf82c82fdcf (patch) | |
tree | 508f232b7efc0c022d8a2a2180155af302b53a52 /src/libsystemd-terminal/idev.c | |
parent | c93e5a62ff599528c3bf2a8656825403aaebe093 (diff) |
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.
Diffstat (limited to 'src/libsystemd-terminal/idev.c')
-rw-r--r-- | src/libsystemd-terminal/idev.c | 62 |
1 files changed, 60 insertions, 2 deletions
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 <systemd/sd-bus.h> #include <systemd/sd-event.h> #include <systemd/sd-login.h> +#include <xkbcommon/xkbcommon.h> #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) { |