示例#1
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))
示例#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))
示例#3
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)
示例#4
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)
示例#5
0
 def setUp(self):
     self.mapping = Mapping()
     self.mapping.set('gamepad.joystick.left_purpose', WHEEL)
     self.mapping.set('gamepad.joystick.right_purpose', WHEEL)
     self.mapping.change(Key(1, 31, 1), 'k(a)')
     self.mapping.change(Key(1, 32, 1), 'b')
     self.mapping.change(Key((1, 33, 1), (1, 34, 1), (1, 35, 1)), 'c')
     self.context = Context(self.mapping)
示例#6
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)

        context = Context(self.mapping)
        context.macros = macro_mapping
        keycode_mapper = KeycodeMapper(context, self.source, None)

        keycode_mapper.macro_write = handler

        keycode_mapper.handle_keycode(new_event(EV_KEY, 1, 1))
        loop = asyncio.get_event_loop()

        loop.run_until_complete(asyncio.sleep(0.1))
        for _ in range(5):
            self.assertTrue(active_macros[(EV_KEY, 1)].is_holding())
            self.assertTrue(active_macros[(EV_KEY, 1)].running)
            keycode_mapper.handle_keycode(new_event(EV_KEY, 1, 1))
            loop.run_until_complete(asyncio.sleep(0.05))

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

        # stop
        keycode_mapper.handle_keycode(new_event(EV_KEY, 1, 0))
        loop.run_until_complete(asyncio.sleep(0.1))
        self.assertEqual(history.count((EV_KEY, code_a, 1)), 1)
        self.assertEqual(history.count((EV_KEY, code_a, 0)), 1)
        self.assertEqual(history.count((EV_KEY, code_c, 1)), 1)
        self.assertEqual(history.count((EV_KEY, code_c, 0)), 1)
        self.assertFalse(active_macros[(EV_KEY, 1)].is_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)
示例#7
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.
        right = (EV_ABS, ABS_HAT0X, 1)
        release = (EV_ABS, ABS_HAT0X, 0)
        left = (EV_ABS, ABS_HAT0X, -1)

        repeats = 10

        macro_mapping = {
            (right,): parse(f'r({repeats}, k(1))', self.mapping),
            (left,): parse(f'r({repeats}, k(2))', self.mapping)
        }

        history = []

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

        context = Context(self.mapping)
        context.macros = macro_mapping
        keycode_mapper = KeycodeMapper(context, self.source, None)

        keycode_mapper.macro_write = handler
        keycode_mapper.macro_write = handler

        keycode_mapper.handle_keycode(new_event(*right))
        self.assertIn((EV_ABS, ABS_HAT0X), unreleased)
        keycode_mapper.handle_keycode(new_event(*release))
        self.assertNotIn((EV_ABS, ABS_HAT0X), unreleased)
        keycode_mapper.handle_keycode(new_event(*left))
        self.assertIn((EV_ABS, ABS_HAT0X), unreleased)

        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(history.count((EV_KEY, code_1, 1)), 10)
        self.assertEqual(history.count((EV_KEY, code_1, 0)), 10)
        self.assertEqual(history.count((EV_KEY, code_2, 1)), 10)
        self.assertEqual(history.count((EV_KEY, code_2, 0)), 10)
        self.assertEqual(len(history), repeats * 4)
示例#8
0
    def test_grab_device_non_existing(self):
        custom_mapping.change(Key(EV_ABS, ABS_HAT0X, 1), 'a')
        self.injector = Injector('foobar', custom_mapping)
        self.injector.context = Context(custom_mapping)

        _grab_device = self.injector._grab_device
        self.assertIsNone(_grab_device('/dev/input/event1234'))
示例#9
0
    def test_gamepad_purpose_none_2(self):
        # forward abs joystick events for the left joystick only
        custom_mapping.set('gamepad.joystick.left_purpose', NONE)
        config.set('gamepad.joystick.right_purpose', MOUSE)

        self.injector = Injector(groups.find(name='gamepad'), custom_mapping)
        self.injector.context = Context(custom_mapping)

        path = '/dev/input/event30'
        device = self.injector._grab_device(path)
        # the right joystick maps as mouse, so it is grabbed
        # even with an empty mapping
        self.assertIsNotNone(device)
        gamepad = classify(device) == GAMEPAD
        self.assertTrue(gamepad)
        capabilities = self.injector._construct_capabilities(gamepad)
        self.assertNotIn(EV_ABS, capabilities)
        self.assertIn(EV_REL, capabilities)

        custom_mapping.change(Key(EV_KEY, BTN_A, 1), 'a')
        device = self.injector._grab_device(path)
        gamepad = classify(device) == GAMEPAD
        self.assertIsNotNone(device)
        self.assertTrue(gamepad)
        capabilities = self.injector._construct_capabilities(gamepad)
        self.assertNotIn(EV_ABS, capabilities)
        self.assertIn(EV_REL, capabilities)
        self.assertIn(EV_KEY, capabilities)
示例#10
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)
        }

        context = Context(self.mapping)
        context.macros = macro_mapping
        keycode_mapper = KeycodeMapper(context, self.source, None)

        keycode_mapper.macro_write = lambda *args: history.append(args)
        keycode_mapper.macro_write = lambda *args: history.append(args)

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

        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((EV_KEY, code_a, 1), history)
        self.assertIn((EV_KEY, code_a, 0), history)
        self.assertIn((EV_KEY, code_b, 1), history)
        self.assertIn((EV_KEY, code_b, 0), history)

        # releasing stuff
        self.assertIn((EV_KEY, 1), unreleased)
        self.assertIn((EV_KEY, 2), unreleased)
        keycode_mapper.handle_keycode(new_event(EV_KEY, 1, 0))
        keycode_mapper.handle_keycode(new_event(EV_KEY, 2, 0))
        self.assertNotIn((EV_KEY, 1), unreleased)
        self.assertNotIn((EV_KEY, 2), unreleased)
        loop.run_until_complete(asyncio.sleep(0.1))
        self.assertEqual(len(history), 12)
示例#11
0
 def test_skip_unused_device(self):
     # skips a device because its capabilities are not used in the mapping
     custom_mapping.change(Key(EV_KEY, 10, 1), 'a')
     self.injector = Injector('device 1', custom_mapping)
     self.injector.context = Context(custom_mapping)
     path = '/dev/input/event11'
     device = self.injector._grab_device(path)
     self.assertIsNone(device)
     self.assertEqual(self.failed, 0)
示例#12
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)
示例#13
0
    def test_grab_device_1(self):
        # according to the fixtures, /dev/input/event30 can do ABS_HAT0X
        custom_mapping.change(Key(EV_ABS, ABS_HAT0X, 1), 'a')
        self.injector = Injector('foobar', custom_mapping)
        self.injector.context = Context(custom_mapping)

        _grab_device = self.injector._grab_device
        self.assertIsNone(_grab_device('/dev/input/event10'))
        self.assertIsNotNone(_grab_device('/dev/input/event30'))
示例#14
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))
示例#15
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))
示例#16
0
    def test_skip_unknown_device(self):
        custom_mapping.change(Key(EV_KEY, 10, 1), 'a')

        # skips a device because its capabilities are not used in the mapping
        self.injector = Injector('device 1', custom_mapping)
        self.injector.context = Context(custom_mapping)
        path = '/dev/input/event11'
        device = self.injector._grab_device(path)

        # skips the device alltogether, so no grab attempts fail
        self.assertEqual(self.failed, 0)
        self.assertIsNone(device)
示例#17
0
    def test_grab_device_1(self):
        custom_mapping.change(Key(EV_ABS, ABS_HAT0X, 1), 'a')
        self.injector = Injector(groups.find(name='gamepad'), custom_mapping)
        self.injector.context = Context(custom_mapping)

        _grab_device = self.injector._grab_device
        # doesn't have the required capability
        self.assertIsNone(_grab_device('/dev/input/event10'))
        # according to the fixtures, /dev/input/event30 can do ABS_HAT0X
        self.assertIsNotNone(_grab_device('/dev/input/event30'))
        # this doesn't exist
        self.assertIsNone(_grab_device('/dev/input/event1234'))
示例#18
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)
示例#19
0
    def test_combination_keycode(self):
        combination = ((EV_KEY, 1, 1), (EV_KEY, 2, 1))
        _key_to_code = {
            combination: 101
        }

        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(*combination[0]))
        keycode_mapper.handle_keycode(new_event(*combination[1]))

        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
        keycode_mapper.handle_keycode(new_event(*combination[0][:2], 0))
        keycode_mapper.handle_keycode(new_event(*combination[1][:2], 0))
        # 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
        keycode_mapper.handle_keycode(new_event(*combination[1]))
        keycode_mapper.handle_keycode(new_event(*combination[0]))
        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))
示例#20
0
    def test_adds_ev_key(self):
        # for some reason, having any EV_KEY capability is needed to
        # be able to control the mouse. it probably wants the mouse click.
        custom_mapping.change(Key(EV_KEY, BTN_A, 1), 'a')
        self.injector = Injector(groups.find(name='gamepad'), custom_mapping)
        custom_mapping.set('gamepad.joystick.left_purpose', MOUSE)
        self.injector.context = Context(custom_mapping)
        """ABS device without any key capability"""

        path = self.new_gamepad_path
        gamepad_template = copy.deepcopy(fixtures['/dev/input/event30'])
        fixtures[path] = {
            'name': 'qux 2',
            'phys': 'abcd',
            'info': '1234',
            'capabilities': gamepad_template['capabilities']
        }
        del fixtures[path]['capabilities'][EV_KEY]
        device = self.injector._grab_device(path)
        # no reason to grab, BTN_A capability is missing in the device
        self.assertIsNone(device)
        """ABS device with a btn_mouse capability"""

        path = self.new_gamepad_path
        gamepad_template = copy.deepcopy(fixtures['/dev/input/event30'])
        fixtures[path] = {
            'name': 'qux 3',
            'phys': 'abcd',
            'info': '1234',
            'capabilities': gamepad_template['capabilities']
        }
        fixtures[path]['capabilities'][EV_KEY].append(BTN_LEFT)
        fixtures[path]['capabilities'][EV_KEY].append(KEY_A)
        device = self.injector._grab_device(path)
        gamepad = classify(device) == GAMEPAD
        capabilities = self.injector._construct_capabilities(gamepad)
        self.assertIn(EV_KEY, capabilities)
        self.assertIn(evdev.ecodes.BTN_MOUSE, capabilities[EV_KEY])
        self.assertIn(evdev.ecodes.KEY_A, capabilities[EV_KEY])
        """a gamepad"""

        path = '/dev/input/event30'
        device = self.injector._grab_device(path)
        gamepad = classify(device) == GAMEPAD
        self.assertIn(EV_KEY, device.capabilities())
        self.assertNotIn(evdev.ecodes.BTN_MOUSE, device.capabilities()[EV_KEY])
        capabilities = self.injector._construct_capabilities(gamepad)
        self.assertIn(EV_KEY, capabilities)
        self.assertGreater(len(capabilities), 1)
        self.assertIn(evdev.ecodes.BTN_MOUSE, capabilities[EV_KEY])
示例#21
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))
示例#22
0
    def test_construct_capabilities_buttons_buttons(self):
        self.mapping.change(Key(EV_KEY, 60, 1), self.macro.code)

        # those settings shouldn't have an effect with gamepad=False
        config.set('gamepad.joystick.left_purpose', BUTTONS)
        self.mapping.set('gamepad.joystick.right_purpose', BUTTONS)

        self.injector = Injector(groups.find(name='foo'), self.mapping)
        self.injector.context = Context(self.mapping)

        capabilities = self.injector._construct_capabilities(gamepad=False)

        self.check_keys(capabilities)
        self.assertNotIn(EV_ABS, capabilities)
        self.assertNotIn(EV_REL, capabilities)
示例#23
0
    def test_grab(self):
        # path is from the fixtures
        custom_mapping.change(Key(EV_KEY, 10, 1), 'a')

        self.injector = Injector('device 1', custom_mapping)
        path = '/dev/input/event10'
        # this test needs to pass around all other constraints of
        # _grab_device
        self.injector.context = Context(custom_mapping)
        device = self.injector._grab_device(path)
        gamepad = classify(device) == GAMEPAD
        self.assertFalse(gamepad)
        self.assertEqual(self.failed, 2)
        # success on the third try
        device.name = fixtures[path]['name']
示例#24
0
    def test_construct_capabilities_gamepad_none_none(self):
        self.mapping.change(Key(EV_KEY, 60, 1), self.macro.code)

        config.set('gamepad.joystick.left_purpose', NONE)
        self.mapping.set('gamepad.joystick.right_purpose', NONE)

        self.injector = Injector(groups.find(name='foo'), self.mapping)
        self.injector.context = Context(self.mapping)
        self.assertFalse(self.injector.context.maps_joystick())
        self.assertFalse(self.injector.context.joystick_as_mouse())
        self.assertFalse(self.injector.context.joystick_as_dpad())

        capabilities = self.injector._construct_capabilities(gamepad=True)
        self.assertNotIn(EV_ABS, capabilities)

        self.check_keys(capabilities)
示例#25
0
    def test_construct_capabilities_gamepad_buttons_buttons(self):
        self.mapping.change(Key((EV_KEY, 60, 1)), self.macro.code)

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

        self.injector = Injector('foo', self.mapping)
        self.injector.context = Context(self.mapping)
        self.assertTrue(self.injector.context.maps_joystick())
        self.assertFalse(self.injector.context.joystick_as_mouse())
        self.assertTrue(self.injector.context.joystick_as_dpad())

        capabilities = self.injector._construct_capabilities(gamepad=True)

        self.check_keys(capabilities)
        self.assertNotIn(EV_ABS, capabilities)
        self.assertNotIn(EV_REL, capabilities)
示例#26
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)
示例#27
0
    def test_construct_capabilities(self):
        self.mapping.change(Key(EV_KEY, 60, 1), self.macro.code)

        self.injector = Injector(groups.find(name='foo'), self.mapping)
        self.injector.context = Context(self.mapping)

        capabilities = self.injector._construct_capabilities(gamepad=False)
        self.assertNotIn(EV_ABS, capabilities)

        self.check_keys(capabilities)
        keys = capabilities[EV_KEY]
        # mouse capabilities were not present in the fake_device and are
        # still not needed
        self.assertNotIn(self.left, keys)

        self.assertNotIn(evdev.ecodes.EV_SYN, capabilities)
        self.assertNotIn(evdev.ecodes.EV_FF, capabilities)
        self.assertNotIn(EV_REL, capabilities)
示例#28
0
    def test_gamepad_purpose_none(self):
        # forward abs joystick events
        custom_mapping.set('gamepad.joystick.left_purpose', NONE)
        config.set('gamepad.joystick.right_purpose', NONE)

        self.injector = Injector(groups.find(name='gamepad'), custom_mapping)
        self.injector.context = Context(custom_mapping)

        path = '/dev/input/event30'
        device = self.injector._grab_device(path)
        self.assertIsNone(device)  # no capability is used, so it won't grab

        custom_mapping.change(Key(EV_KEY, BTN_A, 1), 'a')
        device = self.injector._grab_device(path)
        self.assertIsNotNone(device)
        gamepad = classify(device) == GAMEPAD
        self.assertTrue(gamepad)
        capabilities = self.injector._construct_capabilities(gamepad)
        self.assertNotIn(EV_ABS, capabilities)
示例#29
0
    def test_fail_grab(self):
        self.make_it_fail = 10
        custom_mapping.change(Key(EV_KEY, 10, 1), 'a')

        self.injector = Injector('device 1', custom_mapping)
        path = '/dev/input/event10'
        self.injector.context = Context(custom_mapping)
        device = self.injector._grab_device(path)
        self.assertIsNone(device)
        self.assertGreaterEqual(self.failed, 1)

        self.assertEqual(self.injector.get_state(), UNKNOWN)
        self.injector.start()
        self.assertEqual(self.injector.get_state(), STARTING)
        # since none can be grabbed, the process will terminate. But that
        # actually takes quite some time.
        time.sleep(1.5)
        self.assertFalse(self.injector.is_alive())
        self.assertEqual(self.injector.get_state(), NO_GRAB)
示例#30
0
    def test_construct_capabilities_gamepad(self):
        self.mapping.change(Key((EV_KEY, 60, 1)), self.macro.code)

        config.set('gamepad.joystick.left_purpose', MOUSE)
        self.mapping.set('gamepad.joystick.right_purpose', WHEEL)

        self.injector = Injector(groups.find(name='foo'), self.mapping)
        self.injector.context = Context(self.mapping)
        self.assertTrue(self.injector.context.maps_joystick())
        self.assertTrue(self.injector.context.joystick_as_mouse())
        self.assertFalse(self.injector.context.joystick_as_dpad())

        capabilities = self.injector._construct_capabilities(gamepad=True)
        self.assertNotIn(EV_ABS, capabilities)

        self.check_keys(capabilities)
        keys = capabilities[EV_KEY]

        # now that it is told that it is a gamepad, btn_left is inserted
        # to ensure the operating system interprets it as mouse.
        self.assertIn(self.left, keys)