fixed injection

pull/14/head
sezanzeb 4 years ago
parent cdbb3c8b39
commit 386879752b

@ -321,6 +321,8 @@ class KeycodeInjector:
logger.debug('Parsing macros')
macros = {}
for keycode, output in self.mapping:
keycode -= KEYCODE_OFFSET
if '(' in output and ')' in output and len(output) >= 4:
# probably a macro
macros[keycode] = parse(
@ -332,7 +334,9 @@ class KeycodeInjector:
target_keycode = system_mapping.get(output)
if target_keycode is None:
logger.error('Don\'t know what %s is', output)
return
continue
code_code_mapping[keycode] = target_keycode - KEYCODE_OFFSET
logger.debug(
'Started injecting into %s, fd %s',

@ -29,14 +29,31 @@ from keymapper.state import KEYCODE_OFFSET
def handle_keycode(code_code_mapping, macros, event, uinput):
"""Write the mapped keycode."""
"""Write the mapped keycode.
Parameters
----------
code_code_mapping : dict
mapping of linux-keycode to linux-keycode. No need to substract
anything before writing to the device.
macros : dict
mapping of linux-keycode to _Macro objects
"""
input_keycode = event.code
# for logging purposes. It should log the same keycode as xev and gtk,
# which is also displayed in the UI.
xkb_keycode = input_keycode + KEYCODE_OFFSET
if input_keycode in macros:
if event.value != 1:
# only key-down events trigger macros
return
macro = macros[input_keycode]
logger.spam(
'got code:%s value:%s, maps to macro %s',
event.code + KEYCODE_OFFSET,
xkb_keycode,
event.value,
macro.code
)
@ -47,11 +64,16 @@ def handle_keycode(code_code_mapping, macros, event, uinput):
target_keycode = code_code_mapping[input_keycode]
logger.spam(
'got code:%s value:%s, maps to code:%s',
event.code + KEYCODE_OFFSET,
xkb_keycode,
event.value,
target_keycode
target_keycode + KEYCODE_OFFSET
)
else:
logger.spam(
'got unmapped code:%s value:%s',
xkb_keycode,
event.value,
)
target_keycode = input_keycode
uinput.write(event.type, target_keycode, event.value)

@ -19,6 +19,7 @@
# along with key-mapper. If not, see <https://www.gnu.org/licenses/>.
import asyncio
import unittest
import time
@ -27,10 +28,12 @@ from evdev.ecodes import EV_REL, EV_KEY, EV_ABS
from keymapper.dev.injector import is_numlock_on, toggle_numlock,\
ensure_numlock, KeycodeInjector
from keymapper.dev.keycode_mapper import handle_keycode
from keymapper.state import custom_mapping, system_mapping, \
clear_system_mapping, KEYCODE_OFFSET
from keymapper.mapping import Mapping
from keymapper.config import config
from keymapper.dev.macros import parse
from tests.test import uinput_write_history, Event, pending_events, fixtures, \
clear_write_history, EVENT_READ_TIMEOUT, uinput_write_history_pipe, \
@ -219,11 +222,75 @@ class TestInjector(unittest.TestCase):
self.assertEqual(history[-2][1], rel_y)
self.assertAlmostEqual(history[-2][2], -1)
def test_handle_keycode(self):
code_code_mapping = {
1: 101,
2: 102
}
history = []
class UInput:
def write(self, type, code, value):
history.append((type, code, value))
def syn(self):
pass
uinput = UInput()
EV_KEY = evdev.ecodes.EV_KEY
handle_keycode(code_code_mapping, {}, Event(EV_KEY, 1, 1), uinput)
handle_keycode(code_code_mapping, {}, Event(EV_KEY, 3, 1), uinput)
handle_keycode(code_code_mapping, {}, Event(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))
def test_handle_keycode_macro(self):
history = []
macro_mapping = {
1: parse('k(a)', lambda *args: history.append(args)),
2: parse('r(5, k(b))', lambda *args: history.append(args))
}
code_a = 100
code_b = 101
system_mapping['a'] = code_a
system_mapping['b'] = code_b
clear_system_mapping()
EV_KEY = evdev.ecodes.EV_KEY
handle_keycode({}, macro_mapping, Event(EV_KEY, 1, 1), None)
handle_keycode({}, macro_mapping, Event(EV_KEY, 2, 1), None)
loop = asyncio.get_event_loop()
sleeptime = config.get('macros.keystroke_sleep_ms', 10) * 12
async def sleep():
await asyncio.sleep(sleeptime / 1000 + 0.1)
loop.run_until_complete(sleep())
# 6 keycodes written, with down and up events
self.assertEqual(len(history), 12)
self.assertIn(('a', 1), history)
self.assertIn(('a', 0), history)
self.assertIn(('b', 1), history)
self.assertIn(('b', 0), history)
def test_injector(self):
custom_mapping.change(8, 'k(KEY_Q).k(w)')
custom_mapping.change(9, 'a')
# one mapping that is unknown in the system_mapping on purpose
custom_mapping.change(10, 'b')
input_b = 10
custom_mapping.change(input_b, 'b')
clear_system_mapping()
code_a = 100
@ -242,10 +309,9 @@ class TestInjector(unittest.TestCase):
# normal keystroke
Event(EV_KEY, 1, 1),
Event(EV_KEY, 1, 0),
# ignored because unknown to the system
# just pass those over without modifying
Event(EV_KEY, 2, 1),
Event(EV_KEY, 2, 0),
# just pass those over without modifying
Event(3124, 3564, 6542),
]
@ -262,8 +328,9 @@ class TestInjector(unittest.TestCase):
history.append((event.type, event.code, event.value))
# 4 events for the macro
# 3 for non-macros
self.assertEqual(len(history), 7)
# 2 for mapped keys
# 3 for forwarded events
self.assertEqual(len(history), 9)
# since the macro takes a little bit of time to execute, its
# keystrokes are all over the place.
@ -291,7 +358,9 @@ class TestInjector(unittest.TestCase):
# the rest should be in order.
self.assertEqual(history[0], (ev_key, code_a - KEYCODE_OFFSET, 1))
self.assertEqual(history[1], (ev_key, code_a - KEYCODE_OFFSET, 0))
self.assertEqual(history[2], (3124, 3564, 6542))
self.assertEqual(history[2], (ev_key, input_b - KEYCODE_OFFSET, 1))
self.assertEqual(history[3], (ev_key, input_b - KEYCODE_OFFSET, 0))
self.assertEqual(history[4], (3124, 3564, 6542))
if __name__ == "__main__":

Loading…
Cancel
Save