Beispiel #1
0
    def test_change_device(self):
        push_events('device 1', [
            new_event(EV_KEY, 1, 1),
        ] * 100)

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

        self.create_helper()

        reader.start_reading('device 1')
        time.sleep(0.1)
        self.assertEqual(reader.read(), Key(EV_KEY, 1, 1))

        reader.start_reading('device 2')

        # 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))
Beispiel #2
0
    def test_combine_triggers(self):
        reader.start_reading('device 1')

        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)
Beispiel #3
0
    def test_clear(self):
        push_events('device 1', [
            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('device 1')
        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()
Beispiel #4
0
    def test_are_new_devices_available(self):
        self.create_helper()
        groups.set_groups({})

        # read stuff from the helper, which includes the devices
        self.assertFalse(reader.are_new_devices_available())
        reader.read()

        self.assertTrue(reader.are_new_devices_available())
        # a bit weird, but it assumes the gui handled that and returns
        # false afterwards
        self.assertFalse(reader.are_new_devices_available())

        # send the same devices again
        reader._get_event({
            'type': 'groups',
            'message': groups.dumps()
        })
        self.assertFalse(reader.are_new_devices_available())

        # send changed devices
        message = groups.dumps()
        message = message.replace('Foo Device', 'foo_device')
        reader._get_event({
            'type': 'groups',
            'message': message
        })
        self.assertTrue(reader.are_new_devices_available())
        self.assertFalse(reader.are_new_devices_available())
Beispiel #5
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('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('gamepad')
        time.sleep(0.1)
        self.assertEqual(reader.read(), None)
        self.assertEqual(len(reader._unreleased), 0)
Beispiel #6
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)
Beispiel #7
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)
Beispiel #8
0
 def test_blacklist(self):
     push_events('device 1', [
         new_event(EV_KEY, BTN_TOOL_DOUBLETAP, 1),
         new_event(EV_KEY, CODE_2, 1),
         new_event(EV_KEY, BTN_TOOL_DOUBLETAP, 1),
     ])
     self.create_helper()
     reader.start_reading('device 1')
     time.sleep(0.1)
     self.assertEqual(reader.read(), (EV_KEY, CODE_2, 1))
     self.assertEqual(reader.read(), None)
     self.assertEqual(len(reader._unreleased), 1)
Beispiel #9
0
 def test_reading_ignore_up(self):
     push_events('device 1', [
         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('device 1')
     time.sleep(0.1)
     self.assertEqual(reader.read(), (EV_KEY, CODE_2, 1))
     self.assertEqual(reader.read(), None)
     self.assertEqual(len(reader._unreleased), 1)
Beispiel #10
0
 def test_ignore_value_2(self):
     # this is not a combination, because (EV_KEY CODE_3, 2) is ignored
     push_events(
         'device 1',
         [new_event(EV_ABS, ABS_HAT0X, 1),
          new_event(EV_KEY, CODE_3, 2)])
     self.create_helper()
     reader.start_reading('device 1')
     time.sleep(0.2)
     self.assertEqual(reader.read(), (EV_ABS, ABS_HAT0X, 1))
     self.assertEqual(reader.read(), None)
     self.assertEqual(len(reader._unreleased), 1)
Beispiel #11
0
 def test_blacklisted_events(self):
     push_events('Foo Device 2', [
         new_event(EV_KEY, BTN_TOOL_DOUBLETAP, 1),
         new_event(EV_KEY, CODE_2, 1),
         new_event(EV_KEY, BTN_TOOL_DOUBLETAP, 1),
     ])
     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)
Beispiel #12
0
    def test_reading_3(self):
        self.create_helper()
        # a combination of events via Socket with reads inbetween
        reader.start_reading('gamepad')

        send_event_to_reader(new_event(EV_KEY, CODE_1, 1, 1001))
        self.assertEqual(reader.read(), ((EV_KEY, CODE_1, 1)))

        custom_mapping.set('gamepad.joystick.left_purpose', BUTTONS)
        send_event_to_reader(new_event(EV_ABS, ABS_Y, 1, 1002))
        self.assertEqual(reader.read(),
                         ((EV_KEY, CODE_1, 1), (EV_ABS, ABS_Y, 1)))

        send_event_to_reader(new_event(EV_ABS, ABS_HAT0X, -1, 1003))
        self.assertEqual(reader.read(),
                         ((EV_KEY, CODE_1, 1), (EV_ABS, ABS_Y, 1),
                          (EV_ABS, ABS_HAT0X, -1)))

        # adding duplicate down events won't report a different combination.
        # import for triggers, as they keep reporting more down-events before
        # they are released
        send_event_to_reader(new_event(EV_ABS, ABS_Y, 1, 1005))
        self.assertEqual(reader.read(), None)
        send_event_to_reader(new_event(EV_ABS, ABS_HAT0X, -1, 1006))
        self.assertEqual(reader.read(), None)

        send_event_to_reader(new_event(EV_KEY, CODE_1, 0, 1004))
        read = reader.read()
        self.assertEqual(read, None)

        send_event_to_reader(new_event(EV_ABS, ABS_Y, 0, 1007))
        self.assertEqual(reader.read(), None)

        send_event_to_reader(new_event(EV_KEY, ABS_HAT0X, 0, 1008))
        self.assertEqual(reader.read(), None)
Beispiel #13
0
    def consume_newest_keycode(self):
        """To capture events from keyboards, mice and gamepads."""
        # the "event" event of Gtk.Window wouldn't trigger on gamepad
        # events, so it became a GLib timeout to periodically check kernel
        # events.

        # letting go of one of the keys of a combination won't just make
        # it return the leftover key, it will continue to return None because
        # they have already been read.
        key = reader.read()

        if reader.are_new_devices_available():
            self.populate_devices()

        # TODO highlight if a row for that key exists or something

        # inform the currently selected row about the new keycode
        row, focused = self.get_focused_row()
        if key is not None:
            if isinstance(focused, Gtk.ToggleButton):
                row.set_new_key(key)

            if key.is_problematic() and isinstance(focused, Gtk.ToggleButton):
                self.show_status(
                    CTX_WARNING,
                    'ctrl, alt and shift may not combine properly',
                    'Your system might reinterpret combinations ' +
                    'with those after they are injected, and by doing so ' +
                    'break them.')

        if row is not None:
            row.refresh_state()

        return True
Beispiel #14
0
    def test_reading_ignore_duplicate_down(self):
        send_event_to_reader(new_event(EV_ABS, ABS_Z, 1, 10))

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

        # duplicate
        send_event_to_reader(new_event(EV_ABS, ABS_Z, 1, 10))
        self.assertEqual(reader.read(), None)
        self.assertEqual(len(reader._unreleased), 1)
        self.assertEqual(len(reader.get_unreleased_keys()), 1)
        self.assertIsInstance(reader.get_unreleased_keys(), Key)

        # release
        send_event_to_reader(new_event(EV_ABS, ABS_Z, 0, 10))
        self.assertEqual(reader.read(), None)
        self.assertEqual(len(reader._unreleased), 0)
        self.assertIsNone(reader.get_unreleased_keys())
Beispiel #15
0
 def test_wrong_device(self):
     push_events('device 1', [
         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('device 2')
     time.sleep(EVENT_READ_TIMEOUT * 5)
     self.assertEqual(reader.read(), None)
     self.assertEqual(len(reader._unreleased), 0)
Beispiel #16
0
    def test_reading_2(self):
        # a combination of events
        push_events('device 1', [
            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)
        ])
        self.create_helper()
        reader.start_reading('device 1')

        # sending anything arbitrary does not stop the helper
        reader._commands.send(856794)

        time.sleep(0.2)

        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)
Beispiel #17
0
    def test_switch_device(self):
        push_events('device 2', [new_event(EV_KEY, CODE_1, 1)])
        push_events('device 1', [new_event(EV_KEY, CODE_3, 1)])
        self.create_helper()

        reader.start_reading('device 2')
        self.assertFalse(reader._results.poll())
        self.assertEqual(reader.device_name, 'device 2')
        time.sleep(EVENT_READ_TIMEOUT * 5)

        self.assertTrue(reader._results.poll())
        reader.start_reading('device 1')
        self.assertEqual(reader.device_name, 'device 1')
        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)
Beispiel #18
0
    def test_are_new_devices_available(self):
        self.create_helper()
        set_devices({})

        # read stuff from the helper, which includes the devices
        self.assertFalse(reader.are_new_devices_available())
        reader.read()

        self.assertTrue(reader.are_new_devices_available())
        # a bit weird, but it assumes the gui handled that and returns
        # false afterwards
        self.assertFalse(reader.are_new_devices_available())

        # send the same devices again
        reader._get_event({'type': 'devices', 'message': get_devices()})
        self.assertFalse(reader.are_new_devices_available())

        # send changed devices
        message = {**get_devices()}
        del message['device 1']
        reader._get_event({'type': 'devices', 'message': message})
        self.assertTrue(reader.are_new_devices_available())
        self.assertFalse(reader.are_new_devices_available())
Beispiel #19
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.
     push_events('key-mapper 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('device 2')
     time.sleep(EVENT_READ_TIMEOUT * 5)
     self.assertEqual(reader.read(), None)
     self.assertEqual(len(reader._unreleased), 0)
Beispiel #20
0
    def test_change_wheel_direction(self):
        # not just wheel, anything that suddenly reports a different value.
        # as long as type and code are equal its the same key, so there is no
        # way both directions can be held down.
        self.assertEqual(reader.read(), None)
        self.create_helper()
        self.assertEqual(reader.read(), None)
        reader.start_reading('device 1')
        self.assertEqual(reader.read(), None)

        send_event_to_reader(new_event(EV_REL, REL_WHEEL, 1))
        self.assertEqual(reader.read(), (EV_REL, REL_WHEEL, 1))
        self.assertEqual(len(reader._unreleased), 1)
        self.assertEqual(reader.read(), None)

        send_event_to_reader(new_event(EV_REL, REL_WHEEL, -1))
        self.assertEqual(reader.read(), (EV_REL, REL_WHEEL, -1))
        # notice that this is no combination of two sides, the previous
        # entry in unreleased has to get overwritten. So there is still only
        # one element in it.
        self.assertEqual(len(reader._unreleased), 1)
        self.assertEqual(reader.read(), None)
Beispiel #21
0
    def test_reading_wheel(self):
        # will be treated as released automatically at some point
        self.create_helper()
        reader.start_reading('device 1')

        send_event_to_reader(new_event(EV_REL, REL_WHEEL, 0))
        self.assertIsNone(reader.read())

        send_event_to_reader(new_event(EV_REL, REL_WHEEL, 1))
        result = reader.read()
        self.assertIsInstance(result, Key)
        self.assertEqual(result, (EV_REL, REL_WHEEL, 1))
        self.assertEqual(result, ((EV_REL, REL_WHEEL, 1), ))
        self.assertNotEqual(result, ((EV_REL, REL_WHEEL, 1), (1, 1, 1)))
        self.assertEqual(result.keys, ((EV_REL, REL_WHEEL, 1), ))

        # it won't return the same event twice
        self.assertEqual(reader.read(), None)

        # but it is still remembered unreleased
        self.assertEqual(len(reader._unreleased), 1)
        self.assertEqual(reader.get_unreleased_keys(), (EV_REL, REL_WHEEL, 1))
        self.assertIsInstance(reader.get_unreleased_keys(), Key)

        # as long as new wheel events arrive, it is considered unreleased
        for _ in range(10):
            send_event_to_reader(new_event(EV_REL, REL_WHEEL, 1))
            self.assertEqual(reader.read(), None)
            self.assertEqual(len(reader._unreleased), 1)

        # read a few more times, at some point it is treated as unreleased
        for _ in range(4):
            self.assertEqual(reader.read(), None)
        self.assertEqual(len(reader._unreleased), 0)
        self.assertIsNone(reader.get_unreleased_keys())
        """combinations"""

        send_event_to_reader(new_event(EV_REL, REL_WHEEL, 1, 1000))
        send_event_to_reader(new_event(EV_KEY, KEY_COMMA, 1, 1001))
        combi_1 = ((EV_REL, REL_WHEEL, 1), (EV_KEY, KEY_COMMA, 1))
        combi_2 = ((EV_KEY, KEY_COMMA, 1), (EV_KEY, KEY_A, 1))
        read = reader.read()
        self.assertEqual(read, combi_1)
        self.assertEqual(reader.read(), None)
        self.assertEqual(len(reader._unreleased), 2)
        self.assertEqual(reader.get_unreleased_keys(), combi_1)

        # don't send new wheel down events, it should get released again
        i = 0
        while len(reader._unreleased) == 2:
            read = reader.read()
            if i == 100:
                raise AssertionError('Did not release the wheel')
            i += 1
        # and only the comma remains. However, a changed combination is
        # only returned when a new key is pressed. Only then the pressed
        # down keys are collected in a new Key object.
        self.assertEqual(read, None)
        self.assertEqual(reader.read(), None)
        self.assertEqual(len(reader._unreleased), 1)
        self.assertEqual(reader.get_unreleased_keys(), combi_1[1])

        # press down a new key, now it will return a different combination
        send_event_to_reader(new_event(EV_KEY, KEY_A, 1, 1002))
        self.assertEqual(reader.read(), combi_2)
        self.assertEqual(len(reader._unreleased), 2)

        # release all of them
        send_event_to_reader(new_event(EV_KEY, KEY_COMMA, 0))
        send_event_to_reader(new_event(EV_KEY, KEY_A, 0))
        self.assertEqual(reader.read(), None)
        self.assertEqual(len(reader._unreleased), 0)
        self.assertEqual(reader.get_unreleased_keys(), None)