Ejemplo n.º 1
0
    def test_dont_filter_unmapped(self):
        # if an event is not used at all, it should be written but not
        # furthermore modified. For example wheel events
        # keep reporting events of the same value without a release inbetween,
        # they should be forwarded.

        down = (EV_KEY, 91, 1)
        up = (EV_KEY, 91, 0)
        uinput = UInput()
        forward_to = UInput()

        context = Context(self.mapping)
        context.uinput = uinput
        keycode_mapper = KeycodeMapper(context, self.source, forward_to)

        for _ in range(10):
            # don't filter duplicate events if not mapped
            keycode_mapper.handle_keycode(new_event(*down))

        self.assertEqual(unreleased[(EV_KEY, 91)].input_event_tuple, down)
        self.assertEqual(unreleased[(EV_KEY, 91)].target_type_code, down[:2])
        self.assertEqual(len(unreleased), 1)
        self.assertEqual(forward_to.write_count, 10)
        self.assertEqual(uinput.write_count, 0)

        keycode_mapper.handle_keycode(new_event(*up))
        self.assertEqual(len(unreleased), 0)
        self.assertEqual(forward_to.write_count, 11)
        self.assertEqual(uinput.write_count, 0)
Ejemplo n.º 2
0
    def test_handle_keycode(self):
        code_2 = 2
        # this also makes sure that the keycode_mapper doesn't get confused
        # when input and output codes are the same (because it at some point
        # screwed it up because of that)
        _key_to_code = {
            ((EV_KEY, 1, 1),): 101,
            ((EV_KEY, code_2, 1),): code_2
        }

        uinput_mapped = UInput()
        uinput_forwarded = UInput()

        context = Context(self.mapping)
        context.uinput = uinput_mapped
        context.key_to_code = _key_to_code
        keycode_mapper = KeycodeMapper(context, self.source, uinput_forwarded)

        keycode_mapper.handle_keycode(new_event(EV_KEY, 1, 1))
        keycode_mapper.handle_keycode(new_event(EV_KEY, 3, 1))
        keycode_mapper.handle_keycode(new_event(EV_KEY, code_2, 1))
        keycode_mapper.handle_keycode(new_event(EV_KEY, code_2, 0))

        self.assertEqual(len(uinput_write_history), 4)
        self.assertEqual(uinput_mapped.write_history[0].t, (EV_KEY, 101, 1))
        self.assertEqual(uinput_mapped.write_history[1].t, (EV_KEY, code_2, 1))
        self.assertEqual(uinput_mapped.write_history[2].t, (EV_KEY, code_2, 0))

        self.assertEqual(uinput_forwarded.write_history[0].t, (EV_KEY, 3, 1))
Ejemplo n.º 3
0
    def test_ignore_hold(self):
        # hold as in event-value 2, not in macro-hold.
        # linux will generate events with value 2 after key-mapper injected
        # the key-press, so key-mapper doesn't need to forward them. That
        # would cause duplicate events of those values otherwise.
        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()

        context = Context(self.mapping)
        context.uinput = uinput
        context.key_to_code = _key_to_code
        keycode_mapper = KeycodeMapper(context, self.source, uinput)

        keycode_mapper.handle_keycode(new_event(*ev_1))

        for _ in range(10):
            keycode_mapper.handle_keycode(new_event(*ev_2))

        self.assertIn(key, unreleased)
        keycode_mapper.handle_keycode(new_event(*ev_3))
        self.assertNotIn(key, unreleased)

        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))
Ejemplo n.º 4
0
    def test_filter_trigger_spam(self):
        # test_filter_duplicates
        trigger = (EV_KEY, BTN_TL)

        _key_to_code = {((*trigger, 1), ): 51, ((*trigger, -1), ): 52}

        uinput = UInput()
        """positive"""

        for _ in range(1, 20):
            handle_keycode(_key_to_code, {}, InputEvent(*trigger, 1), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*trigger, 0), uinput)

        self.assertEqual(len(uinput_write_history), 2)
        """negative"""

        for _ in range(1, 20):
            handle_keycode(_key_to_code, {}, InputEvent(*trigger, -1), 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))
Ejemplo n.º 5
0
    def test_combination_keycode(self):
        combination = ((EV_KEY, 1, 1), (EV_KEY, 2, 1))
        _key_to_code = {combination: 101}

        uinput = UInput()
        handle_keycode(_key_to_code, {}, InputEvent(*combination[0]), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*combination[1]), uinput)

        self.assertEqual(len(uinput_write_history), 2)
        # the first event is written and then the triggered combination
        self.assertEqual(uinput_write_history[0].t, (EV_KEY, 1, 1))
        self.assertEqual(uinput_write_history[1].t, (EV_KEY, 101, 1))

        # release them
        handle_keycode(_key_to_code, {}, InputEvent(*combination[0][:2], 0),
                       uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*combination[1][:2], 0),
                       uinput)
        # the first key writes its release event. The second key is hidden
        # behind the executed combination. The result of the combination is
        # also released, because it acts like a key.
        self.assertEqual(len(uinput_write_history), 4)
        self.assertEqual(uinput_write_history[2].t, (EV_KEY, 1, 0))
        self.assertEqual(uinput_write_history[3].t, (EV_KEY, 101, 0))

        # press them in the wrong order (the wrong key at the end, the order
        # of all other keys won't matter). no combination should be triggered
        handle_keycode(_key_to_code, {}, InputEvent(*combination[1]), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*combination[0]), uinput)
        self.assertEqual(len(uinput_write_history), 6)
        self.assertEqual(uinput_write_history[4].t, (EV_KEY, 2, 1))
        self.assertEqual(uinput_write_history[5].t, (EV_KEY, 1, 1))
Ejemplo n.º 6
0
    def test_d_pad_combination(self):
        ev_1 = (EV_ABS, ABS_HAT0X, 1)
        ev_2 = (EV_ABS, ABS_HAT0Y, -1)

        ev_3 = (EV_ABS, ABS_HAT0X, 0)
        ev_4 = (EV_ABS, ABS_HAT0Y, 0)

        _key_to_code = {
            (ev_1, ev_2): 51,
            (ev_2, ): 52,
        }

        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_2), uinput)
        # (what_will_be_released, what_caused_the_key_down)
        self.assertEqual(unreleased.get(ev_1[:2]), ((EV_ABS, ABS_HAT0X), ev_1))
        self.assertEqual(unreleased.get(ev_2[:2]), ((EV_KEY, 51), ev_2))
        self.assertEqual(len(unreleased), 2)

        # ev_1 is unmapped and the other is the triggered combination
        self.assertEqual(len(uinput_write_history), 2)
        self.assertEqual(uinput_write_history[0].t, ev_1)
        self.assertEqual(uinput_write_history[1].t, (EV_KEY, 51, 1))

        # release all of them
        handle_keycode(_key_to_code, {}, InputEvent(*ev_3), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*ev_4), uinput)
        self.assertEqual(len(unreleased), 0)

        self.assertEqual(len(uinput_write_history), 4)
        self.assertEqual(uinput_write_history[2].t, ev_3)
        self.assertEqual(uinput_write_history[3].t, (EV_KEY, 51, 0))
Ejemplo n.º 7
0
    def test_release_joystick_button(self):
        # with the left joystick mapped as button, it will release the mapped
        # key when it goes back to close to its resting position
        ev_1 = (3, 0, MAX_ABS // 10)  # release
        ev_3 = (3, 0, MIN_ABS)  # press

        uinput = UInput()

        _key_to_code = {
            ((3, 0, -1),): 73
        }

        self.mapping.set('gamepad.joystick.left_purpose', BUTTONS)

        # something with gamepad capabilities
        source = InputDevice('/dev/input/event30')

        context = Context(self.mapping)
        context.uinput = uinput
        context.key_to_code = _key_to_code
        keycode_mapper = KeycodeMapper(context, source, uinput)

        keycode_mapper.handle_keycode(new_event(*ev_3))
        keycode_mapper.handle_keycode(new_event(*ev_1))

        # array of 3-tuples
        history = [a.t for a in uinput_write_history]

        self.assertIn((EV_KEY, 73, 1), history)
        self.assertEqual(history.count((EV_KEY, 73, 1)), 1)

        self.assertIn((EV_KEY, 73, 0), history)
        self.assertEqual(history.count((EV_KEY, 73, 0)), 1)
Ejemplo n.º 8
0
    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)
        self.assertEqual(len(unreleased), 2)
        self.assertEqual(unreleased.get(ev_1[:2]),
                         ((EV_KEY, _key_to_code[(ev_1, )]), ev_1))
        self.assertEqual(unreleased.get(ev_4[:2]),
                         ((EV_KEY, _key_to_code[(ev_4, )]), ev_4))

        # release all of them
        handle_keycode(_key_to_code, {}, InputEvent(*ev_3), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*ev_6), uinput)
        self.assertEqual(len(unreleased), 0)

        # repeat with other values
        handle_keycode(_key_to_code, {}, InputEvent(*ev_2), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*ev_5), uinput)
        self.assertEqual(len(unreleased), 2)
        self.assertEqual(unreleased.get(ev_2[:2]),
                         ((EV_KEY, _key_to_code[(ev_2, )]), ev_2))
        self.assertEqual(unreleased.get(ev_5[:2]),
                         ((EV_KEY, _key_to_code[(ev_5, )]), ev_5))

        # 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(unreleased), 0)

        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))
Ejemplo n.º 9
0
    def test_handle_keycode(self):
        _key_to_code = {((EV_KEY, 1, 1), ): 101, ((EV_KEY, 2, 1), ): 102}

        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)

        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))
Ejemplo n.º 10
0
    def test_combination_keycode_2(self):
        combination_1 = ((EV_KEY, 1, 1), (EV_KEY, 2, 1), (EV_KEY, 3, 1),
                         (EV_KEY, 4, 1))
        combination_2 = (
            # should not be triggered, combination_1 should be prioritized
            # when all of its keys are down
            (EV_KEY, 2, 1),
            (EV_KEY, 3, 1),
            (EV_KEY, 4, 1))

        down_5 = (EV_KEY, 5, 1)
        up_5 = (EV_KEY, 5, 0)
        up_4 = (EV_KEY, 4, 0)

        _key_to_code = {
            combination_1: 101,
            combination_2: 102,
            (down_5, ): 103
        }

        uinput = UInput()
        # 10 and 11: more key-down events than needed
        handle_keycode(_key_to_code, {}, InputEvent(EV_KEY, 10, 1), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*combination_1[0]), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*combination_1[1]), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*combination_1[2]), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(EV_KEY, 11, 1), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*combination_1[3]), uinput)

        self.assertEqual(len(uinput_write_history), 6)
        # the first event is written and then the triggered combination
        self.assertEqual(uinput_write_history[1].t, (EV_KEY, 1, 1))
        self.assertEqual(uinput_write_history[2].t, (EV_KEY, 2, 1))
        self.assertEqual(uinput_write_history[3].t, (EV_KEY, 3, 1))
        self.assertEqual(uinput_write_history[5].t, (EV_KEY, 101, 1))

        # while the combination is down, another unrelated key can be used
        handle_keycode(_key_to_code, {}, InputEvent(*down_5), uinput)
        # the keycode_mapper searches for subsets of the current held-down
        # keys to activate combinations, down_5 should not trigger them
        # again.
        self.assertEqual(len(uinput_write_history), 7)
        self.assertEqual(uinput_write_history[6].t, (EV_KEY, 103, 1))

        # release the combination by releasing the last key, and release
        # the unrelated key
        handle_keycode(_key_to_code, {}, InputEvent(*up_4), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*up_5), uinput)
        self.assertEqual(len(uinput_write_history), 9)

        self.assertEqual(uinput_write_history[7].t, (EV_KEY, 101, 0))
        self.assertEqual(uinput_write_history[8].t, (EV_KEY, 103, 0))
Ejemplo n.º 11
0
    def setUp(self):
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)

        self.mapping = Mapping()

        device = InputDevice('/dev/input/event30')
        uinput = UInput()
        asyncio.ensure_future(
            ev_abs_mapper(abs_state, device, uinput, self.mapping))

        config.set('gamepad.joystick.x_scroll_speed', 1)
        config.set('gamepad.joystick.y_scroll_speed', 1)
Ejemplo n.º 12
0
    def test_macro_writes_to_context_uinput(self):
        macro_mapping = {
            ((EV_KEY, 1, 1),): parse('k(a)', self.mapping)
        }

        context = Context(self.mapping)
        context.macros = macro_mapping
        context.uinput = UInput()
        forward_to = UInput()
        keycode_mapper = KeycodeMapper(context, self.source, forward_to)

        keycode_mapper.handle_keycode(new_event(EV_KEY, 1, 1))

        loop = asyncio.get_event_loop()
        sleeptime = config.get('macros.keystroke_sleep_ms', 10) * 12
        loop.run_until_complete(asyncio.sleep(sleeptime / 1000 + 0.1))

        self.assertEqual(context.uinput.write_count, 2)  # down and up
        self.assertEqual(forward_to.write_count, 0)

        keycode_mapper.handle_keycode(new_event(EV_KEY, 2, 1))
        self.assertEqual(forward_to.write_count, 1)
Ejemplo n.º 13
0
    def setUp(self):
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)

        self.mapping = Mapping()
        self.context = Context(self.mapping)

        uinput = UInput()
        self.context.uinput = uinput

        device = InputDevice('/dev/input/event30')
        self.event_producer = EventProducer(self.context)
        self.event_producer.set_abs_range_from(device)
        asyncio.ensure_future(self.event_producer.run())

        config.set('gamepad.joystick.x_scroll_speed', 1)
        config.set('gamepad.joystick.y_scroll_speed', 1)
Ejemplo n.º 14
0
    def test_not_forward(self):
        down = (EV_KEY, 91, 1)
        up = (EV_KEY, 91, 0)
        uinput = UInput()

        context = Context(self.mapping)
        context.uinput = uinput
        keycode_mapper = KeycodeMapper(context, self.source, uinput)

        keycode_mapper.handle_keycode(new_event(*down), forward=False)
        self.assertEqual(unreleased[(EV_KEY, 91)].input_event_tuple, down)
        self.assertEqual(unreleased[(EV_KEY, 91)].target_type_code, down[:2])
        self.assertEqual(len(unreleased), 1)
        self.assertEqual(uinput.write_count, 0)

        keycode_mapper.handle_keycode(new_event(*up), forward=False)
        self.assertEqual(len(unreleased), 0)
        self.assertEqual(uinput.write_count, 0)
Ejemplo n.º 15
0
    def test_d_pad_combination(self):
        ev_1 = (EV_ABS, ABS_HAT0X, 1)
        ev_2 = (EV_ABS, ABS_HAT0Y, -1)

        ev_3 = (EV_ABS, ABS_HAT0X, 0)
        ev_4 = (EV_ABS, ABS_HAT0Y, 0)

        _key_to_code = {
            (ev_1, ev_2): 51,
            (ev_2,): 52,
        }

        uinput = UInput()

        context = Context(self.mapping)
        context.uinput = uinput
        context.key_to_code = _key_to_code
        keycode_mapper = KeycodeMapper(context, self.source, uinput)

        # a bunch of d-pad key down events at once
        keycode_mapper.handle_keycode(new_event(*ev_1))
        keycode_mapper.handle_keycode(new_event(*ev_2))
        # (what_will_be_released, what_caused_the_key_down)
        self.assertEqual(unreleased.get(ev_1[:2]).target_type_code, (EV_ABS, ABS_HAT0X))
        self.assertEqual(unreleased.get(ev_1[:2]).input_event_tuple, ev_1)
        self.assertEqual(unreleased.get(ev_2[:2]).target_type_code, (EV_KEY, 51))
        self.assertEqual(unreleased.get(ev_2[:2]).input_event_tuple, ev_2)
        self.assertEqual(len(unreleased), 2)

        # ev_1 is unmapped and the other is the triggered combination
        self.assertEqual(len(uinput_write_history), 2)
        self.assertEqual(uinput_write_history[0].t, ev_1)
        self.assertEqual(uinput_write_history[1].t, (EV_KEY, 51, 1))

        # release all of them
        keycode_mapper.handle_keycode(new_event(*ev_3))
        keycode_mapper.handle_keycode(new_event(*ev_4))
        self.assertEqual(len(unreleased), 0)

        self.assertEqual(len(uinput_write_history), 4)
        self.assertEqual(uinput_write_history[2].t, ev_3)
        self.assertEqual(uinput_write_history[3].t, (EV_KEY, 51, 0))
Ejemplo n.º 16
0
    def test_filter_trigger_spam(self):
        # test_filter_duplicates
        trigger = (EV_KEY, BTN_TL)

        _key_to_code = {
            ((*trigger, 1),): 51,
            ((*trigger, -1),): 52
        }

        uinput = UInput()

        context = Context(self.mapping)
        context.uinput = uinput
        context.key_to_code = _key_to_code
        keycode_mapper = KeycodeMapper(context, self.source, uinput)

        """positive"""

        for _ in range(1, 20):
            keycode_mapper.handle_keycode(new_event(*trigger, 1))
            self.assertIn(trigger, unreleased)

        keycode_mapper.handle_keycode(new_event(*trigger, 0))
        self.assertNotIn(trigger, unreleased)

        self.assertEqual(len(uinput_write_history), 2)

        """negative"""

        for _ in range(1, 20):
            keycode_mapper.handle_keycode(new_event(*trigger, -1))
            self.assertIn(trigger, unreleased)

        keycode_mapper.handle_keycode(new_event(*trigger, 0))
        self.assertNotIn(trigger, unreleased)

        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))
Ejemplo n.º 17
0
    def test_ignore_hold(self):
        # hold as in event-value 2, not in macro-hold.
        # linux will generate events with value 2 after key-mapper injected
        # the key-press, so key-mapper doesn't need to forward them.
        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))
Ejemplo n.º 18
0
    def test_filter_combi_mapped_duplicate_down(self):
        # the opposite of the other test, but don't map the key directly
        # but rather as the trigger for a combination
        down_1 = (EV_KEY, 91, 1)
        down_2 = (EV_KEY, 92, 1)
        up_1 = (EV_KEY, 91, 0)
        up_2 = (EV_KEY, 92, 0)
        uinput = UInput()

        output = 71

        key_to_code = {
            (down_1, down_2): 71
        }

        context = Context(self.mapping)
        context.uinput = uinput
        context.key_to_code = key_to_code
        keycode_mapper = KeycodeMapper(context, self.source, uinput)

        keycode_mapper.handle_keycode(new_event(*down_1))
        for _ in range(10):
            keycode_mapper.handle_keycode(new_event(*down_2))

        # all duplicate down events should have been ignored
        self.assertEqual(len(unreleased), 2)
        self.assertEqual(uinput.write_count, 2)
        self.assertEqual(uinput_write_history[0].t, down_1)
        self.assertEqual(uinput_write_history[1].t, (EV_KEY, output, 1))

        keycode_mapper.handle_keycode(new_event(*up_1))
        keycode_mapper.handle_keycode(new_event(*up_2))
        self.assertEqual(len(unreleased), 0)
        self.assertEqual(uinput.write_count, 4)
        self.assertEqual(uinput_write_history[2].t, up_1)
        self.assertEqual(uinput_write_history[3].t, (EV_KEY, output, 0))
Ejemplo n.º 19
0
    def test_combination_keycode_macro_mix(self):
        # ev_1 triggers macro, ev_1 + ev_2 triggers key while the macro is
        # still running
        system_mapping.clear()
        system_mapping._set('a', 92)

        down_1 = (EV_ABS, ABS_HAT1X, 1)
        down_2 = (EV_ABS, ABS_HAT1Y, -1)
        up_1 = (EV_ABS, ABS_HAT1X, 0)
        up_2 = (EV_ABS, ABS_HAT1Y, 0)

        macro_mapping = {(down_1,): parse('h(k(a))', self.mapping)}
        _key_to_code = {(down_1, down_2): 91}

        macro_history = []
        def handler(*args):
            # handler prevents uinput_write_history form growing
            macro_history.append(args)

        uinput = UInput()
        forward_to = UInput()

        loop = asyncio.get_event_loop()

        context = Context(self.mapping)
        context.uinput = uinput
        context.key_to_code = _key_to_code
        context.macros = macro_mapping
        keycode_mapper = KeycodeMapper(context, self.source, forward_to)

        keycode_mapper.macro_write = handler

        # macro starts
        keycode_mapper.handle_keycode(new_event(*down_1))
        loop.run_until_complete(asyncio.sleep(0.05))
        self.assertEqual(len(uinput_write_history), 0)
        self.assertGreater(len(macro_history), 1)
        self.assertIn(down_1[:2], unreleased)
        self.assertIn((EV_KEY, 92, 1), macro_history)

        # combination triggered
        keycode_mapper.handle_keycode(new_event(*down_2))
        self.assertIn(down_1[:2], unreleased)
        self.assertIn(down_2[:2], unreleased)
        self.assertEqual(uinput_write_history[0].t, (EV_KEY, 91, 1))

        len_a = len(macro_history)
        loop.run_until_complete(asyncio.sleep(0.05))
        len_b = len(macro_history)
        # still running
        self.assertGreater(len_b, len_a)

        # release
        keycode_mapper.handle_keycode(new_event(*up_1))
        self.assertNotIn(down_1[:2], unreleased)
        self.assertIn(down_2[:2], unreleased)
        loop.run_until_complete(asyncio.sleep(0.05))
        len_c = len(macro_history)
        loop.run_until_complete(asyncio.sleep(0.05))
        len_d = len(macro_history)
        # not running anymore
        self.assertEqual(len_c, len_d)

        keycode_mapper.handle_keycode(new_event(*up_2))
        self.assertEqual(uinput_write_history[1].t, (EV_KEY, 91, 0))
        self.assertEqual(len(uinput_write_history), 2)
        self.assertNotIn(down_1[:2], unreleased)
        self.assertNotIn(down_2[:2], unreleased)
Ejemplo n.º 20
0
    def test_hold_two(self):
        # holding two macros at the same time,
        # the first one is triggered by a combination
        history = []

        code_1 = 100
        code_2 = 101
        code_3 = 102
        code_a = 103
        code_b = 104
        code_c = 105
        system_mapping.clear()
        system_mapping._set('1', code_1)
        system_mapping._set('2', code_2)
        system_mapping._set('3', code_3)
        system_mapping._set('a', code_a)
        system_mapping._set('b', code_b)
        system_mapping._set('c', code_c)

        key_0 = (EV_KEY, 10)
        key_1 = (EV_KEY, 11)
        key_2 = (EV_ABS, ABS_HAT0X)
        down_0 = (*key_0, 1)
        down_1 = (*key_1, 1)
        down_2 = (*key_2, -1)
        up_0 = (*key_0, 0)
        up_1 = (*key_1, 0)
        up_2 = (*key_2, 0)

        macro_mapping = {
            (down_0, down_1): parse('k(1).h(k(2)).k(3)', self.mapping),
            (down_2, ): parse('k(a).h(k(b)).k(c)', self.mapping)
        }

        def handler(*args):
            history.append(args)

        macro_mapping[(down_0, down_1)].set_handler(handler)
        macro_mapping[(down_2, )].set_handler(handler)

        loop = asyncio.get_event_loop()

        macros_uinput = UInput()
        keys_uinput = UInput()

        # key up won't do anything
        handle_keycode({}, macro_mapping, InputEvent(*up_0), macros_uinput)
        handle_keycode({}, macro_mapping, InputEvent(*up_1), macros_uinput)
        handle_keycode({}, macro_mapping, InputEvent(*up_2), macros_uinput)
        loop.run_until_complete(asyncio.sleep(0.1))
        self.assertEqual(len(active_macros), 0)
        """start macros"""

        handle_keycode({}, macro_mapping, InputEvent(*down_0), keys_uinput)
        self.assertEqual(keys_uinput.write_count, 1)
        handle_keycode({}, macro_mapping, InputEvent(*down_1), keys_uinput)
        handle_keycode({}, macro_mapping, InputEvent(*down_2), keys_uinput)
        self.assertEqual(keys_uinput.write_count, 1)

        # let the mainloop run for some time so that the macro does its stuff
        sleeptime = 500
        keystroke_sleep = config.get('macros.keystroke_sleep_ms', 10)
        loop.run_until_complete(asyncio.sleep(sleeptime / 1000))

        self.assertEqual(len(active_macros), 2)
        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"""

        # releasing the last key of a combination releases the whole macro
        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[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 = calculate_event_number(sleeptime, 1, 1) * 2

        self.assertGreater(len(history), events * 0.9)
        self.assertLess(len(history), events * 1.1)

        self.assertIn((code_a, 1), history)
        self.assertIn((code_a, 0), history)
        self.assertIn((code_b, 1), history)
        self.assertIn((code_b, 0), history)
        self.assertIn((code_c, 1), history)
        self.assertIn((code_c, 0), history)
        self.assertIn((code_1, 1), history)
        self.assertIn((code_1, 0), history)
        self.assertIn((code_2, 1), history)
        self.assertIn((code_2, 0), history)
        self.assertIn((code_3, 1), history)
        self.assertIn((code_3, 0), history)
        self.assertGreater(history.count((code_b, 1)), 1)
        self.assertGreater(history.count((code_b, 0)), 1)
        self.assertGreater(history.count((code_2, 1)), 1)
        self.assertGreater(history.count((code_2, 0)), 1)

        # it's stopped and won't write stuff anymore
        count_before = len(history)
        loop.run_until_complete(asyncio.sleep(0.2))
        count_after = len(history)
        self.assertEqual(count_before, count_after)
Ejemplo n.º 21
0
    def test_ignore_disabled(self):
        ev_1 = (EV_ABS, ABS_HAT0Y, 1)
        ev_2 = (EV_ABS, ABS_HAT0Y, 0)

        ev_3 = (EV_ABS, ABS_HAT0X, 1)  # disabled
        ev_4 = (EV_ABS, ABS_HAT0X, 0)

        ev_5 = (EV_KEY, KEY_A, 1)
        ev_6 = (EV_KEY, KEY_A, 0)

        combi_1 = (ev_5, ev_3)
        combi_2 = (ev_3, ev_5)

        _key_to_code = {
            (ev_1,): 61,
            (ev_3,): DISABLE_CODE,
            combi_1: 62,
            combi_2: 63
        }

        uinput = UInput()
        forward_to = UInput()

        context = Context(self.mapping)
        context.uinput = uinput
        context.key_to_code = _key_to_code
        keycode_mapper = KeycodeMapper(context, self.source, forward_to)

        def expect_writecounts(uinput_count, forwarded_count):
            self.assertEqual(uinput.write_count, uinput_count)
            self.assertEqual(forward_to.write_count, forwarded_count)

        """single keys"""

        # down
        keycode_mapper.handle_keycode(new_event(*ev_1))
        keycode_mapper.handle_keycode(new_event(*ev_3))
        self.assertIn(ev_1[:2], unreleased)
        self.assertIn(ev_3[:2], unreleased)
        expect_writecounts(1, 0)
        # up
        keycode_mapper.handle_keycode(new_event(*ev_2))
        keycode_mapper.handle_keycode(new_event(*ev_4))
        expect_writecounts(2, 0)
        self.assertNotIn(ev_1[:2], unreleased)
        self.assertNotIn(ev_3[:2], unreleased)

        self.assertEqual(len(uinput_write_history), 2)
        self.assertEqual(uinput_write_history[0].t, (EV_KEY, 61, 1))
        self.assertEqual(uinput_write_history[1].t, (EV_KEY, 61, 0))

        """a combination that ends in a disabled key"""

        # ev_5 should be forwarded and the combination triggered
        keycode_mapper.handle_keycode(new_event(*combi_1[0]))  # ev_5
        keycode_mapper.handle_keycode(new_event(*combi_1[1]))  # ev_3
        expect_writecounts(3, 1)
        self.assertEqual(len(uinput_write_history), 4)
        self.assertEqual(uinput_write_history[2].t, (EV_KEY, KEY_A, 1))
        self.assertEqual(uinput_write_history[3].t, (EV_KEY, 62, 1))
        self.assertIn(combi_1[0][:2], unreleased)
        self.assertIn(combi_1[1][:2], unreleased)
        # since this event did not trigger anything, key is None
        self.assertEqual(unreleased[combi_1[0][:2]].triggered_key, None)
        # that one triggered something from _key_to_code, so the key is that
        self.assertEqual(unreleased[combi_1[1][:2]].triggered_key, combi_1)

        # release the last key of the combi first, it should
        # release what the combination maps to
        event = new_event(combi_1[1][0], combi_1[1][1], 0)
        keycode_mapper.handle_keycode(event)
        expect_writecounts(4, 1)
        self.assertEqual(len(uinput_write_history), 5)
        self.assertEqual(uinput_write_history[-1].t, (EV_KEY, 62, 0))
        self.assertIn(combi_1[0][:2], unreleased)
        self.assertNotIn(combi_1[1][:2], unreleased)

        event = new_event(combi_1[0][0], combi_1[0][1], 0)
        keycode_mapper.handle_keycode(event)
        expect_writecounts(4, 2)
        self.assertEqual(len(uinput_write_history), 6)
        self.assertEqual(uinput_write_history[-1].t, (EV_KEY, KEY_A, 0))
        self.assertNotIn(combi_1[0][:2], unreleased)
        self.assertNotIn(combi_1[1][:2], unreleased)

        """a combination that starts with a disabled key"""

        # only the combination should get triggered
        keycode_mapper.handle_keycode(new_event(*combi_2[0]))
        keycode_mapper.handle_keycode(new_event(*combi_2[1]))
        expect_writecounts(5, 2)
        self.assertEqual(len(uinput_write_history), 7)
        self.assertEqual(uinput_write_history[-1].t, (EV_KEY, 63, 1))

        # release the last key of the combi first, it should
        # release what the combination maps to
        event = new_event(combi_2[1][0], combi_2[1][1], 0)
        keycode_mapper.handle_keycode(event)
        self.assertEqual(len(uinput_write_history), 8)
        self.assertEqual(uinput_write_history[-1].t, (EV_KEY, 63, 0))
        expect_writecounts(6, 2)

        # the first key of combi_2 is disabled, so it won't write another
        # key-up event
        event = new_event(combi_2[0][0], combi_2[0][1], 0)
        keycode_mapper.handle_keycode(event)
        self.assertEqual(len(uinput_write_history), 8)
        expect_writecounts(6, 2)
Ejemplo n.º 22
0
    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)

        uinput = UInput()
        context = Context(self.mapping)
        context.uinput = uinput
        context.key_to_code = {
            (ev_1,): 51,
            (ev_2,): 52,
            (ev_4,): 54,
            (ev_5,): 55,
        }

        keycode_mapper = KeycodeMapper(context, self.source, uinput)

        # a bunch of d-pad key down events at once
        keycode_mapper.handle_keycode(new_event(*ev_1))
        keycode_mapper.handle_keycode(new_event(*ev_4))
        self.assertEqual(len(unreleased), 2)

        self.assertEqual(
            unreleased.get(ev_1[:2]).target_type_code,
            (EV_KEY, context.key_to_code[(ev_1,)])
        )
        self.assertEqual(unreleased.get(ev_1[:2]).input_event_tuple, ev_1)
        self.assertEqual(unreleased.get(ev_1[:2]).triggered_key, (ev_1,))  # as seen in key_to_code

        self.assertEqual(
            unreleased.get(ev_4[:2]).target_type_code,
            (EV_KEY, context.key_to_code[(ev_4,)]), ev_4
        )
        self.assertEqual(unreleased.get(ev_4[:2]).input_event_tuple, ev_4)
        self.assertEqual(unreleased.get(ev_4[:2]).triggered_key, (ev_4,))

        # release all of them
        keycode_mapper.handle_keycode(new_event(*ev_3))
        keycode_mapper.handle_keycode(new_event(*ev_6))
        self.assertEqual(len(unreleased), 0)

        # repeat with other values
        keycode_mapper.handle_keycode(new_event(*ev_2))
        keycode_mapper.handle_keycode(new_event(*ev_5))
        self.assertEqual(len(unreleased), 2)
        self.assertEqual(
            unreleased.get(ev_2[:2]).target_type_code,
            (EV_KEY, context.key_to_code[(ev_2,)])
        )
        self.assertEqual(
            unreleased.get(ev_2[:2]).input_event_tuple,
            ev_2
        )
        self.assertEqual(
            unreleased.get(ev_5[:2]).target_type_code,
            (EV_KEY, context.key_to_code[(ev_5,)])
        )
        self.assertEqual(
            unreleased.get(ev_5[:2]).input_event_tuple,
            ev_5
        )

        # release all of them again
        keycode_mapper.handle_keycode(new_event(*ev_3))
        keycode_mapper.handle_keycode(new_event(*ev_6))
        self.assertEqual(len(unreleased), 0)

        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))
Ejemplo n.º 23
0
    def test_wheel_combination_release_failure(self):
        # test based on a bug that once occurred
        # 1 | 22.6698, ((1, 276, 1)) -------------- forwarding
        # 2 | 22.9904, ((1, 276, 1), (2, 8, -1)) -- maps to 30
        # 3 | 23.0103, ((1, 276, 1), (2, 8, -1)) -- duplicate key down
        # 4 | ... 34 more duplicate key downs (scrolling)
        # 5 | 23.7104, ((1, 276, 1), (2, 8, -1)) -- duplicate key down
        # 6 | 23.7283, ((1, 276, 0)) -------------- forwarding release
        # 7 | 23.7303, ((2, 8, -1)) --------------- forwarding
        # 8 | 23.7865, ((2, 8, 0)) ---------------- not forwarding release
        # line 7 should have been "duplicate key down" as well
        # line 8 should have released 30, instead it was never released

        scroll = (2, 8, -1)
        scroll_up = (2, 8, 0)
        btn_down = (1, 276, 1)
        btn_up = (1, 276, 0)
        combination = ((1, 276, 1), (2, 8, -1))

        system_mapping.clear()
        system_mapping._set('a', 30)
        k2c = {combination: 30}

        uinput = UInput()

        context = Context(self.mapping)
        context.uinput = uinput
        context.key_to_code = k2c
        keycode_mapper = KeycodeMapper(context, self.source, uinput)

        keycode_mapper.handle_keycode(new_event(*btn_down))
        # "forwarding"
        self.assertEqual(uinput_write_history[0].t, btn_down)

        keycode_mapper.handle_keycode(new_event(*scroll))
        # "maps to 30"
        self.assertEqual(uinput_write_history[1].t, (1, 30, 1))

        for _ in range(5):
            # keep scrolling
            # "duplicate key down"
            keycode_mapper.handle_keycode(new_event(*scroll))

        # nothing new since all of them were duplicate key downs
        self.assertEqual(len(uinput_write_history), 2)

        keycode_mapper.handle_keycode(new_event(*btn_up))
        # "forwarding release"
        self.assertEqual(uinput_write_history[2].t, btn_up)

        # one more scroll event. since the combination is still not released,
        # it should be ignored as duplicate key-down
        self.assertEqual(len(uinput_write_history), 3)
        # "forwarding" (should be "duplicate key down")
        keycode_mapper.handle_keycode(new_event(*scroll))
        self.assertEqual(len(uinput_write_history), 3)

        # the failure to release the mapped key
        # forward=False is what the debouncer uses, because a
        # "scroll release" doesn't actually exist so it is not actually
        # written if it doesn't release any mapping
        keycode_mapper.handle_keycode(new_event(*scroll_up), forward=False)

        # 30 should be released
        self.assertEqual(uinput_write_history[3].t, (1, 30, 0))
        self.assertEqual(len(uinput_write_history), 4)
Ejemplo n.º 24
0
    def test_ignore_disabled(self):
        ev_1 = (EV_ABS, ABS_HAT0Y, 1)
        ev_2 = (EV_ABS, ABS_HAT0Y, 0)

        ev_3 = (EV_ABS, ABS_HAT0X, 1)
        ev_4 = (EV_ABS, ABS_HAT0X, 0)

        ev_5 = (EV_KEY, KEY_A, 1)
        ev_6 = (EV_KEY, KEY_A, 0)

        combi_1 = (ev_5, ev_3)
        combi_2 = (ev_3, ev_5)

        _key_to_code = {
            (ev_1, ): 61,
            (ev_3, ): DISABLE_CODE,
            combi_1: 62,
            combi_2: 63
        }

        uinput = UInput()
        """single keys"""

        # down
        handle_keycode(_key_to_code, {}, InputEvent(*ev_1), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*ev_3), uinput)
        # up
        handle_keycode(_key_to_code, {}, InputEvent(*ev_2), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*ev_4), uinput)

        self.assertEqual(len(uinput_write_history), 2)
        self.assertEqual(uinput_write_history[0].t, (EV_KEY, 61, 1))
        self.assertEqual(uinput_write_history[1].t, (EV_KEY, 61, 0))
        """a combination that ends in a disabled key"""

        # ev_5 should be forwarded and the combination triggered
        handle_keycode(_key_to_code, {}, InputEvent(*combi_1[0]), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*combi_1[1]), uinput)
        self.assertEqual(len(uinput_write_history), 4)
        self.assertEqual(uinput_write_history[2].t, (EV_KEY, KEY_A, 1))
        self.assertEqual(uinput_write_history[3].t, (EV_KEY, 62, 1))

        # release the last key of the combi first, it should
        # release what the combination maps to
        event = InputEvent(combi_1[1][0], combi_1[1][1], 0)
        handle_keycode(_key_to_code, {}, event, uinput)
        self.assertEqual(len(uinput_write_history), 5)
        self.assertEqual(uinput_write_history[-1].t, (EV_KEY, 62, 0))

        event = InputEvent(combi_1[0][0], combi_1[0][1], 0)
        handle_keycode(_key_to_code, {}, event, uinput)
        self.assertEqual(len(uinput_write_history), 6)
        self.assertEqual(uinput_write_history[-1].t, (EV_KEY, KEY_A, 0))
        """a combination that starts with a disabled key"""

        # only the combination should get triggered
        handle_keycode(_key_to_code, {}, InputEvent(*combi_2[0]), uinput)
        handle_keycode(_key_to_code, {}, InputEvent(*combi_2[1]), uinput)
        self.assertEqual(len(uinput_write_history), 7)
        self.assertEqual(uinput_write_history[-1].t, (EV_KEY, 63, 1))

        # release the last key of the combi first, it should
        # release what the combination maps to
        event = InputEvent(combi_2[1][0], combi_2[1][1], 0)
        handle_keycode(_key_to_code, {}, event, uinput)
        self.assertEqual(len(uinput_write_history), 8)
        self.assertEqual(uinput_write_history[-1].t, (EV_KEY, 63, 0))

        # the first key of combi_2 is disabled, so it won't write another
        # key-up event
        event = InputEvent(combi_2[0][0], combi_2[0][1], 0)
        handle_keycode(_key_to_code, {}, event, uinput)
        self.assertEqual(len(uinput_write_history), 8)
Ejemplo n.º 25
0
    def test_combination_keycode_2(self):
        combination_1 = (
            (EV_KEY, 1, 1),
            (EV_ABS, ABS_Y, MIN_ABS),
            (EV_KEY, 3, 1),
            (EV_KEY, 4, 1)
        )
        combination_2 = (
            # should not be triggered, combination_1 should be prioritized
            # when all of its keys are down
            (EV_KEY, 2, 1),
            (EV_KEY, 3, 1),
            (EV_KEY, 4, 1)
        )

        down_5 = (EV_KEY, 5, 1)
        up_5 = (EV_KEY, 5, 0)
        up_4 = (EV_KEY, 4, 0)

        def sign_value(key):
            return key[0], key[1], key[2] / abs(key[2])

        _key_to_code = {
            # key_to_code is supposed to only contain normalized values
            tuple([sign_value(a) for a in combination_1]): 101,
            combination_2: 102,
            (down_5,): 103
        }

        uinput = UInput()

        source = InputDevice('/dev/input/event30')

        # ABS_Y is part of the combination, which only works if the joystick
        # is configured as D-Pad
        self.mapping.set('gamepad.joystick.left_purpose', BUTTONS)
        context = Context(self.mapping)
        context.uinput = uinput
        context.key_to_code = _key_to_code
        keycode_mapper = KeycodeMapper(context, source, uinput)

        # 10 and 11: insert some more arbitrary key-down events,
        # they should not break the combinations
        keycode_mapper.handle_keycode(new_event(EV_KEY, 10, 1))
        keycode_mapper.handle_keycode(new_event(*combination_1[0]))
        keycode_mapper.handle_keycode(new_event(*combination_1[1]))
        keycode_mapper.handle_keycode(new_event(*combination_1[2]))
        keycode_mapper.handle_keycode(new_event(EV_KEY, 11, 1))
        keycode_mapper.handle_keycode(new_event(*combination_1[3]))
        # combination_1 should have been triggered now

        self.assertEqual(len(uinput_write_history), 6)
        # the first events are written and then the triggered combination,
        # while the triggering event is the only one that is omitted
        self.assertEqual(uinput_write_history[1].t, combination_1[0])
        self.assertEqual(uinput_write_history[2].t, combination_1[1])
        self.assertEqual(uinput_write_history[3].t, combination_1[2])
        self.assertEqual(uinput_write_history[5].t, (EV_KEY, 101, 1))

        # while the combination is down, another unrelated key can be used
        keycode_mapper.handle_keycode(new_event(*down_5))
        # the keycode_mapper searches for subsets of the current held-down
        # keys to activate combinations, down_5 should not trigger them
        # again.
        self.assertEqual(len(uinput_write_history), 7)
        self.assertEqual(uinput_write_history[6].t, (EV_KEY, 103, 1))

        # release the combination by releasing the last key, and release
        # the unrelated key
        keycode_mapper.handle_keycode(new_event(*up_4))
        keycode_mapper.handle_keycode(new_event(*up_5))
        self.assertEqual(len(uinput_write_history), 9)

        self.assertEqual(uinput_write_history[7].t, (EV_KEY, 101, 0))
        self.assertEqual(uinput_write_history[8].t, (EV_KEY, 103, 0))