fixed bug for simultaneous injections, improved injection log

pull/14/head
sezanzeb 4 years ago
parent cb829befb2
commit 56b89451ee

@ -292,6 +292,13 @@ class KeycodeInjector:
Stuff is non-blocking by using asyncio in order to do multiple things Stuff is non-blocking by using asyncio in order to do multiple things
somewhat concurrently. somewhat concurrently.
""" """
# create a new event loop, because somehow running an infinite loop
# that sleeps on iterations (ev_abs_mapper) in one process causes
# another injection process to screw up reading from the grabbed
# device.
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
numlock_state = is_numlock_on() numlock_state = is_numlock_on()
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
@ -423,7 +430,6 @@ class KeycodeInjector:
# forward the rest # forward the rest
uinput.write(event.type, event.code, event.value) uinput.write(event.type, event.code, event.value)
# this already includes SYN events, so need to syn here again # this already includes SYN events, so need to syn here again
continue
logger.error( logger.error(
'The injector for "%s" stopped early', 'The injector for "%s" stopped early',

@ -135,6 +135,7 @@ def handle_keycode(key_to_code, macros, event, uinput):
# duplicate key-down. skip this event. Avoid writing millions of # duplicate key-down. skip this event. Avoid writing millions of
# key-down events when a continuous value is reported, for example # key-down events when a continuous value is reported, for example
# for gamepad triggers # for gamepad triggers
logger.spam('%s, duplicate key down', key)
return return
if is_key_up(event) and short in unreleased: if is_key_up(event) and short in unreleased:
@ -142,17 +143,18 @@ def handle_keycode(key_to_code, macros, event, uinput):
target_value = 0 target_value = 0
target_code = unreleased[short] target_code = unreleased[short]
del unreleased[short] del unreleased[short]
logger.spam('%s, releasing %s', key, target_code)
elif key in key_to_code and is_key_down(event): elif key in key_to_code and is_key_down(event):
target_type = EV_KEY target_type = EV_KEY
target_value = 1 target_value = 1
target_code = key_to_code[key] target_code = key_to_code[key]
unreleased[short] = target_code unreleased[short] = target_code
logger.spam('got %s, maps to EV_KEY:%s', key, target_code) logger.spam('%s, maps to %s', key, target_code)
else: else:
target_type = key[0] target_type = key[0]
target_code = key[1] target_code = key[1]
target_value = key[2] target_value = key[2]
logger.spam('got unmapped %s', key) logger.spam('%s, unmapped', key)
uinput.write(target_type, target_code, target_value) uinput.write(target_type, target_code, target_value)
uinput.syn() uinput.syn()

@ -131,14 +131,27 @@ class _KeycodeReader:
logger.debug('Pipe closed, reader stops.') logger.debug('Pipe closed, reader stops.')
sys.exit(0) sys.exit(0)
if should_map_event_as_btn(event.type, event.code): click_events = [
logger.spam( evdev.ecodes.BTN_LEFT,
'got (%s, %s, %s)', evdev.ecodes.BTN_TOOL_DOUBLETAP
event.type, ]
event.code,
event.value if event.type == EV_KEY and event.code in click_events:
) # disable mapping the left mouse button because it would break
self._pipe[1].send(event) # the mouse. Also it is emitted right when focusing the row
# which breaks the current workflow.
return
if not should_map_event_as_btn(event.type, event.code):
return
logger.spam(
'got (%s, %s, %s)',
event.type,
event.code,
event.value
)
self._pipe[1].send(event)
def _read_worker(self): def _read_worker(self):
"""Process that reads keycodes and buffers them into a pipe.""" """Process that reads keycodes and buffers them into a pipe."""

@ -323,17 +323,6 @@ class Window:
if key is None: if key is None:
return True return True
click_events = [
evdev.ecodes.BTN_LEFT,
evdev.ecodes.BTN_TOOL_DOUBLETAP
]
if key[0] == EV_KEY and key[1] in click_events:
# disable mapping the left mouse button because it would break
# the mouse. Also it is emitted right when focusing the row
# which breaks the current workflow.
return True
self.get('keycode').set_text(to_string(*key)) self.get('keycode').set_text(to_string(*key))
# inform the currently selected row about the new keycode # inform the currently selected row about the new keycode

@ -317,13 +317,6 @@ class TestIntegration(unittest.TestCase):
if key: if key:
# modifies the keycode in the row not by writing into the input, # modifies the keycode in the row not by writing into the input,
# but by sending an event # but by sending an event
# click events are ignored because it would render the mouse
# useless. It can still be changed in the config files.
keycode_reader._pipe[1].send(InputEvent(EV_KEY, BTN_LEFT, 1))
time.sleep(0.1)
gtk_iteration()
keycode_reader._pipe[1].send(InputEvent(*key)) keycode_reader._pipe[1].send(InputEvent(*key))
time.sleep(0.1) time.sleep(0.1)
gtk_iteration() gtk_iteration()

@ -81,14 +81,30 @@ class TestReader(unittest.TestCase):
self.assertEqual(keycode_reader.read(), (EV_ABS, ABS_HAT0X, 1)) self.assertEqual(keycode_reader.read(), (EV_ABS, ABS_HAT0X, 1))
self.assertEqual(keycode_reader.read(), None) self.assertEqual(keycode_reader.read(), None)
def test_ignore_btn_left(self):
# click events are ignored because overwriting them would render the
# mouse useless, but a mouse is needed to stop the injection
# comfortably. Furthermore, reading mouse events breaks clicking
# around in the table. It can still be changed in the config files.
pending_events['device 1'] = [
InputEvent(EV_KEY, BTN_LEFT, 1),
InputEvent(EV_KEY, CODE_2, 1),
InputEvent(EV_KEY, BTN_TOOL_DOUBLETAP, 1),
]
keycode_reader.start_reading('device 1')
time.sleep(0.1)
self.assertEqual(keycode_reader.read(), (EV_KEY, CODE_2, 1))
self.assertEqual(keycode_reader.read(), None)
def test_reading_ignore_up(self): def test_reading_ignore_up(self):
pending_events['device 1'] = [ pending_events['device 1'] = [
InputEvent(EV_KEY, CODE_1, 0, 10), InputEvent(EV_KEY, CODE_1, 0, 10),
InputEvent(EV_KEY, CODE_2, 0, 11), InputEvent(EV_KEY, CODE_2, 1, 11),
InputEvent(EV_KEY, CODE_3, 0, 12), InputEvent(EV_KEY, CODE_3, 0, 12),
] ]
keycode_reader.start_reading('device 1') keycode_reader.start_reading('device 1')
time.sleep(0.1) time.sleep(0.1)
self.assertEqual(keycode_reader.read(), (EV_KEY, CODE_2, 1))
self.assertEqual(keycode_reader.read(), None) self.assertEqual(keycode_reader.read(), None)
def test_wrong_device(self): def test_wrong_device(self):

Loading…
Cancel
Save