got rid of the confusing xkb keycode offset

pull/14/head
sezanzeb 4 years ago
parent d355806c5a
commit 8ac2092e74

@ -33,7 +33,7 @@ from evdev.ecodes import EV_KEY, EV_ABS
from keymapper.logger import logger
from keymapper.getdevices import get_devices
from keymapper.state import system_mapping, KEYCODE_OFFSET
from keymapper.state import system_mapping
from keymapper.dev.keycode_mapper import handle_keycode, \
should_map_event_as_btn
from keymapper.dev.ev_abs_mapper import ev_abs_mapper, JOYSTICK
@ -144,7 +144,7 @@ class KeycodeInjector:
needed = False
for (ev_type, keycode), _ in self.mapping:
# TODO test ev_type
if keycode - KEYCODE_OFFSET in capabilities.get(ev_type, []):
if keycode in capabilities.get(ev_type, []):
needed = True
break
@ -208,7 +208,7 @@ class KeycodeInjector:
keycode = system_mapping.get(character)
if keycode is not None:
capabilities[EV_KEY].append(keycode - KEYCODE_OFFSET)
capabilities[EV_KEY].append(keycode)
if abs_to_rel:
del capabilities[ecodes.EV_ABS]
@ -315,7 +315,7 @@ class KeycodeInjector:
'macro writes code:%s value:%d char:%s',
keycode, value, character
)
uinput.write(EV_KEY, keycode - KEYCODE_OFFSET, value)
uinput.write(EV_KEY, keycode, value)
uinput.syn()
async def _keycode_loop(self, device, uinput, abs_to_rel):
@ -340,8 +340,6 @@ class KeycodeInjector:
logger.debug('Parsing macros')
macros = {}
for (ev_type, keycode), output in self.mapping:
keycode -= KEYCODE_OFFSET
if '(' in output and ')' in output and len(output) >= 4:
# probably a macro
macros[keycode] = parse(
@ -355,7 +353,7 @@ class KeycodeInjector:
logger.error('Don\'t know what %s is', output)
continue
code_code_mapping[keycode] = target_keycode - KEYCODE_OFFSET
code_code_mapping[keycode] = target_keycode
logger.debug(
'Started injecting into %s, fd %s',

@ -27,7 +27,6 @@ import asyncio
import evdev
from keymapper.logger import logger
from keymapper.state import KEYCODE_OFFSET
from keymapper.dev.ev_abs_mapper import JOYSTICK
@ -60,8 +59,7 @@ def handle_keycode(code_code_mapping, macros, event, uinput):
Parameters
----------
code_code_mapping : dict
mapping of linux-keycode to linux-keycode. No need to substract
anything before writing to the device.
mapping of linux-keycode to linux-keycode.
macros : dict
mapping of linux-keycode to _Macro objects
"""
@ -72,10 +70,6 @@ def handle_keycode(code_code_mapping, macros, event, uinput):
input_keycode = event.code
input_type = event.type
# 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
@ -84,7 +78,7 @@ def handle_keycode(code_code_mapping, macros, event, uinput):
macro = macros[input_keycode]
logger.spam(
'got code:%s value:%s, maps to macro %s',
xkb_keycode,
input_keycode,
event.value,
macro.code
)
@ -96,15 +90,15 @@ def handle_keycode(code_code_mapping, macros, event, uinput):
target_type = evdev.events.EV_KEY
logger.spam(
'got code:%s value:%s event:%s, maps to EV_KEY:%s',
xkb_keycode,
input_keycode,
event.value,
evdev.ecodes.EV[event.type],
target_keycode + KEYCODE_OFFSET
target_keycode
)
else:
logger.spam(
'got unmapped code:%s value:%s',
xkb_keycode,
input_keycode,
event.value,
)
target_keycode = input_keycode

@ -30,7 +30,6 @@ import evdev
from keymapper.logger import logger
from keymapper.getdevices import get_devices, refresh_devices
from keymapper.state import KEYCODE_OFFSET
from keymapper.dev.keycode_mapper import should_map_event_as_btn
@ -114,11 +113,11 @@ class _KeycodeReader:
if should_map_event_as_btn(event.type, event.code):
logger.spam(
'got code:%s value:%s type:%s',
event.code + KEYCODE_OFFSET,
event.code,
event.value,
evdev.ecodes.EV[event.type]
)
self._pipe[1].send((event.type, event.code + KEYCODE_OFFSET))
self._pipe[1].send((event.type, event.code))
def _read_worker(self):
"""Process that reads keycodes and buffers them into a pipe."""

@ -63,15 +63,14 @@ class Mapping:
Everything will be mapped to EV_KEY.
new_keycode : int
The source keycode, what the mouse would report without any
modification. xkb keycode.
modification.
character : string or string[]
A single character known to xkb, Examples: KP_1, Shift_L, a, B.
Can also be an array, which is used for reading the xkbmap output
completely.
A single character known to xkb or linux.
Examples: KP_1, Shift_L, a, B, BTN_LEFT.
previous_keycode : int or None
If None, will not remove any previous mapping. If you recently
used 10 for new_keycode and want to overwrite that with 11,
provide 5 here. xkb keycode.
provide 5 here.
"""
try:
new_keycode = int(new_keycode)
@ -98,7 +97,6 @@ class Mapping:
Parameters
----------
keycode : int
the xkb keycode
ev_type : int
one of evdev.events
"""

@ -30,8 +30,8 @@ import evdev
from keymapper.mapping import Mapping
# offset between xkb and linux keycodes. linux keycodes are lower
KEYCODE_OFFSET = 8
# xkb uses keycodes that are 8 higher than those from evdev
XKB_KEYCODE_OFFSET = 8
def populate_system_mapping():
@ -42,10 +42,10 @@ def populate_system_mapping():
mappings = re.findall(r'(\d+) = (.+)\n', xmodmap)
for keycode, names in mappings:
for name in names.split():
mapping[name] = int(keycode)
mapping[name] = int(keycode) - XKB_KEYCODE_OFFSET
for name, ecode in evdev.ecodes.ecodes.items():
mapping[name] = ecode + KEYCODE_OFFSET
mapping[name] = ecode
return mapping

@ -149,8 +149,7 @@ class Event:
type : int
one of evdev.ecodes.EV_*
code : int
keyboard event code as known to linux. E.g. 2 for the '1' button,
which would be 10 in xkb
keyboard event code as known to linux. E.g. 2 for the '1' button
value : int
1 for down, 0 for up, 2 for hold
"""

@ -31,7 +31,7 @@ gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from keymapper.state import custom_mapping, system_mapping, \
clear_system_mapping, KEYCODE_OFFSET
clear_system_mapping
from keymapper.config import config
from keymapper.daemon import Daemon, get_dbus_interface, BUS_NAME
@ -97,7 +97,7 @@ class TestDaemon(unittest.TestCase):
config.set_autoload_preset('device 2', preset)
pending_events['device 2'] = [
Event(evdev.events.EV_KEY, keycode_from_1 - KEYCODE_OFFSET, 0),
Event(evdev.events.EV_KEY, keycode_from_1, 0),
]
self.daemon = Daemon()
@ -108,15 +108,15 @@ class TestDaemon(unittest.TestCase):
event = uinput_write_history_pipe[0].recv()
self.assertEqual(event.type, evdev.events.EV_KEY)
self.assertEqual(event.code, keycode_to_1 - KEYCODE_OFFSET)
self.assertEqual(event.code, keycode_to_1)
self.assertEqual(event.value, 0)
self.daemon.stop_injecting('device 2')
self.assertFalse(self.daemon.is_injecting('device 2'))
pending_events['device 2'] = [
Event(evdev.events.EV_KEY, keycode_from_2 - KEYCODE_OFFSET, 1),
Event(evdev.events.EV_KEY, keycode_from_2 - KEYCODE_OFFSET, 0),
Event(evdev.events.EV_KEY, keycode_from_2, 1),
Event(evdev.events.EV_KEY, keycode_from_2, 0),
]
time.sleep(0.2)
@ -126,12 +126,12 @@ class TestDaemon(unittest.TestCase):
event = uinput_write_history_pipe[0].recv()
self.assertEqual(event.type, evdev.events.EV_KEY)
self.assertEqual(event.code, keycode_to_2 - KEYCODE_OFFSET)
self.assertEqual(event.code, keycode_to_2)
self.assertEqual(event.value, 1)
event = uinput_write_history_pipe[0].recv()
self.assertEqual(event.type, evdev.events.EV_KEY)
self.assertEqual(event.code, keycode_to_2 - KEYCODE_OFFSET)
self.assertEqual(event.code, keycode_to_2)
self.assertEqual(event.value, 0)

@ -30,12 +30,12 @@ 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
clear_system_mapping
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, \
from tests.test import Event, pending_events, fixtures, \
clear_write_history, EVENT_READ_TIMEOUT, uinput_write_history_pipe, \
MAX_ABS
@ -81,7 +81,7 @@ class TestInjector(unittest.TestCase):
character='a'
)
maps_to = system_mapping['a'] - KEYCODE_OFFSET
maps_to = system_mapping['a']
self.injector = KeycodeInjector('foo', mapping)
fake_device = FakeDevice()
@ -302,14 +302,14 @@ class TestInjector(unittest.TestCase):
# keycode used in X and in the mappings
pending_events['device 2'] = [
# should execute a macro
Event(EV_KEY, 0, 1),
Event(EV_KEY, 0, 0),
Event(EV_KEY, 8, 1),
Event(EV_KEY, 8, 0),
# normal keystroke
Event(EV_KEY, 1, 1),
Event(EV_KEY, 1, 0),
Event(EV_KEY, 9, 1),
Event(EV_KEY, 9, 0),
# just pass those over without modifying
Event(EV_KEY, 2, 1),
Event(EV_KEY, 2, 0),
Event(EV_KEY, 10, 1),
Event(EV_KEY, 10, 0),
Event(3124, 3564, 6542),
]
@ -334,30 +334,30 @@ class TestInjector(unittest.TestCase):
# keystrokes are all over the place.
# just check if they are there and if so, remove them from the list.
ev_key = EV_KEY
self.assertIn((ev_key, code_q - KEYCODE_OFFSET, 1), history)
self.assertIn((ev_key, code_q - KEYCODE_OFFSET, 0), history)
self.assertIn((ev_key, code_w - KEYCODE_OFFSET, 1), history)
self.assertIn((ev_key, code_w - KEYCODE_OFFSET, 0), history)
index_q_1 = history.index((ev_key, code_q - KEYCODE_OFFSET, 1))
index_q_0 = history.index((ev_key, code_q - KEYCODE_OFFSET, 0))
index_w_1 = history.index((ev_key, code_w - KEYCODE_OFFSET, 1))
index_w_0 = history.index((ev_key, code_w - KEYCODE_OFFSET, 0))
self.assertIn((ev_key, code_q, 1), history)
self.assertIn((ev_key, code_q, 0), history)
self.assertIn((ev_key, code_w, 1), history)
self.assertIn((ev_key, code_w, 0), history)
index_q_1 = history.index((ev_key, code_q, 1))
index_q_0 = history.index((ev_key, code_q, 0))
index_w_1 = history.index((ev_key, code_w, 1))
index_w_0 = history.index((ev_key, code_w, 0))
self.assertGreater(index_q_0, index_q_1)
self.assertGreater(index_w_1, index_q_0)
self.assertGreater(index_w_0, index_w_1)
del history[index_q_1]
index_q_0 = history.index((ev_key, code_q - KEYCODE_OFFSET, 0))
index_q_0 = history.index((ev_key, code_q, 0))
del history[index_q_0]
index_w_1 = history.index((ev_key, code_w - KEYCODE_OFFSET, 1))
index_w_1 = history.index((ev_key, code_w, 1))
del history[index_w_1]
index_w_0 = history.index((ev_key, code_w - KEYCODE_OFFSET, 0))
index_w_0 = history.index((ev_key, code_w, 0))
del history[index_w_0]
# 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], (ev_key, input_b - KEYCODE_OFFSET, 1))
self.assertEqual(history[3], (ev_key, input_b - KEYCODE_OFFSET, 0))
self.assertEqual(history[0], (ev_key, code_a, 1))
self.assertEqual(history[1], (ev_key, code_a, 0))
self.assertEqual(history[2], (ev_key, input_b, 1))
self.assertEqual(history[3], (ev_key, input_b, 0))
self.assertEqual(history[4], (3124, 3564, 6542))

@ -36,7 +36,7 @@ gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from keymapper.state import custom_mapping, system_mapping, \
clear_system_mapping, KEYCODE_OFFSET
clear_system_mapping
from keymapper.paths import CONFIG, get_config_path
from keymapper.config import config
from keymapper.dev.reader import keycode_reader
@ -408,8 +408,8 @@ class TestIntegration(unittest.TestCase):
system_mapping['a'] = keycode_to
pending_events['device 2'] = [
Event(evdev.events.EV_KEY, keycode_from - KEYCODE_OFFSET, 1),
Event(evdev.events.EV_KEY, keycode_from - KEYCODE_OFFSET, 0)
Event(evdev.events.EV_KEY, keycode_from, 1),
Event(evdev.events.EV_KEY, keycode_from, 0)
]
custom_mapping.save('device 2', 'foo preset')
@ -428,12 +428,12 @@ class TestIntegration(unittest.TestCase):
event = uinput_write_history_pipe[0].recv()
self.assertEqual(event.type, evdev.events.EV_KEY)
self.assertEqual(event.code, keycode_to - KEYCODE_OFFSET)
self.assertEqual(event.code, keycode_to)
self.assertEqual(event.value, 1)
event = uinput_write_history_pipe[0].recv()
self.assertEqual(event.type, evdev.events.EV_KEY)
self.assertEqual(event.code, keycode_to - KEYCODE_OFFSET)
self.assertEqual(event.code, keycode_to)
self.assertEqual(event.value, 0)
def test_stop_injecting(self):
@ -446,7 +446,7 @@ class TestIntegration(unittest.TestCase):
# not all of those events should be processed, since that takes some
# time due to time.sleep in the fakes and the injection is stopped.
pending_events['device 2'] = [Event(1, keycode_from - KEYCODE_OFFSET, 1)] * 100
pending_events['device 2'] = [Event(1, keycode_from, 1)] * 100
custom_mapping.save('device 2', 'foo preset')

@ -35,10 +35,8 @@ class TestMapping(unittest.TestCase):
# not actually a mapping object, just a dict
mapping = populate_system_mapping()
self.assertGreater(len(mapping), 100)
# xkb keycode 10 is typically mapped to '1'
self.assertEqual(mapping['1'], 10)
# linux keycodes are properly increased to the xkb keycodes
self.assertEqual(mapping['KEY_1'], 10)
self.assertEqual(mapping['1'], 2)
self.assertEqual(mapping['KEY_1'], 2)
self.assertEqual(mapping['KEY_LEFTSHIFT'], mapping['Shift_L'])
def test_clone(self):

@ -25,7 +25,6 @@ from evdev.events import EV_KEY
import time
from keymapper.dev.reader import keycode_reader
from keymapper.state import KEYCODE_OFFSET
from tests.test import Event, pending_events, EVENT_READ_TIMEOUT
@ -58,7 +57,7 @@ class TestReader(unittest.TestCase):
keycode_reader._pipe[0].send((EV_KEY, 1234))
time.sleep(EVENT_READ_TIMEOUT * 5)
self.assertEqual(keycode_reader.read(), (EV_KEY, CODE_3 + KEYCODE_OFFSET))
self.assertEqual(keycode_reader.read(), (EV_KEY, CODE_3))
self.assertEqual(keycode_reader.read(), (None, None))
def test_wrong_device(self):
@ -106,7 +105,7 @@ class TestReader(unittest.TestCase):
keycode_reader.start_reading('device 1')
time.sleep(EVENT_READ_TIMEOUT * 5)
self.assertEqual(keycode_reader.read(), (EV_KEY, CODE_3 + KEYCODE_OFFSET))
self.assertEqual(keycode_reader.read(), (EV_KEY, CODE_3))
self.assertEqual(keycode_reader.read(), (None, None))

Loading…
Cancel
Save