Esempio n. 1
0
    def test_hold(self):
        history = []

        code_a = 100
        code_b = 101
        code_c = 102
        system_mapping.clear()
        system_mapping._set('a', code_a)
        system_mapping._set('b', code_b)
        system_mapping._set('c', code_c)

        macro_mapping = {
            ((EV_KEY, 1, 1), ): parse('k(a).h(k(b)).k(c)', self.mapping)
        }

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

        macro_mapping[((EV_KEY, 1, 1), )].set_handler(handler)
        """start macro"""

        handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 1, 1), None)

        loop = asyncio.get_event_loop()

        # 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.assertTrue(active_macros[(EV_KEY, 1)].holding)
        self.assertTrue(active_macros[(EV_KEY, 1)].running)
        """stop macro"""

        handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 1, 0), None)

        loop.run_until_complete(asyncio.sleep(keystroke_sleep * 10 / 1000))

        events = calculate_event_number(sleeptime, 1, 1)

        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.assertGreater(history.count((code_b, 1)), 1)
        self.assertGreater(history.count((code_b, 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)

        self.assertFalse(active_macros[(EV_KEY, 1)].holding)
        self.assertFalse(active_macros[(EV_KEY, 1)].running)
Esempio n. 2
0
        def do_stuff():
            if self.injector is not None:
                # discard the previous injector
                self.injector.stop_injecting()
                time.sleep(0.1)
                while uinput_write_history_pipe[0].poll():
                    uinput_write_history_pipe[0].recv()

            pending_events['gamepad'] = [
                InputEvent(*w_down),
                InputEvent(*d_down),
                InputEvent(*w_up),
                InputEvent(*d_up),
            ]

            self.injector = KeycodeInjector('gamepad', custom_mapping)

            # the injector will otherwise skip the device because
            # the capabilities don't contain EV_TYPE
            input = InputDevice('/dev/input/event30')
            self.injector._prepare_device = lambda *args: (input, False)

            self.injector.start_injecting()
            uinput_write_history_pipe[0].poll(timeout=1)
            time.sleep(EVENT_READ_TIMEOUT * 10)
            return read_write_history_pipe()
Esempio n. 3
0
    def test_handle_keycode_macro(self):
        history = []

        code_a = 100
        code_b = 101
        system_mapping.clear()
        system_mapping._set('a', code_a)
        system_mapping._set('b', code_b)

        macro_mapping = {
            ((EV_KEY, 1, 1), ): parse('k(a)', self.mapping),
            ((EV_KEY, 2, 1), ): parse('r(5, k(b))', self.mapping)
        }

        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)

        loop = asyncio.get_event_loop()

        sleeptime = config.get('macros.keystroke_sleep_ms', 10) * 12

        # let the mainloop run for some time so that the macro does its stuff
        loop.run_until_complete(asyncio.sleep(sleeptime / 1000 + 0.1))

        # 6 keycodes written, with down and up events
        self.assertEqual(len(history), 12)
        self.assertIn((code_a, 1), history)
        self.assertIn((code_a, 0), history)
        self.assertIn((code_b, 1), history)
        self.assertIn((code_b, 0), history)
Esempio 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))
Esempio n. 5
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))
Esempio n. 6
0
 def test_wrong_device(self):
     pending_events['device 1'] = [
         InputEvent(EV_KEY, CODE_1, 1),
         InputEvent(EV_KEY, CODE_2, 1),
         InputEvent(EV_KEY, CODE_3, 1)
     ]
     keycode_reader.start_reading('device 2')
     time.sleep(EVENT_READ_TIMEOUT * 5)
     self.assertEqual(keycode_reader.read(), None)
     self.assertEqual(len(keycode_reader._unreleased), 0)
Esempio n. 7
0
 def test_reading_ignore_up(self):
     pending_events['device 1'] = [
         InputEvent(EV_KEY, CODE_1, 0, 10),
         InputEvent(EV_KEY, CODE_2, 1, 11),
         InputEvent(EV_KEY, CODE_3, 0, 12),
     ]
     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)
     self.assertEqual(len(keycode_reader._unreleased), 1)
Esempio n. 8
0
 def test_ignore_value_2(self):
     # this is not a combination, because (EV_KEY CODE_3, 2) is ignored
     pending_events['device 1'] = [
         InputEvent(EV_ABS, ABS_HAT0X, 1),
         InputEvent(EV_KEY, CODE_3, 2)
     ]
     keycode_reader.start_reading('device 1')
     wait(keycode_reader._pipe[0].poll, 0.5)
     self.assertEqual(keycode_reader.read(), (EV_ABS, ABS_HAT0X, 1))
     self.assertEqual(keycode_reader.read(), None)
     self.assertEqual(len(keycode_reader._unreleased), 1)
Esempio n. 9
0
    def test_switch_device(self):
        pending_events['device 2'] = [InputEvent(EV_KEY, CODE_1, 1)]
        pending_events['device 1'] = [InputEvent(EV_KEY, CODE_3, 1)]

        keycode_reader.start_reading('device 2')
        time.sleep(EVENT_READ_TIMEOUT * 5)

        keycode_reader.start_reading('device 1')
        time.sleep(EVENT_READ_TIMEOUT * 5)

        self.assertEqual(keycode_reader.read(), (EV_KEY, CODE_3, 1))
        self.assertEqual(keycode_reader.read(), None)
Esempio n. 10
0
    def test_abs_to_rel(self):
        # maps gamepad joystick events to mouse events
        config.set('gamepad.joystick.non_linearity', 1)
        pointer_speed = 80
        config.set('gamepad.joystick.pointer_speed', pointer_speed)

        rel_x = evdev.ecodes.REL_X
        rel_y = evdev.ecodes.REL_Y

        # they need to sum up before something is written
        divisor = 10
        x = MAX_ABS / pointer_speed / divisor
        y = MAX_ABS / pointer_speed / divisor
        pending_events['gamepad'] = [
            InputEvent(EV_ABS, rel_x, x),
            InputEvent(EV_ABS, rel_y, y),
            InputEvent(EV_ABS, rel_x, -x),
            InputEvent(EV_ABS, rel_y, -y),
        ]

        self.injector = KeycodeInjector('gamepad', custom_mapping)
        self.injector.start_injecting()

        # wait for the injector to start sending, at most 1s
        uinput_write_history_pipe[0].poll(1)

        # wait a bit more for it to sum up
        sleep = 0.5
        time.sleep(sleep)

        # convert the write history to some easier to manage list
        history = []
        while uinput_write_history_pipe[0].poll():
            event = uinput_write_history_pipe[0].recv()
            history.append((event.type, event.code, event.value))

        if history[0][0] == EV_ABS:
            raise AssertionError(
                'The injector probably just forwarded them unchanged')

        # movement is written at 60hz and it takes `divisor` steps to
        # move 1px. take it times 2 for both x and y events.
        self.assertGreater(len(history), 60 * sleep * 0.9 * 2 / divisor)
        self.assertLess(len(history), 60 * sleep * 1.1 * 2 / divisor)

        # those may be in arbitrary order, the injector happens to write
        # y first
        self.assertEqual(history[-1][0], EV_REL)
        self.assertEqual(history[-1][1], rel_x)
        self.assertAlmostEqual(history[-1][2], -1)
        self.assertEqual(history[-2][0], EV_REL)
        self.assertEqual(history[-2][1], rel_y)
        self.assertAlmostEqual(history[-2][2], -1)
Esempio n. 11
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))
Esempio n. 12
0
    def test_hold_3(self):
        # test irregular input patterns
        code_a = 100
        code_b = 101
        code_c = 102
        system_mapping.clear()
        system_mapping._set('a', code_a)
        system_mapping._set('b', code_b)
        system_mapping._set('c', code_c)

        macro_mapping = {
            ((EV_KEY, 1, 1), ): parse('k(a).h(k(b)).k(c)', self.mapping),
        }

        history = []

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

        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[(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))

        # duplicate key down events don't do anything
        self.assertEqual(history.count((code_a, 1)), 1)
        self.assertEqual(history.count((code_a, 0)), 1)
        self.assertEqual(history.count((code_c, 1)), 0)
        self.assertEqual(history.count((code_c, 0)), 0)

        # stop
        handle_keycode({}, macro_mapping, InputEvent(EV_KEY, 1, 0), None)
        loop.run_until_complete(asyncio.sleep(0.1))
        self.assertEqual(history.count((code_a, 1)), 1)
        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[(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)
        loop.run_until_complete(asyncio.sleep(0.1))
        count_after = len(history)
        self.assertEqual(count_before, count_after)
Esempio n. 13
0
 def test_prioritizing_3_normalize(self):
     # take the sign of -1234, just like in test_prioritizing_2_normalize
     pending_events['device 1'] = [
         InputEvent(EV_ABS, ABS_HAT0X, -1234, 1234.0000),
         InputEvent(EV_ABS, ABS_HAT0Y, 0, 1234.0030)  # ignored
         # this time don't release anything as well, but it's not
         # a combination because only one event is accepted
     ]
     keycode_reader.start_reading('device 1')
     wait(keycode_reader._pipe[0].poll, 0.5)
     self.assertEqual(keycode_reader.read(), (EV_ABS, ABS_HAT0X, -1))
     self.assertEqual(keycode_reader.read(), None)
     self.assertEqual(len(keycode_reader._unreleased), 1)
Esempio n. 14
0
    def test_reading_ignore_duplicate_down(self):
        pipe = multiprocessing.Pipe()
        pipe[1].send(InputEvent(EV_ABS, ABS_Z, 1, 10))
        keycode_reader._pipe = pipe

        self.assertEqual(keycode_reader.read(), (EV_ABS, ABS_Z, 1))
        self.assertEqual(keycode_reader.read(), None)

        pipe[1].send(InputEvent(EV_ABS, ABS_Z, 1, 10))
        # still none
        self.assertEqual(keycode_reader.read(), None)

        self.assertEqual(len(keycode_reader._unreleased), 1)
Esempio n. 15
0
 def test_keymapper_devices(self):
     # Don't read from keymapper devices, their keycodes are not
     # representative for the original key. As long as this is not
     # intentionally programmed it won't even do that. But it was at some
     # point.
     pending_events['key-mapper device 2'] = [
         InputEvent(EV_KEY, CODE_1, 1),
         InputEvent(EV_KEY, CODE_2, 1),
         InputEvent(EV_KEY, CODE_3, 1)
     ]
     keycode_reader.start_reading('device 2')
     time.sleep(EVENT_READ_TIMEOUT * 5)
     self.assertEqual(keycode_reader.read(), None)
     self.assertEqual(len(keycode_reader._unreleased), 0)
Esempio n. 16
0
 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)
     self.assertEqual(len(keycode_reader._unreleased), 1)
Esempio n. 17
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))
Esempio n. 18
0
    def test_xmodmap_file(self):
        from_keycode = evdev.ecodes.KEY_A
        to_name = 'qux'
        to_keycode = 100
        event = (EV_KEY, from_keycode, 1)

        device = 'device 2'
        preset = 'foo'

        path = get_preset_path(device, preset)

        custom_mapping.change(Key(event), to_name)
        custom_mapping.save(path)

        system_mapping.clear()

        config.set_autoload_preset(device, preset)

        pending_events[device] = [InputEvent(*event)]

        xmodmap_path = os.path.join(tmp, 'foobar.json')
        with open(xmodmap_path, 'w') as file:
            file.write(f'{{"{to_name}":{to_keycode}}}')

        self.daemon = Daemon()
        self.daemon.start_injecting(device, path, xmodmap_path)

        event = uinput_write_history_pipe[0].recv()
        self.assertEqual(event.type, EV_KEY)
        self.assertEqual(event.code, to_keycode)
        self.assertEqual(event.value, 1)
Esempio n. 19
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))
Esempio n. 20
0
    def test_reads_joysticks(self):
        # if their purpose is "buttons"
        custom_mapping.set('gamepad.joystick.left_purpose', BUTTONS)
        pending_events['gamepad'] = [InputEvent(EV_ABS, ABS_Y, MAX_ABS)]
        keycode_reader.start_reading('gamepad')
        wait(keycode_reader._pipe[0].poll, 0.5)
        self.assertEqual(keycode_reader.read(), (EV_ABS, ABS_Y, 1))
        self.assertEqual(keycode_reader.read(), None)
        self.assertEqual(len(keycode_reader._unreleased), 1)

        keycode_reader._unreleased = {}
        custom_mapping.set('gamepad.joystick.left_purpose', MOUSE)
        pending_events['gamepad'] = [InputEvent(EV_ABS, ABS_Y, MAX_ABS)]
        keycode_reader.start_reading('gamepad')
        time.sleep(0.1)
        self.assertEqual(keycode_reader.read(), None)
        self.assertEqual(len(keycode_reader._unreleased), 0)
Esempio n. 21
0
 def test_reading_1(self):
     # a single event
     pending_events['device 1'] = [InputEvent(EV_ABS, ABS_HAT0X, 1)]
     keycode_reader.start_reading('device 1')
     wait(keycode_reader._pipe[0].poll, 0.5)
     self.assertEqual(keycode_reader.read(), (EV_ABS, ABS_HAT0X, 1))
     self.assertEqual(keycode_reader.read(), None)
     self.assertEqual(len(keycode_reader._unreleased), 1)
Esempio n. 22
0
    def test_reading_2(self):
        # a combination of events
        pending_events['device 1'] = [
            InputEvent(EV_KEY, CODE_1, 1, 10000.1234),
            InputEvent(EV_KEY, CODE_3, 1, 10001.1234),
            InputEvent(EV_ABS, ABS_HAT0X, -1, 10002.1234)
        ]
        keycode_reader.start_reading('device 1')

        # sending anything arbitrary does not stop the pipe
        keycode_reader._pipe[0].send((EV_KEY, 1234))

        wait(keycode_reader._pipe[0].poll, 0.5)

        self.assertEqual(keycode_reader.read(),
                         ((EV_KEY, CODE_1, 1), (EV_KEY, CODE_3, 1),
                          (EV_ABS, ABS_HAT0X, -1)))
        self.assertEqual(keycode_reader.read(), None)
        self.assertEqual(len(keycode_reader._unreleased), 3)
Esempio n. 23
0
    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))', self.mapping),
            (down_2, ): parse(f'r({repeats}, k(2))', self.mapping)
        }

        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)
Esempio n. 24
0
 def test_prioritizing_2_normalize(self):
     # a value of 1234 becomes 1 in the reader in order to properly map
     # it. Value like that are usually some sort of continuous trigger
     # value and normal for some ev_abs events.
     custom_mapping.set('gamepad.joystick.left_purpose', BUTTONS)
     pending_events['gamepad'] = [
         InputEvent(EV_ABS, ABS_HAT0X, 1, 1234.0000),
         InputEvent(EV_ABS, ABS_MISC, 1, 1235.0000),  # ignored
         InputEvent(EV_ABS, ABS_Y, MAX_ABS, 1235.0010),
         InputEvent(EV_ABS, ABS_MISC, 1, 1235.0020),  # ignored
         InputEvent(EV_ABS, ABS_MISC, 1, 1235.0030)  # ignored
         # this time, don't release anything. the combination should
         # ignore stuff as well.
     ]
     keycode_reader.start_reading('gamepad')
     time.sleep(0.5)
     wait(keycode_reader._pipe[0].poll, 0.5)
     self.assertEqual(keycode_reader.read(),
                      ((EV_ABS, ABS_HAT0X, 1), (EV_ABS, ABS_Y, 1)))
     self.assertEqual(keycode_reader.read(), None)
     self.assertEqual(len(keycode_reader._unreleased), 2)
Esempio n. 25
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))
Esempio n. 26
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))
Esempio n. 27
0
    def test_start_injecting(self):
        keycode_from = 9
        keycode_to = 200

        self.change_empty_row(Key(EV_KEY, keycode_from, 1), 'a')
        system_mapping.clear()
        system_mapping._set('a', keycode_to)

        pending_events['device 2'] = [
            InputEvent(evdev.events.EV_KEY, keycode_from, 1),
            InputEvent(evdev.events.EV_KEY, keycode_from, 0)
        ]

        custom_mapping.save(get_preset_path('device 2', 'foo preset'))

        # use only the manipulated system_mapping
        os.remove(os.path.join(tmp, XMODMAP_FILENAME))

        self.window.selected_device = 'device 2'
        self.window.selected_preset = 'foo preset'
        self.window.on_apply_preset_clicked(None)

        # the integration tests will cause the injection to be started as
        # processes, as intended. Luckily, recv will block until the events
        # are handled and pushed.

        # Note, that pushing events to pending_events won't work anymore
        # from here on because the injector processes memory cannot be
        # modified from here.

        event = uinput_write_history_pipe[0].recv()
        self.assertEqual(event.type, evdev.events.EV_KEY)
        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)
        self.assertEqual(event.value, 0)
Esempio n. 28
0
 def test_prioritizing_1(self):
     # filter the ABS_MISC events of the wacom intuos 5 out that come
     # with every button press. Or more general, prioritize them
     # based on the event type
     pending_events['device 1'] = [
         InputEvent(EV_ABS, ABS_HAT0X, 1, 1234.0000),
         InputEvent(EV_ABS, ABS_HAT0X, 0, 1234.0001),
         InputEvent(EV_ABS, ABS_HAT0X, 1, 1235.0000),  # ignored
         InputEvent(EV_ABS, ABS_HAT0X, 0, 1235.0001),
         InputEvent(EV_KEY, KEY_COMMA, 1, 1235.0010),
         InputEvent(EV_KEY, KEY_COMMA, 0, 1235.0011),
         InputEvent(EV_ABS, ABS_HAT0X, 1, 1235.0020),  # ignored
         InputEvent(EV_ABS, ABS_HAT0X, 0, 1235.0021),  # ignored
         InputEvent(EV_ABS, ABS_HAT0X, 1, 1236.0000)
     ]
     keycode_reader.start_reading('device 1')
     wait(keycode_reader._pipe[0].poll, 0.5)
     self.assertEqual(keycode_reader.read(), (EV_ABS, ABS_HAT0X, 1))
     self.assertEqual(keycode_reader.read(), None)
     self.assertEqual(len(keycode_reader._unreleased), 1)
Esempio n. 29
0
    def test_stop_injecting(self):
        keycode_from = 16
        keycode_to = 90

        self.change_empty_row(Key(EV_KEY, keycode_from, 1), 't')
        system_mapping.clear()
        system_mapping._set('t', keycode_to)

        # 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'] = [InputEvent(1, keycode_from, 1)] * 100

        custom_mapping.save(get_preset_path('device 2', 'foo preset'))

        self.window.selected_device = 'device 2'
        self.window.selected_preset = 'foo preset'
        self.window.on_apply_preset_clicked(None)

        pipe = uinput_write_history_pipe[0]
        # block until the first event is available, indicating that
        # the injector is ready
        write_history = [pipe.recv()]

        # stop
        self.window.on_apply_system_layout_clicked(None)

        # try to receive a few of the events
        time.sleep(0.2)
        while pipe.poll():
            write_history.append(pipe.recv())

        len_before = len(write_history)
        self.assertLess(len(write_history), 50)

        # since the injector should not be running anymore, no more events
        # should be received after waiting even more time
        time.sleep(0.2)
        while pipe.poll():
            write_history.append(pipe.recv())
        self.assertEqual(len(write_history), len_before)
Esempio n. 30
0
    def test_refresh_devices_on_start(self):
        ev = (EV_KEY, 9)
        keycode_to = 100
        device = '9876 name'
        # this test only makes sense if this device is unknown yet
        self.assertIsNone(get_devices().get(device))
        custom_mapping.change(Key(*ev, 1), 'a')
        system_mapping.clear()
        system_mapping._set('a', keycode_to)
        preset = 'foo'
        custom_mapping.save(get_preset_path(device, preset))
        config.set_autoload_preset(device, preset)
        pending_events[device] = [InputEvent(*ev, 1)]
        self.daemon = Daemon()
        preset_path = get_preset_path(device, preset)

        # make sure the devices are populated
        get_devices()
        fixtures[self.new_fixture] = {
            'capabilities': {
                evdev.ecodes.EV_KEY: [ev[1]]
            },
            'phys': '9876 phys',
            'info': 'abcd',
            'name': device
        }

        self.daemon.start_injecting(device, preset_path)

        # test if the injector called refresh_devices successfully
        self.assertIsNotNone(get_devices().get(device))

        event = uinput_write_history_pipe[0].recv()
        self.assertEqual(event.type, EV_KEY)
        self.assertEqual(event.code, keycode_to)
        self.assertEqual(event.value, 1)

        self.daemon.stop_injecting(device)
        self.assertFalse(self.daemon.is_injecting(device))