Mercurial > sdl-ios-xcode
comparison src/events/SDL_keyboard.c @ 2268:4baee598306d
Date: Thu, 05 Jul 2007 14:02:33 -0700
From: Sam Lantinga
Subject: SDL 1.3 keyboard plan
After lots of discussion with Christian, this is what we came up with:
> So, to sum up...
> SDLK_* become the physical keys, starting at > (1<<21)
> We create a macro SDLK_INDEX(X)
> We have two functions SDL_GetLayoutKey(SDLKey) and SDL_GetKeyName()
> SDL_GetLayoutKey maps to UCS4 for printable characters, and SDLK* for
non-printable characters
> and does so based on the OS's current keyboard layout
> SDL_GetKeyName() handles both SDLK_* and UCS4, converting UCS4 to UTF-8 and
converting SDLK_* into our names, which are UTF-8 for printable characters.
> WASD folks use SDLK_*, and 'I' folks use SDL_GetLayoutKey(SDLK_*)
Here is the patch he came up with, and his e-mail about it:
Date: Fri, 17 Aug 2007 19:50:28 +0200
From: Christian Walther
Subject: Re: SDL 1.3 keyboard plan
> Sounds great, go ahead and send me a patch.
Here goes! Thanks for having a look. Don't hesitate to comment if
anything does not conform to your ideas.
One caveat: Committing this now may break compilability of some video
drivers - specifically, if they use any of the SDLK_* codes that were
obsoleted and moved into SDL_compat.h. I only tried Cocoa (which did
break, but is already fixed) and X11 (which didn't, but then its key
handling is #iffed out). If that's a problem, it may need to go into
a branch.
-Christian
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 19 Aug 2007 14:52:52 +0000 |
parents | 22342048bcb8 |
children | dbc6d1893869 |
comparison
equal
deleted
inserted
replaced
2267:c785543d1843 | 2268:4baee598306d |
---|---|
25 | 25 |
26 #include "SDL_timer.h" | 26 #include "SDL_timer.h" |
27 #include "SDL_events.h" | 27 #include "SDL_events.h" |
28 #include "SDL_events_c.h" | 28 #include "SDL_events_c.h" |
29 #include "SDL_sysevents.h" | 29 #include "SDL_sysevents.h" |
30 #include "SDL_keynames.h" | |
30 | 31 |
31 | 32 |
32 /* Global keyboard information */ | 33 /* Global keyboard information */ |
33 int SDL_TranslateUNICODE = 0; | 34 int SDL_TranslateUNICODE = 0; |
34 static int SDL_num_keyboards; | 35 static int SDL_num_keyboards; |
35 static int SDL_current_keyboard; | 36 static int SDL_current_keyboard; |
36 static SDL_Keyboard **SDL_keyboards; | 37 static SDL_Keyboard **SDL_keyboards; |
37 | 38 |
38 static const char *SDL_keynames[SDLK_LAST]; /* Array of keycode names */ | |
39 | |
40 /* Public functions */ | 39 /* Public functions */ |
41 int | 40 int |
42 SDL_KeyboardInit(void) | 41 SDL_KeyboardInit(void) |
43 { | 42 { |
44 int i; | |
45 | |
46 /* Set default mode of UNICODE translation */ | 43 /* Set default mode of UNICODE translation */ |
47 SDL_EnableUNICODE(DEFAULT_UNICODE_TRANSLATION); | 44 SDL_EnableUNICODE(DEFAULT_UNICODE_TRANSLATION); |
48 | 45 |
49 /* Initialize the tables */ | |
50 for (i = 0; i < SDL_arraysize(SDL_keynames); ++i) { | |
51 switch (i) { | |
52 case SDLK_BACKSPACE: | |
53 SDL_keynames[i] = "backspace"; | |
54 break; | |
55 case SDLK_TAB: | |
56 SDL_keynames[i] = "tab"; | |
57 break; | |
58 case SDLK_CLEAR: | |
59 SDL_keynames[i] = "clear"; | |
60 break; | |
61 case SDLK_RETURN: | |
62 SDL_keynames[i] = "return"; | |
63 break; | |
64 case SDLK_PAUSE: | |
65 SDL_keynames[i] = "pause"; | |
66 break; | |
67 case SDLK_ESCAPE: | |
68 SDL_keynames[i] = "escape"; | |
69 break; | |
70 case SDLK_SPACE: | |
71 SDL_keynames[i] = "space"; | |
72 break; | |
73 | |
74 case SDLK_KP0: | |
75 SDL_keynames[i] = "[0]"; | |
76 break; | |
77 case SDLK_KP1: | |
78 SDL_keynames[i] = "[1]"; | |
79 break; | |
80 case SDLK_KP2: | |
81 SDL_keynames[i] = "[2]"; | |
82 break; | |
83 case SDLK_KP3: | |
84 SDL_keynames[i] = "[3]"; | |
85 break; | |
86 case SDLK_KP4: | |
87 SDL_keynames[i] = "[4]"; | |
88 break; | |
89 case SDLK_KP5: | |
90 SDL_keynames[i] = "[5]"; | |
91 break; | |
92 case SDLK_KP6: | |
93 SDL_keynames[i] = "[6]"; | |
94 break; | |
95 case SDLK_KP7: | |
96 SDL_keynames[i] = "[7]"; | |
97 break; | |
98 case SDLK_KP8: | |
99 SDL_keynames[i] = "[8]"; | |
100 break; | |
101 case SDLK_KP9: | |
102 SDL_keynames[i] = "[9]"; | |
103 break; | |
104 case SDLK_KP_PERIOD: | |
105 SDL_keynames[i] = "[.]"; | |
106 break; | |
107 case SDLK_KP_DIVIDE: | |
108 SDL_keynames[i] = "[/]"; | |
109 break; | |
110 case SDLK_KP_MULTIPLY: | |
111 SDL_keynames[i] = "[*]"; | |
112 break; | |
113 case SDLK_KP_MINUS: | |
114 SDL_keynames[i] = "[-]"; | |
115 break; | |
116 case SDLK_KP_PLUS: | |
117 SDL_keynames[i] = "[+]"; | |
118 break; | |
119 case SDLK_KP_ENTER: | |
120 SDL_keynames[i] = "enter"; | |
121 break; | |
122 case SDLK_KP_EQUALS: | |
123 SDL_keynames[i] = "equals"; | |
124 break; | |
125 | |
126 case SDLK_UP: | |
127 SDL_keynames[i] = "up"; | |
128 break; | |
129 case SDLK_DOWN: | |
130 SDL_keynames[i] = "down"; | |
131 break; | |
132 case SDLK_RIGHT: | |
133 SDL_keynames[i] = "right"; | |
134 break; | |
135 case SDLK_LEFT: | |
136 SDL_keynames[i] = "left"; | |
137 break; | |
138 case SDLK_INSERT: | |
139 SDL_keynames[i] = "insert"; | |
140 break; | |
141 case SDLK_HOME: | |
142 SDL_keynames[i] = "home"; | |
143 break; | |
144 case SDLK_END: | |
145 SDL_keynames[i] = "end"; | |
146 break; | |
147 case SDLK_PAGEUP: | |
148 SDL_keynames[i] = "page up"; | |
149 break; | |
150 case SDLK_PAGEDOWN: | |
151 SDL_keynames[i] = "page down"; | |
152 break; | |
153 | |
154 case SDLK_F1: | |
155 SDL_keynames[i] = "f1"; | |
156 break; | |
157 case SDLK_F2: | |
158 SDL_keynames[i] = "f2"; | |
159 break; | |
160 case SDLK_F3: | |
161 SDL_keynames[i] = "f3"; | |
162 break; | |
163 case SDLK_F4: | |
164 SDL_keynames[i] = "f4"; | |
165 break; | |
166 case SDLK_F5: | |
167 SDL_keynames[i] = "f5"; | |
168 break; | |
169 case SDLK_F6: | |
170 SDL_keynames[i] = "f6"; | |
171 break; | |
172 case SDLK_F7: | |
173 SDL_keynames[i] = "f7"; | |
174 break; | |
175 case SDLK_F8: | |
176 SDL_keynames[i] = "f8"; | |
177 break; | |
178 case SDLK_F9: | |
179 SDL_keynames[i] = "f9"; | |
180 break; | |
181 case SDLK_F10: | |
182 SDL_keynames[i] = "f10"; | |
183 break; | |
184 case SDLK_F11: | |
185 SDL_keynames[i] = "f11"; | |
186 break; | |
187 case SDLK_F12: | |
188 SDL_keynames[i] = "f12"; | |
189 break; | |
190 case SDLK_F13: | |
191 SDL_keynames[i] = "f13"; | |
192 break; | |
193 case SDLK_F14: | |
194 SDL_keynames[i] = "f14"; | |
195 break; | |
196 case SDLK_F15: | |
197 SDL_keynames[i] = "f15"; | |
198 break; | |
199 | |
200 case SDLK_NUMLOCK: | |
201 SDL_keynames[i] = "numlock"; | |
202 break; | |
203 case SDLK_CAPSLOCK: | |
204 SDL_keynames[i] = "caps lock"; | |
205 break; | |
206 case SDLK_SCROLLOCK: | |
207 SDL_keynames[i] = "scroll lock"; | |
208 break; | |
209 case SDLK_RSHIFT: | |
210 SDL_keynames[i] = "right shift"; | |
211 break; | |
212 case SDLK_LSHIFT: | |
213 SDL_keynames[i] = "left shift"; | |
214 break; | |
215 case SDLK_RCTRL: | |
216 SDL_keynames[i] = "right ctrl"; | |
217 break; | |
218 case SDLK_LCTRL: | |
219 SDL_keynames[i] = "left ctrl"; | |
220 break; | |
221 case SDLK_RALT: | |
222 SDL_keynames[i] = "right alt"; | |
223 break; | |
224 case SDLK_LALT: | |
225 SDL_keynames[i] = "left alt"; | |
226 break; | |
227 case SDLK_RMETA: | |
228 SDL_keynames[i] = "right meta"; | |
229 break; | |
230 case SDLK_LMETA: | |
231 SDL_keynames[i] = "left meta"; | |
232 break; | |
233 case SDLK_LSUPER: | |
234 SDL_keynames[i] = "left super"; /* "Windows" keys */ | |
235 break; | |
236 case SDLK_RSUPER: | |
237 SDL_keynames[i] = "right super"; | |
238 break; | |
239 case SDLK_MODE: | |
240 SDL_keynames[i] = "alt gr"; | |
241 break; | |
242 case SDLK_COMPOSE: | |
243 SDL_keynames[i] = "compose"; | |
244 break; | |
245 | |
246 case SDLK_HELP: | |
247 SDL_keynames[i] = "help"; | |
248 break; | |
249 case SDLK_PRINT: | |
250 SDL_keynames[i] = "print screen"; | |
251 break; | |
252 case SDLK_SYSREQ: | |
253 SDL_keynames[i] = "sys req"; | |
254 break; | |
255 case SDLK_BREAK: | |
256 SDL_keynames[i] = "break"; | |
257 break; | |
258 case SDLK_MENU: | |
259 SDL_keynames[i] = "menu"; | |
260 break; | |
261 case SDLK_POWER: | |
262 SDL_keynames[i] = "power"; | |
263 break; | |
264 case SDLK_EURO: | |
265 SDL_keynames[i] = "euro"; | |
266 break; | |
267 case SDLK_UNDO: | |
268 SDL_keynames[i] = "undo"; | |
269 break; | |
270 | |
271 default: | |
272 SDL_keynames[i] = NULL; | |
273 break; | |
274 } | |
275 } | |
276 | |
277 /* Done. Whew. */ | |
278 return (0); | 46 return (0); |
279 } | 47 } |
280 | 48 |
281 SDL_Keyboard * | 49 SDL_Keyboard * |
282 SDL_GetKeyboard(int index) | 50 SDL_GetKeyboard(int index) |
336 | 104 |
337 void | 105 void |
338 SDL_ResetKeyboard(int index) | 106 SDL_ResetKeyboard(int index) |
339 { | 107 { |
340 SDL_Keyboard *keyboard = SDL_GetKeyboard(index); | 108 SDL_Keyboard *keyboard = SDL_GetKeyboard(index); |
341 SDLKey key; | 109 int key; |
342 | 110 |
343 if (!keyboard) { | 111 if (!keyboard) { |
344 return; | 112 return; |
345 } | 113 } |
346 | 114 |
347 for (key = SDLK_FIRST; key < SDLK_LAST; ++key) { | 115 for (key = SDLK_FIRST; key < SDLK_LAST; ++key) { |
348 if (keyboard->keystate[key] == SDL_PRESSED) { | 116 if (keyboard->keystate[key] == SDL_PRESSED) { |
349 SDL_SendKeyboardKey(index, SDL_RELEASED, 0, key); | 117 SDL_SendKeyboardKey(index, SDL_RELEASED, 0, |
118 key | SDL_KEY_CAN_BE_PHYSICAL_BIT); | |
350 } | 119 } |
351 } | 120 } |
352 } | 121 } |
353 | 122 |
354 void | 123 void |
430 return; | 199 return; |
431 } | 200 } |
432 keyboard->modstate = modstate; | 201 keyboard->modstate = modstate; |
433 } | 202 } |
434 | 203 |
204 SDLKey | |
205 SDL_GetLayoutKey(SDLKey physicalKey) | |
206 { | |
207 SDL_VideoDevice *_this = SDL_GetVideoDevice(); | |
208 if (_this && _this->GetLayoutKey) { | |
209 return _this->GetLayoutKey(_this, physicalKey) | |
210 | (physicalKey & SDL_KEY_KEYPAD_BIT); | |
211 } else { | |
212 return physicalKey; | |
213 } | |
214 } | |
215 | |
435 const char * | 216 const char * |
436 SDL_GetKeyName(SDLKey key) | 217 SDL_GetKeyName(SDLKey layoutKey) |
437 { | 218 { |
438 const char *keyname; | 219 const char *keyname = NULL; |
439 | 220 |
440 if (key < SDL_arraysize(SDL_keynames)) { | 221 if ((layoutKey & SDL_KEY_LAYOUT_SPECIAL_BIT) != 0) { |
441 keyname = SDL_keynames[key]; | 222 SDL_VideoDevice *_this = SDL_GetVideoDevice(); |
223 if (_this && _this->GetSpecialKeyName) { | |
224 keyname = _this->GetSpecialKeyName(_this, layoutKey); | |
225 } | |
226 } else if ((layoutKey & SDL_KEY_CAN_BE_PHYSICAL_BIT) == 0) { | |
227 /* SDLK_INDEX(layoutKey) is the unicode code point of the character generated by the key */ | |
228 static char buffer[9]; /* 6 (maximal UTF-8 char length) + 2 ([] for keypad) + 1 (null teminator) */ | |
229 char *bufferPtr = &buffer[1]; | |
230 SDL_iconv_t cd; | |
231 size_t inbytesleft = 4, outbytesleft = 8; | |
232 Uint32 codepoint = SDLK_INDEX(layoutKey); | |
233 const char *codepointPtr = (const char *) &codepoint; | |
234 | |
235 /* Unaccented letter keys on latin keyboards are normally labeled in upper case (and probably on others like Greek or Cyrillic too, so if you happen to know for sure, please adapt this). */ | |
236 if (codepoint >= 'a' && codepoint <= 'z') { | |
237 codepoint -= 32; | |
238 } | |
239 | |
240 cd = SDL_iconv_open("UTF-8", "UCS-4"); | |
241 if (cd == (SDL_iconv_t) (-1)) | |
242 return ""; | |
243 SDL_iconv(cd, &codepointPtr, &inbytesleft, &bufferPtr, &outbytesleft); | |
244 SDL_iconv_close(cd); | |
245 *bufferPtr = '\0'; | |
246 | |
247 if ((layoutKey & SDL_KEY_KEYPAD_BIT) != 0) { | |
248 buffer[0] = '['; | |
249 *bufferPtr++ = ']'; | |
250 *bufferPtr = '\0'; | |
251 keyname = buffer; | |
252 } else { | |
253 keyname = &buffer[1]; | |
254 } | |
442 } else { | 255 } else { |
443 keyname = NULL; | 256 /* SDLK_INDEX(layoutKey) is a physical key number */ |
444 } | 257 if (SDLK_INDEX(layoutKey) < SDL_arraysize(SDL_keynames)) { |
258 keyname = SDL_keynames[SDLK_INDEX(layoutKey)]; | |
259 } | |
260 } | |
261 | |
445 if (keyname == NULL) { | 262 if (keyname == NULL) { |
446 if (key < 256) { | 263 keyname = SDL_keynames[SDLK_INDEX(SDLK_UNKNOWN)]; |
447 static char temp[4]; | 264 } |
448 char *cvt; | 265 |
449 temp[0] = (char) key; | |
450 temp[1] = '\0'; | |
451 cvt = SDL_iconv_string("UTF-8", "ISO-8859-1", temp, 1); | |
452 if (cvt) { | |
453 SDL_strlcpy(temp, cvt, SDL_arraysize(temp)); | |
454 SDL_free(cvt); | |
455 } | |
456 keyname = temp; | |
457 } else { | |
458 keyname = "unknown key"; | |
459 } | |
460 } | |
461 return keyname; | 266 return keyname; |
267 } | |
268 | |
269 void | |
270 SDL_SetKeyName(SDLKey physicalKey, const char *name) | |
271 { | |
272 physicalKey = SDLK_INDEX(physicalKey); | |
273 if (physicalKey < SDL_arraysize(SDL_keynames)) { | |
274 SDL_keynames[physicalKey] = name; | |
275 } | |
462 } | 276 } |
463 | 277 |
464 void | 278 void |
465 SDL_SetKeyboardFocus(int index, SDL_WindowID windowID) | 279 SDL_SetKeyboardFocus(int index, SDL_WindowID windowID) |
466 { | 280 { |
511 } | 325 } |
512 } | 326 } |
513 } | 327 } |
514 | 328 |
515 int | 329 int |
516 SDL_SendKeyboardKey(int index, Uint8 state, Uint8 scancode, SDLKey key) | 330 SDL_SendKeyboardKey(int index, Uint8 state, Uint8 scancode, |
331 SDLKey physicalKey) | |
517 { | 332 { |
518 SDL_Keyboard *keyboard = SDL_GetKeyboard(index); | 333 SDL_Keyboard *keyboard = SDL_GetKeyboard(index); |
519 int posted; | 334 int posted; |
520 Uint16 modstate; | 335 Uint16 modstate; |
521 Uint8 type; | 336 Uint8 type; |
522 | 337 |
523 if (!keyboard) { | 338 if (!keyboard || physicalKey == SDLK_NONE) { |
524 return 0; | 339 return 0; |
525 } | 340 } |
526 #if 0 | 341 #if 0 |
527 printf("The '%s' key has been %s\n", SDL_GetKeyName(key), | 342 printf("The '%s' key has been %s\n", SDL_GetKeyName(physicalKey), |
528 state == SDL_PRESSED ? "pressed" : "released"); | 343 state == SDL_PRESSED ? "pressed" : "released"); |
529 #endif | 344 #endif |
530 if (state == SDL_PRESSED) { | 345 if (state == SDL_PRESSED) { |
531 modstate = keyboard->modstate; | 346 modstate = keyboard->modstate; |
532 switch (key) { | 347 switch (physicalKey) { |
533 case SDLK_UNKNOWN: | 348 case SDLK_UNKNOWN: |
534 break; | 349 break; |
535 case SDLK_NUMLOCK: | 350 case SDLK_KP_NUMLOCKCLEAR: |
536 keyboard->modstate ^= KMOD_NUM; | 351 keyboard->modstate ^= KMOD_NUM; |
537 break; | 352 break; |
538 case SDLK_CAPSLOCK: | 353 case SDLK_CAPSLOCK: |
539 keyboard->modstate ^= KMOD_CAPS; | 354 keyboard->modstate ^= KMOD_CAPS; |
540 break; | 355 break; |
567 break; | 382 break; |
568 default: | 383 default: |
569 break; | 384 break; |
570 } | 385 } |
571 } else { | 386 } else { |
572 switch (key) { | 387 switch (physicalKey) { |
573 case SDLK_UNKNOWN: | 388 case SDLK_UNKNOWN: |
574 break; | 389 break; |
575 case SDLK_NUMLOCK: | 390 case SDLK_KP_NUMLOCKCLEAR: |
576 case SDLK_CAPSLOCK: | 391 case SDLK_CAPSLOCK: |
577 break; | 392 break; |
578 case SDLK_LCTRL: | 393 case SDLK_LCTRL: |
579 keyboard->modstate &= ~KMOD_LCTRL; | 394 keyboard->modstate &= ~KMOD_LCTRL; |
580 break; | 395 break; |
619 default: | 434 default: |
620 /* Invalid state -- bail */ | 435 /* Invalid state -- bail */ |
621 return 0; | 436 return 0; |
622 } | 437 } |
623 | 438 |
624 if (key != SDLK_UNKNOWN) { | 439 if (physicalKey != SDLK_UNKNOWN) { |
625 /* Drop events that don't change state */ | 440 /* Drop events that don't change state */ |
626 if (keyboard->keystate[key] == state) { | 441 if (keyboard->keystate[SDLK_INDEX(physicalKey)] == state) { |
627 #if 0 | 442 #if 0 |
628 printf("Keyboard event didn't change state - dropped!\n"); | 443 printf("Keyboard event didn't change state - dropped!\n"); |
629 #endif | 444 #endif |
630 return 0; | 445 return 0; |
631 } | 446 } |
632 | 447 |
633 /* Update internal keyboard state */ | 448 /* Update internal keyboard state */ |
634 keyboard->keystate[key] = state; | 449 keyboard->keystate[SDLK_INDEX(physicalKey)] = state; |
635 } | 450 } |
636 | 451 |
637 /* Post the event, if desired */ | 452 /* Post the event, if desired */ |
638 posted = 0; | 453 posted = 0; |
639 if (SDL_ProcessEvents[type] == SDL_ENABLE) { | 454 if (SDL_ProcessEvents[type] == SDL_ENABLE) { |
640 SDL_Event event; | 455 SDL_Event event; |
641 event.key.type = type; | 456 event.key.type = type; |
642 event.key.which = (Uint8) index; | 457 event.key.which = (Uint8) index; |
643 event.key.state = state; | 458 event.key.state = state; |
644 event.key.keysym.scancode = scancode; | 459 event.key.keysym.scancode = scancode; |
645 event.key.keysym.sym = (Uint16) key; | 460 event.key.keysym.sym = physicalKey; |
646 event.key.keysym.mod = modstate; | 461 event.key.keysym.mod = modstate; |
647 event.key.keysym.unicode = 0; | 462 event.key.keysym.unicode = 0; |
648 event.key.windowID = keyboard->focus; | 463 event.key.windowID = keyboard->focus; |
649 posted = (SDL_PushEvent(&event) > 0); | 464 posted = (SDL_PushEvent(&event) > 0); |
650 } | 465 } |