|
|
|
@ -21,8 +21,10 @@
|
|
|
|
|
|
|
|
|
|
import unittest
|
|
|
|
|
import asyncio
|
|
|
|
|
import time
|
|
|
|
|
|
|
|
|
|
from evdev.ecodes import EV_KEY, EV_ABS, ABS_HAT0X, KEY_A, ABS_X, EV_REL, REL_X
|
|
|
|
|
from evdev.ecodes import EV_KEY, EV_ABS, ABS_HAT0X, ABS_HAT0Y, KEY_A, ABS_X, \
|
|
|
|
|
EV_REL, REL_X, BTN_TL
|
|
|
|
|
|
|
|
|
|
from keymapper.dev.keycode_mapper import should_map_event_as_btn, \
|
|
|
|
|
active_macros, handle_keycode
|
|
|
|
@ -30,14 +32,50 @@ from keymapper.state import system_mapping
|
|
|
|
|
from keymapper.dev.macros import parse
|
|
|
|
|
from keymapper.config import config
|
|
|
|
|
|
|
|
|
|
from tests.test import InputEvent
|
|
|
|
|
from tests.test import InputEvent, UInput, uinput_write_history, \
|
|
|
|
|
clear_write_history
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def wait(func, timeout=1.0):
|
|
|
|
|
"""Wait for func to return True."""
|
|
|
|
|
iterations = 0
|
|
|
|
|
sleepytime = 0.1
|
|
|
|
|
while not func():
|
|
|
|
|
time.sleep(sleepytime)
|
|
|
|
|
iterations += 1
|
|
|
|
|
if iterations * sleepytime > timeout:
|
|
|
|
|
raise Exception('Timeout')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def calculate_event_number(holdtime, before, after):
|
|
|
|
|
"""
|
|
|
|
|
Parameters
|
|
|
|
|
----------
|
|
|
|
|
holdtime : int
|
|
|
|
|
in ms, how long was the key held down
|
|
|
|
|
before : int
|
|
|
|
|
how many extra k() calls are executed before h()
|
|
|
|
|
after : int
|
|
|
|
|
how many extra k() calls are executed after h()
|
|
|
|
|
"""
|
|
|
|
|
keystroke_sleep = config.get('macros.keystroke_sleep_ms', 10)
|
|
|
|
|
# down and up: two sleeps per k
|
|
|
|
|
# one initial k(a):
|
|
|
|
|
events = before * 2
|
|
|
|
|
holdtime -= keystroke_sleep * 2
|
|
|
|
|
# hold events
|
|
|
|
|
events += (holdtime / (keystroke_sleep * 2)) * 2
|
|
|
|
|
# one trailing k(c)
|
|
|
|
|
events += after * 2
|
|
|
|
|
return events
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
def tearDown(self):
|
|
|
|
|
system_mapping.populate()
|
|
|
|
|
|
|
|
|
|
# make sure all macros are stopped by tests
|
|
|
|
|
for code in active_macros:
|
|
|
|
|
macro = active_macros[code]
|
|
|
|
|
for macro in active_macros.values():
|
|
|
|
|
if macro.holding:
|
|
|
|
|
macro.release_key()
|
|
|
|
|
self.assertFalse(macro.holding)
|
|
|
|
@ -47,7 +85,54 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
for key in keys:
|
|
|
|
|
del active_macros[key]
|
|
|
|
|
|
|
|
|
|
system_mapping.populate()
|
|
|
|
|
clear_write_history()
|
|
|
|
|
|
|
|
|
|
def test_d_pad(self):
|
|
|
|
|
ev_1 = (EV_ABS, ABS_HAT0X, 1)
|
|
|
|
|
ev_2 = (EV_ABS, ABS_HAT0X, -1)
|
|
|
|
|
ev_3 = (EV_ABS, ABS_HAT0X, 0)
|
|
|
|
|
|
|
|
|
|
ev_4 = (EV_ABS, ABS_HAT0Y, 1)
|
|
|
|
|
ev_5 = (EV_ABS, ABS_HAT0Y, -1)
|
|
|
|
|
ev_6 = (EV_ABS, ABS_HAT0Y, 0)
|
|
|
|
|
|
|
|
|
|
_key_to_code = {
|
|
|
|
|
ev_1: 51,
|
|
|
|
|
ev_2: 52,
|
|
|
|
|
ev_4: 54,
|
|
|
|
|
ev_5: 55,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uinput = UInput()
|
|
|
|
|
# a bunch of d-pad key down events at once
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_1), uinput)
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_4), uinput)
|
|
|
|
|
|
|
|
|
|
# release all of them
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_3), uinput)
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_6), uinput)
|
|
|
|
|
|
|
|
|
|
# repeat with other values
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_2), uinput)
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_5), uinput)
|
|
|
|
|
|
|
|
|
|
# release all of them again
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_3), uinput)
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_6), uinput)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(len(uinput_write_history), 8)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(uinput_write_history[0].t, (EV_KEY, 51, 1))
|
|
|
|
|
self.assertEqual(uinput_write_history[1].t, (EV_KEY, 54, 1))
|
|
|
|
|
|
|
|
|
|
self.assertEqual(uinput_write_history[2].t, (EV_KEY, 51, 0))
|
|
|
|
|
self.assertEqual(uinput_write_history[3].t, (EV_KEY, 54, 0))
|
|
|
|
|
|
|
|
|
|
self.assertEqual(uinput_write_history[4].t, (EV_KEY, 52, 1))
|
|
|
|
|
self.assertEqual(uinput_write_history[5].t, (EV_KEY, 55, 1))
|
|
|
|
|
|
|
|
|
|
self.assertEqual(uinput_write_history[6].t, (EV_KEY, 52, 0))
|
|
|
|
|
self.assertEqual(uinput_write_history[7].t, (EV_KEY, 55, 0))
|
|
|
|
|
|
|
|
|
|
def test_should_map_event_as_btn(self):
|
|
|
|
|
self.assertTrue(should_map_event_as_btn(EV_ABS, ABS_HAT0X))
|
|
|
|
@ -56,33 +141,20 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
self.assertFalse(should_map_event_as_btn(EV_REL, REL_X))
|
|
|
|
|
|
|
|
|
|
def test_handle_keycode(self):
|
|
|
|
|
_code_to_code = {
|
|
|
|
|
1: 101,
|
|
|
|
|
2: 102
|
|
|
|
|
_key_to_code = {
|
|
|
|
|
(EV_KEY, 1, 1): 101,
|
|
|
|
|
(EV_KEY, 2, 1): 102
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
history = []
|
|
|
|
|
|
|
|
|
|
class UInput:
|
|
|
|
|
def write(self, type, code, value):
|
|
|
|
|
history.append((type, code, value))
|
|
|
|
|
|
|
|
|
|
def capabilities(self, *args, **kwargs):
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
def syn(self):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
uinput = UInput()
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(EV_KEY, 1, 1), uinput)
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(EV_KEY, 3, 1), uinput)
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(EV_KEY, 2, 1), uinput)
|
|
|
|
|
|
|
|
|
|
handle_keycode(_code_to_code, {}, InputEvent(EV_KEY, 1, 1), uinput)
|
|
|
|
|
handle_keycode(_code_to_code, {}, InputEvent(EV_KEY, 3, 1), uinput)
|
|
|
|
|
handle_keycode(_code_to_code, {}, InputEvent(EV_KEY, 2, 1), uinput)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(len(history), 3)
|
|
|
|
|
self.assertEqual(history[0], (EV_KEY, 101, 1))
|
|
|
|
|
self.assertEqual(history[1], (EV_KEY, 3, 1))
|
|
|
|
|
self.assertEqual(history[2], (EV_KEY, 102, 1))
|
|
|
|
|
self.assertEqual(len(uinput_write_history), 3)
|
|
|
|
|
self.assertEqual(uinput_write_history[0].t, (EV_KEY, 101, 1))
|
|
|
|
|
self.assertEqual(uinput_write_history[1].t, (EV_KEY, 3, 1))
|
|
|
|
|
self.assertEqual(uinput_write_history[2].t, (EV_KEY, 102, 1))
|
|
|
|
|
|
|
|
|
|
def test_handle_keycode_macro(self):
|
|
|
|
|
history = []
|
|
|
|
@ -94,12 +166,12 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
system_mapping._set('b', code_b)
|
|
|
|
|
|
|
|
|
|
macro_mapping = {
|
|
|
|
|
1: parse('k(a)'),
|
|
|
|
|
2: parse('r(5, k(b))')
|
|
|
|
|
(EV_KEY, 1, 1): parse('k(a)'),
|
|
|
|
|
(EV_KEY, 2, 1): parse('r(5, k(b))')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_mapping[1].set_handler(lambda *args: history.append(args))
|
|
|
|
|
macro_mapping[2].set_handler(lambda *args: history.append(args))
|
|
|
|
|
macro_mapping[(EV_KEY, 1, 1)].set_handler(lambda *args: history.append(args))
|
|
|
|
|
macro_mapping[(EV_KEY, 2, 1)].set_handler(lambda *args: history.append(args))
|
|
|
|
|
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 1, 1), None)
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 2, 1), None)
|
|
|
|
@ -118,28 +190,6 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
self.assertIn((code_b, 1), history)
|
|
|
|
|
self.assertIn((code_b, 0), history)
|
|
|
|
|
|
|
|
|
|
def calculate_event_number(self, holdtime, before, after):
|
|
|
|
|
"""
|
|
|
|
|
Parameters
|
|
|
|
|
----------
|
|
|
|
|
holdtime : int
|
|
|
|
|
in ms, how long was the key held down
|
|
|
|
|
before : int
|
|
|
|
|
how many extra k() calls are executed before h()
|
|
|
|
|
after : int
|
|
|
|
|
how many extra k() calls are executed after h()
|
|
|
|
|
"""
|
|
|
|
|
keystroke_sleep = config.get('macros.keystroke_sleep_ms', 10)
|
|
|
|
|
# down and up: two sleeps per k
|
|
|
|
|
# one initial k(a):
|
|
|
|
|
events = before * 2
|
|
|
|
|
holdtime -= keystroke_sleep * 2
|
|
|
|
|
# hold events
|
|
|
|
|
events += (holdtime / (keystroke_sleep * 2)) * 2
|
|
|
|
|
# one trailing k(c)
|
|
|
|
|
events += after * 2
|
|
|
|
|
return events
|
|
|
|
|
|
|
|
|
|
def test_hold(self):
|
|
|
|
|
history = []
|
|
|
|
|
|
|
|
|
@ -152,13 +202,13 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
system_mapping._set('c', code_c)
|
|
|
|
|
|
|
|
|
|
macro_mapping = {
|
|
|
|
|
1: parse('k(a).h(k(b)).k(c)')
|
|
|
|
|
(EV_KEY, 1, 1): parse('k(a).h(k(b)).k(c)')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def handler(*args):
|
|
|
|
|
history.append(args)
|
|
|
|
|
|
|
|
|
|
macro_mapping[1].set_handler(handler)
|
|
|
|
|
macro_mapping[(EV_KEY, 1, 1)].set_handler(handler)
|
|
|
|
|
|
|
|
|
|
"""start macro"""
|
|
|
|
|
|
|
|
|
@ -171,8 +221,8 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
keystroke_sleep = config.get('macros.keystroke_sleep_ms', 10)
|
|
|
|
|
loop.run_until_complete(asyncio.sleep(sleeptime / 1000))
|
|
|
|
|
|
|
|
|
|
self.assertTrue(active_macros[1].holding)
|
|
|
|
|
self.assertTrue(active_macros[1].running)
|
|
|
|
|
self.assertTrue(active_macros[(EV_KEY, 1)].holding)
|
|
|
|
|
self.assertTrue(active_macros[(EV_KEY, 1)].running)
|
|
|
|
|
|
|
|
|
|
"""stop macro"""
|
|
|
|
|
|
|
|
|
@ -180,7 +230,7 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
loop.run_until_complete(asyncio.sleep(keystroke_sleep * 10 / 1000))
|
|
|
|
|
|
|
|
|
|
events = self.calculate_event_number(sleeptime, 1, 1)
|
|
|
|
|
events = calculate_event_number(sleeptime, 1, 1)
|
|
|
|
|
|
|
|
|
|
self.assertGreater(len(history), events * 0.9)
|
|
|
|
|
self.assertLess(len(history), events * 1.1)
|
|
|
|
@ -200,8 +250,8 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
count_after = len(history)
|
|
|
|
|
self.assertEqual(count_before, count_after)
|
|
|
|
|
|
|
|
|
|
self.assertFalse(active_macros[1].holding)
|
|
|
|
|
self.assertFalse(active_macros[1].running)
|
|
|
|
|
self.assertFalse(active_macros[(EV_KEY, 1)].holding)
|
|
|
|
|
self.assertFalse(active_macros[(EV_KEY, 1)].running)
|
|
|
|
|
|
|
|
|
|
def test_hold_2(self):
|
|
|
|
|
# test irregular input patterns
|
|
|
|
@ -216,9 +266,9 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
system_mapping._set('d', code_d)
|
|
|
|
|
|
|
|
|
|
macro_mapping = {
|
|
|
|
|
1: parse('h(k(b))'),
|
|
|
|
|
2: parse('k(c).r(1, r(1, r(1, h(k(a))))).k(d)'),
|
|
|
|
|
3: parse('h(k(b))')
|
|
|
|
|
(EV_KEY, 1, 1): parse('h(k(b))'),
|
|
|
|
|
(EV_KEY, 2, 1): parse('k(c).r(1, r(1, r(1, h(k(a))))).k(d)'),
|
|
|
|
|
(EV_KEY, 3, 1): parse('h(k(b))')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
history = []
|
|
|
|
@ -226,9 +276,9 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
def handler(*args):
|
|
|
|
|
history.append(args)
|
|
|
|
|
|
|
|
|
|
macro_mapping[1].set_handler(handler)
|
|
|
|
|
macro_mapping[2].set_handler(handler)
|
|
|
|
|
macro_mapping[3].set_handler(handler)
|
|
|
|
|
macro_mapping[(EV_KEY, 1, 1)].set_handler(handler)
|
|
|
|
|
macro_mapping[(EV_KEY, 2, 1)].set_handler(handler)
|
|
|
|
|
macro_mapping[(EV_KEY, 3, 1)].set_handler(handler)
|
|
|
|
|
|
|
|
|
|
"""start macro 2"""
|
|
|
|
|
|
|
|
|
@ -245,12 +295,12 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 1, 1), None)
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 3, 1), None)
|
|
|
|
|
loop.run_until_complete(asyncio.sleep(0.05))
|
|
|
|
|
self.assertTrue(active_macros[1].holding)
|
|
|
|
|
self.assertTrue(active_macros[1].running)
|
|
|
|
|
self.assertTrue(active_macros[2].holding)
|
|
|
|
|
self.assertTrue(active_macros[2].running)
|
|
|
|
|
self.assertTrue(active_macros[3].holding)
|
|
|
|
|
self.assertTrue(active_macros[3].running)
|
|
|
|
|
self.assertTrue(active_macros[(EV_KEY, 1)].holding)
|
|
|
|
|
self.assertTrue(active_macros[(EV_KEY, 1)].running)
|
|
|
|
|
self.assertTrue(active_macros[(EV_KEY, 2)].holding)
|
|
|
|
|
self.assertTrue(active_macros[(EV_KEY, 2)].running)
|
|
|
|
|
self.assertTrue(active_macros[(EV_KEY, 3)].holding)
|
|
|
|
|
self.assertTrue(active_macros[(EV_KEY, 3)].running)
|
|
|
|
|
|
|
|
|
|
# there should only be one code_c in the events, because no key
|
|
|
|
|
# up event was ever done so the hold just continued
|
|
|
|
@ -293,12 +343,12 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 1, 0), None)
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 3, 0), None)
|
|
|
|
|
loop.run_until_complete(asyncio.sleep(0.05))
|
|
|
|
|
self.assertFalse(active_macros[1].holding)
|
|
|
|
|
self.assertFalse(active_macros[1].running)
|
|
|
|
|
self.assertTrue(active_macros[2].holding)
|
|
|
|
|
self.assertTrue(active_macros[2].running)
|
|
|
|
|
self.assertFalse(active_macros[3].holding)
|
|
|
|
|
self.assertFalse(active_macros[3].running)
|
|
|
|
|
self.assertFalse(active_macros[(EV_KEY, 1)].holding)
|
|
|
|
|
self.assertFalse(active_macros[(EV_KEY, 1)].running)
|
|
|
|
|
self.assertTrue(active_macros[(EV_KEY, 2)].holding)
|
|
|
|
|
self.assertTrue(active_macros[(EV_KEY, 2)].running)
|
|
|
|
|
self.assertFalse(active_macros[(EV_KEY, 3)].holding)
|
|
|
|
|
self.assertFalse(active_macros[(EV_KEY, 3)].running)
|
|
|
|
|
|
|
|
|
|
# stop macro 2
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 2, 0), None)
|
|
|
|
@ -321,12 +371,12 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
count_after = len(history)
|
|
|
|
|
self.assertEqual(count_before, count_after)
|
|
|
|
|
|
|
|
|
|
self.assertFalse(active_macros[1].holding)
|
|
|
|
|
self.assertFalse(active_macros[1].running)
|
|
|
|
|
self.assertFalse(active_macros[2].holding)
|
|
|
|
|
self.assertFalse(active_macros[2].running)
|
|
|
|
|
self.assertFalse(active_macros[3].holding)
|
|
|
|
|
self.assertFalse(active_macros[3].running)
|
|
|
|
|
self.assertFalse(active_macros[(EV_KEY, 1)].holding)
|
|
|
|
|
self.assertFalse(active_macros[(EV_KEY, 1)].running)
|
|
|
|
|
self.assertFalse(active_macros[(EV_KEY, 2)].holding)
|
|
|
|
|
self.assertFalse(active_macros[(EV_KEY, 2)].running)
|
|
|
|
|
self.assertFalse(active_macros[(EV_KEY, 3)].holding)
|
|
|
|
|
self.assertFalse(active_macros[(EV_KEY, 3)].running)
|
|
|
|
|
|
|
|
|
|
def test_hold_3(self):
|
|
|
|
|
# test irregular input patterns
|
|
|
|
@ -339,7 +389,7 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
system_mapping._set('c', code_c)
|
|
|
|
|
|
|
|
|
|
macro_mapping = {
|
|
|
|
|
1: parse('k(a).h(k(b)).k(c)'),
|
|
|
|
|
(EV_KEY, 1, 1): parse('k(a).h(k(b)).k(c)'),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
history = []
|
|
|
|
@ -347,15 +397,15 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
def handler(*args):
|
|
|
|
|
history.append(args)
|
|
|
|
|
|
|
|
|
|
macro_mapping[1].set_handler(handler)
|
|
|
|
|
macro_mapping[(EV_KEY, 1, 1)].set_handler(handler)
|
|
|
|
|
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 1, 1), None)
|
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
|
|
|
|
|
|
loop.run_until_complete(asyncio.sleep(0.1))
|
|
|
|
|
for _ in range(5):
|
|
|
|
|
self.assertTrue(active_macros[1].holding)
|
|
|
|
|
self.assertTrue(active_macros[1].running)
|
|
|
|
|
self.assertTrue(active_macros[(EV_KEY, 1)].holding)
|
|
|
|
|
self.assertTrue(active_macros[(EV_KEY, 1)].running)
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 1, 1), None)
|
|
|
|
|
loop.run_until_complete(asyncio.sleep(0.05))
|
|
|
|
|
|
|
|
|
@ -372,8 +422,8 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
self.assertEqual(history.count((code_a, 0)), 1)
|
|
|
|
|
self.assertEqual(history.count((code_c, 1)), 1)
|
|
|
|
|
self.assertEqual(history.count((code_c, 0)), 1)
|
|
|
|
|
self.assertFalse(active_macros[1].holding)
|
|
|
|
|
self.assertFalse(active_macros[1].running)
|
|
|
|
|
self.assertFalse(active_macros[(EV_KEY, 1)].holding)
|
|
|
|
|
self.assertFalse(active_macros[(EV_KEY, 1)].running)
|
|
|
|
|
|
|
|
|
|
# it's stopped and won't write stuff anymore
|
|
|
|
|
count_before = len(history)
|
|
|
|
@ -382,6 +432,7 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
self.assertEqual(count_before, count_after)
|
|
|
|
|
|
|
|
|
|
def test_hold_two(self):
|
|
|
|
|
# holding two macros at the same time
|
|
|
|
|
history = []
|
|
|
|
|
|
|
|
|
|
code_1 = 100
|
|
|
|
@ -398,29 +449,37 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
system_mapping._set('b', code_b)
|
|
|
|
|
system_mapping._set('c', code_c)
|
|
|
|
|
|
|
|
|
|
key_1 = (EV_KEY, 1)
|
|
|
|
|
key_2 = (EV_ABS, ABS_HAT0X)
|
|
|
|
|
down_1 = (*key_1, 1)
|
|
|
|
|
down_2 = (*key_2, -1)
|
|
|
|
|
up_1 = (*key_1, 0)
|
|
|
|
|
up_2 = (*key_2, 0)
|
|
|
|
|
|
|
|
|
|
macro_mapping = {
|
|
|
|
|
1: parse('k(1).h(k(2)).k(3)'),
|
|
|
|
|
2: parse('k(a).h(k(b)).k(c)')
|
|
|
|
|
down_1: parse('k(1).h(k(2)).k(3)'),
|
|
|
|
|
down_2: parse('k(a).h(k(b)).k(c)')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def handler(*args):
|
|
|
|
|
history.append(args)
|
|
|
|
|
|
|
|
|
|
macro_mapping[1].set_handler(handler)
|
|
|
|
|
macro_mapping[2].set_handler(handler)
|
|
|
|
|
macro_mapping[down_1].set_handler(handler)
|
|
|
|
|
macro_mapping[down_2].set_handler(handler)
|
|
|
|
|
|
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
|
|
|
|
|
|
# key up won't do anything
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 1, 0), None)
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 2, 0), None)
|
|
|
|
|
uinput = UInput()
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(*up_1), uinput)
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(*up_2), uinput)
|
|
|
|
|
loop.run_until_complete(asyncio.sleep(0.1))
|
|
|
|
|
self.assertEqual(len(active_macros), 0)
|
|
|
|
|
|
|
|
|
|
"""start macros"""
|
|
|
|
|
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 1, 1), None)
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 2, 1), None)
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(*down_1), None)
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(*down_2), None)
|
|
|
|
|
|
|
|
|
|
# let the mainloop run for some time so that the macro does its stuff
|
|
|
|
|
sleeptime = 500
|
|
|
|
@ -428,24 +487,24 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
loop.run_until_complete(asyncio.sleep(sleeptime / 1000))
|
|
|
|
|
|
|
|
|
|
self.assertEqual(len(active_macros), 2)
|
|
|
|
|
self.assertTrue(active_macros[1].holding)
|
|
|
|
|
self.assertTrue(active_macros[1].running)
|
|
|
|
|
self.assertTrue(active_macros[2].holding)
|
|
|
|
|
self.assertTrue(active_macros[2].running)
|
|
|
|
|
self.assertTrue(active_macros[key_1].holding)
|
|
|
|
|
self.assertTrue(active_macros[key_1].running)
|
|
|
|
|
self.assertTrue(active_macros[key_2].holding)
|
|
|
|
|
self.assertTrue(active_macros[key_2].running)
|
|
|
|
|
|
|
|
|
|
"""stop macros"""
|
|
|
|
|
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 1, 0), None)
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 2, 0), None)
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(*up_1), None)
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(*up_2), None)
|
|
|
|
|
|
|
|
|
|
loop.run_until_complete(asyncio.sleep(keystroke_sleep * 10 / 1000))
|
|
|
|
|
|
|
|
|
|
self.assertFalse(active_macros[1].holding)
|
|
|
|
|
self.assertFalse(active_macros[1].running)
|
|
|
|
|
self.assertFalse(active_macros[2].holding)
|
|
|
|
|
self.assertFalse(active_macros[2].running)
|
|
|
|
|
self.assertFalse(active_macros[key_1].holding)
|
|
|
|
|
self.assertFalse(active_macros[key_1].running)
|
|
|
|
|
self.assertFalse(active_macros[key_2].holding)
|
|
|
|
|
self.assertFalse(active_macros[key_2].running)
|
|
|
|
|
|
|
|
|
|
events = self.calculate_event_number(sleeptime, 1, 1) * 2
|
|
|
|
|
events = calculate_event_number(sleeptime, 1, 1) * 2
|
|
|
|
|
|
|
|
|
|
self.assertGreater(len(history), events * 0.9)
|
|
|
|
|
self.assertLess(len(history), events * 1.1)
|
|
|
|
@ -473,6 +532,132 @@ class TestKeycodeMapper(unittest.TestCase):
|
|
|
|
|
count_after = len(history)
|
|
|
|
|
self.assertEqual(count_before, count_after)
|
|
|
|
|
|
|
|
|
|
def test_two_d_pad_macros(self):
|
|
|
|
|
# executing two macros that stop automatically at the same time
|
|
|
|
|
|
|
|
|
|
code_1 = 61
|
|
|
|
|
code_2 = 62
|
|
|
|
|
system_mapping.clear()
|
|
|
|
|
system_mapping._set('1', code_1)
|
|
|
|
|
system_mapping._set('2', code_2)
|
|
|
|
|
|
|
|
|
|
# try two concurrent macros with D-Pad events because they are
|
|
|
|
|
# more difficult to manage, since their only difference is their
|
|
|
|
|
# value, and one of them is negative.
|
|
|
|
|
down_1 = (EV_ABS, ABS_HAT0X, 1)
|
|
|
|
|
down_2 = (EV_ABS, ABS_HAT0X, -1)
|
|
|
|
|
|
|
|
|
|
repeats = 10
|
|
|
|
|
|
|
|
|
|
macro_mapping = {
|
|
|
|
|
down_1: parse(f'r({repeats}, k(1))'),
|
|
|
|
|
down_2: parse(f'r({repeats}, k(2))')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
history = []
|
|
|
|
|
|
|
|
|
|
def handler(*args):
|
|
|
|
|
history.append(args)
|
|
|
|
|
|
|
|
|
|
macro_mapping[down_1].set_handler(handler)
|
|
|
|
|
macro_mapping[down_2].set_handler(handler)
|
|
|
|
|
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(*down_1), None)
|
|
|
|
|
handle_keycode({}, macro_mapping, InputEvent(*down_2), None)
|
|
|
|
|
|
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
|
sleeptime = config.get('macros.keystroke_sleep_ms') / 1000
|
|
|
|
|
loop.run_until_complete(asyncio.sleep(1.1 * repeats * 2 * sleeptime))
|
|
|
|
|
|
|
|
|
|
self.assertEqual(len(history), repeats * 4)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(history.count((code_1, 1)), 10)
|
|
|
|
|
self.assertEqual(history.count((code_1, 0)), 10)
|
|
|
|
|
self.assertEqual(history.count((code_2, 1)), 10)
|
|
|
|
|
self.assertEqual(history.count((code_2, 0)), 10)
|
|
|
|
|
|
|
|
|
|
def test_normalize(self):
|
|
|
|
|
# -1234 to -1, 5678 to 1, 0 to 0
|
|
|
|
|
|
|
|
|
|
key_1 = (EV_KEY, BTN_TL)
|
|
|
|
|
ev_1 = (*key_1, 5678)
|
|
|
|
|
ev_2 = (*key_1, 0)
|
|
|
|
|
|
|
|
|
|
# doesn't really matter if it makes sense, the A key reports
|
|
|
|
|
# negative values now.
|
|
|
|
|
key_2 = (EV_KEY, KEY_A)
|
|
|
|
|
ev_3 = (*key_2, -1234)
|
|
|
|
|
ev_4 = (*key_2, 0)
|
|
|
|
|
|
|
|
|
|
_key_to_code = {
|
|
|
|
|
(*key_1, 1): 41,
|
|
|
|
|
(*key_2, -1): 42
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uinput = UInput()
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_1), uinput)
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_2), uinput)
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_3), uinput)
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_4), uinput)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(len(uinput_write_history), 4)
|
|
|
|
|
self.assertEqual(uinput_write_history[0].t, (EV_KEY, 41, 1))
|
|
|
|
|
self.assertEqual(uinput_write_history[1].t, (EV_KEY, 41, 0))
|
|
|
|
|
self.assertEqual(uinput_write_history[2].t, (EV_KEY, 42, 1))
|
|
|
|
|
self.assertEqual(uinput_write_history[3].t, (EV_KEY, 42, 0))
|
|
|
|
|
|
|
|
|
|
def test_filter_trigger_spam(self):
|
|
|
|
|
trigger = (EV_KEY, BTN_TL)
|
|
|
|
|
|
|
|
|
|
_key_to_code = {
|
|
|
|
|
(*trigger, 1): 51,
|
|
|
|
|
(*trigger, -1): 52
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uinput = UInput()
|
|
|
|
|
|
|
|
|
|
"""positive"""
|
|
|
|
|
|
|
|
|
|
for i in range(1, 20):
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*trigger, i), uinput)
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*trigger, 0), uinput)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(len(uinput_write_history), 2)
|
|
|
|
|
|
|
|
|
|
"""negative"""
|
|
|
|
|
|
|
|
|
|
for i in range(1, 20):
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*trigger, -i), uinput)
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*trigger, 0), uinput)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(len(uinput_write_history), 4)
|
|
|
|
|
self.assertEqual(uinput_write_history[0].t, (EV_KEY, 51, 1))
|
|
|
|
|
self.assertEqual(uinput_write_history[1].t, (EV_KEY, 51, 0))
|
|
|
|
|
self.assertEqual(uinput_write_history[2].t, (EV_KEY, 52, 1))
|
|
|
|
|
self.assertEqual(uinput_write_history[3].t, (EV_KEY, 52, 0))
|
|
|
|
|
|
|
|
|
|
def test_ignore_hold(self):
|
|
|
|
|
key = (EV_KEY, KEY_A)
|
|
|
|
|
ev_1 = (*key, 1)
|
|
|
|
|
ev_2 = (*key, 2)
|
|
|
|
|
ev_3 = (*key, 0)
|
|
|
|
|
|
|
|
|
|
_key_to_code = {
|
|
|
|
|
(*key, 1): 21,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uinput = UInput()
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_1), uinput)
|
|
|
|
|
for _ in range(10):
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_2), uinput)
|
|
|
|
|
handle_keycode(_key_to_code, {}, InputEvent(*ev_3), uinput)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(len(uinput_write_history), 2)
|
|
|
|
|
self.assertEqual(uinput_write_history[0].t, (EV_KEY, 21, 1))
|
|
|
|
|
self.assertEqual(uinput_write_history[1].t, (EV_KEY, 21, 0))
|
|
|
|
|
# linux will generate events with value 2 after key-mapper injected
|
|
|
|
|
# the key-press
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
unittest.main()
|
|
|
|
|