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)
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)
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)
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)
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)
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('device 1', 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)
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])
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)
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)
def test_gamepad_to_mouse_event_producer(self): custom_mapping.set('gamepad.joystick.left_purpose', MOUSE) custom_mapping.set('gamepad.joystick.right_purpose', NONE) self.injector = Injector('gamepad', custom_mapping) # the stop message will be available in the pipe right away, # so run won't block and just stop. all the stuff # will be initialized though, so that stuff can be tested self.injector.stop_injecting() # the context serves no purpose in the main process self.assertIsNone(self.injector.context) self.injector.run() # not in a process, so the event_producer state can be checked self.assertEqual(self.injector._event_producer.abs_range[0], MIN_ABS) self.assertEqual(self.injector._event_producer.abs_range[1], MAX_ABS) self.assertEqual( self.injector.context.mapping.get('gamepad.joystick.left_purpose'), MOUSE)
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)
def test_gamepad_capabilities(self): self.injector = Injector(groups.find(name='gamepad'), custom_mapping) # give the injector a reason to grab the device custom_mapping.set('gamepad.joystick.left_purpose', MOUSE) self.injector.context = Context(custom_mapping) path = '/dev/input/event30' 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(evdev.ecodes.REL_X, capabilities.get(EV_REL)) self.assertIn(evdev.ecodes.REL_Y, capabilities.get(EV_REL)) self.assertIn(evdev.ecodes.REL_WHEEL, capabilities.get(EV_REL)) self.assertIn(evdev.ecodes.REL_HWHEEL, capabilities.get(EV_REL)) self.assertIn(EV_KEY, capabilities) self.assertIn(evdev.ecodes.BTN_LEFT, capabilities[EV_KEY])
def on_joystick_mouse_speed_changed(self, gtk_range): """Set how fast the joystick moves the mouse.""" speed = 2**gtk_range.get_value() custom_mapping.set('gamepad.joystick.pointer_speed', speed)
def on_right_joystick_changed(self, dropdown): """Set the purpose of the right joystick.""" purpose = dropdown.get_active_id() custom_mapping.set('gamepad.joystick.right_purpose', purpose) self.save_preset()
def on_left_joystick_purpose_changed(self, dropdown): """Set the purpose of the left joystick.""" purpose = dropdown.get_active_id() custom_mapping.set('gamepad.joystick.left_purpose', purpose)