Mercurial > sdl-ios-xcode
comparison src/video/cocoa/SDL_cocoakeyboard.m @ 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 | 243bc7ae5a21 |
children | d5a11262f067 |
comparison
equal
deleted
inserted
replaced
2267:c785543d1843 | 2268:4baee598306d |
---|---|
24 #include "SDL_cocoavideo.h" | 24 #include "SDL_cocoavideo.h" |
25 #include "SDL_cocoakeys.h" | 25 #include "SDL_cocoakeys.h" |
26 | 26 |
27 #include "../../events/SDL_keyboard_c.h" | 27 #include "../../events/SDL_keyboard_c.h" |
28 | 28 |
29 #include <Carbon/Carbon.h> | |
30 | |
29 | 31 |
30 #ifndef NX_DEVICERCTLKEYMASK | 32 #ifndef NX_DEVICERCTLKEYMASK |
31 #define NX_DEVICELCTLKEYMASK 0x00000001 | 33 #define NX_DEVICELCTLKEYMASK 0x00000001 |
32 #endif | 34 #endif |
33 #ifndef NX_DEVICELSHIFTKEYMASK | 35 #ifndef NX_DEVICELSHIFTKEYMASK |
49 #define NX_DEVICERALTKEYMASK 0x00000040 | 51 #define NX_DEVICERALTKEYMASK 0x00000040 |
50 #endif | 52 #endif |
51 #ifndef NX_DEVICERCTLKEYMASK | 53 #ifndef NX_DEVICERCTLKEYMASK |
52 #define NX_DEVICERCTLKEYMASK 0x00002000 | 54 #define NX_DEVICERCTLKEYMASK 0x00002000 |
53 #endif | 55 #endif |
54 | |
55 static void | |
56 InitKeymap (SDLKey *keymap) | |
57 { | |
58 const void *KCHRPtr; | |
59 UInt32 state; | |
60 UInt32 value; | |
61 int i; | |
62 | |
63 for ( i=0; i<256; ++i ) | |
64 keymap[i] = SDLK_UNKNOWN; | |
65 | |
66 /* This keymap is almost exactly the same as the OS 9 one */ | |
67 keymap[KEY_ESCAPE] = SDLK_ESCAPE; | |
68 keymap[KEY_F1] = SDLK_F1; | |
69 keymap[KEY_F2] = SDLK_F2; | |
70 keymap[KEY_F3] = SDLK_F3; | |
71 keymap[KEY_F4] = SDLK_F4; | |
72 keymap[KEY_F5] = SDLK_F5; | |
73 keymap[KEY_F6] = SDLK_F6; | |
74 keymap[KEY_F7] = SDLK_F7; | |
75 keymap[KEY_F8] = SDLK_F8; | |
76 keymap[KEY_F9] = SDLK_F9; | |
77 keymap[KEY_F10] = SDLK_F10; | |
78 keymap[KEY_F11] = SDLK_F11; | |
79 keymap[KEY_F12] = SDLK_F12; | |
80 keymap[KEY_F13] = SDLK_F13; | |
81 keymap[KEY_F14] = SDLK_F14; | |
82 keymap[KEY_F15] = SDLK_F15; | |
83 /* | |
84 keymap[KEY_PRINT] = SDLK_PRINT; | |
85 keymap[KEY_SCROLLOCK] = SDLK_SCROLLOCK; | |
86 keymap[KEY_PAUSE] = SDLK_PAUSE; | |
87 */ | |
88 keymap[KEY_POWER] = SDLK_POWER; | |
89 keymap[KEY_BACKQUOTE] = SDLK_BACKQUOTE; | |
90 keymap[KEY_1] = SDLK_1; | |
91 keymap[KEY_2] = SDLK_2; | |
92 keymap[KEY_3] = SDLK_3; | |
93 keymap[KEY_4] = SDLK_4; | |
94 keymap[KEY_5] = SDLK_5; | |
95 keymap[KEY_6] = SDLK_6; | |
96 keymap[KEY_7] = SDLK_7; | |
97 keymap[KEY_8] = SDLK_8; | |
98 keymap[KEY_9] = SDLK_9; | |
99 keymap[KEY_0] = SDLK_0; | |
100 keymap[KEY_MINUS] = SDLK_MINUS; | |
101 keymap[KEY_EQUALS] = SDLK_EQUALS; | |
102 keymap[KEY_BACKSPACE] = SDLK_BACKSPACE; | |
103 keymap[KEY_INSERT] = SDLK_INSERT; | |
104 keymap[KEY_HOME] = SDLK_HOME; | |
105 keymap[KEY_PAGEUP] = SDLK_PAGEUP; | |
106 keymap[KEY_NUMLOCK] = SDLK_NUMLOCK; | |
107 keymap[KEY_KP_EQUALS] = SDLK_KP_EQUALS; | |
108 keymap[KEY_KP_DIVIDE] = SDLK_KP_DIVIDE; | |
109 keymap[KEY_KP_MULTIPLY] = SDLK_KP_MULTIPLY; | |
110 keymap[KEY_TAB] = SDLK_TAB; | |
111 keymap[KEY_q] = SDLK_q; | |
112 keymap[KEY_w] = SDLK_w; | |
113 keymap[KEY_e] = SDLK_e; | |
114 keymap[KEY_r] = SDLK_r; | |
115 keymap[KEY_t] = SDLK_t; | |
116 keymap[KEY_y] = SDLK_y; | |
117 keymap[KEY_u] = SDLK_u; | |
118 keymap[KEY_i] = SDLK_i; | |
119 keymap[KEY_o] = SDLK_o; | |
120 keymap[KEY_p] = SDLK_p; | |
121 keymap[KEY_LEFTBRACKET] = SDLK_LEFTBRACKET; | |
122 keymap[KEY_RIGHTBRACKET] = SDLK_RIGHTBRACKET; | |
123 keymap[KEY_BACKSLASH] = SDLK_BACKSLASH; | |
124 keymap[KEY_DELETE] = SDLK_DELETE; | |
125 keymap[KEY_END] = SDLK_END; | |
126 keymap[KEY_PAGEDOWN] = SDLK_PAGEDOWN; | |
127 keymap[KEY_KP7] = SDLK_KP7; | |
128 keymap[KEY_KP8] = SDLK_KP8; | |
129 keymap[KEY_KP9] = SDLK_KP9; | |
130 keymap[KEY_KP_MINUS] = SDLK_KP_MINUS; | |
131 keymap[KEY_CAPSLOCK] = SDLK_CAPSLOCK; | |
132 keymap[KEY_a] = SDLK_a; | |
133 keymap[KEY_s] = SDLK_s; | |
134 keymap[KEY_d] = SDLK_d; | |
135 keymap[KEY_f] = SDLK_f; | |
136 keymap[KEY_g] = SDLK_g; | |
137 keymap[KEY_h] = SDLK_h; | |
138 keymap[KEY_j] = SDLK_j; | |
139 keymap[KEY_k] = SDLK_k; | |
140 keymap[KEY_l] = SDLK_l; | |
141 keymap[KEY_SEMICOLON] = SDLK_SEMICOLON; | |
142 keymap[KEY_QUOTE] = SDLK_QUOTE; | |
143 keymap[KEY_RETURN] = SDLK_RETURN; | |
144 keymap[KEY_KP4] = SDLK_KP4; | |
145 keymap[KEY_KP5] = SDLK_KP5; | |
146 keymap[KEY_KP6] = SDLK_KP6; | |
147 keymap[KEY_KP_PLUS] = SDLK_KP_PLUS; | |
148 keymap[KEY_LSHIFT] = SDLK_LSHIFT; | |
149 keymap[KEY_RSHIFT] = SDLK_RSHIFT; | |
150 keymap[KEY_z] = SDLK_z; | |
151 keymap[KEY_x] = SDLK_x; | |
152 keymap[KEY_c] = SDLK_c; | |
153 keymap[KEY_v] = SDLK_v; | |
154 keymap[KEY_b] = SDLK_b; | |
155 keymap[KEY_n] = SDLK_n; | |
156 keymap[KEY_m] = SDLK_m; | |
157 keymap[KEY_COMMA] = SDLK_COMMA; | |
158 keymap[KEY_PERIOD] = SDLK_PERIOD; | |
159 keymap[KEY_SLASH] = SDLK_SLASH; | |
160 keymap[KEY_UP] = SDLK_UP; | |
161 keymap[KEY_KP1] = SDLK_KP1; | |
162 keymap[KEY_KP2] = SDLK_KP2; | |
163 keymap[KEY_KP3] = SDLK_KP3; | |
164 keymap[KEY_KP_ENTER] = SDLK_KP_ENTER; | |
165 keymap[KEY_LCTRL] = SDLK_LCTRL; | |
166 keymap[KEY_LALT] = SDLK_LALT; | |
167 keymap[KEY_LMETA] = SDLK_LMETA; | |
168 keymap[KEY_RCTRL] = SDLK_RCTRL; | |
169 keymap[KEY_RALT] = SDLK_RALT; | |
170 keymap[KEY_RMETA] = SDLK_RMETA; | |
171 keymap[KEY_SPACE] = SDLK_SPACE; | |
172 keymap[KEY_LEFT] = SDLK_LEFT; | |
173 keymap[KEY_DOWN] = SDLK_DOWN; | |
174 keymap[KEY_RIGHT] = SDLK_RIGHT; | |
175 keymap[KEY_KP0] = SDLK_KP0; | |
176 keymap[KEY_KP_PERIOD] = SDLK_KP_PERIOD; | |
177 keymap[KEY_IBOOK_ENTER] = SDLK_KP_ENTER; | |
178 keymap[KEY_IBOOK_RIGHT] = SDLK_RIGHT; | |
179 keymap[KEY_IBOOK_DOWN] = SDLK_DOWN; | |
180 keymap[KEY_IBOOK_UP] = SDLK_UP; | |
181 keymap[KEY_IBOOK_LEFT] = SDLK_LEFT; | |
182 | |
183 /* | |
184 Up there we setup a static scancode->keysym map. However, it will not | |
185 work very well on international keyboard. Hence we now query Mac OS X | |
186 for its own keymap to adjust our own mapping table. However, this is | |
187 basically only useful for ascii char keys. This is also the reason | |
188 why we keep the static table, too. | |
189 */ | |
190 | |
191 /* Get a pointer to the systems cached KCHR */ | |
192 KCHRPtr = (void *)GetScriptManagerVariable(smKCHRCache); | |
193 if (KCHRPtr) { | |
194 /* Loop over all 127 possible scan codes */ | |
195 for (i = 0; i < 0x7F; i++) { | |
196 /* We pretend a clean start to begin with (i.e. no dead keys active */ | |
197 state = 0; | |
198 | |
199 /* Now translate the key code to a key value */ | |
200 value = KeyTranslate(KCHRPtr, i, &state) & 0xff; | |
201 | |
202 /* If the state become 0, it was a dead key. We need to translate again, | |
203 passing in the new state, to get the actual key value */ | |
204 if (state != 0) | |
205 value = KeyTranslate(KCHRPtr, i, &state) & 0xff; | |
206 | |
207 /* Now we should have a latin1 value, which are SDL keysyms */ | |
208 if (value >= 32 && value <= 255) { | |
209 keymap[i] = value; | |
210 } | |
211 } | |
212 } | |
213 | |
214 /* | |
215 The keypad codes are re-setup here, because the loop above cannot | |
216 distinguish between a key on the keypad and a regular key. We maybe | |
217 could get around this problem in another fashion: NSEvent's flags | |
218 include a "NSNumericPadKeyMask" bit; we could check that and modify | |
219 the symbol we return on the fly. However, this flag seems to exhibit | |
220 some weird behaviour related to the num lock key | |
221 */ | |
222 keymap[KEY_KP0] = SDLK_KP0; | |
223 keymap[KEY_KP1] = SDLK_KP1; | |
224 keymap[KEY_KP2] = SDLK_KP2; | |
225 keymap[KEY_KP3] = SDLK_KP3; | |
226 keymap[KEY_KP4] = SDLK_KP4; | |
227 keymap[KEY_KP5] = SDLK_KP5; | |
228 keymap[KEY_KP6] = SDLK_KP6; | |
229 keymap[KEY_KP7] = SDLK_KP7; | |
230 keymap[KEY_KP8] = SDLK_KP8; | |
231 keymap[KEY_KP9] = SDLK_KP9; | |
232 keymap[KEY_KP_MINUS] = SDLK_KP_MINUS; | |
233 keymap[KEY_KP_PLUS] = SDLK_KP_PLUS; | |
234 keymap[KEY_KP_PERIOD] = SDLK_KP_PERIOD; | |
235 keymap[KEY_KP_EQUALS] = SDLK_KP_EQUALS; | |
236 keymap[KEY_KP_DIVIDE] = SDLK_KP_DIVIDE; | |
237 keymap[KEY_KP_MULTIPLY] = SDLK_KP_MULTIPLY; | |
238 keymap[KEY_KP_ENTER] = SDLK_KP_ENTER; | |
239 } | |
240 | 56 |
241 /* This is the original behavior, before support was added for | 57 /* This is the original behavior, before support was added for |
242 * differentiating between left and right versions of the keys. | 58 * differentiating between left and right versions of the keys. |
243 */ | 59 */ |
244 static void | 60 static void |
431 | 247 |
432 oldMask = oldMods & NSNumericPadKeyMask; | 248 oldMask = oldMods & NSNumericPadKeyMask; |
433 newMask = newMods & NSNumericPadKeyMask; | 249 newMask = newMods & NSNumericPadKeyMask; |
434 | 250 |
435 if (oldMask != newMask) { | 251 if (oldMask != newMask) { |
436 SDL_SendKeyboardKey(keyboard, SDL_PRESSED, (Uint8)scancode, SDLK_NUMLOCK); | 252 SDL_SendKeyboardKey(keyboard, SDL_PRESSED, (Uint8)scancode, SDLK_KP_NUMLOCKCLEAR); |
437 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, SDLK_NUMLOCK); | 253 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, SDLK_KP_NUMLOCKCLEAR); |
438 } | 254 } |
439 } | 255 } |
440 | 256 |
441 /* This function will handle the modifier keys and also determine the | 257 /* This function will handle the modifier keys and also determine the |
442 * correct side of the key. | 258 * correct side of the key. |
511 { | 327 { |
512 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; | 328 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; |
513 SDL_Keyboard keyboard; | 329 SDL_Keyboard keyboard; |
514 NSAutoreleasePool *pool; | 330 NSAutoreleasePool *pool; |
515 | 331 |
516 InitKeymap(data->keymap); | |
517 | |
518 pool = [[NSAutoreleasePool alloc] init]; | 332 pool = [[NSAutoreleasePool alloc] init]; |
519 data->fieldEdit = [[NSTextView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 0.0, 0.0)]; | 333 data->fieldEdit = [[NSTextView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 0.0, 0.0)]; |
520 [pool release]; | 334 [pool release]; |
521 | 335 |
522 SDL_zero(keyboard); | 336 SDL_zero(keyboard); |
523 data->keyboard = SDL_AddKeyboard(&keyboard, -1); | 337 data->keyboard = SDL_AddKeyboard(&keyboard, -1); |
338 | |
339 /* Set our own names for the platform-dependent but layout-independent keys */ | |
340 SDL_SetKeyName(SDLK_KP_NUMLOCKCLEAR, "clear"); | |
341 SDL_SetKeyName(SDLK_LALT, "left option"); | |
342 SDL_SetKeyName(SDLK_LMETA, "left command"); | |
343 SDL_SetKeyName(SDLK_RALT, "right option"); | |
344 SDL_SetKeyName(SDLK_RMETA, "right command"); | |
524 } | 345 } |
525 | 346 |
526 void | 347 void |
527 Cocoa_HandleKeyEvent(_THIS, NSEvent *event) | 348 Cocoa_HandleKeyEvent(_THIS, NSEvent *event) |
528 { | 349 { |
529 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; | 350 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; |
530 unsigned short scancode = [event keyCode]; | 351 unsigned short scancode = [event keyCode]; |
352 SDLKey physicalKey; | |
531 const char *text; | 353 const char *text; |
532 | 354 |
533 if (scancode >= 256) { | 355 if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) { |
356 /* see comments in SDL_cocoakeys.h */ | |
357 scancode = 60 - scancode; | |
358 } | |
359 if (scancode < SDL_arraysize(macToSDLKey)) { | |
360 physicalKey = macToSDLKey[scancode]; | |
361 } | |
362 else { | |
534 /* Hmm, does this ever happen? If so, need to extend the keymap... */ | 363 /* Hmm, does this ever happen? If so, need to extend the keymap... */ |
535 return; | 364 physicalKey = SDLK_UNKNOWN; |
536 } | 365 } |
537 | 366 |
538 switch ([event type]) { | 367 switch ([event type]) { |
539 case NSKeyDown: | 368 case NSKeyDown: |
540 if (![event isARepeat]) { | 369 if (![event isARepeat]) { |
541 SDL_SendKeyboardKey(data->keyboard, SDL_PRESSED, (Uint8)scancode, | 370 SDL_SendKeyboardKey(data->keyboard, SDL_PRESSED, (Uint8)scancode, physicalKey); |
542 data->keymap[scancode]); | 371 #if 1 |
372 if (physicalKey == SDLK_UNKNOWN) { | |
373 fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, report this to the SDL mailing list <sdl@libsdl.org> or to Christian Walther <cwalther@gmx.ch>. Mac virtual key code is %d.\n", scancode); | |
374 } | |
375 #endif | |
543 } | 376 } |
544 if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) { | 377 if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) { |
378 /* FIXME CW 2007-08-16: only send those events to the field editor for which we actually want text events, not e.g. esc or function keys. Arrow keys in particular seem to produce crashes sometimes. */ | |
545 [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]]; | 379 [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]]; |
546 text = [[event characters] UTF8String]; | 380 text = [[event characters] UTF8String]; |
547 if(text && *text) { | 381 if(text && *text) { |
548 SDL_SendKeyboardText(data->keyboard, text); | 382 SDL_SendKeyboardText(data->keyboard, text); |
549 } | 383 } |
550 } | 384 } |
551 break; | 385 break; |
552 case NSKeyUp: | 386 case NSKeyUp: |
553 SDL_SendKeyboardKey(data->keyboard, SDL_RELEASED, (Uint8)scancode, | 387 SDL_SendKeyboardKey(data->keyboard, SDL_RELEASED, (Uint8)scancode, physicalKey); |
554 data->keymap[scancode]); | |
555 break; | 388 break; |
556 case NSFlagsChanged: | 389 case NSFlagsChanged: |
390 /* FIXME CW 2007-08-14: check if this whole mess that takes up half of this file is really necessary */ | |
557 HandleModifiers(_this, scancode, [event modifierFlags]); | 391 HandleModifiers(_this, scancode, [event modifierFlags]); |
558 break; | 392 break; |
393 default: /* just to avoid compiler warnings */ | |
394 break; | |
395 } | |
396 } | |
397 | |
398 SDLKey | |
399 Cocoa_GetLayoutKey(_THIS, SDLKey physicalKey) | |
400 { | |
401 switch (physicalKey) { | |
402 /* Many of these keys would generate a character in the translation by keyboard layout, but an inappropriate one, so we catch them before. */ | |
403 case SDLK_UNKNOWN: | |
404 case SDLK_RETURN: | |
405 case SDLK_ESCAPE: | |
406 case SDLK_BACKSPACE: | |
407 case SDLK_TAB: | |
408 case SDLK_SPACE: | |
409 case SDLK_CAPSLOCK: | |
410 case SDLK_F1: | |
411 case SDLK_F2: | |
412 case SDLK_F3: | |
413 case SDLK_F4: | |
414 case SDLK_F5: | |
415 case SDLK_F6: | |
416 case SDLK_F7: | |
417 case SDLK_F8: | |
418 case SDLK_F9: | |
419 case SDLK_F10: | |
420 case SDLK_F11: | |
421 case SDLK_F12: | |
422 case SDLK_PRINTSCREEN: | |
423 case SDLK_SCROLLLOCK: | |
424 case SDLK_PAUSE: | |
425 case SDLK_INSERT: | |
426 case SDLK_HOME: | |
427 case SDLK_PAGEUP: | |
428 case SDLK_DELETE: | |
429 case SDLK_END: | |
430 case SDLK_PAGEDOWN: | |
431 case SDLK_RIGHT: | |
432 case SDLK_LEFT: | |
433 case SDLK_DOWN: | |
434 case SDLK_UP: | |
435 case SDLK_KP_NUMLOCKCLEAR: | |
436 case SDLK_KP_ENTER: | |
437 case SDLK_APPLICATION: | |
438 case SDLK_POWER: | |
439 case SDLK_F13: | |
440 case SDLK_F14: | |
441 case SDLK_F15: | |
442 case SDLK_F16: | |
443 case SDLK_LCTRL: | |
444 case SDLK_LSHIFT: | |
445 case SDLK_LALT: | |
446 case SDLK_LMETA: | |
447 case SDLK_RCTRL: | |
448 case SDLK_RSHIFT: | |
449 case SDLK_RALT: | |
450 case SDLK_RMETA: | |
451 return physicalKey; | |
452 | |
453 /* For the rest, we try the translation first. */ | |
454 default: { | |
455 UInt16 vkey = 0; | |
456 KeyboardLayoutRef layout; | |
457 KeyboardLayoutKind kind; | |
458 UInt32 keyboardType = LMGetKbdType(); | |
459 | |
460 /* Look up pkey to get a Mac virtual key code - linear search isn't terribly efficient, this might have to be optimized. */ | |
461 while (vkey < 128 && physicalKey != macToSDLKey[vkey]) vkey++; | |
462 if (vkey == 128) return physicalKey; | |
463 if ((vkey == 10 || vkey == 50) && KBGetLayoutType(keyboardType) == kKeyboardISO) vkey = 60 - vkey; /* see comments in SDL_cocoakeys.h */ | |
464 | |
465 if (KLGetCurrentKeyboardLayout(&layout) != noErr) return physicalKey; | |
466 if (KLGetKeyboardLayoutProperty(layout, kKLKind, (const void **)&kind) != noErr) return physicalKey; | |
467 if (kind == kKLKCHRuchrKind || kind == kKLuchrKind) { | |
468 UniChar utf16String[4]; | |
469 UInt32 deadKeyState = 0; | |
470 UniCharCount actualStringLength; | |
471 const UCKeyboardLayout *uchrData; | |
472 | |
473 if (KLGetKeyboardLayoutProperty(layout, kKLuchrData, (const void **)&uchrData) != noErr) return physicalKey; | |
474 if (UCKeyTranslate(uchrData, vkey, kUCKeyActionDisplay, 0, keyboardType, 0, &deadKeyState, 4, &actualStringLength, utf16String) != noErr) return physicalKey; | |
475 /* kUCKeyActionDisplay (instead of kUCKeyActionDown) seems to take care of dead keys, so no need to check for that case and simulate a second key press */ | |
476 | |
477 if (actualStringLength == 0) return physicalKey; | |
478 | |
479 /* Decode the first character from UTF-16. I'm not sure if this is appropriate for keyboard layouts that generate more than 1 character, or if we would have to use SDL_KEY_LAYOUT_SPECIAL_BIT in that case. */ | |
480 if (utf16String[0] < 0xD800 || utf16String[0] > 0xDFFF) { | |
481 return utf16String[0]; | |
482 } | |
483 else if (utf16String[0] > 0xDBFF || utf16String[1] < 0xDC00 || utf16String[1] > 0xDFFF) { | |
484 /* invalid UTF-16 */ | |
485 return physicalKey; | |
486 } | |
487 else { | |
488 return (((utf16String[0] & 0x3FF) << 10) | (utf16String[1] & 0x3FF)) + 0x10000; | |
489 } | |
490 } | |
491 else { /* kind == kKLKCHRKind */ | |
492 const void *kchrData; | |
493 UInt32 state = 0; | |
494 UInt8 charCode; | |
495 SInt32 scriptCode; | |
496 TextEncoding keyboardEncoding; | |
497 CFStringRef conversionString; | |
498 UniChar codepoint; | |
499 | |
500 if (KLGetKeyboardLayoutProperty(layout, kKLKCHRData, &kchrData) != noErr) return physicalKey; | |
501 charCode = KeyTranslate(kchrData, vkey, &state) & 0xFF; /* Actually returns a UInt32 containing two character codes (and two 'reserved' bytes), but we're only interested in the second (or only) one */ | |
502 if (charCode == 0) { | |
503 /* It's a dead key, so simulate a second key press */ | |
504 charCode = KeyTranslate(kchrData, vkey, &state) & 0xFF; | |
505 /* Still zero? Give up. */ | |
506 if (charCode == 0) return physicalKey; | |
507 } | |
508 if (KLGetKeyboardLayoutProperty(layout, kKLGroupIdentifier, (const void **)&scriptCode) != noErr) return physicalKey; /* That the group identifier is actually a script code is not documented, but confirmed here: <http://lists.apple.com/archives/carbon-dev/2005/Jan/msg00533.html> */ | |
509 if (UpgradeScriptInfoToTextEncoding(scriptCode, kTextLanguageDontCare, kTextRegionDontCare, NULL, &keyboardEncoding) != noErr) return physicalKey; | |
510 | |
511 conversionString = CFStringCreateWithBytes(kCFAllocatorDefault, &charCode, 1, keyboardEncoding, FALSE); | |
512 codepoint = CFStringGetCharacterAtIndex(conversionString, 0); | |
513 CFRelease(conversionString); | |
514 return codepoint; | |
515 } | |
516 } | |
559 } | 517 } |
560 } | 518 } |
561 | 519 |
562 void | 520 void |
563 Cocoa_QuitKeyboard(_THIS) | 521 Cocoa_QuitKeyboard(_THIS) |