1# Copyright 2004-2021 Tom Rothamel <pytom@bishoujo.us> 2# 3# Permission is hereby granted, free of charge, to any person 4# obtaining a copy of this software and associated documentation files 5# (the "Software"), to deal in the Software without restriction, 6# including without limitation the rights to use, copy, modify, merge, 7# publish, distribute, sublicense, and/or sell copies of the Software, 8# and to permit persons to whom the Software is furnished to do so, 9# subject to the following conditions: 10# 11# The above copyright notice and this permission notice shall be 12# included in all copies or substantial portions of the Software. 13# 14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22from __future__ import division, absolute_import, with_statement, print_function, unicode_literals 23from renpy.compat import * 24 25import pygame_sdl2 26 27code_to_unicode = { 28 pygame_sdl2.K_UNKNOWN : "", 29 pygame_sdl2.K_RETURN : "\n", 30 pygame_sdl2.K_ESCAPE : "\e", 31 pygame_sdl2.K_BACKSPACE : "\b", 32 pygame_sdl2.K_TAB : "\t", 33 pygame_sdl2.K_SPACE : " ", 34 pygame_sdl2.K_EXCLAIM : "!", 35 pygame_sdl2.K_QUOTEDBL : "\"", 36 pygame_sdl2.K_HASH : "#", 37 pygame_sdl2.K_PERCENT : "%", 38 pygame_sdl2.K_DOLLAR : "$", 39 pygame_sdl2.K_AMPERSAND : "&", 40 pygame_sdl2.K_QUOTE : "'", 41 pygame_sdl2.K_LEFTPAREN : "(", 42 pygame_sdl2.K_RIGHTPAREN : ")", 43 pygame_sdl2.K_ASTERISK : "*", 44 pygame_sdl2.K_PLUS : "+", 45 pygame_sdl2.K_COMMA : ",", 46 pygame_sdl2.K_MINUS : "-", 47 pygame_sdl2.K_PERIOD : ".", 48 pygame_sdl2.K_SLASH : "/", 49 pygame_sdl2.K_0 : "0", 50 pygame_sdl2.K_1 : "1", 51 pygame_sdl2.K_2 : "2", 52 pygame_sdl2.K_3 : "3", 53 pygame_sdl2.K_4 : "4", 54 pygame_sdl2.K_5 : "5", 55 pygame_sdl2.K_6 : "6", 56 pygame_sdl2.K_7 : "7", 57 pygame_sdl2.K_8 : "8", 58 pygame_sdl2.K_9 : "9", 59 pygame_sdl2.K_COLON : ":", 60 pygame_sdl2.K_SEMICOLON : ";", 61 pygame_sdl2.K_LESS : "<", 62 pygame_sdl2.K_EQUALS : ":", 63 pygame_sdl2.K_GREATER : ">", 64 pygame_sdl2.K_QUESTION : "?", 65 pygame_sdl2.K_AT : "@", 66 pygame_sdl2.K_LEFTBRACKET : "[", 67 pygame_sdl2.K_BACKSLASH : "\\", 68 pygame_sdl2.K_RIGHTBRACKET : "]", 69 pygame_sdl2.K_CARET : "^", 70 pygame_sdl2.K_UNDERSCORE : "_", 71 pygame_sdl2.K_BACKQUOTE : "`", 72 pygame_sdl2.K_a : "a", 73 pygame_sdl2.K_b : "b", 74 pygame_sdl2.K_c : "c", 75 pygame_sdl2.K_d : "d", 76 pygame_sdl2.K_e : "e", 77 pygame_sdl2.K_f : "f", 78 pygame_sdl2.K_g : "g", 79 pygame_sdl2.K_h : "h", 80 pygame_sdl2.K_i : "i", 81 pygame_sdl2.K_j : "j", 82 pygame_sdl2.K_k : "k", 83 pygame_sdl2.K_l : "l", 84 pygame_sdl2.K_m : "m", 85 pygame_sdl2.K_n : "n", 86 pygame_sdl2.K_o : "o", 87 pygame_sdl2.K_p : "p", 88 pygame_sdl2.K_q : "q", 89 pygame_sdl2.K_r : "r", 90 pygame_sdl2.K_s : "s", 91 pygame_sdl2.K_t : "t", 92 pygame_sdl2.K_u : "u", 93 pygame_sdl2.K_v : "v", 94 pygame_sdl2.K_w : "w", 95 pygame_sdl2.K_x : "x", 96 pygame_sdl2.K_y : "y", 97 pygame_sdl2.K_z : "z", 98 pygame_sdl2.K_CAPSLOCK : "", 99 pygame_sdl2.K_F1 : "", 100 pygame_sdl2.K_F2 : "", 101 pygame_sdl2.K_F3 : "", 102 pygame_sdl2.K_F4 : "", 103 pygame_sdl2.K_F5 : "", 104 pygame_sdl2.K_F6 : "", 105 pygame_sdl2.K_F7 : "", 106 pygame_sdl2.K_F8 : "", 107 pygame_sdl2.K_F9 : "", 108 pygame_sdl2.K_F10 : "", 109 pygame_sdl2.K_F11 : "", 110 pygame_sdl2.K_F12 : "", 111 pygame_sdl2.K_PRINTSCREEN : "", 112 pygame_sdl2.K_SCROLLLOCK : "", 113 pygame_sdl2.K_PAUSE : "", 114 pygame_sdl2.K_INSERT : "", 115 pygame_sdl2.K_HOME : "", 116 pygame_sdl2.K_PAGEUP : "", 117 pygame_sdl2.K_DELETE : "", 118 pygame_sdl2.K_END : "", 119 pygame_sdl2.K_PAGEDOWN : "", 120 pygame_sdl2.K_RIGHT : "", 121 pygame_sdl2.K_LEFT : "", 122 pygame_sdl2.K_DOWN : "", 123 pygame_sdl2.K_UP : "", 124 pygame_sdl2.K_NUMLOCKCLEAR : "", 125 pygame_sdl2.K_KP_DIVIDE : "/", 126 pygame_sdl2.K_KP_MULTIPLY : "*", 127 pygame_sdl2.K_KP_MINUS : "-", 128 pygame_sdl2.K_KP_PLUS : "+", 129 pygame_sdl2.K_KP_ENTER : "\n", 130 pygame_sdl2.K_KP_1 : "1", 131 pygame_sdl2.K_KP_2 : "2", 132 pygame_sdl2.K_KP_3 : "3", 133 pygame_sdl2.K_KP_4 : "4", 134 pygame_sdl2.K_KP_5 : "5", 135 pygame_sdl2.K_KP_6 : "6", 136 pygame_sdl2.K_KP_7 : "7", 137 pygame_sdl2.K_KP_8 : "8", 138 pygame_sdl2.K_KP_9 : "9", 139 pygame_sdl2.K_KP_0 : "0", 140 pygame_sdl2.K_KP_PERIOD : ".", 141 pygame_sdl2.K_APPLICATION : "", 142 pygame_sdl2.K_POWER : "", 143 pygame_sdl2.K_KP_EQUALS : ":", 144 pygame_sdl2.K_F13 : "", 145 pygame_sdl2.K_F14 : "", 146 pygame_sdl2.K_F15 : "", 147 pygame_sdl2.K_F16 : "", 148 pygame_sdl2.K_F17 : "", 149 pygame_sdl2.K_F18 : "", 150 pygame_sdl2.K_F19 : "", 151 pygame_sdl2.K_F20 : "", 152 pygame_sdl2.K_F21 : "", 153 pygame_sdl2.K_F22 : "", 154 pygame_sdl2.K_F23 : "", 155 pygame_sdl2.K_F24 : "", 156 pygame_sdl2.K_EXECUTE : "", 157 pygame_sdl2.K_HELP : "", 158 pygame_sdl2.K_MENU : "", 159 pygame_sdl2.K_SELECT : "", 160 pygame_sdl2.K_STOP : "", 161 pygame_sdl2.K_AGAIN : "", 162 pygame_sdl2.K_UNDO : "", 163 pygame_sdl2.K_CUT : "", 164 pygame_sdl2.K_COPY : "", 165 pygame_sdl2.K_PASTE : "", 166 pygame_sdl2.K_FIND : "", 167 pygame_sdl2.K_MUTE : "", 168 pygame_sdl2.K_VOLUMEUP : "", 169 pygame_sdl2.K_VOLUMEDOWN : "", 170 pygame_sdl2.K_KP_COMMA : "", 171 pygame_sdl2.K_KP_EQUALSAS400 : "", 172 pygame_sdl2.K_ALTERASE : "", 173 pygame_sdl2.K_SYSREQ : "", 174 pygame_sdl2.K_CANCEL : "", 175 pygame_sdl2.K_CLEAR : "", 176 pygame_sdl2.K_PRIOR : "", 177 pygame_sdl2.K_RETURN2 : "", 178 pygame_sdl2.K_SEPARATOR : "", 179 pygame_sdl2.K_OUT : "", 180 pygame_sdl2.K_OPER : "", 181 pygame_sdl2.K_CLEARAGAIN : "", 182 pygame_sdl2.K_CRSEL : "", 183 pygame_sdl2.K_EXSEL : "", 184 pygame_sdl2.K_KP_00 : "", 185 pygame_sdl2.K_KP_000 : "", 186 pygame_sdl2.K_THOUSANDSSEPARATOR : "", 187 pygame_sdl2.K_DECIMALSEPARATOR : "", 188 pygame_sdl2.K_CURRENCYUNIT : "", 189 pygame_sdl2.K_CURRENCYSUBUNIT : "", 190 pygame_sdl2.K_KP_LEFTPAREN : "", 191 pygame_sdl2.K_KP_RIGHTPAREN : "", 192 pygame_sdl2.K_KP_LEFTBRACE : "", 193 pygame_sdl2.K_KP_RIGHTBRACE : "", 194 pygame_sdl2.K_KP_TAB : "", 195 pygame_sdl2.K_KP_BACKSPACE : "", 196 pygame_sdl2.K_KP_A : "", 197 pygame_sdl2.K_KP_B : "", 198 pygame_sdl2.K_KP_C : "", 199 pygame_sdl2.K_KP_D : "", 200 pygame_sdl2.K_KP_E : "", 201 pygame_sdl2.K_KP_F : "", 202 pygame_sdl2.K_KP_XOR : "", 203 pygame_sdl2.K_KP_POWER : "", 204 pygame_sdl2.K_KP_PERCENT : "", 205 pygame_sdl2.K_KP_LESS : "", 206 pygame_sdl2.K_KP_GREATER : "", 207 pygame_sdl2.K_KP_AMPERSAND : "", 208 pygame_sdl2.K_KP_DBLAMPERSAND : "", 209 pygame_sdl2.K_KP_VERTICALBAR : "", 210 pygame_sdl2.K_KP_DBLVERTICALBAR : "", 211 pygame_sdl2.K_KP_COLON : "", 212 pygame_sdl2.K_KP_HASH : "", 213 pygame_sdl2.K_KP_SPACE : "", 214 pygame_sdl2.K_KP_AT : "", 215 pygame_sdl2.K_KP_EXCLAM : "", 216 pygame_sdl2.K_KP_MEMSTORE : "", 217 pygame_sdl2.K_KP_MEMRECALL : "", 218 pygame_sdl2.K_KP_MEMCLEAR : "", 219 pygame_sdl2.K_KP_MEMADD : "", 220 pygame_sdl2.K_KP_MEMSUBTRACT : "", 221 pygame_sdl2.K_KP_MEMMULTIPLY : "", 222 pygame_sdl2.K_KP_MEMDIVIDE : "", 223 pygame_sdl2.K_KP_PLUSMINUS : "", 224 pygame_sdl2.K_KP_CLEAR : "", 225 pygame_sdl2.K_KP_CLEARENTRY : "", 226 pygame_sdl2.K_KP_BINARY : "", 227 pygame_sdl2.K_KP_OCTAL : "", 228 pygame_sdl2.K_KP_DECIMAL : "", 229 pygame_sdl2.K_KP_HEXADECIMAL : "", 230 pygame_sdl2.K_LCTRL : "", 231 pygame_sdl2.K_LSHIFT : "", 232 pygame_sdl2.K_LALT : "", 233 pygame_sdl2.K_LGUI : "", 234 pygame_sdl2.K_RCTRL : "", 235 pygame_sdl2.K_RSHIFT : "", 236 pygame_sdl2.K_RALT : "", 237 pygame_sdl2.K_RGUI : "", 238 pygame_sdl2.K_MODE : "", 239 pygame_sdl2.K_AUDIONEXT : "", 240 pygame_sdl2.K_AUDIOPREV : "", 241 pygame_sdl2.K_AUDIOSTOP : "", 242 pygame_sdl2.K_AUDIOPLAY : "", 243 pygame_sdl2.K_AUDIOMUTE : "", 244 pygame_sdl2.K_MEDIASELECT : "", 245 pygame_sdl2.K_WWW : "", 246 pygame_sdl2.K_MAIL : "", 247 pygame_sdl2.K_CALCULATOR : "", 248 pygame_sdl2.K_COMPUTER : "", 249 pygame_sdl2.K_AC_SEARCH : "", 250 pygame_sdl2.K_AC_HOME : "", 251 pygame_sdl2.K_AC_BACK : "", 252 pygame_sdl2.K_AC_FORWARD : "", 253 pygame_sdl2.K_AC_STOP : "", 254 pygame_sdl2.K_AC_REFRESH : "", 255 pygame_sdl2.K_AC_BOOKMARKS : "", 256 pygame_sdl2.K_BRIGHTNESSDOWN : "", 257 pygame_sdl2.K_BRIGHTNESSUP : "", 258 pygame_sdl2.K_DISPLAYSWITCH : "", 259 pygame_sdl2.K_KBDILLUMTOGGLE : "", 260 pygame_sdl2.K_KBDILLUMDOWN : "", 261 pygame_sdl2.K_KBDILLUMUP : "", 262 pygame_sdl2.K_EJECT : "", 263 pygame_sdl2.K_SLEEP : "", 264} 265 266unicode_to_code = { } 267for k, v in sorted(code_to_unicode.items()): 268 if v and (v not in unicode_to_code): 269 unicode_to_code[v] = k 270 271 272def get_keycode(node, keysym): 273 274 c = keysym.split("_") 275 276 mods = 0 277 278 while c: 279 if c[0] == "shift": 280 mods |= pygame_sdl2.KMOD_LSHIFT 281 c.pop(0) 282 elif c[0] == "ctrl": 283 mods |= pygame_sdl2.KMOD_LCTRL 284 c.pop(0) 285 elif c[0] == "alt": 286 mods |= pygame_sdl2.KMOD_LALT 287 c.pop(0) 288 elif c[0] == "meta": 289 mods |= pygame_sdl2.KMOD_LMETA 290 c.pop(0) 291 else: 292 break 293 294 key = "_".join(c) 295 296 if key in unicode_to_code: 297 if ord(key) >= 32: 298 u = key 299 else: 300 u = None 301 302 code = unicode_to_code[key] 303 304 elif key.lower() in unicode_to_code: 305 u = key 306 code = unicode_to_code[key.lower()] 307 mods |= pygame_sdl2.KMOD_LSHIFT 308 309 else: 310 code = getattr(pygame_sdl2, "K_" + key, None) 311 312 if code is None: 313 raise Exception("Could not find keysym {!r} at {}:{}.".format(keysym, node.filename, node.linenumber)) 314 315 u = code_to_unicode.get(code, "") 316 317 if not u: 318 u = None 319 elif ord(u) < 32: 320 u = None 321 322 return code, u, mods 323 324 325def down(node, keysym): 326 code, u, mods = get_keycode(node, keysym) 327 328 if pygame_sdl2.key.text_input: 329 pygame_sdl2.event.post(pygame_sdl2.event.Event( 330 pygame_sdl2.KEYDOWN, 331 unicode='', 332 key=code, 333 scancode=code, 334 mod=mods, 335 repeat=False, 336 test=True)) 337 338 pygame_sdl2.event.post(pygame_sdl2.event.Event( 339 pygame_sdl2.TEXTINPUT, 340 text=u, 341 test=True)) 342 343 else: 344 345 pygame_sdl2.event.post(pygame_sdl2.event.Event( 346 pygame_sdl2.KEYDOWN, 347 unicode=u, 348 key=code, 349 scancode=code, 350 mod=mods, 351 repeat=False, 352 test=True)) 353 354 355def up(node, keysym): 356 code, _, mods = get_keycode(node, keysym) 357 358 pygame_sdl2.event.post(pygame_sdl2.event.Event( 359 pygame_sdl2.KEYUP, 360 key=code, 361 scancode=code, 362 mod=mods, 363 repeat=False, 364 test=True)) 365