[RFC PATCH libinput 2/2] evdev: hook up keysym API
Peter Hutterer
peter.hutterer at who-t.net
Sun Dec 7 22:05:57 PST 2014
The kernel doesn't do real keysym handling through evdev, so this patch is a
basic proof-of-concept and incomplete.
It emulates a keysym-sending event by waiting for EV_KEY/KEY_MAX-1, then
waiting for the next EV_MSC/MSC_SCAN and parsing event->value as a 4-byte UTF8
sequence.
No checking is done for proper key releasing, etc.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
Cc: Samuel Thibault <samuel.thibault at ens-lyon.org>
---
src/evdev.c | 48 +++++++++++++++++++++++++++++
src/evdev.h | 5 +++
test/Makefile.am | 1 +
test/keyboard.c | 71 +++++++++++++++++++++++++++++++++++++++++++
test/litest-keyboard-string.c | 59 +++++++++++++++++++++++++++++++++++
test/litest.c | 2 ++
test/litest.h | 2 ++
7 files changed, 188 insertions(+)
create mode 100644 test/litest-keyboard-string.c
diff --git a/src/evdev.c b/src/evdev.c
index fbfbcd3..afc54ee 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -46,6 +46,7 @@
enum evdev_key_type {
EVDEV_KEY_TYPE_NONE,
EVDEV_KEY_TYPE_KEY,
+ EVDEV_KEY_TYPE_STRING,
EVDEV_KEY_TYPE_BUTTON,
};
@@ -365,6 +366,8 @@ get_key_type(uint16_t code)
if (code == BTN_TOUCH)
return EVDEV_KEY_TYPE_NONE;
+ if (code == KEY_MAX - 1)
+ return EVDEV_KEY_TYPE_STRING;
if (code >= KEY_ESC && code <= KEY_MICMUTE)
return EVDEV_KEY_TYPE_KEY;
if (code >= BTN_MISC && code <= BTN_GEAR_UP)
@@ -447,6 +450,7 @@ evdev_process_key(struct evdev_device *device,
if (e->value == 0) {
switch (type) {
case EVDEV_KEY_TYPE_NONE:
+ case EVDEV_KEY_TYPE_STRING:
break;
case EVDEV_KEY_TYPE_KEY:
case EVDEV_KEY_TYPE_BUTTON:
@@ -460,6 +464,11 @@ evdev_process_key(struct evdev_device *device,
switch (type) {
case EVDEV_KEY_TYPE_NONE:
break;
+ case EVDEV_KEY_TYPE_STRING:
+ device->string.pending = true;
+ device->string.state = e->value ? LIBINPUT_KEY_STATE_PRESSED :
+ LIBINPUT_KEY_STATE_RELEASED;
+ break;
case EVDEV_KEY_TYPE_KEY:
evdev_keyboard_notify_key(
device,
@@ -654,6 +663,36 @@ evdev_tag_trackpoint(struct evdev_device *device,
}
static void
+evdev_process_msc(struct evdev_device *device,
+ struct input_event *e, uint64_t time)
+{
+ char utf8[5];
+ char *string;
+
+ if (!device->string.pending)
+ return;
+
+ /* Until evdev has real keysym handling, simply interpret e->value
+ * as a four-byte string sequence */
+ utf8[0] = (e->value & 0xff000000) >> 24;
+ utf8[1] = (e->value & 0x00ff0000) >> 16;
+ utf8[2] = (e->value & 0x0000ff00) >> 8;
+ utf8[3] = (e->value & 0x000000ff);
+ utf8[4] = 0;
+
+ string = utf8;
+ while (*string == '\0' && string < &utf8[4])
+ string++;
+
+ keyboard_notify_string(&device->base,
+ time,
+ string,
+ device->string.state);
+
+ device->string.pending = false;
+}
+
+static void
fallback_process(struct evdev_dispatch *dispatch,
struct evdev_device *device,
struct input_event *event,
@@ -671,11 +710,16 @@ fallback_process(struct evdev_dispatch *dispatch,
case EV_KEY:
evdev_process_key(device, event, time);
break;
+ case EV_MSC:
+ evdev_process_msc(device, event, time);
+ break;
case EV_SYN:
need_frame = evdev_need_touch_frame(device);
evdev_flush_pending_event(device, time);
if (need_frame)
touch_notify_frame(&device->base, time);
+
+ device->string.pending = false;
break;
}
}
@@ -1406,6 +1450,7 @@ evdev_configure_device(struct evdev_device *device)
case EVDEV_KEY_TYPE_NONE:
break;
case EVDEV_KEY_TYPE_KEY:
+ case EVDEV_KEY_TYPE_STRING:
has_keyboard = 1;
break;
case EVDEV_KEY_TYPE_BUTTON:
@@ -1894,6 +1939,9 @@ release_pressed_keys(struct evdev_device *device)
switch (get_key_type(code)) {
case EVDEV_KEY_TYPE_NONE:
break;
+ case EVDEV_KEY_TYPE_STRING:
+ /* FIXME: */
+ break;
case EVDEV_KEY_TYPE_KEY:
evdev_keyboard_notify_key(
device,
diff --git a/src/evdev.h b/src/evdev.h
index 033d455..b9084f0 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -141,6 +141,11 @@ struct evdev_device {
uint8_t key_count[KEY_CNT];
struct {
+ bool pending;
+ enum libinput_key_state state;
+ } string;
+
+ struct {
struct libinput_device_config_left_handed config_left_handed;
/* left-handed currently enabled */
bool left_handed;
diff --git a/test/Makefile.am b/test/Makefile.am
index 2c36e3f..fda7538 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -17,6 +17,7 @@ liblitest_la_SOURCES = \
litest-bcm5974.c \
litest-generic-singletouch.c \
litest-keyboard.c \
+ litest-keyboard-string.c \
litest-mouse.c \
litest-ms-surface-cover.c \
litest-qemu-usb-tablet.c \
diff --git a/test/keyboard.c b/test/keyboard.c
index 4563ce6..573daf3 100644
--- a/test/keyboard.c
+++ b/test/keyboard.c
@@ -290,6 +290,75 @@ START_TEST(keyboard_key_auto_release)
}
END_TEST
+static void
+assert_string_event(struct libinput *li,
+ const char *string,
+ enum libinput_key_state state)
+{
+ struct libinput_event *event;
+ struct libinput_event_keyboard *kevent;
+
+ event = libinput_get_event(li);
+ ck_assert_int_eq(libinput_event_get_type(event),
+ LIBINPUT_EVENT_KEYBOARD_STRING);
+
+ kevent = libinput_event_get_keyboard_event(event);
+ ck_assert_int_eq(libinput_event_keyboard_get_key_state(kevent),
+ state);
+
+ ck_assert_str_eq(libinput_event_keyboard_get_string(kevent),
+ string);
+
+ libinput_event_destroy(event);
+}
+
+START_TEST(keyboard_string_events)
+{
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+
+ litest_drain_events(dev->libinput);
+
+ litest_event(dev, EV_KEY, KEY_MAX - 1, 1);
+ litest_event(dev, EV_MSC, MSC_SCAN, 'a');
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+
+ libinput_dispatch(li);
+ assert_string_event(li, "a", LIBINPUT_KEY_STATE_PRESSED);
+
+ litest_event(dev, EV_KEY, KEY_MAX - 1, 0);
+ litest_event(dev, EV_MSC, MSC_SCAN, 'a');
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+
+ libinput_dispatch(li);
+ assert_string_event(li, "a", LIBINPUT_KEY_STATE_RELEASED);
+
+ litest_event(dev, EV_KEY, KEY_MAX - 1, 1);
+ litest_event(dev, EV_MSC, MSC_SCAN, 'a' << 16 | 'b' << 8 | 'c');
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+
+ litest_event(dev, EV_KEY, KEY_MAX - 1, 0);
+ litest_event(dev, EV_MSC, MSC_SCAN, 'a' << 16| 'b' << 8 | 'c');
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+
+ libinput_dispatch(li);
+ assert_string_event(li, "abc", LIBINPUT_KEY_STATE_PRESSED);
+ assert_string_event(li, "abc", LIBINPUT_KEY_STATE_RELEASED);
+
+ litest_event(dev, EV_KEY, KEY_MAX - 1, 1);
+ litest_event(dev, EV_MSC, MSC_SCAN, 0xE282AC); /* euro sign */
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+
+ litest_event(dev, EV_KEY, KEY_MAX - 1, 0);
+ litest_event(dev, EV_MSC, MSC_SCAN, 0xE282AC); /* euro sign */
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+
+ libinput_dispatch(li);
+ assert_string_event(li, "€", LIBINPUT_KEY_STATE_PRESSED);
+ assert_string_event(li, "€", LIBINPUT_KEY_STATE_RELEASED);
+}
+END_TEST
+
int
main(int argc, char **argv)
{
@@ -297,5 +366,7 @@ main(int argc, char **argv)
litest_add_no_device("keyboard:key counting", keyboard_ignore_no_pressed_release);
litest_add_no_device("keyboard:key counting", keyboard_key_auto_release);
+ litest_add("keyboards:strings", keyboard_string_events, LITEST_STRINGS, LITEST_ANY);
+
return litest_run(argc, argv);
}
diff --git a/test/litest-keyboard-string.c b/test/litest-keyboard-string.c
new file mode 100644
index 0000000..8f85ffe
--- /dev/null
+++ b/test/litest-keyboard-string.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2014 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "litest.h"
+#include "litest-int.h"
+
+static void litest_keyboard_string_setup(void)
+{
+ struct litest_device *d = litest_create_device(LITEST_KEYBOARD_STRING);
+ litest_set_current_device(d);
+}
+
+static struct input_id input_id = {
+ .bustype = 0x11,
+ .vendor = 0x1,
+ .product = 0x1,
+};
+
+static int events[] = {
+ EV_KEY, KEY_MAX - 1,
+ EV_MSC, MSC_SCAN,
+ -1, -1,
+};
+
+struct litest_test_device litest_keyboard_string_device = {
+ .type = LITEST_KEYBOARD_STRING,
+ .features = LITEST_STRINGS,
+ .shortname = "default keyboard_string",
+ .setup = litest_keyboard_string_setup,
+ .interface = NULL,
+
+ .name = "Fake string keyboard",
+ .id = &input_id,
+ .events = events,
+ .absinfo = NULL,
+};
diff --git a/test/litest.c b/test/litest.c
index 2ab802b..c93f096 100644
--- a/test/litest.c
+++ b/test/litest.c
@@ -90,6 +90,7 @@ extern struct litest_test_device litest_generic_singletouch_device;
extern struct litest_test_device litest_qemu_tablet_device;
extern struct litest_test_device litest_xen_virtual_pointer_device;
extern struct litest_test_device litest_vmware_virtmouse_device;
+extern struct litest_test_device litest_keyboard_string_device;
struct litest_test_device* devices[] = {
&litest_synaptics_clickpad_device,
@@ -105,6 +106,7 @@ struct litest_test_device* devices[] = {
&litest_qemu_tablet_device,
&litest_xen_virtual_pointer_device,
&litest_vmware_virtmouse_device,
+ &litest_keyboard_string_device,
NULL,
};
diff --git a/test/litest.h b/test/litest.h
index 99c6ae3..1e68c85 100644
--- a/test/litest.h
+++ b/test/litest.h
@@ -49,6 +49,7 @@ enum litest_device_type {
LITEST_QEMU_TABLET = -13,
LITEST_XEN_VIRTUAL_POINTER = -14,
LITEST_VMWARE_VIRTMOUSE = -15,
+ LITEST_KEYBOARD_STRING = -16,
};
enum litest_device_feature {
@@ -68,6 +69,7 @@ enum litest_device_feature {
LITEST_POINTINGSTICK = 1 << 11,
LITEST_FAKE_MT = 1 << 12,
LITEST_ABSOLUTE = 1 << 13,
+ LITEST_STRINGS = 1 << 14,
};
struct litest_device {
--
2.1.0
More information about the wayland-devel
mailing list