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))
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))
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)
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))
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))
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))
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))
def test_combination_keycode_2(self): combination_1 = ( (EV_KEY, 1, 1), (EV_ABS, ABS_Y, MIN_ABS), (EV_KEY, 3, 1), (EV_KEY, 4, 1) ) combination_2 = ( # should not be triggered, combination_1 should be prioritized # when all of its keys are down (EV_KEY, 2, 1), (EV_KEY, 3, 1), (EV_KEY, 4, 1) ) down_5 = (EV_KEY, 5, 1) up_5 = (EV_KEY, 5, 0) up_4 = (EV_KEY, 4, 0) def sign_value(key): return key[0], key[1], key[2] / abs(key[2]) _key_to_code = { # key_to_code is supposed to only contain normalized values tuple([sign_value(a) for a in combination_1]): 101, combination_2: 102, (down_5,): 103 } uinput = UInput() source = InputDevice('/dev/input/event30') # ABS_Y is part of the combination, which only works if the joystick # is configured as D-Pad self.mapping.set('gamepad.joystick.left_purpose', BUTTONS) context = Context(self.mapping) context.uinput = uinput context.key_to_code = _key_to_code keycode_mapper = KeycodeMapper(context, source, uinput) # 10 and 11: insert some more arbitrary key-down events, # they should not break the combinations keycode_mapper.handle_keycode(new_event(EV_KEY, 10, 1)) keycode_mapper.handle_keycode(new_event(*combination_1[0])) keycode_mapper.handle_keycode(new_event(*combination_1[1])) keycode_mapper.handle_keycode(new_event(*combination_1[2])) keycode_mapper.handle_keycode(new_event(EV_KEY, 11, 1)) keycode_mapper.handle_keycode(new_event(*combination_1[3])) # combination_1 should have been triggered now self.assertEqual(len(uinput_write_history), 6) # the first events are written and then the triggered combination, # while the triggering event is the only one that is omitted self.assertEqual(uinput_write_history[1].t, combination_1[0]) self.assertEqual(uinput_write_history[2].t, combination_1[1]) self.assertEqual(uinput_write_history[3].t, combination_1[2]) self.assertEqual(uinput_write_history[5].t, (EV_KEY, 101, 1)) # while the combination is down, another unrelated key can be used keycode_mapper.handle_keycode(new_event(*down_5)) # the keycode_mapper searches for subsets of the current held-down # keys to activate combinations, down_5 should not trigger them # again. self.assertEqual(len(uinput_write_history), 7) self.assertEqual(uinput_write_history[6].t, (EV_KEY, 103, 1)) # release the combination by releasing the last key, and release # the unrelated key keycode_mapper.handle_keycode(new_event(*up_4)) keycode_mapper.handle_keycode(new_event(*up_5)) self.assertEqual(len(uinput_write_history), 9) self.assertEqual(uinput_write_history[7].t, (EV_KEY, 101, 0)) self.assertEqual(uinput_write_history[8].t, (EV_KEY, 103, 0))
def test_wheel_combination_release_failure(self): # test based on a bug that once occurred # 1 | 22.6698, ((1, 276, 1)) -------------- forwarding # 2 | 22.9904, ((1, 276, 1), (2, 8, -1)) -- maps to 30 # 3 | 23.0103, ((1, 276, 1), (2, 8, -1)) -- duplicate key down # 4 | ... 34 more duplicate key downs (scrolling) # 5 | 23.7104, ((1, 276, 1), (2, 8, -1)) -- duplicate key down # 6 | 23.7283, ((1, 276, 0)) -------------- forwarding release # 7 | 23.7303, ((2, 8, -1)) --------------- forwarding # 8 | 23.7865, ((2, 8, 0)) ---------------- not forwarding release # line 7 should have been "duplicate key down" as well # line 8 should have released 30, instead it was never released scroll = (2, 8, -1) scroll_up = (2, 8, 0) btn_down = (1, 276, 1) btn_up = (1, 276, 0) combination = ((1, 276, 1), (2, 8, -1)) system_mapping.clear() system_mapping._set('a', 30) k2c = {combination: 30} uinput = UInput() context = Context(self.mapping) context.uinput = uinput context.key_to_code = k2c keycode_mapper = KeycodeMapper(context, self.source, uinput) keycode_mapper.handle_keycode(new_event(*btn_down)) # "forwarding" self.assertEqual(uinput_write_history[0].t, btn_down) keycode_mapper.handle_keycode(new_event(*scroll)) # "maps to 30" self.assertEqual(uinput_write_history[1].t, (1, 30, 1)) for _ in range(5): # keep scrolling # "duplicate key down" keycode_mapper.handle_keycode(new_event(*scroll)) # nothing new since all of them were duplicate key downs self.assertEqual(len(uinput_write_history), 2) keycode_mapper.handle_keycode(new_event(*btn_up)) # "forwarding release" self.assertEqual(uinput_write_history[2].t, btn_up) # one more scroll event. since the combination is still not released, # it should be ignored as duplicate key-down self.assertEqual(len(uinput_write_history), 3) # "forwarding" (should be "duplicate key down") keycode_mapper.handle_keycode(new_event(*scroll)) self.assertEqual(len(uinput_write_history), 3) # the failure to release the mapped key # forward=False is what the debouncer uses, because a # "scroll release" doesn't actually exist so it is not actually # written if it doesn't release any mapping keycode_mapper.handle_keycode(new_event(*scroll_up), forward=False) # 30 should be released self.assertEqual(uinput_write_history[3].t, (1, 30, 0)) self.assertEqual(len(uinput_write_history), 4)
def test_combination_keycode_macro_mix(self): # ev_1 triggers macro, ev_1 + ev_2 triggers key while the macro is # still running system_mapping.clear() system_mapping._set('a', 92) down_1 = (EV_ABS, ABS_HAT1X, 1) down_2 = (EV_ABS, ABS_HAT1Y, -1) up_1 = (EV_ABS, ABS_HAT1X, 0) up_2 = (EV_ABS, ABS_HAT1Y, 0) macro_mapping = {(down_1,): parse('h(k(a))', self.mapping)} _key_to_code = {(down_1, down_2): 91} macro_history = [] def handler(*args): # handler prevents uinput_write_history form growing macro_history.append(args) uinput = UInput() forward_to = UInput() loop = asyncio.get_event_loop() context = Context(self.mapping) context.uinput = uinput context.key_to_code = _key_to_code context.macros = macro_mapping keycode_mapper = KeycodeMapper(context, self.source, forward_to) keycode_mapper.macro_write = handler # macro starts keycode_mapper.handle_keycode(new_event(*down_1)) loop.run_until_complete(asyncio.sleep(0.05)) self.assertEqual(len(uinput_write_history), 0) self.assertGreater(len(macro_history), 1) self.assertIn(down_1[:2], unreleased) self.assertIn((EV_KEY, 92, 1), macro_history) # combination triggered keycode_mapper.handle_keycode(new_event(*down_2)) self.assertIn(down_1[:2], unreleased) self.assertIn(down_2[:2], unreleased) self.assertEqual(uinput_write_history[0].t, (EV_KEY, 91, 1)) len_a = len(macro_history) loop.run_until_complete(asyncio.sleep(0.05)) len_b = len(macro_history) # still running self.assertGreater(len_b, len_a) # release keycode_mapper.handle_keycode(new_event(*up_1)) self.assertNotIn(down_1[:2], unreleased) self.assertIn(down_2[:2], unreleased) loop.run_until_complete(asyncio.sleep(0.05)) len_c = len(macro_history) loop.run_until_complete(asyncio.sleep(0.05)) len_d = len(macro_history) # not running anymore self.assertEqual(len_c, len_d) keycode_mapper.handle_keycode(new_event(*up_2)) self.assertEqual(uinput_write_history[1].t, (EV_KEY, 91, 0)) self.assertEqual(len(uinput_write_history), 2) self.assertNotIn(down_1[:2], unreleased) self.assertNotIn(down_2[:2], unreleased)
def test_ignore_disabled(self): ev_1 = (EV_ABS, ABS_HAT0Y, 1) ev_2 = (EV_ABS, ABS_HAT0Y, 0) ev_3 = (EV_ABS, ABS_HAT0X, 1) # disabled ev_4 = (EV_ABS, ABS_HAT0X, 0) ev_5 = (EV_KEY, KEY_A, 1) ev_6 = (EV_KEY, KEY_A, 0) combi_1 = (ev_5, ev_3) combi_2 = (ev_3, ev_5) _key_to_code = { (ev_1,): 61, (ev_3,): DISABLE_CODE, combi_1: 62, combi_2: 63 } uinput = UInput() forward_to = UInput() context = Context(self.mapping) context.uinput = uinput context.key_to_code = _key_to_code keycode_mapper = KeycodeMapper(context, self.source, forward_to) def expect_writecounts(uinput_count, forwarded_count): self.assertEqual(uinput.write_count, uinput_count) self.assertEqual(forward_to.write_count, forwarded_count) """single keys""" # down keycode_mapper.handle_keycode(new_event(*ev_1)) keycode_mapper.handle_keycode(new_event(*ev_3)) self.assertIn(ev_1[:2], unreleased) self.assertIn(ev_3[:2], unreleased) expect_writecounts(1, 0) # up keycode_mapper.handle_keycode(new_event(*ev_2)) keycode_mapper.handle_keycode(new_event(*ev_4)) expect_writecounts(2, 0) self.assertNotIn(ev_1[:2], unreleased) self.assertNotIn(ev_3[:2], unreleased) self.assertEqual(len(uinput_write_history), 2) self.assertEqual(uinput_write_history[0].t, (EV_KEY, 61, 1)) self.assertEqual(uinput_write_history[1].t, (EV_KEY, 61, 0)) """a combination that ends in a disabled key""" # ev_5 should be forwarded and the combination triggered keycode_mapper.handle_keycode(new_event(*combi_1[0])) # ev_5 keycode_mapper.handle_keycode(new_event(*combi_1[1])) # ev_3 expect_writecounts(3, 1) self.assertEqual(len(uinput_write_history), 4) self.assertEqual(uinput_write_history[2].t, (EV_KEY, KEY_A, 1)) self.assertEqual(uinput_write_history[3].t, (EV_KEY, 62, 1)) self.assertIn(combi_1[0][:2], unreleased) self.assertIn(combi_1[1][:2], unreleased) # since this event did not trigger anything, key is None self.assertEqual(unreleased[combi_1[0][:2]].triggered_key, None) # that one triggered something from _key_to_code, so the key is that self.assertEqual(unreleased[combi_1[1][:2]].triggered_key, combi_1) # release the last key of the combi first, it should # release what the combination maps to event = new_event(combi_1[1][0], combi_1[1][1], 0) keycode_mapper.handle_keycode(event) expect_writecounts(4, 1) self.assertEqual(len(uinput_write_history), 5) self.assertEqual(uinput_write_history[-1].t, (EV_KEY, 62, 0)) self.assertIn(combi_1[0][:2], unreleased) self.assertNotIn(combi_1[1][:2], unreleased) event = new_event(combi_1[0][0], combi_1[0][1], 0) keycode_mapper.handle_keycode(event) expect_writecounts(4, 2) self.assertEqual(len(uinput_write_history), 6) self.assertEqual(uinput_write_history[-1].t, (EV_KEY, KEY_A, 0)) self.assertNotIn(combi_1[0][:2], unreleased) self.assertNotIn(combi_1[1][:2], unreleased) """a combination that starts with a disabled key""" # only the combination should get triggered keycode_mapper.handle_keycode(new_event(*combi_2[0])) keycode_mapper.handle_keycode(new_event(*combi_2[1])) expect_writecounts(5, 2) self.assertEqual(len(uinput_write_history), 7) self.assertEqual(uinput_write_history[-1].t, (EV_KEY, 63, 1)) # release the last key of the combi first, it should # release what the combination maps to event = new_event(combi_2[1][0], combi_2[1][1], 0) keycode_mapper.handle_keycode(event) self.assertEqual(len(uinput_write_history), 8) self.assertEqual(uinput_write_history[-1].t, (EV_KEY, 63, 0)) expect_writecounts(6, 2) # the first key of combi_2 is disabled, so it won't write another # key-up event event = new_event(combi_2[0][0], combi_2[0][1], 0) keycode_mapper.handle_keycode(event) self.assertEqual(len(uinput_write_history), 8) expect_writecounts(6, 2)
def test_d_pad(self): ev_1 = (EV_ABS, ABS_HAT0X, 1) ev_2 = (EV_ABS, ABS_HAT0X, -1) ev_3 = (EV_ABS, ABS_HAT0X, 0) ev_4 = (EV_ABS, ABS_HAT0Y, 1) ev_5 = (EV_ABS, ABS_HAT0Y, -1) ev_6 = (EV_ABS, ABS_HAT0Y, 0) uinput = UInput() context = Context(self.mapping) context.uinput = uinput context.key_to_code = { (ev_1,): 51, (ev_2,): 52, (ev_4,): 54, (ev_5,): 55, } 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_4)) self.assertEqual(len(unreleased), 2) self.assertEqual( unreleased.get(ev_1[:2]).target_type_code, (EV_KEY, context.key_to_code[(ev_1,)]) ) self.assertEqual(unreleased.get(ev_1[:2]).input_event_tuple, ev_1) self.assertEqual(unreleased.get(ev_1[:2]).triggered_key, (ev_1,)) # as seen in key_to_code self.assertEqual( unreleased.get(ev_4[:2]).target_type_code, (EV_KEY, context.key_to_code[(ev_4,)]), ev_4 ) self.assertEqual(unreleased.get(ev_4[:2]).input_event_tuple, ev_4) self.assertEqual(unreleased.get(ev_4[:2]).triggered_key, (ev_4,)) # release all of them keycode_mapper.handle_keycode(new_event(*ev_3)) keycode_mapper.handle_keycode(new_event(*ev_6)) self.assertEqual(len(unreleased), 0) # repeat with other values keycode_mapper.handle_keycode(new_event(*ev_2)) keycode_mapper.handle_keycode(new_event(*ev_5)) self.assertEqual(len(unreleased), 2) self.assertEqual( unreleased.get(ev_2[:2]).target_type_code, (EV_KEY, context.key_to_code[(ev_2,)]) ) self.assertEqual( unreleased.get(ev_2[:2]).input_event_tuple, ev_2 ) self.assertEqual( unreleased.get(ev_5[:2]).target_type_code, (EV_KEY, context.key_to_code[(ev_5,)]) ) self.assertEqual( unreleased.get(ev_5[:2]).input_event_tuple, ev_5 ) # release all of them again keycode_mapper.handle_keycode(new_event(*ev_3)) keycode_mapper.handle_keycode(new_event(*ev_6)) self.assertEqual(len(unreleased), 0) self.assertEqual(len(uinput_write_history), 8) self.assertEqual(uinput_write_history[0].t, (EV_KEY, 51, 1)) self.assertEqual(uinput_write_history[1].t, (EV_KEY, 54, 1)) self.assertEqual(uinput_write_history[2].t, (EV_KEY, 51, 0)) self.assertEqual(uinput_write_history[3].t, (EV_KEY, 54, 0)) self.assertEqual(uinput_write_history[4].t, (EV_KEY, 52, 1)) self.assertEqual(uinput_write_history[5].t, (EV_KEY, 55, 1)) self.assertEqual(uinput_write_history[6].t, (EV_KEY, 52, 0)) self.assertEqual(uinput_write_history[7].t, (EV_KEY, 55, 0))