Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libsuinput/src/suinput.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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--) {
Expand Down
21 changes: 18 additions & 3 deletions src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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):
Expand All @@ -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()

Expand All @@ -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()

Expand All @@ -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()

Expand Down