# ---------------------------------------------------------------------------- # pyglet # Copyright (c) 2006-2008 Alex Holkner # Copyright (c) 2008-2022 pyglet contributors # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of pyglet nor the names of its # contributors may be used to endorse or promote products # derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # ---------------------------------------------------------------------------- """Key constants and utilities for pyglet.window. Usage:: from pyglet.window import Window from pyglet.window import key window = Window() @window.event def on_key_press(symbol, modifiers): # Symbolic names: if symbol == key.RETURN: # Alphabet keys: elif symbol == key.Z: # Number keys: elif symbol == key._1: # Number keypad keys: elif symbol == key.NUM_1: # Modifiers: if modifiers & key.MOD_CTRL: """ from pyglet import compat_platform class KeyStateHandler: """Simple handler that tracks the state of keys on the keyboard. If a key is pressed then this handler holds a True value for it. If the window loses focus, all keys will be reset to False to avoid a "sticky" key state. For example:: >>> win = window.Window >>> keyboard = key.KeyStateHandler() >>> win.push_handlers(keyboard) # Hold down the "up" arrow... >>> keyboard[key.UP] True >>> keyboard[key.DOWN] False """ def __init__(self): self.data = {} def on_key_press(self, symbol, modifiers): self.data[symbol] = True def on_key_release(self, symbol, modifiers): self.data[symbol] = False def on_deactivate(self): self.data.clear() def __getitem__(self, key): return self.data.get(key, False) def modifiers_string(modifiers): """Return a string describing a set of modifiers. Example:: >>> modifiers_string(MOD_SHIFT | MOD_CTRL) 'MOD_SHIFT|MOD_CTRL' :Parameters: `modifiers` : int Bitwise combination of modifier constants. :rtype: str """ mod_names = [] if modifiers & MOD_SHIFT: mod_names.append('MOD_SHIFT') if modifiers & MOD_CTRL: mod_names.append('MOD_CTRL') if modifiers & MOD_ALT: mod_names.append('MOD_ALT') if modifiers & MOD_CAPSLOCK: mod_names.append('MOD_CAPSLOCK') if modifiers & MOD_NUMLOCK: mod_names.append('MOD_NUMLOCK') if modifiers & MOD_SCROLLLOCK: mod_names.append('MOD_SCROLLLOCK') if modifiers & MOD_COMMAND: mod_names.append('MOD_COMMAND') if modifiers & MOD_OPTION: mod_names.append('MOD_OPTION') if modifiers & MOD_FUNCTION: mod_names.append('MOD_FUNCTION') return '|'.join(mod_names) def symbol_string(symbol): """Return a string describing a key symbol. Example:: >>> symbol_string(BACKSPACE) 'BACKSPACE' :Parameters: `symbol` : int Symbolic key constant. :rtype: str """ if symbol < 1 << 32: return _key_names.get(symbol, str(symbol)) else: return 'user_key(%x)' % (symbol >> 32) def motion_string(motion): """Return a string describing a text motion. Example:: >>> motion_string(MOTION_NEXT_WORD) 'MOTION_NEXT_WORD' :Parameters: `motion` : int Text motion constant. :rtype: str """ return _motion_names.get(motion, str(motion)) def user_key(scancode): """Return a key symbol for a key not supported by pyglet. This can be used to map virtual keys or scancodes from unsupported keyboard layouts into a machine-specific symbol. The symbol will be meaningless on any other machine, or under a different keyboard layout. Applications should use user-keys only when user explicitly binds them (for example, mapping keys to actions in a game options screen). """ assert scancode > 0 return scancode << 32 # Modifier mask constants MOD_SHIFT = 1 << 0 MOD_CTRL = 1 << 1 MOD_ALT = 1 << 2 MOD_CAPSLOCK = 1 << 3 MOD_NUMLOCK = 1 << 4 MOD_WINDOWS = 1 << 5 MOD_COMMAND = 1 << 6 MOD_OPTION = 1 << 7 MOD_SCROLLLOCK = 1 << 8 MOD_FUNCTION = 1 << 9 #: Accelerator modifier. On Windows and Linux, this is ``MOD_CTRL``, on #: Mac OS X it's ``MOD_COMMAND``. MOD_ACCEL = MOD_CTRL if compat_platform == 'darwin': MOD_ACCEL = MOD_COMMAND # Key symbol constants # ASCII commands BACKSPACE = 0xff08 TAB = 0xff09 LINEFEED = 0xff0a CLEAR = 0xff0b RETURN = 0xff0d ENTER = 0xff0d # synonym PAUSE = 0xff13 SCROLLLOCK = 0xff14 SYSREQ = 0xff15 ESCAPE = 0xff1b SPACE = 0xff20 # Cursor control and motion HOME = 0xff50 LEFT = 0xff51 UP = 0xff52 RIGHT = 0xff53 DOWN = 0xff54 PAGEUP = 0xff55 PAGEDOWN = 0xff56 END = 0xff57 BEGIN = 0xff58 # Misc functions DELETE = 0xffff SELECT = 0xff60 PRINT = 0xff61 EXECUTE = 0xff62 INSERT = 0xff63 UNDO = 0xff65 REDO = 0xff66 MENU = 0xff67 FIND = 0xff68 CANCEL = 0xff69 HELP = 0xff6a BREAK = 0xff6b MODESWITCH = 0xff7e SCRIPTSWITCH = 0xff7e FUNCTION = 0xffd2 # Text motion constants: these are allowed to clash with key constants MOTION_UP = UP MOTION_RIGHT = RIGHT MOTION_DOWN = DOWN MOTION_LEFT = LEFT MOTION_NEXT_WORD = 1 MOTION_PREVIOUS_WORD = 2 MOTION_BEGINNING_OF_LINE = 3 MOTION_END_OF_LINE = 4 MOTION_NEXT_PAGE = PAGEDOWN MOTION_PREVIOUS_PAGE = PAGEUP MOTION_BEGINNING_OF_FILE = 5 MOTION_END_OF_FILE = 6 MOTION_BACKSPACE = BACKSPACE MOTION_DELETE = DELETE MOTION_COPY = 7 MOTION_PASTE = 8 # Number pad NUMLOCK = 0xff7f NUM_SPACE = 0xff80 NUM_TAB = 0xff89 NUM_ENTER = 0xff8d NUM_F1 = 0xff91 NUM_F2 = 0xff92 NUM_F3 = 0xff93 NUM_F4 = 0xff94 NUM_HOME = 0xff95 NUM_LEFT = 0xff96 NUM_UP = 0xff97 NUM_RIGHT = 0xff98 NUM_DOWN = 0xff99 NUM_PRIOR = 0xff9a NUM_PAGE_UP = 0xff9a NUM_NEXT = 0xff9b NUM_PAGE_DOWN = 0xff9b NUM_END = 0xff9c NUM_BEGIN = 0xff9d NUM_INSERT = 0xff9e NUM_DELETE = 0xff9f NUM_EQUAL = 0xffbd NUM_MULTIPLY = 0xffaa NUM_ADD = 0xffab NUM_SEPARATOR = 0xffac NUM_SUBTRACT = 0xffad NUM_DECIMAL = 0xffae NUM_DIVIDE = 0xffaf NUM_0 = 0xffb0 NUM_1 = 0xffb1 NUM_2 = 0xffb2 NUM_3 = 0xffb3 NUM_4 = 0xffb4 NUM_5 = 0xffb5 NUM_6 = 0xffb6 NUM_7 = 0xffb7 NUM_8 = 0xffb8 NUM_9 = 0xffb9 # Function keys F1 = 0xffbe F2 = 0xffbf F3 = 0xffc0 F4 = 0xffc1 F5 = 0xffc2 F6 = 0xffc3 F7 = 0xffc4 F8 = 0xffc5 F9 = 0xffc6 F10 = 0xffc7 F11 = 0xffc8 F12 = 0xffc9 F13 = 0xffca F14 = 0xffcb F15 = 0xffcc F16 = 0xffcd F17 = 0xffce F18 = 0xffcf F19 = 0xffd0 F20 = 0xffd1 # Modifiers LSHIFT = 0xffe1 RSHIFT = 0xffe2 LCTRL = 0xffe3 RCTRL = 0xffe4 CAPSLOCK = 0xffe5 LMETA = 0xffe7 RMETA = 0xffe8 LALT = 0xffe9 RALT = 0xffea LWINDOWS = 0xffeb RWINDOWS = 0xffec LCOMMAND = 0xffed RCOMMAND = 0xffee LOPTION = 0xffef ROPTION = 0xfff0 # Latin-1 SPACE = 0x020 EXCLAMATION = 0x021 DOUBLEQUOTE = 0x022 HASH = 0x023 POUND = 0x023 # synonym DOLLAR = 0x024 PERCENT = 0x025 AMPERSAND = 0x026 APOSTROPHE = 0x027 PARENLEFT = 0x028 PARENRIGHT = 0x029 ASTERISK = 0x02a PLUS = 0x02b COMMA = 0x02c MINUS = 0x02d PERIOD = 0x02e SLASH = 0x02f _0 = 0x030 _1 = 0x031 _2 = 0x032 _3 = 0x033 _4 = 0x034 _5 = 0x035 _6 = 0x036 _7 = 0x037 _8 = 0x038 _9 = 0x039 COLON = 0x03a SEMICOLON = 0x03b LESS = 0x03c EQUAL = 0x03d GREATER = 0x03e QUESTION = 0x03f AT = 0x040 BRACKETLEFT = 0x05b BACKSLASH = 0x05c BRACKETRIGHT = 0x05d ASCIICIRCUM = 0x05e UNDERSCORE = 0x05f GRAVE = 0x060 QUOTELEFT = 0x060 A = 0x061 B = 0x062 C = 0x063 D = 0x064 E = 0x065 F = 0x066 G = 0x067 H = 0x068 I = 0x069 J = 0x06a K = 0x06b L = 0x06c M = 0x06d N = 0x06e O = 0x06f P = 0x070 Q = 0x071 R = 0x072 S = 0x073 T = 0x074 U = 0x075 V = 0x076 W = 0x077 X = 0x078 Y = 0x079 Z = 0x07a BRACELEFT = 0x07b BAR = 0x07c BRACERIGHT = 0x07d ASCIITILDE = 0x07e _key_names = {} _motion_names = {} for _name, _value in locals().copy().items(): if _name[:2] != '__' and _name.upper() == _name and \ not _name.startswith('MOD_'): if _name.startswith('MOTION_'): _motion_names[_value] = _name else: _key_names[_value] = _name