summaryrefslogtreecommitdiff
path: root/src/libsystemd-terminal/idev.c
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2014-08-27 18:34:55 +0200
committerDavid Herrmann <dh.herrmann@gmail.com>2014-08-27 18:42:28 +0200
commite06cc7b07465369fb7c01c9778b84cf82c82fdcf (patch)
tree508f232b7efc0c022d8a2a2180155af302b53a52 /src/libsystemd-terminal/idev.c
parentc93e5a62ff599528c3bf2a8656825403aaebe093 (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.c62
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) {