Rename keycodes to keys, simpler and easier to deal with
This commit is contained in:
		
							
								
								
									
										608
									
								
								kmk/keys.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										608
									
								
								kmk/keys.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,608 @@ | ||||
| import gc | ||||
|  | ||||
| import kmk.handlers.layers as layers | ||||
| import kmk.handlers.stock as handlers | ||||
| from kmk.consts import UnicodeMode | ||||
| from kmk.types import (AttrDict, KeySeqSleepMeta, LayerKeyMeta, | ||||
|                        TapDanceKeyMeta, UnicodeModeKeyMeta) | ||||
|  | ||||
| FIRST_KMK_INTERNAL_KEY = 1000 | ||||
| NEXT_AVAILABLE_KEY = 1000 | ||||
|  | ||||
| KEY_SIMPLE = 0 | ||||
| KEY_MODIFIER = 1 | ||||
| KEY_CONSUMER = 2 | ||||
|  | ||||
| # Global state, will be filled in througout this file, and | ||||
| # anywhere the user creates custom keys | ||||
| KC = AttrDict() | ||||
|  | ||||
|  | ||||
| class Key: | ||||
|     def __init__( | ||||
|         self, | ||||
|         code, | ||||
|         has_modifiers=None, | ||||
|         no_press=False, | ||||
|         no_release=False, | ||||
|         on_press=handlers.default_pressed, | ||||
|         on_release=handlers.default_released, | ||||
|         meta=object(), | ||||
|     ): | ||||
|         self.code = code | ||||
|         self.has_modifiers = has_modifiers | ||||
|         # cast to bool() in case we get a None value | ||||
|         self.no_press = bool(no_press) | ||||
|         self.no_release = bool(no_press) | ||||
|  | ||||
|         self._on_press = on_press | ||||
|         self._on_release = on_release | ||||
|         self.meta = meta | ||||
|  | ||||
|     def __call__(self, no_press=None, no_release=None): | ||||
|         if no_press is None and no_release is None: | ||||
|             return self | ||||
|  | ||||
|         return Key( | ||||
|             code=self.code, | ||||
|             has_modifiers=self.has_modifiers, | ||||
|             no_press=no_press, | ||||
|             no_release=no_release, | ||||
|         ) | ||||
|  | ||||
|     def __repr__(self): | ||||
|         return 'Key(code={}, has_modifiers={})'.format(self.code, self.has_modifiers) | ||||
|  | ||||
|     def on_press(self, state, coord_int, coord_raw): | ||||
|         return self._on_press(self, state, KC, coord_int, coord_raw) | ||||
|  | ||||
|     def on_release(self, state, coord_int, coord_raw): | ||||
|         return self._on_release(self, state, KC, coord_int, coord_raw) | ||||
|  | ||||
|  | ||||
| class ModifierKey(Key): | ||||
|     # FIXME this is atrocious to read. Please, please, please, strike down upon | ||||
|     # this with great vengeance and furious anger. | ||||
|  | ||||
|     FAKE_CODE = -1 | ||||
|  | ||||
|     def __call__(self, modified_code=None, no_press=None, no_release=None): | ||||
|         if modified_code is None and no_press is None and no_release is None: | ||||
|             return self | ||||
|  | ||||
|         if modified_code is not None: | ||||
|             if isinstance(modified_code, ModifierKey): | ||||
|                 new_keycode = ModifierKey( | ||||
|                     ModifierKey.FAKE_CODE, | ||||
|                     set() if self.has_modifiers is None else self.has_modifiers, | ||||
|                     no_press=no_press, | ||||
|                     no_release=no_release, | ||||
|                 ) | ||||
|  | ||||
|                 if self.code != ModifierKey.FAKE_CODE: | ||||
|                     new_keycode.has_modifiers.add(self.code) | ||||
|  | ||||
|                 if modified_code.code != ModifierKey.FAKE_CODE: | ||||
|                     new_keycode.has_modifiers.add(modified_code.code) | ||||
|             else: | ||||
|                 new_keycode = Key( | ||||
|                     modified_code.code, | ||||
|                     {self.code}, | ||||
|                     no_press=no_press, | ||||
|                     no_release=no_release, | ||||
|                 ) | ||||
|  | ||||
|             if modified_code.has_modifiers: | ||||
|                 new_keycode.has_modifiers |= modified_code.has_modifiers | ||||
|         else: | ||||
|             new_keycode = Key( | ||||
|                 self.code, | ||||
|                 no_press=no_press, | ||||
|                 no_release=no_release, | ||||
|             ) | ||||
|  | ||||
|         return new_keycode | ||||
|  | ||||
|     def __repr__(self): | ||||
|         return 'ModifierKey(code={}, has_modifiers={})'.format(self.code, self.has_modifiers) | ||||
|  | ||||
|  | ||||
| class ConsumerKey(Key): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| def register_key_names(key, names=tuple()):  # NOQA | ||||
|     ''' | ||||
|     Names are globally unique. If a later key is created with | ||||
|     the same name as an existing entry in `KC`, it will overwrite | ||||
|     the existing entry. | ||||
|  | ||||
|     If a name entry is only a single letter, its entry in the KC | ||||
|     object will not be case-sensitive (meaning `names=('A',)` is | ||||
|     sufficient to create a key accessible by both `KC.A` and `KC.a`). | ||||
|     ''' | ||||
|  | ||||
|     for name in names: | ||||
|         KC[name] = key | ||||
|  | ||||
|         if len(name) == 1: | ||||
|             KC[name.upper()] = key | ||||
|             KC[name.lower()] = key | ||||
|  | ||||
|     return key | ||||
|  | ||||
|  | ||||
| def make_key( | ||||
|     code=None, | ||||
|     names=tuple(),  # NOQA | ||||
|     type=KEY_SIMPLE, | ||||
|     **kwargs, | ||||
| ): | ||||
|     ''' | ||||
|     Create a new key, aliased by `names` in the KC lookup table. | ||||
|  | ||||
|     If a code is not specified, the key is assumed to be a custom | ||||
|     internal key to be handled in a state callback rather than | ||||
|     sent directly to the OS. These codes will autoincrement. | ||||
|  | ||||
|     See register_key_names() for details on the assignment. | ||||
|  | ||||
|     All **kwargs are passed to the Key constructor | ||||
|     ''' | ||||
|  | ||||
|     global NEXT_AVAILABLE_KEY | ||||
|  | ||||
|     if type == KEY_SIMPLE: | ||||
|         constructor = Key | ||||
|     elif type == KEY_MODIFIER: | ||||
|         constructor = ModifierKey | ||||
|     elif type == KEY_CONSUMER: | ||||
|         constructor = ConsumerKey | ||||
|     else: | ||||
|         raise ValueError('Unrecognized key type') | ||||
|  | ||||
|     if code is None: | ||||
|         code = NEXT_AVAILABLE_KEY | ||||
|         NEXT_AVAILABLE_KEY += 1 | ||||
|     elif code >= FIRST_KMK_INTERNAL_KEY: | ||||
|         # Try to ensure future auto-generated internal keycodes won't | ||||
|         # be overridden by continuing to +1 the sequence from the provided | ||||
|         # code | ||||
|         NEXT_AVAILABLE_KEY = max(NEXT_AVAILABLE_KEY, code + 1) | ||||
|  | ||||
|     key = constructor(code=code, **kwargs) | ||||
|  | ||||
|     register_key_names(key, names) | ||||
|  | ||||
|     return key | ||||
|  | ||||
|  | ||||
| def make_mod_key(*args, **kwargs): | ||||
|     return make_key(*args, **kwargs, type=KEY_MODIFIER) | ||||
|  | ||||
|  | ||||
| def make_shifted_key(target_name, names=tuple()):  # NOQA | ||||
|     key = KC.LSFT(KC[target_name]) | ||||
|  | ||||
|     register_key_names(key, names) | ||||
|  | ||||
|     return key | ||||
|  | ||||
|  | ||||
| def make_consumer_key(*args, **kwargs): | ||||
|     return make_key(*args, **kwargs, type=KEY_CONSUMER) | ||||
|  | ||||
|  | ||||
| # Argumented keys are implicitly internal, so auto-gen of code | ||||
| # is almost certainly the best plan here | ||||
| def make_argumented_key( | ||||
|     validator=lambda *validator_args, **validator_kwargs: object(), | ||||
|     names=tuple(),  # NOQA | ||||
|     *constructor_args, | ||||
|     **constructor_kwargs, | ||||
| ): | ||||
|     global NEXT_AVAILABLE_KEY | ||||
|  | ||||
|     def _argumented_key(*user_args, **user_kwargs): | ||||
|         global NEXT_AVAILABLE_KEY | ||||
|  | ||||
|         meta = validator(*user_args, **user_kwargs) | ||||
|  | ||||
|         if meta: | ||||
|             key = Key( | ||||
|                 NEXT_AVAILABLE_KEY, | ||||
|                 meta=meta, | ||||
|                 *constructor_args, | ||||
|                 **constructor_kwargs, | ||||
|             ) | ||||
|  | ||||
|             NEXT_AVAILABLE_KEY += 1 | ||||
|  | ||||
|             return key | ||||
|  | ||||
|         else: | ||||
|             raise ValueError( | ||||
|                 'Argumented key validator failed for unknown reasons. ' | ||||
|                 'This may not be the keymap\'s fault, as a more specific error ' | ||||
|                 'should have been raised.', | ||||
|             ) | ||||
|  | ||||
|     for name in names: | ||||
|         KC[name] = _argumented_key | ||||
|  | ||||
|     return _argumented_key | ||||
|  | ||||
|  | ||||
| gc.collect() | ||||
|  | ||||
| # Modifiers | ||||
| make_mod_key(code=0x01, names=('LEFT_CONTROL', 'LCTRL', 'LCTL')) | ||||
| make_mod_key(code=0x02, names=('LEFT_SHIFT', 'LSHIFT', 'LSFT')) | ||||
| make_mod_key(code=0x04, names=('LEFT_ALT', 'LALT')) | ||||
| make_mod_key(code=0x08, names=('LEFT_SUPER', 'LGUI', 'LCMD', 'LWIN')) | ||||
| make_mod_key(code=0x10, names=('RIGHT_CONTROL', 'RCTRL', 'RCTL')) | ||||
| make_mod_key(code=0x20, names=('RIGHT_SHIFT', 'RSHIFT', 'RSFT')) | ||||
| make_mod_key(code=0x40, names=('RIGHT_ALT', 'RALT')) | ||||
| make_mod_key(code=0x80, names=('RIGHT_SUPER', 'RGUI', 'RCMD', 'RWIN')) | ||||
| # MEH = LCTL | LALT | LSFT | ||||
| make_mod_key(code=0x07, names=('MEH',)) | ||||
| # HYPR = LCTL | LALT | LSFT | LGUI | ||||
| make_mod_key(code=0x0F, names=('HYPER', 'HYPR')) | ||||
|  | ||||
| gc.collect() | ||||
|  | ||||
| # Basic ASCII letters | ||||
| make_key(code=4, names=('A',)) | ||||
| make_key(code=5, names=('B',)) | ||||
| make_key(code=6, names=('C',)) | ||||
| make_key(code=7, names=('D',)) | ||||
| make_key(code=8, names=('E',)) | ||||
| make_key(code=9, names=('F',)) | ||||
| make_key(code=10, names=('G',)) | ||||
| make_key(code=11, names=('H',)) | ||||
| make_key(code=12, names=('I',)) | ||||
| make_key(code=13, names=('J',)) | ||||
| make_key(code=14, names=('K',)) | ||||
| make_key(code=15, names=('L',)) | ||||
| make_key(code=16, names=('M',)) | ||||
| make_key(code=17, names=('N',)) | ||||
| make_key(code=18, names=('O',)) | ||||
| make_key(code=19, names=('P',)) | ||||
| make_key(code=20, names=('Q',)) | ||||
| make_key(code=21, names=('R',)) | ||||
| make_key(code=22, names=('S',)) | ||||
| make_key(code=23, names=('T',)) | ||||
| make_key(code=24, names=('U',)) | ||||
| make_key(code=25, names=('V',)) | ||||
| make_key(code=26, names=('W',)) | ||||
| make_key(code=27, names=('X',)) | ||||
| make_key(code=28, names=('Y',)) | ||||
| make_key(code=29, names=('Z',)) | ||||
|  | ||||
| gc.collect() | ||||
|  | ||||
| # Numbers | ||||
| # Aliases to play nicely with AttrDict, since KC.1 isn't a valid | ||||
| # attribute key in Python, but KC.N1 is | ||||
| make_key(code=30, names=('1', 'N1')) | ||||
| make_key(code=31, names=('2', 'N2')) | ||||
| make_key(code=32, names=('3', 'N3')) | ||||
| make_key(code=33, names=('4', 'N4')) | ||||
| make_key(code=34, names=('5', 'N5')) | ||||
| make_key(code=35, names=('6', 'N6')) | ||||
| make_key(code=36, names=('7', 'N7')) | ||||
| make_key(code=37, names=('8', 'N8')) | ||||
| make_key(code=38, names=('9', 'N9')) | ||||
| make_key(code=39, names=('0', 'N0')) | ||||
|  | ||||
| gc.collect() | ||||
|  | ||||
| # More ASCII standard keys | ||||
| make_key(code=40, names=('ENTER', 'ENT', "\n")) | ||||
| make_key(code=41, names=('ESCAPE', 'ESC')) | ||||
| make_key(code=42, names=('BACKSPACE', 'BSPC', 'BKSP')) | ||||
| make_key(code=43, names=('TAB', "\t")) | ||||
| make_key(code=44, names=('SPACE', 'SPC', ' ')) | ||||
| make_key(code=45, names=('MINUS', 'MINS', '-')) | ||||
| make_key(code=46, names=('EQUAL', 'EQL', '=')) | ||||
| make_key(code=47, names=('LBRACKET', 'LBRC', '[')) | ||||
| make_key(code=48, names=('RBRACKET', 'RBRC', ']')) | ||||
| make_key(code=49, names=('BACKSLASH', 'BSLASH', 'BSLS', "\\")) | ||||
| make_key(code=51, names=('SEMICOLON', 'SCOLON', 'SCLN', ';')) | ||||
| make_key(code=52, names=('QUOTE', 'QUOT', "'")) | ||||
| make_key(code=53, names=('GRAVE', 'GRV', 'ZKHK', '`')) | ||||
| make_key(code=54, names=('COMMA', 'COMM', ',')) | ||||
| make_key(code=55, names=('DOT', '.')) | ||||
| make_key(code=56, names=('SLASH', 'SLSH')) | ||||
|  | ||||
| gc.collect() | ||||
|  | ||||
| # Function Keys | ||||
| make_key(code=58, names=('F1',)) | ||||
| make_key(code=59, names=('F2',)) | ||||
| make_key(code=60, names=('F3',)) | ||||
| make_key(code=61, names=('F4',)) | ||||
| make_key(code=62, names=('F5',)) | ||||
| make_key(code=63, names=('F6',)) | ||||
| make_key(code=64, names=('F7',)) | ||||
| make_key(code=65, names=('F8',)) | ||||
| make_key(code=66, names=('F9',)) | ||||
| make_key(code=67, names=('F10',)) | ||||
| make_key(code=68, names=('F11',)) | ||||
| make_key(code=69, names=('F12',)) | ||||
| make_key(code=104, names=('F13',)) | ||||
| make_key(code=105, names=('F14',)) | ||||
| make_key(code=106, names=('F15',)) | ||||
| make_key(code=107, names=('F16',)) | ||||
| make_key(code=108, names=('F17',)) | ||||
| make_key(code=109, names=('F18',)) | ||||
| make_key(code=110, names=('F19',)) | ||||
| make_key(code=111, names=('F20',)) | ||||
| make_key(code=112, names=('F21',)) | ||||
| make_key(code=113, names=('F22',)) | ||||
| make_key(code=114, names=('F23',)) | ||||
| make_key(code=115, names=('F24',)) | ||||
|  | ||||
| gc.collect() | ||||
|  | ||||
| # Lock Keys, Navigation, etc. | ||||
| make_key(code=57, names=('CAPS_LOCK', 'CAPSLOCK', 'CLCK', 'CAPS')) | ||||
| # FIXME: Investigate whether this key actually works, and | ||||
| #        uncomment when/if it does. | ||||
| # make_key(code=130, names=('LOCKING_CAPS', 'LCAP')) | ||||
| make_key(code=70, names=('PRINT_SCREEN', 'PSCREEN', 'PSCR')) | ||||
| make_key(code=71, names=('SCROLL_LOCK', 'SCROLLLOCK', 'SLCK')) | ||||
| # FIXME: Investigate whether this key actually works, and | ||||
| #        uncomment when/if it does. | ||||
| # make_key(code=132, names=('LOCKING_SCROLL', 'LSCRL')) | ||||
| make_key(code=72, names=('PAUSE', 'PAUS', 'BRK')) | ||||
| make_key(code=73, names=('INSERT', 'INS')) | ||||
| make_key(code=74, names=('HOME',)) | ||||
| make_key(code=75, names=('PGUP',)) | ||||
| make_key(code=76, names=('DELETE', 'DEL')) | ||||
| make_key(code=77, names=('END',)) | ||||
| make_key(code=78, names=('PGDOWN', 'PGDN')) | ||||
| make_key(code=79, names=('RIGHT', 'RGHT')) | ||||
| make_key(code=80, names=('LEFT',)) | ||||
| make_key(code=81, names=('DOWN',)) | ||||
| make_key(code=82, names=('UP',)) | ||||
|  | ||||
| gc.collect() | ||||
|  | ||||
| # Numpad | ||||
| make_key(code=83, names=('NUM_LOCK', 'NUMLOCK', 'NLCK')) | ||||
| # FIXME: Investigate whether this key actually works, and | ||||
| #        uncomment when/if it does. | ||||
| # make_key(code=131, names=('LOCKING_NUM', 'LNUM')) | ||||
| make_key(code=84, names=('KP_SLASH', 'NUMPAD_SLASH', 'PSLS')) | ||||
| make_key(code=85, names=('KP_ASTERISK', 'NUMPAD_ASTERISK', 'PAST')) | ||||
| make_key(code=86, names=('KP_MINUS', 'NUMPAD_MINUS', 'PMNS')) | ||||
| make_key(code=87, names=('KP_PLUS', 'NUMPAD_PLUS', 'PPLS')) | ||||
| make_key(code=88, names=('KP_ENTER', 'NUMPAD_ENTER', 'PENT')) | ||||
| make_key(code=89, names=('KP_1', 'P1', 'NUMPAD_1')) | ||||
| make_key(code=90, names=('KP_2', 'P2', 'NUMPAD_2')) | ||||
| make_key(code=91, names=('KP_3', 'P3', 'NUMPAD_3')) | ||||
| make_key(code=92, names=('KP_4', 'P4', 'NUMPAD_4')) | ||||
| make_key(code=93, names=('KP_5', 'P5', 'NUMPAD_5')) | ||||
| make_key(code=94, names=('KP_6', 'P6', 'NUMPAD_6')) | ||||
| make_key(code=95, names=('KP_7', 'P7', 'NUMPAD_7')) | ||||
| make_key(code=96, names=('KP_8', 'P8', 'NUMPAD_8')) | ||||
| make_key(code=97, names=('KP_9', 'P9', 'NUMPAD_9')) | ||||
| make_key(code=98, names=('KP_0', 'P0', 'NUMPAD_0')) | ||||
| make_key(code=99, names=('KP_DOT', 'PDOT', 'NUMPAD_DOT')) | ||||
| make_key(code=103, names=('KP_EQUAL', 'PEQL', 'NUMPAD_EQUAL')) | ||||
| make_key(code=133, names=('KP_COMMA', 'PCMM', 'NUMPAD_COMMA')) | ||||
| make_key(code=134, names=('KP_EQUAL_AS400', 'NUMPAD_EQUAL_AS400')) | ||||
|  | ||||
| gc.collect() | ||||
|  | ||||
| # Making life better for folks on tiny keyboards especially: exposes | ||||
| # the "shifted" keys as raw keys. Under the hood we're still | ||||
| # sending Shift+(whatever key is normally pressed) to get these, so | ||||
| # for example `KC_AT` will hold shift and press 2. | ||||
| make_shifted_key('GRAVE', names=('TILDE', 'TILD', '~')) | ||||
| make_shifted_key('1', names=('EXCLAIM', 'EXLM', '!')) | ||||
| make_shifted_key('2', names=('AT', '@')) | ||||
| make_shifted_key('3', names=('HASH', 'POUND', '#')) | ||||
| make_shifted_key('4', names=('DOLLAR', 'DLR', '$')) | ||||
| make_shifted_key('5', names=('PERCENT', 'PERC', '%')) | ||||
| make_shifted_key('6', names=('CIRCUMFLEX', 'CIRC', '^')) | ||||
| make_shifted_key('7', names=('AMPERSAND', 'AMPR', '&')) | ||||
| make_shifted_key('8', names=('ASTERISK', 'ASTR', '*')) | ||||
| make_shifted_key('9', names=('LEFT_PAREN', 'LPRN', '(')) | ||||
| make_shifted_key('0', names=('RIGHT_PAREN', 'RPRN', ')')) | ||||
| make_shifted_key('MINUS', names=('UNDERSCORE', 'UNDS', '_')) | ||||
| make_shifted_key('EQUAL', names=('PLUS', '+')) | ||||
| make_shifted_key('LBRACKET', names=('LEFT_CURLY_BRACE', 'LCBR', '{')) | ||||
| make_shifted_key('RBRACKET', names=('RIGHT_CURLY_BRACE', 'RCBR', '}')) | ||||
| make_shifted_key('BACKSLASH', names=('PIPE', '|')) | ||||
| make_shifted_key('SEMICOLON', names=('COLON', 'COLN', ':')) | ||||
| make_shifted_key('QUOTE', names=('DOUBLE_QUOTE', 'DQUO', 'DQT', '"')) | ||||
| make_shifted_key('COMMA', names=('LEFT_ANGLE_BRACKET', 'LABK', '<')) | ||||
| make_shifted_key('DOT', names=('RIGHT_ANGLE_BRACKET', 'RABK', '>')) | ||||
| make_shifted_key('SLSH', names=('QUESTION', 'QUES', '?')) | ||||
|  | ||||
| gc.collect() | ||||
|  | ||||
| # International | ||||
| make_key(code=50, names=('NONUS_HASH', 'NUHS')) | ||||
| make_key(code=100, names=('NONUS_BSLASH', 'NUBS')) | ||||
|  | ||||
| make_key(code=135, names=('INT1', 'RO')) | ||||
| make_key(code=136, names=('INT2', 'KANA')) | ||||
| make_key(code=137, names=('INT3', 'JYEN')) | ||||
| make_key(code=138, names=('INT4', 'HENK')) | ||||
| make_key(code=139, names=('INT5', 'MHEN')) | ||||
| make_key(code=140, names=('INT6',)) | ||||
| make_key(code=141, names=('INT7',)) | ||||
| make_key(code=142, names=('INT8',)) | ||||
| make_key(code=143, names=('INT9',)) | ||||
| make_key(code=144, names=('LANG1', 'HAEN')) | ||||
| make_key(code=145, names=('LANG2', 'HAEJ')) | ||||
| make_key(code=146, names=('LANG3',)) | ||||
| make_key(code=147, names=('LANG4',)) | ||||
| make_key(code=148, names=('LANG5',)) | ||||
| make_key(code=149, names=('LANG6',)) | ||||
| make_key(code=150, names=('LANG7',)) | ||||
| make_key(code=151, names=('LANG8',)) | ||||
| make_key(code=152, names=('LANG9',)) | ||||
|  | ||||
| gc.collect() | ||||
|  | ||||
| # Consumer ("media") keys. Most known keys aren't supported here. A much | ||||
| # longer list used to exist in this file, but the codes were almost certainly | ||||
| # incorrect, conflicting with each other, or otherwise "weird". We'll add them | ||||
| # back in piecemeal as needed. PRs welcome. | ||||
| # | ||||
| # A super useful reference for these is http://www.freebsddiary.org/APC/usb_hid_usages.php | ||||
| # Note that currently we only have the PC codes. Recent MacOS versions seem to | ||||
| # support PC media keys, so I don't know how much value we would get out of | ||||
| # adding the old Apple-specific consumer codes, but again, PRs welcome if the | ||||
| # lack of them impacts you. | ||||
| make_consumer_key(code=226, names=('AUDIO_MUTE', 'MUTE'))  # 0xE2 | ||||
| make_consumer_key(code=233, names=('AUDIO_VOL_UP', 'VOLU'))  # 0xE9 | ||||
| make_consumer_key(code=234, names=('AUDIO_VOL_DOWN', 'VOLD'))  # 0xEA | ||||
| make_consumer_key(code=181, names=('MEDIA_NEXT_TRACK', 'MNXT'))  # 0xB5 | ||||
| make_consumer_key(code=182, names=('MEDIA_PREV_TRACK', 'MPRV'))  # 0xB6 | ||||
| make_consumer_key(code=183, names=('MEDIA_STOP', 'MSTP'))  # 0xB7 | ||||
| make_consumer_key(code=205, names=('MEDIA_PLAY_PAUSE', 'MPLY'))  # 0xCD (this may not be right) | ||||
| make_consumer_key(code=184, names=('MEDIA_EJECT', 'EJCT'))  # 0xB8 | ||||
| make_consumer_key(code=179, names=('MEDIA_FAST_FORWARD', 'MFFD'))  # 0xB3 | ||||
| make_consumer_key(code=180, names=('MEDIA_REWIND', 'MRWD'))  # 0xB4 | ||||
|  | ||||
| gc.collect() | ||||
|  | ||||
| # Internal, diagnostic, or auxiliary/enhanced keys | ||||
|  | ||||
| # NO and TRNS are functionally identical in how they (don't) mutate | ||||
| # the state, but are tracked semantically separately, so create | ||||
| # two keys with the exact same functionality | ||||
| for names in (('NO',), ('TRANSPARENT', 'TRNS')): | ||||
|     make_key( | ||||
|         names=names, | ||||
|         on_press=handlers.passthrough, | ||||
|         on_release=handlers.passthrough, | ||||
|     ) | ||||
|  | ||||
| make_key(names=('RESET',), on_press=handlers.reset) | ||||
| make_key(names=('BOOTLOADER',), on_press=handlers.bootloader) | ||||
| make_key(names=('DEBUG', 'DBG'), on_press=handlers.debug_pressed, on_release=handlers.passthrough) | ||||
|  | ||||
| make_key(names=('GESC',), on_press=handlers.gesc_pressed, on_release=handlers.gesc_released) | ||||
| make_key( | ||||
|     names=('LEADER', 'LEAD'), | ||||
|     on_press=handlers.leader_pressed, | ||||
|     on_release=handlers.passthrough, | ||||
| ) | ||||
|  | ||||
|  | ||||
| def layer_key_validator(layer, kc=None): | ||||
|     ''' | ||||
|     Validates the syntax (but not semantics) of a layer key call.  We won't | ||||
|     have access to the keymap here, so we can't verify much of anything useful | ||||
|     here (like whether the target layer actually exists). The spirit of this | ||||
|     existing is mostly that Python will catch extraneous args/kwargs and error | ||||
|     out. | ||||
|     ''' | ||||
|     return LayerKeyMeta(layer=layer, kc=kc) | ||||
|  | ||||
|  | ||||
| # Layers | ||||
| make_argumented_key( | ||||
|     validator=layer_key_validator, | ||||
|     names=('MO',), | ||||
|     on_press=layers.mo_pressed, | ||||
|     on_release=layers.mo_released, | ||||
| ) | ||||
| make_argumented_key( | ||||
|     validator=layer_key_validator, | ||||
|     names=('DF',), | ||||
|     on_press=layers.df_pressed, | ||||
| ) | ||||
| make_argumented_key( | ||||
|     validator=layer_key_validator, | ||||
|     names=('LM',), | ||||
|     on_press=layers.lm_pressed, | ||||
|     on_release=layers.lm_released, | ||||
| ) | ||||
| make_argumented_key( | ||||
|     validator=layer_key_validator, | ||||
|     names=('LT',), | ||||
|     on_press=layers.lt_pressed, | ||||
|     on_release=layers.lt_released, | ||||
| ) | ||||
| make_argumented_key( | ||||
|     validator=layer_key_validator, | ||||
|     names=('TG',), | ||||
|     on_press=layers.tg_pressed, | ||||
| ) | ||||
| make_argumented_key( | ||||
|     validator=layer_key_validator, | ||||
|     names=('TO',), | ||||
|     on_press=layers.to_pressed, | ||||
| ) | ||||
| make_argumented_key( | ||||
|     validator=layer_key_validator, | ||||
|     names=('TT',), | ||||
|     on_press=layers.tt_pressed, | ||||
|     on_release=layers.tt_released, | ||||
| ) | ||||
|  | ||||
|  | ||||
| gc.collect() | ||||
|  | ||||
|  | ||||
| def key_seq_sleep_validator(ms): | ||||
|     return KeySeqSleepMeta(ms) | ||||
|  | ||||
|  | ||||
| # A dummy key to trigger a sleep_ms call in a sequence of other keys in a | ||||
| # simple sequence macro. | ||||
| make_argumented_key( | ||||
|     validator=key_seq_sleep_validator, | ||||
|     names=('MACRO_SLEEP_MS', 'SLEEP_IN_SEQ'), | ||||
|     on_press=handlers.sleep_pressed, | ||||
| ) | ||||
|  | ||||
|  | ||||
| # Switch unicode modes at runtime | ||||
| make_key( | ||||
|     names=('UC_MODE_NOOP', 'UC_DISABLE'), | ||||
|     meta=UnicodeModeKeyMeta(UnicodeMode.NOOP), | ||||
|     on_press=handlers.uc_mode_pressed, | ||||
| ) | ||||
| make_key( | ||||
|     names=('UC_MODE_LINUX', 'UC_MODE_IBUS'), | ||||
|     meta=UnicodeModeKeyMeta(UnicodeMode.IBUS), | ||||
|     on_press=handlers.uc_mode_pressed, | ||||
| ) | ||||
| make_key( | ||||
|     names=('UC_MODE_MACOS', 'UC_MODE_OSX', 'US_MODE_RALT'), | ||||
|     meta=UnicodeModeKeyMeta(UnicodeMode.RALT), | ||||
|     on_press=handlers.uc_mode_pressed, | ||||
| ) | ||||
| make_key( | ||||
|     names=('UC_MODE_WINC',), | ||||
|     meta=UnicodeModeKeyMeta(UnicodeMode.WINC), | ||||
|     on_press=handlers.uc_mode_pressed, | ||||
| ) | ||||
|  | ||||
|  | ||||
| def unicode_mode_key_validator(mode): | ||||
|     return UnicodeModeKeyMeta(mode) | ||||
|  | ||||
|  | ||||
| make_argumented_key( | ||||
|     validator=unicode_mode_key_validator, | ||||
|     names=('UC_MODE',), | ||||
|     on_press=handlers.uc_mode_pressed, | ||||
| ) | ||||
|  | ||||
|  | ||||
| # Tap Dance | ||||
| make_argumented_key( | ||||
|     validator=lambda *codes: TapDanceKeyMeta(codes), | ||||
|     names=('TAP_DANCE', 'TD'), | ||||
|     on_press=handlers.td_pressed, | ||||
|     on_release=handlers.td_released, | ||||
| ) | ||||
		Reference in New Issue
	
	Block a user