Esempio n. 1
0
    def test_refresh_for_unknown_key(self):
        device = '9876 name'
        # this test only makes sense if this device is unknown yet
        self.assertIsNone(groups.find(name=device))

        self.daemon = Daemon()

        # make sure the devices are populated
        groups.refresh()

        self.daemon.refresh()

        fixtures[self.new_fixture_path] = {
            'capabilities': {
                evdev.ecodes.EV_KEY: [evdev.ecodes.KEY_A]
            },
            'phys': '9876 phys',
            'info': evdev.device.DeviceInfo(4, 5, 6, 7),
            'name': device
        }

        self.daemon._autoload('25v7j9q4vtj')
        # this is unknown, so the daemon will scan the devices again

        # test if the injector called groups.refresh successfully
        self.assertIsNotNone(groups.find(name=device))
Esempio n. 2
0
    def _handle_commands(self):
        """Handle all unread commands."""
        # wait for something to do
        select.select([self._commands], [], [])

        while self._commands.poll():
            cmd = self._commands.recv()
            logger.debug('Received command "%s"', cmd)

            if cmd == TERMINATE:
                logger.debug('Helper terminates')
                sys.exit(0)

            if cmd == REFRESH_GROUPS:
                groups.refresh()
                self._send_groups()
                continue

            group = groups.find(key=cmd)
            if group is None:
                groups.refresh()
                group = groups.find(key=cmd)

            if group is not None:
                self.group = group
                continue

            logger.error('Received unknown command "%s"', cmd)
Esempio n. 3
0
    def test_reads_joysticks(self):
        # if their purpose is "buttons"
        custom_mapping.set('gamepad.joystick.left_purpose', BUTTONS)
        push_events('gamepad', [
            new_event(EV_ABS, ABS_Y, MAX_ABS),
            # the value of that one is interpreted as release, because
            # it is too small
            new_event(EV_ABS, ABS_X, MAX_ABS // 10)
        ])
        self.create_helper()

        reader.start_reading(groups.find(name='gamepad'))
        time.sleep(0.2)
        self.assertEqual(reader.read(), (EV_ABS, ABS_Y, 1))
        self.assertEqual(reader.read(), None)
        self.assertEqual(len(reader._unreleased), 1)

        reader._unreleased = {}
        custom_mapping.set('gamepad.joystick.left_purpose', MOUSE)
        push_events('gamepad', [
            new_event(EV_ABS, ABS_Y, MAX_ABS)
        ])
        self.create_helper()

        reader.start_reading(groups.find(name='gamepad'))
        time.sleep(0.1)
        self.assertEqual(reader.read(), None)
        self.assertEqual(len(reader._unreleased), 0)
Esempio n. 4
0
    def on_select_device(self, dropdown):
        """List all presets, create one if none exist yet."""
        self.save_preset()

        if self.group and dropdown.get_active_id() == self.group.key:
            return

        # selecting a device will also automatically select a different
        # preset. Prevent another unsaved-changes dialog to pop up
        custom_mapping.changed = False

        group_key = dropdown.get_active_id()

        if group_key is None:
            return

        logger.debug('Selecting device "%s"', group_key)

        self.group = groups.find(key=group_key)
        self.preset_name = None

        self.populate_presets()

        reader.start_reading(groups.find(key=group_key))

        self.show_device_mapping_status()
Esempio n. 5
0
    def test_change_device(self):
        push_events('Foo Device 2', [
            new_event(EV_KEY, 1, 1),
        ] * 100)

        push_events('Bar Device', [
            new_event(EV_KEY, 2, 1),
        ] * 100)

        self.create_helper()

        reader.start_reading(groups.find(key='Foo Device 2'))
        time.sleep(0.1)
        self.assertEqual(reader.read(), Key(EV_KEY, 1, 1))

        reader.start_reading(groups.find(name='Bar Device'))

        # it's plausible that right after sending the new read command more
        # events from the old device might still appear. Give the helper
        # some time to handle the new command.
        time.sleep(0.1)
        reader.clear()

        time.sleep(0.1)
        self.assertEqual(reader.read(), Key(EV_KEY, 2, 1))
Esempio n. 6
0
    def test_refresh_on_start(self):
        if os.path.exists(get_config_path('xmodmap.json')):
            os.remove(get_config_path('xmodmap.json'))

        ev = (EV_KEY, 9)
        keycode_to = 100
        group_name = '9876 name'

        # expected key of the group
        group_key = group_name

        group = groups.find(name=group_name)
        # this test only makes sense if this device is unknown yet
        self.assertIsNone(group)
        custom_mapping.change(Key(*ev, 1), 'a')
        system_mapping.clear()
        system_mapping._set('a', keycode_to)

        # make the daemon load the file instead
        with open(get_config_path('xmodmap.json'), 'w') as file:
            json.dump(system_mapping._mapping, file, indent=4)
        system_mapping.clear()

        preset = 'foo'
        custom_mapping.save(get_preset_path(group_name, preset))
        config.set_autoload_preset(group_key, preset)
        push_events(group_key, [new_event(*ev, 1)])
        self.daemon = Daemon()

        # make sure the devices are populated
        groups.refresh()

        # the daemon is supposed to find this device by calling refresh
        fixtures[self.new_fixture_path] = {
            'capabilities': {
                evdev.ecodes.EV_KEY: [ev[1]]
            },
            'phys': '9876 phys',
            'info': evdev.device.DeviceInfo(4, 5, 6, 7),
            'name': group_name
        }

        self.daemon.set_config_dir(get_config_path())
        self.daemon.start_injecting(group_key, preset)

        # test if the injector called groups.refresh successfully
        group = groups.find(key=group_key)
        self.assertEqual(group.name, group_name)
        self.assertEqual(group.key, group_key)

        time.sleep(0.1)
        self.assertTrue(uinput_write_history_pipe[0].poll())

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

        self.daemon.stop_injecting(group_key)
        self.assertEqual(self.daemon.get_state(group_key), STOPPED)
Esempio n. 7
0
    def test_skip_camera(self):
        fixtures['/foo/bar'] = {
            'name': 'camera',
            'phys': 'abcd1',
            'info': evdev.DeviceInfo(1, 2, 3, 4),
            'capabilities': {
                evdev.ecodes.EV_KEY: [evdev.ecodes.KEY_CAMERA]
            }
        }

        groups.refresh()
        self.assertIsNone(groups.find(name='camera'))
        self.assertIsNotNone(groups.find(name='gamepad'))
Esempio n. 8
0
    def test_clear(self):
        push_events('Foo Device 2', [
            new_event(EV_KEY, CODE_1, 1),
            new_event(EV_KEY, CODE_2, 1),
            new_event(EV_KEY, CODE_3, 1)
        ] * 15)

        self.create_helper()
        reader.start_reading(groups.find(key='Foo Device 2'))
        time.sleep(START_READING_DELAY + EVENT_READ_TIMEOUT * 3)

        reader.read()
        self.assertEqual(len(reader._unreleased), 3)
        self.assertIsNotNone(reader.previous_event)
        self.assertIsNotNone(reader.previous_result)

        # make the helper send more events to the reader
        time.sleep(EVENT_READ_TIMEOUT * 2)
        self.assertTrue(reader._results.poll())
        reader.clear()

        self.assertFalse(reader._results.poll())
        self.assertEqual(reader.read(), None)
        self.assertEqual(len(reader._unreleased), 0)
        self.assertIsNone(reader.get_unreleased_keys())
        self.assertIsNone(reader.previous_event)
        self.assertIsNone(reader.previous_result)
        self.tearDown()
Esempio n. 9
0
    def test_combine_triggers(self):
        reader.start_reading(groups.find(key='Foo Device 2'))

        i = 0

        def next_timestamp():
            nonlocal i
            i += 1
            return time.time() + i

        # based on an observed bug
        send_event_to_reader(new_event(3, 1, 0, next_timestamp()))
        send_event_to_reader(new_event(3, 0, 0, next_timestamp()))
        send_event_to_reader(new_event(3, 2, 1, next_timestamp()))
        self.assertEqual(reader.read(), (EV_ABS, ABS_Z, 1))
        send_event_to_reader(new_event(3, 0, 0, next_timestamp()))
        send_event_to_reader(new_event(3, 5, 1, next_timestamp()))
        self.assertEqual(reader.read(), ((EV_ABS, ABS_Z, 1), (EV_ABS, ABS_RZ, 1)))
        send_event_to_reader(new_event(3, 5, 0, next_timestamp()))
        send_event_to_reader(new_event(3, 0, 0, next_timestamp()))
        send_event_to_reader(new_event(3, 1, 0, next_timestamp()))
        self.assertEqual(reader.read(), None)
        send_event_to_reader(new_event(3, 2, 1, next_timestamp()))
        send_event_to_reader(new_event(3, 1, 0, next_timestamp()))
        send_event_to_reader(new_event(3, 0, 0, next_timestamp()))
        # due to not properly handling the duplicate down event it cleared
        # the combination and returned it. Instead it should report None
        # and by doing that keep the previous combination.
        self.assertEqual(reader.read(), None)
Esempio n. 10
0
    def test_store_permutations_for_macros(self):
        mapping = Mapping()
        ev_1 = (EV_KEY, 41, 1)
        ev_2 = (EV_KEY, 42, 1)
        ev_3 = (EV_KEY, 43, 1)
        # a combination
        mapping.change(Key(ev_1, ev_2, ev_3), 'k(a)')
        self.injector = Injector(groups.find(key='Foo Device 2'), mapping)

        history = []

        class Stop(Exception):
            pass

        def _construct_capabilities(*args):
            history.append(args)
            # avoid going into any mainloop
            raise Stop()

        with mock.patch.object(self.injector, '_construct_capabilities',
                               _construct_capabilities):
            try:
                self.injector.run()
            except Stop:
                pass

            # one call
            self.assertEqual(len(history), 1)
            # first argument of the first call
            macros = self.injector.context.macros
            self.assertEqual(len(macros), 2)
            self.assertEqual(macros[(ev_1, ev_2, ev_3)].code, 'k(a)')
            self.assertEqual(macros[(ev_2, ev_1, ev_3)].code, 'k(a)')
Esempio n. 11
0
    def test_gamepad_forward_joysticks(self):
        push_events(
            'gamepad',
            [
                # should forward them unmodified
                new_event(EV_ABS, ABS_X, 10),
                new_event(EV_ABS, ABS_Y, 20),
                new_event(EV_ABS, ABS_X, -30),
                new_event(EV_ABS, ABS_Y, -40),
                new_event(EV_KEY, BTN_A, 1),
                new_event(EV_KEY, BTN_A, 0)
            ] * 2)

        custom_mapping.set('gamepad.joystick.left_purpose', NONE)
        custom_mapping.set('gamepad.joystick.right_purpose', NONE)
        # BTN_A -> 77
        custom_mapping.change(Key((1, BTN_A, 1)), 'b')
        system_mapping._set('b', 77)
        self.injector = Injector(groups.find(name='gamepad'), custom_mapping)
        self.injector.start()

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

        # convert the write history to some easier to manage list
        history = read_write_history_pipe()

        self.assertEqual(history.count((EV_ABS, ABS_X, 10)), 2)
        self.assertEqual(history.count((EV_ABS, ABS_Y, 20)), 2)
        self.assertEqual(history.count((EV_ABS, ABS_X, -30)), 2)
        self.assertEqual(history.count((EV_ABS, ABS_Y, -40)), 2)
        self.assertEqual(history.count((EV_KEY, 77, 1)), 2)
        self.assertEqual(history.count((EV_KEY, 77, 0)), 2)
Esempio n. 12
0
    def test_reading_2(self):
        # a combination of events
        push_events('Foo Device 2', [
            new_event(EV_KEY, CODE_1, 1, 10000.1234),
            new_event(EV_KEY, CODE_3, 1, 10001.1234),
            new_event(EV_ABS, ABS_HAT0X, -1, 10002.1234)
        ])

        pipe = multiprocessing.Pipe()

        def refresh():
            # from within the helper process notify this test that
            # refresh was called as expected
            pipe[1].send('refreshed')

        with mock.patch.object(groups, 'refresh', refresh):
            self.create_helper()

        reader.start_reading(groups.find(key='Foo Device 2'))

        # sending anything arbitrary does not stop the helper
        reader._commands.send(856794)
        time.sleep(0.2)
        # but it makes it look for new devices because maybe its list of
        # groups is not up-to-date
        self.assertTrue(pipe[0].poll())
        self.assertEqual(pipe[0].recv(), 'refreshed')

        self.assertEqual(reader.read(), (
            (EV_KEY, CODE_1, 1),
            (EV_KEY, CODE_3, 1),
            (EV_ABS, ABS_HAT0X, -1)
        ))
        self.assertEqual(reader.read(), None)
        self.assertEqual(len(reader._unreleased), 3)
Esempio n. 13
0
    def test_start_stop(self):
        group = groups.find(key='Foo Device 2')
        preset = 'preset9'

        daemon = Daemon()

        start_history = []
        stop_history = []
        stop_all_history = []
        daemon.start_injecting = lambda *args: start_history.append(args)
        daemon.stop_injecting = lambda *args: stop_history.append(args)
        daemon.stop_all = lambda *args: stop_all_history.append(args)

        communicate(
            options('start', None, preset, group.paths[0], False, False,
                    False), daemon)
        self.assertEqual(len(start_history), 1)
        self.assertEqual(start_history[0], (group.key, preset))

        communicate(
            options('stop', None, None, group.paths[1], False, False, False),
            daemon)
        self.assertEqual(len(stop_history), 1)
        # provided any of the groups paths as --device argument, figures out
        # the correct group.key to use here
        self.assertEqual(stop_history[0], (group.key, ))

        communicate(options('stop-all', None, None, None, False, False, False),
                    daemon)
        self.assertEqual(len(stop_all_history), 1)
        self.assertEqual(stop_all_history[0], ())
Esempio n. 14
0
    def test_gamepad_trigger(self):
        # map one of the triggers to BTN_NORTH, while the other one
        # should be forwarded unchanged
        value = MAX_ABS // 2
        push_events('gamepad', [
            new_event(EV_ABS, ABS_Z, value),
            new_event(EV_ABS, ABS_RZ, value),
        ])

        # ABS_Z -> 77
        # ABS_RZ is not mapped
        custom_mapping.change(Key((EV_ABS, ABS_Z, 1)), 'b')
        system_mapping._set('b', 77)
        self.injector = Injector(groups.find(name='gamepad'), custom_mapping)
        self.injector.start()

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

        # convert the write history to some easier to manage list
        history = read_write_history_pipe()

        self.assertEqual(history.count((EV_KEY, 77, 1)), 1)
        self.assertEqual(history.count((EV_ABS, ABS_RZ, value)), 1)
Esempio n. 15
0
 def test_gamepad_to_buttons_event_producer(self):
     custom_mapping.set('gamepad.joystick.left_purpose', BUTTONS)
     custom_mapping.set('gamepad.joystick.right_purpose', BUTTONS)
     self.injector = Injector(groups.find(name='gamepad'), custom_mapping)
     self.injector.stop_injecting()
     self.injector.run()
     self.assertIsNone(self.injector._event_producer.abs_range)
Esempio n. 16
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()

            push_events('gamepad', [
                new_event(*w_down),
                new_event(*d_down),
                new_event(*w_up),
                new_event(*d_up),
            ])

            self.injector = Injector(groups.find(name='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._grab_device = lambda *args: input

            self.injector.start()
            uinput_write_history_pipe[0].poll(timeout=1)
            time.sleep(EVENT_READ_TIMEOUT * 10)
            return read_write_history_pipe()
Esempio n. 17
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)
Esempio n. 18
0
    def test_autoload_other_path(self):
        device_names = ['Foo Device', 'Bar Device']
        groups_ = [groups.find(name=name) for name in device_names]
        presets = ['bar123', 'bar2']
        config_dir = os.path.join(tmp, 'qux', 'quux')
        paths = [
            os.path.join(config_dir, 'presets', device_names[0],
                         presets[0] + '.json'),
            os.path.join(config_dir, 'presets', device_names[1],
                         presets[1] + '.json')
        ]

        Mapping().save(paths[0])
        Mapping().save(paths[1])

        daemon = Daemon()

        start_history = []
        daemon.start_injecting = lambda *args: start_history.append(args)

        config.path = os.path.join(config_dir, 'config.json')
        config.load_config()
        config.set_autoload_preset(device_names[0], presets[0])
        config.set_autoload_preset(device_names[1], presets[1])
        config.save_config()

        communicate(
            options('autoload', config_dir, None, None, False, False, False),
            daemon)

        self.assertEqual(len(start_history), 2)
        self.assertEqual(start_history[0], (groups_[0].key, presets[0]))
        self.assertEqual(start_history[1], (groups_[1].key, presets[1]))
Esempio n. 19
0
 def select_newest_preset(self):
     """Find and select the newest preset (and its device)."""
     device, preset = find_newest_preset()
     group = groups.find(name=device)
     if device is not None:
         self.get('device_selection').set_active_id(group.key)
     if preset is not None:
         self.get('preset_selection').set_active_id(preset)
Esempio n. 20
0
    def test_autoload(self):
        preset = 'preset7'
        group = groups.find(key='Foo Device 2')

        daemon = Daemon()
        self.daemon = daemon
        self.daemon.set_config_dir(get_config_path())

        mapping = Mapping()
        mapping.change(Key(3, 2, 1), 'a')
        mapping.save(group.get_preset_path(preset))

        # no autoloading is configured yet
        self.daemon._autoload(group.key)
        self.assertNotIn(group.key, daemon.autoload_history._autoload_history)
        self.assertTrue(daemon.autoload_history.may_autoload(
            group.key, preset))

        config.set_autoload_preset(group.key, preset)
        config.save_config()
        self.daemon.set_config_dir(get_config_path())
        len_before = len(self.daemon.autoload_history._autoload_history)
        # now autoloading is configured, so it will autoload
        self.daemon._autoload(group.key)
        len_after = len(self.daemon.autoload_history._autoload_history)
        self.assertEqual(
            daemon.autoload_history._autoload_history[group.key][1], preset)
        self.assertFalse(
            daemon.autoload_history.may_autoload(group.key, preset))
        injector = daemon.injectors[group.key]
        self.assertEqual(len_before + 1, len_after)

        # calling duplicate _autoload does nothing
        self.daemon._autoload(group.key)
        self.assertEqual(
            daemon.autoload_history._autoload_history[group.key][1], preset)
        self.assertEqual(injector, daemon.injectors[group.key])
        self.assertFalse(
            daemon.autoload_history.may_autoload(group.key, preset))

        # explicit start_injecting clears the autoload history
        self.daemon.start_injecting(group.key, preset)
        self.assertTrue(daemon.autoload_history.may_autoload(
            group.key, preset))

        # calling autoload for (yet) unknown devices does nothing
        len_before = len(self.daemon.autoload_history._autoload_history)
        self.daemon._autoload('unknown-key-1234')
        len_after = len(self.daemon.autoload_history._autoload_history)
        self.assertEqual(len_before, len_after)

        # autoloading key-mapper devices does nothing
        len_before = len(self.daemon.autoload_history._autoload_history)
        self.daemon.autoload_single('Bar Device')
        len_after = len(self.daemon.autoload_history._autoload_history)
        self.assertEqual(len_before, len_after)
Esempio n. 21
0
 def test_device1_event_producer(self):
     custom_mapping.set('gamepad.joystick.left_purpose', MOUSE)
     custom_mapping.set('gamepad.joystick.right_purpose', WHEEL)
     self.injector = Injector(groups.find(key='Foo Device 2'),
                              custom_mapping)
     self.injector.stop_injecting()
     self.injector.run()
     # not a gamepad, so _event_producer is not initialized for that.
     # it can still debounce stuff though
     self.assertIsNone(self.injector._event_producer.abs_range)
Esempio n. 22
0
    def test_duplicate_device(self):
        fixtures['/dev/input/event20']['name'] = 'Foo Device'
        groups.refresh()

        group1 = groups.find(key='Foo Device')
        group2 = groups.find(key='Foo Device 2')
        group3 = groups.find(key='Foo Device 3')

        self.assertIn('/dev/input/event1', group1.paths)
        self.assertIn('/dev/input/event10', group2.paths)
        self.assertIn('/dev/input/event20', group3.paths)

        self.assertEqual(group1.key, 'Foo Device')
        self.assertEqual(group2.key, 'Foo Device 2')
        self.assertEqual(group3.key, 'Foo Device 3')

        self.assertEqual(group1.name, 'Foo Device')
        self.assertEqual(group2.name, 'Foo Device')
        self.assertEqual(group3.name, 'Foo Device')
Esempio n. 23
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(groups.find(key='Foo Device 2'),
                              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)
Esempio n. 24
0
 def test_reading_1(self):
     # a single event
     push_events('Foo Device 2', [new_event(EV_ABS, ABS_HAT0X, 1)])
     push_events('Foo Device 2', [new_event(EV_ABS, REL_X, 1)])  # mouse movements are ignored
     self.create_helper()
     reader.start_reading(groups.find(key='Foo Device 2'))
     time.sleep(0.2)
     self.assertEqual(reader.read(), (EV_ABS, ABS_HAT0X, 1))
     self.assertEqual(reader.read(), None)
     self.assertEqual(len(reader._unreleased), 1)
Esempio n. 25
0
 def test_wrong_device(self):
     push_events('Foo Device 2', [
         new_event(EV_KEY, CODE_1, 1),
         new_event(EV_KEY, CODE_2, 1),
         new_event(EV_KEY, CODE_3, 1)
     ])
     self.create_helper()
     reader.start_reading(groups.find(name='Bar Device'))
     time.sleep(EVENT_READ_TIMEOUT * 5)
     self.assertEqual(reader.read(), None)
     self.assertEqual(len(reader._unreleased), 0)
Esempio n. 26
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'))
Esempio n. 27
0
    def test_switch_device(self):
        push_events('Bar Device', [new_event(EV_KEY, CODE_1, 1)])
        push_events('Foo Device 2', [new_event(EV_KEY, CODE_3, 1)])
        self.create_helper()

        reader.start_reading(groups.find(name='Bar Device'))
        self.assertFalse(reader._results.poll())
        self.assertEqual(reader.group.name, 'Bar Device')
        time.sleep(EVENT_READ_TIMEOUT * 5)

        self.assertTrue(reader._results.poll())
        reader.start_reading(groups.find(key='Foo Device 2'))
        self.assertEqual(reader.group.name, 'Foo Device')
        self.assertFalse(reader._results.poll())  # pipe resets

        time.sleep(EVENT_READ_TIMEOUT * 5)
        self.assertTrue(reader._results.poll())

        self.assertEqual(reader.read(), (EV_KEY, CODE_3, 1))
        self.assertEqual(reader.read(), None)
        self.assertEqual(len(reader._unreleased), 1)
Esempio n. 28
0
    def test_capabilities_and_uinput_presence(self, ungrab_patch):
        custom_mapping.change(Key(EV_KEY, KEY_A, 1), 'c')
        custom_mapping.change(Key(EV_REL, REL_HWHEEL, 1), 'k(b)')
        self.injector = Injector(groups.find(key='Foo Device 2'),
                                 custom_mapping)
        self.injector.stop_injecting()
        self.injector.run()

        self.assertEqual(
            self.injector.context.mapping.get_symbol(Key(EV_KEY, KEY_A, 1)),
            'c')
        self.assertEqual(
            self.injector.context.key_to_code[((EV_KEY, KEY_A, 1), )], KEY_C)
        self.assertEqual(
            self.injector.context.mapping.get_symbol(Key(
                EV_REL, REL_HWHEEL, 1)), 'k(b)')
        self.assertEqual(
            self.injector.context.macros[((EV_REL, REL_HWHEEL, 1), )].code,
            'k(b)')

        self.assertListEqual(
            sorted(uinputs.keys()),
            sorted([
                # reading and preventing original events from reaching the
                # display server
                'key-mapper Foo Device foo forwarded',
                'key-mapper Foo Device forwarded',
                # injection
                'key-mapper Foo Device 2 mapped'
            ]))

        forwarded_foo = uinputs.get('key-mapper Foo Device foo forwarded')
        forwarded = uinputs.get('key-mapper Foo Device forwarded')
        mapped = uinputs.get('key-mapper Foo Device 2 mapped')
        self.assertIsNotNone(forwarded_foo)
        self.assertIsNotNone(forwarded)
        self.assertIsNotNone(mapped)

        # puts the needed capabilities into the new key-mapper device
        self.assertIn(EV_KEY, mapped.capabilities())
        self.assertEqual(len(mapped.capabilities()[EV_KEY]), 2)
        self.assertIn(KEY_C, mapped.capabilities()[EV_KEY])
        self.assertIn(KEY_B, mapped.capabilities()[EV_KEY])
        # not a gamepad that maps joysticks to mouse movements
        self.assertNotIn(EV_REL, mapped.capabilities())

        # copies capabilities for all other forwarded devices
        self.assertIn(EV_REL, forwarded_foo.capabilities())
        self.assertIn(EV_KEY, forwarded.capabilities())
        self.assertEqual(sorted(forwarded.capabilities()[EV_KEY]),
                         keyboard_keys)

        self.assertEqual(ungrab_patch.call_count, 2)
Esempio n. 29
0
    def test_device_with_only_ev_abs(self):
        # could be anything, a lot of devices have ABS_X capabilities,
        # so it is not treated as gamepad joystick and since it also
        # doesn't have key capabilities, there is nothing to map.
        fixtures['/foo/bar'] = {
            'name': 'qux',
            'phys': 'abcd2',
            'info': evdev.DeviceInfo(1, 2, 3, 4),
            'capabilities': {
                evdev.ecodes.EV_ABS: [evdev.ecodes.ABS_X]
            }
        }

        groups.refresh()
        self.assertIsNotNone(groups.find(name='gamepad'))
        self.assertIsNone(groups.find(name='qux'))

        # verify this test even works at all
        fixtures['/foo/bar']['capabilities'][EV_KEY] = [KEY_A]
        groups.refresh()
        self.assertIsNotNone(groups.find(name='qux'))
Esempio n. 30
0
 def test_reading_ignore_up(self):
     push_events('Foo Device 2', [
         new_event(EV_KEY, CODE_1, 0, 10),
         new_event(EV_KEY, CODE_2, 1, 11),
         new_event(EV_KEY, CODE_3, 0, 12),
     ])
     self.create_helper()
     reader.start_reading(groups.find(key='Foo Device 2'))
     time.sleep(0.1)
     self.assertEqual(reader.read(), (EV_KEY, CODE_2, 1))
     self.assertEqual(reader.read(), None)
     self.assertEqual(len(reader._unreleased), 1)