From b0deaaef1abe36d2c3ac2b2cc599541089d87c89 Mon Sep 17 00:00:00 2001 From: Chazzz <270857+Chazzz@users.noreply.github.com> Date: Wed, 2 Jan 2019 03:11:48 -0800 Subject: [PATCH] Added libinput compatibility --- libsuinput/src/suinput.c | 2 ++ src/__init__.py | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/libsuinput/src/suinput.c b/libsuinput/src/suinput.c index 8d5fb71..f1e0257 100644 --- a/libsuinput/src/suinput.c +++ b/libsuinput/src/suinput.c @@ -57,6 +57,7 @@ int suinput_emit_click(const int uinput_fd, const uint16_t key_code) { if (suinput_emit(uinput_fd, EV_KEY, key_code, 1) == -1) return -1; + suinput_syn(uinput_fd); //Required for mouse click to register correctly return suinput_emit(uinput_fd, EV_KEY, key_code, 0); } @@ -78,6 +79,7 @@ int suinput_emit_combo(const int uinput_fd, const uint16_t *const key_codes, combination is missing or broken. */ } } + suinput_syn(uinput_fd); //Required for mouse click to register correctly /* Try to release every pressed key, no matter what. */ while (i--) { diff --git a/src/__init__.py b/src/__init__.py index 396cf66..ee5b7f4 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -187,6 +187,7 @@ def __init__(self, events, name="python-uinput", user_dev.absflat[ev_code] = absflat _libsuinput.suinput_create(self.__uinput_fd, ctypes.pointer(user_dev)) + self.__emit_stack = [] def syn(self): """Fire all emitted events. @@ -201,8 +202,22 @@ def syn(self): d.emit(uinput.REL_Y, 1) The call above appears as a single (+1, +1) event. + + For some events (KEY_TYPE_BUTTON), the libinput driver + requires syn to be called between key-press and key-release + in order for the keypress to correctly register. + Consequently, syn is encoded into suinput_emit_click and + suinput_emit_combo, but this can cause events to fire early. + To minimize the consequences of this interaction, python-uinput + keeps its own stack of events which haven't been "fired" + and only fires them once self.syn() is called. """ + while len(self.__emit_stack) > 0: + emit_fun, args = self.__emit_stack.pop(0) + emit_fun(*args) + + _libsuinput.suinput_syn(self.__uinput_fd) def emit(self, event, value, syn=True): @@ -219,7 +234,7 @@ def emit(self, event, value, syn=True): """ ev_type, ev_code = event - _libsuinput.suinput_emit(self.__uinput_fd, ev_type, ev_code, value) + self.__emit_stack.append((_libsuinput.suinput_emit, (self.__uinput_fd, ev_type, ev_code, value))) if syn: self.syn() @@ -234,7 +249,7 @@ def emit_click(self, event, syn=True): ev_type, ev_code = event if ev_type != 0x01: raise ValueError("event must be of type KEY or BTN") - _libsuinput.suinput_emit_click(self.__uinput_fd, ev_code) + self.__emit_stack.append((_libsuinput.suinput_emit_click, (self.__uinput_fd, ev_code))) if syn: self.syn() @@ -252,7 +267,7 @@ def emit_combo(self, events, syn=True): raise ValueError("all events must be of type KEY or BTN") arrtype = ctypes.c_uint16 * len(events) - _libsuinput.suinput_emit_combo(self.__uinput_fd, arrtype(*ev_codes), len(events)) + self.__emit_stack.append((_libsuinput.suinput_emit_combo, (self.__uinput_fd, arrtype(*ev_codes), len(events)))) if syn: self.syn()