Mercurial > sdl-ios-xcode
comparison src/video/cocoa/SDL_cocoakeyboard.m @ 2303:d87417504c75
First pass implementation of new SDL scancode concept, as discussed with
Christian Walther. Currently only implemented on Mac OS X for sanity
checking purposes.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 05 Feb 2008 07:19:23 +0000 |
parents | f629d566ec6b |
children | 50f58ce12497 |
comparison
equal
deleted
inserted
replaced
2302:7ae1c419b626 | 2303:d87417504c75 |
---|---|
69 */ | 69 */ |
70 static void | 70 static void |
71 DoUnsidedModifiers(int keyboard, unsigned short scancode, | 71 DoUnsidedModifiers(int keyboard, unsigned short scancode, |
72 unsigned int oldMods, unsigned int newMods) | 72 unsigned int oldMods, unsigned int newMods) |
73 { | 73 { |
74 const int mapping[] = { SDLK_CAPSLOCK, SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA }; | 74 const int mapping[] = { |
75 SDL_SCANCODE_CAPSLOCK, | |
76 SDL_SCANCODE_LSHIFT, | |
77 SDL_SCANCODE_LCTRL, | |
78 SDL_SCANCODE_LALT, | |
79 SDL_SCANCODE_LGUI | |
80 }; | |
75 unsigned int i, bit; | 81 unsigned int i, bit; |
76 | 82 |
77 /* Iterate through the bits, testing each against the current modifiers */ | 83 /* Iterate through the bits, testing each against the current modifiers */ |
78 for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) { | 84 for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) { |
79 unsigned int oldMask, newMask; | 85 unsigned int oldMask, newMask; |
82 newMask = newMods & bit; | 88 newMask = newMods & bit; |
83 | 89 |
84 if (oldMask && oldMask != newMask) { /* modifier up event */ | 90 if (oldMask && oldMask != newMask) { /* modifier up event */ |
85 /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ | 91 /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ |
86 if (bit == NSAlphaShiftKeyMask) { | 92 if (bit == NSAlphaShiftKeyMask) { |
87 SDL_SendKeyboardKey(keyboard, SDL_PRESSED, (Uint8)scancode, mapping[i]); | 93 SDL_SendKeyboardKey(keyboard, SDL_PRESSED, mapping[i]); |
88 } | 94 } |
89 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, mapping[i]); | 95 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, mapping[i]); |
90 } else if (newMask && oldMask != newMask) { /* modifier down event */ | 96 } else if (newMask && oldMask != newMask) { /* modifier down event */ |
91 SDL_SendKeyboardKey(keyboard, SDL_PRESSED, (Uint8)scancode, mapping[i]); | 97 SDL_SendKeyboardKey(keyboard, SDL_PRESSED, mapping[i]); |
92 /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ | 98 /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ |
93 if (bit == NSAlphaShiftKeyMask) { | 99 if (bit == NSAlphaShiftKeyMask) { |
94 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, mapping[i]); | 100 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, mapping[i]); |
95 } | 101 } |
96 } | 102 } |
97 } | 103 } |
98 } | 104 } |
99 | 105 |
100 /* This is a helper function for HandleModifierSide. This | 106 /* This is a helper function for HandleModifierSide. This |
101 * function reverts back to behavior before the distinction between | 107 * function reverts back to behavior before the distinction between |
102 * sides was made. | 108 * sides was made. |
103 */ | 109 */ |
104 static void | 110 static void |
105 HandleNonDeviceModifier(int keyboard, unsigned short scancode, | 111 HandleNonDeviceModifier(int keyboard, |
106 unsigned int device_independent_mask, | 112 unsigned int device_independent_mask, |
107 unsigned int oldMods, | 113 unsigned int oldMods, |
108 unsigned int newMods, | 114 unsigned int newMods, |
109 SDLKey key_sym) | 115 SDL_scancode scancode) |
110 { | 116 { |
111 unsigned int oldMask, newMask; | 117 unsigned int oldMask, newMask; |
112 | 118 |
113 /* Isolate just the bits we care about in the depedent bits so we can | 119 /* Isolate just the bits we care about in the depedent bits so we can |
114 * figure out what changed | 120 * figure out what changed |
115 */ | 121 */ |
116 oldMask = oldMods & device_independent_mask; | 122 oldMask = oldMods & device_independent_mask; |
117 newMask = newMods & device_independent_mask; | 123 newMask = newMods & device_independent_mask; |
118 | 124 |
119 if (oldMask && oldMask != newMask) { | 125 if (oldMask && oldMask != newMask) { |
120 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, key_sym); | 126 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, scancode); |
121 } else if (newMask && oldMask != newMask) { | 127 } else if (newMask && oldMask != newMask) { |
122 SDL_SendKeyboardKey(keyboard, SDL_PRESSED, (Uint8)scancode, key_sym); | 128 SDL_SendKeyboardKey(keyboard, SDL_PRESSED, scancode); |
123 } | 129 } |
124 } | 130 } |
125 | 131 |
126 /* This is a helper function for HandleModifierSide. | 132 /* This is a helper function for HandleModifierSide. |
127 * This function sets the actual SDL_PrivateKeyboard event. | 133 * This function sets the actual SDL_PrivateKeyboard event. |
128 */ | 134 */ |
129 static void | 135 static void |
130 HandleModifierOneSide(int keyboard, unsigned short scancode, | 136 HandleModifierOneSide(int keyboard, |
131 unsigned int oldMods, unsigned int newMods, | 137 unsigned int oldMods, unsigned int newMods, |
132 SDLKey key_sym, | 138 SDL_scancode scancode, |
133 unsigned int sided_device_dependent_mask) | 139 unsigned int sided_device_dependent_mask) |
134 { | 140 { |
135 unsigned int old_dep_mask, new_dep_mask; | 141 unsigned int old_dep_mask, new_dep_mask; |
136 | 142 |
137 /* Isolate just the bits we care about in the depedent bits so we can | 143 /* Isolate just the bits we care about in the depedent bits so we can |
143 /* We now know that this side bit flipped. But we don't know if | 149 /* We now know that this side bit flipped. But we don't know if |
144 * it went pressed to released or released to pressed, so we must | 150 * it went pressed to released or released to pressed, so we must |
145 * find out which it is. | 151 * find out which it is. |
146 */ | 152 */ |
147 if (new_dep_mask && old_dep_mask != new_dep_mask) { | 153 if (new_dep_mask && old_dep_mask != new_dep_mask) { |
148 SDL_SendKeyboardKey(keyboard, SDL_PRESSED, (Uint8)scancode, key_sym); | 154 SDL_SendKeyboardKey(keyboard, SDL_PRESSED, scancode); |
149 } else { | 155 } else { |
150 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, key_sym); | 156 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, scancode); |
151 } | 157 } |
152 } | 158 } |
153 | 159 |
154 /* This is a helper function for DoSidedModifiers. | 160 /* This is a helper function for DoSidedModifiers. |
155 * This function will figure out if the modifier key is the left or right side, | 161 * This function will figure out if the modifier key is the left or right side, |
156 * e.g. left-shift vs right-shift. | 162 * e.g. left-shift vs right-shift. |
157 */ | 163 */ |
158 static void | 164 static void |
159 HandleModifierSide(int keyboard, unsigned short scancode, | 165 HandleModifierSide(int keyboard, |
160 int device_independent_mask, | 166 int device_independent_mask, |
161 unsigned int oldMods, unsigned int newMods, | 167 unsigned int oldMods, unsigned int newMods, |
162 SDLKey left_key_sym, | 168 SDL_scancode left_scancode, |
163 SDLKey right_key_sym, | 169 SDL_scancode right_scancode, |
164 unsigned int left_device_dependent_mask, | 170 unsigned int left_device_dependent_mask, |
165 unsigned int right_device_dependent_mask) | 171 unsigned int right_device_dependent_mask) |
166 { | 172 { |
167 unsigned int device_dependent_mask = (left_device_dependent_mask | | 173 unsigned int device_dependent_mask = (left_device_dependent_mask | |
168 right_device_dependent_mask); | 174 right_device_dependent_mask); |
172 * no device dependent flags set, we'll assume that we can't detect this | 178 * no device dependent flags set, we'll assume that we can't detect this |
173 * keyboard and revert to the unsided behavior. | 179 * keyboard and revert to the unsided behavior. |
174 */ | 180 */ |
175 if ((device_dependent_mask & newMods) == 0) { | 181 if ((device_dependent_mask & newMods) == 0) { |
176 /* Revert to the old behavior */ | 182 /* Revert to the old behavior */ |
177 HandleNonDeviceModifier(keyboard, scancode, device_independent_mask, oldMods, newMods, left_key_sym); | 183 HandleNonDeviceModifier(keyboard, device_independent_mask, oldMods, newMods, left_scancode); |
178 return; | 184 return; |
179 } | 185 } |
180 | 186 |
181 /* XOR the previous state against the new state to see if there's a change */ | 187 /* XOR the previous state against the new state to see if there's a change */ |
182 diff_mod = (device_dependent_mask & oldMods) ^ | 188 diff_mod = (device_dependent_mask & oldMods) ^ |
185 /* A change in state was found. Isolate the left and right bits | 191 /* A change in state was found. Isolate the left and right bits |
186 * to handle them separately just in case the values can simulataneously | 192 * to handle them separately just in case the values can simulataneously |
187 * change or if the bits don't both exist. | 193 * change or if the bits don't both exist. |
188 */ | 194 */ |
189 if (left_device_dependent_mask & diff_mod) { | 195 if (left_device_dependent_mask & diff_mod) { |
190 HandleModifierOneSide(keyboard, scancode, oldMods, newMods, left_key_sym, left_device_dependent_mask); | 196 HandleModifierOneSide(keyboard, oldMods, newMods, left_scancode, left_device_dependent_mask); |
191 } | 197 } |
192 if (right_device_dependent_mask & diff_mod) { | 198 if (right_device_dependent_mask & diff_mod) { |
193 HandleModifierOneSide(keyboard, scancode, oldMods, newMods, right_key_sym, right_device_dependent_mask); | 199 HandleModifierOneSide(keyboard, oldMods, newMods, right_scancode, right_device_dependent_mask); |
194 } | 200 } |
195 } | 201 } |
196 } | 202 } |
197 | 203 |
198 /* This is a helper function for DoSidedModifiers. | 204 /* This is a helper function for DoSidedModifiers. |
199 * This function will release a key press in the case that | 205 * This function will release a key press in the case that |
200 * it is clear that the modifier has been released (i.e. one side | 206 * it is clear that the modifier has been released (i.e. one side |
201 * can't still be down). | 207 * can't still be down). |
202 */ | 208 */ |
203 static void | 209 static void |
204 ReleaseModifierSide(int keyboard, unsigned short scancode, | 210 ReleaseModifierSide(int keyboard, |
205 unsigned int device_independent_mask, | 211 unsigned int device_independent_mask, |
206 unsigned int oldMods, unsigned int newMods, | 212 unsigned int oldMods, unsigned int newMods, |
207 SDLKey left_key_sym, | 213 SDL_scancode left_scancode, |
208 SDLKey right_key_sym, | 214 SDL_scancode right_scancode, |
209 unsigned int left_device_dependent_mask, | 215 unsigned int left_device_dependent_mask, |
210 unsigned int right_device_dependent_mask) | 216 unsigned int right_device_dependent_mask) |
211 { | 217 { |
212 unsigned int device_dependent_mask = (left_device_dependent_mask | | 218 unsigned int device_dependent_mask = (left_device_dependent_mask | |
213 right_device_dependent_mask); | 219 right_device_dependent_mask); |
218 */ | 224 */ |
219 if ((device_dependent_mask & oldMods) == 0) { | 225 if ((device_dependent_mask & oldMods) == 0) { |
220 /* In this case, we can't detect the keyboard, so use the left side | 226 /* In this case, we can't detect the keyboard, so use the left side |
221 * to represent both, and release it. | 227 * to represent both, and release it. |
222 */ | 228 */ |
223 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, left_key_sym); | 229 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, left_scancode); |
224 return; | 230 return; |
225 } | 231 } |
226 | 232 |
227 /* | 233 /* |
228 * This could have been done in an if-else case because at this point, | 234 * This could have been done in an if-else case because at this point, |
229 * we know that all keys have been released when calling this function. | 235 * we know that all keys have been released when calling this function. |
230 * But I'm being paranoid so I want to handle each separately, | 236 * But I'm being paranoid so I want to handle each separately, |
231 * so I hope this doesn't cause other problems. | 237 * so I hope this doesn't cause other problems. |
232 */ | 238 */ |
233 if ( left_device_dependent_mask & oldMods ) { | 239 if ( left_device_dependent_mask & oldMods ) { |
234 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, left_key_sym); | 240 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, left_scancode); |
235 } | 241 } |
236 if ( right_device_dependent_mask & oldMods ) { | 242 if ( right_device_dependent_mask & oldMods ) { |
237 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, right_key_sym); | 243 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, right_scancode); |
238 } | 244 } |
239 } | 245 } |
240 | 246 |
241 /* This is a helper function for DoSidedModifiers. | 247 /* This is a helper function for DoSidedModifiers. |
242 * This function handles the CapsLock case. | 248 * This function handles the CapsLock case. |
249 | 255 |
250 oldMask = oldMods & NSAlphaShiftKeyMask; | 256 oldMask = oldMods & NSAlphaShiftKeyMask; |
251 newMask = newMods & NSAlphaShiftKeyMask; | 257 newMask = newMods & NSAlphaShiftKeyMask; |
252 | 258 |
253 if (oldMask != newMask) { | 259 if (oldMask != newMask) { |
254 SDL_SendKeyboardKey(keyboard, SDL_PRESSED, (Uint8)scancode, SDLK_CAPSLOCK); | 260 SDL_SendKeyboardKey(keyboard, SDL_PRESSED, SDL_SCANCODE_CAPSLOCK); |
255 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, SDLK_CAPSLOCK); | 261 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, SDL_SCANCODE_CAPSLOCK); |
256 } | 262 } |
257 | 263 |
258 oldMask = oldMods & NSNumericPadKeyMask; | 264 oldMask = oldMods & NSNumericPadKeyMask; |
259 newMask = newMods & NSNumericPadKeyMask; | 265 newMask = newMods & NSNumericPadKeyMask; |
260 | 266 |
261 if (oldMask != newMask) { | 267 if (oldMask != newMask) { |
262 SDL_SendKeyboardKey(keyboard, SDL_PRESSED, (Uint8)scancode, SDLK_KP_NUMLOCKCLEAR); | 268 SDL_SendKeyboardKey(keyboard, SDL_PRESSED, SDL_SCANCODE_NUMLOCKCLEAR); |
263 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, SDLK_KP_NUMLOCKCLEAR); | 269 SDL_SendKeyboardKey(keyboard, SDL_RELEASED, SDL_SCANCODE_NUMLOCKCLEAR); |
264 } | 270 } |
265 } | 271 } |
266 | 272 |
267 /* This function will handle the modifier keys and also determine the | 273 /* This function will handle the modifier keys and also determine the |
268 * correct side of the key. | 274 * correct side of the key. |
270 static void | 276 static void |
271 DoSidedModifiers(int keyboard, unsigned short scancode, | 277 DoSidedModifiers(int keyboard, unsigned short scancode, |
272 unsigned int oldMods, unsigned int newMods) | 278 unsigned int oldMods, unsigned int newMods) |
273 { | 279 { |
274 /* Set up arrays for the key syms for the left and right side. */ | 280 /* Set up arrays for the key syms for the left and right side. */ |
275 const SDLKey left_mapping[] = { SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA }; | 281 const SDL_scancode left_mapping[] = { |
276 const SDLKey right_mapping[] = { SDLK_RSHIFT, SDLK_RCTRL, SDLK_RALT, SDLK_RMETA }; | 282 SDL_SCANCODE_LSHIFT, |
283 SDL_SCANCODE_LCTRL, | |
284 SDL_SCANCODE_LALT, | |
285 SDL_SCANCODE_LGUI | |
286 }; | |
287 const SDL_scancode right_mapping[] = { | |
288 SDL_SCANCODE_RSHIFT, | |
289 SDL_SCANCODE_RCTRL, | |
290 SDL_SCANCODE_RALT, | |
291 SDL_SCANCODE_RGUI | |
292 }; | |
277 /* Set up arrays for the device dependent masks with indices that | 293 /* Set up arrays for the device dependent masks with indices that |
278 * correspond to the _mapping arrays | 294 * correspond to the _mapping arrays |
279 */ | 295 */ |
280 const unsigned int left_device_mapping[] = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK }; | 296 const unsigned int left_device_mapping[] = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK }; |
281 const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK }; | 297 const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK }; |
294 | 310 |
295 /* If the bit is set, we must always examine it because the left | 311 /* If the bit is set, we must always examine it because the left |
296 * and right side keys may alternate or both may be pressed. | 312 * and right side keys may alternate or both may be pressed. |
297 */ | 313 */ |
298 if (newMask) { | 314 if (newMask) { |
299 HandleModifierSide(keyboard, scancode, bit, oldMods, newMods, | 315 HandleModifierSide(keyboard, bit, oldMods, newMods, |
300 left_mapping[i], right_mapping[i], | 316 left_mapping[i], right_mapping[i], |
301 left_device_mapping[i], right_device_mapping[i]); | 317 left_device_mapping[i], right_device_mapping[i]); |
302 } | 318 } |
303 /* If the state changed from pressed to unpressed, we must examine | 319 /* If the state changed from pressed to unpressed, we must examine |
304 * the device dependent bits to release the correct keys. | 320 * the device dependent bits to release the correct keys. |
305 */ | 321 */ |
306 else if (oldMask && oldMask != newMask) { | 322 else if (oldMask && oldMask != newMask) { |
307 ReleaseModifierSide(keyboard, scancode, bit, oldMods, newMods, | 323 ReleaseModifierSide(keyboard, bit, oldMods, newMods, |
308 left_mapping[i], right_mapping[i], | 324 left_mapping[i], right_mapping[i], |
309 left_device_mapping[i], right_device_mapping[i]); | 325 left_device_mapping[i], right_device_mapping[i]); |
310 } | 326 } |
311 } | 327 } |
312 } | 328 } |
330 DoUnsidedModifiers(data->keyboard, scancode, data->modifierFlags, modifierFlags); | 346 DoUnsidedModifiers(data->keyboard, scancode, data->modifierFlags, modifierFlags); |
331 } | 347 } |
332 data->modifierFlags = modifierFlags; | 348 data->modifierFlags = modifierFlags; |
333 } | 349 } |
334 | 350 |
351 static void | |
352 UpdateKeymap(SDL_VideoData *data) | |
353 { | |
354 KeyboardLayoutRef key_layout; | |
355 const void *chr_data; | |
356 int i; | |
357 SDL_scancode scancode; | |
358 SDLKey keymap[SDL_NUM_SCANCODES]; | |
359 | |
360 /* See if the keymap needs to be updated */ | |
361 KLGetCurrentKeyboardLayout(&key_layout); | |
362 if (key_layout == data->key_layout) { | |
363 return; | |
364 } | |
365 data->key_layout = key_layout; | |
366 | |
367 SDL_GetDefaultKeymap(keymap); | |
368 | |
369 /* Try Unicode data first (preferred as of Mac OS X 10.5) */ | |
370 KLGetKeyboardLayoutProperty(key_layout, kKLuchrData, &chr_data); | |
371 if (chr_data) { | |
372 UInt32 keyboard_type = LMGetKbdType(); | |
373 OSStatus err; | |
374 | |
375 for (i = 0; i < SDL_arraysize(scancode_table); i++) { | |
376 UniChar s[8]; | |
377 UniCharCount len; | |
378 UInt32 dead_key_state; | |
379 | |
380 /* Make sure this scancode is a valid character scancode */ | |
381 scancode = scancode_table[i]; | |
382 if (scancode == SDL_SCANCODE_UNKNOWN || | |
383 (keymap[scancode] & SDLK_SCANCODE_MASK)) { | |
384 continue; | |
385 } | |
386 | |
387 dead_key_state = 0; | |
388 err = UCKeyTranslate (chr_data, i, kUCKeyActionDown, | |
389 0, keyboard_type, | |
390 kUCKeyTranslateNoDeadKeysMask, | |
391 &dead_key_state, 8, &len, s); | |
392 if (err != noErr) | |
393 continue; | |
394 | |
395 if (len > 0 && s[0] != 0x10) { | |
396 keymap[scancode] = s[0]; | |
397 } | |
398 } | |
399 SDL_SetKeymap(data->keyboard, 0, keymap, SDL_NUM_SCANCODES); | |
400 return; | |
401 } | |
402 | |
403 /* Fall back to older style key map data */ | |
404 KLGetKeyboardLayoutProperty(key_layout, kKLKCHRData, &chr_data); | |
405 if (chr_data) { | |
406 for (i = 0; i < 128; i++) { | |
407 UInt32 c, state = 0; | |
408 | |
409 /* Make sure this scancode is a valid character scancode */ | |
410 scancode = scancode_table[i]; | |
411 if (scancode == SDL_SCANCODE_UNKNOWN || | |
412 (keymap[scancode] & SDLK_SCANCODE_MASK)) { | |
413 continue; | |
414 } | |
415 | |
416 c = KeyTranslate (chr_data, i, &state); | |
417 if (state) { | |
418 /* Dead key, process key up */ | |
419 c = KeyTranslate (chr_data, i | 128, &state); | |
420 } | |
421 | |
422 if (c != 0 && c != 0x10 && c < 256) { | |
423 /* MacRoman to Unicode table, taken from X.org sources */ | |
424 static const unsigned short macroman_table[128] = { | |
425 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, | |
426 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8, | |
427 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, | |
428 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc, | |
429 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf, | |
430 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8, | |
431 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211, | |
432 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8, | |
433 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab, | |
434 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153, | |
435 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca, | |
436 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02, | |
437 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1, | |
438 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4, | |
439 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc, | |
440 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7, | |
441 }; | |
442 | |
443 if (c >= 128) { | |
444 c = macroman_table[c - 128]; | |
445 } | |
446 keymap[scancode] = c; | |
447 } | |
448 } | |
449 SDL_SetKeymap(data->keyboard, 0, keymap, SDL_NUM_SCANCODES); | |
450 return; | |
451 } | |
452 } | |
453 | |
335 void | 454 void |
336 Cocoa_InitKeyboard(_THIS) | 455 Cocoa_InitKeyboard(_THIS) |
337 { | 456 { |
338 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; | 457 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; |
339 SDL_Keyboard keyboard; | 458 SDL_Keyboard keyboard; |
343 data->fieldEdit = [[SDLTranslatorResponder alloc] initWithFrame:NSMakeRect(0.0, 0.0, 0.0, 0.0)]; | 462 data->fieldEdit = [[SDLTranslatorResponder alloc] initWithFrame:NSMakeRect(0.0, 0.0, 0.0, 0.0)]; |
344 [pool release]; | 463 [pool release]; |
345 | 464 |
346 SDL_zero(keyboard); | 465 SDL_zero(keyboard); |
347 data->keyboard = SDL_AddKeyboard(&keyboard, -1); | 466 data->keyboard = SDL_AddKeyboard(&keyboard, -1); |
467 UpdateKeymap(data); | |
348 | 468 |
349 /* Set our own names for the platform-dependent but layout-independent keys */ | 469 /* Set our own names for the platform-dependent but layout-independent keys */ |
350 SDL_SetKeyName(SDLK_KP_NUMLOCKCLEAR, "clear"); | 470 /* This key is NumLock on the MacBook keyboard. :) */ |
351 SDL_SetKeyName(SDLK_LALT, "left option"); | 471 /*SDL_SetScancodeName(SDL_SCANCODE_NUMLOCKCLEAR, "Clear");*/ |
352 SDL_SetKeyName(SDLK_LMETA, "left command"); | 472 SDL_SetScancodeName(SDL_SCANCODE_LALT, "Left Option"); |
353 SDL_SetKeyName(SDLK_RALT, "right option"); | 473 SDL_SetScancodeName(SDL_SCANCODE_LGUI, "Left Command"); |
354 SDL_SetKeyName(SDLK_RMETA, "right command"); | 474 SDL_SetScancodeName(SDL_SCANCODE_RALT, "Right Option"); |
475 SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Command"); | |
355 } | 476 } |
356 | 477 |
357 void | 478 void |
358 Cocoa_HandleKeyEvent(_THIS, NSEvent *event) | 479 Cocoa_HandleKeyEvent(_THIS, NSEvent *event) |
359 { | 480 { |
360 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; | 481 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; |
361 unsigned short scancode = [event keyCode]; | 482 unsigned short scancode = [event keyCode]; |
362 SDLKey physicalKey; | 483 SDL_scancode code; |
363 const char *text; | 484 const char *text; |
364 | 485 |
365 if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) { | 486 if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) { |
366 /* see comments in SDL_cocoakeys.h */ | 487 /* see comments in SDL_cocoakeys.h */ |
367 scancode = 60 - scancode; | 488 scancode = 60 - scancode; |
368 } | 489 } |
369 if (scancode < SDL_arraysize(macToSDLKey)) { | 490 if (scancode < SDL_arraysize(scancode_table)) { |
370 physicalKey = macToSDLKey[scancode]; | 491 code = scancode_table[scancode]; |
371 } | 492 } |
372 else { | 493 else { |
373 /* Hmm, does this ever happen? If so, need to extend the keymap... */ | 494 /* Hmm, does this ever happen? If so, need to extend the keymap... */ |
374 physicalKey = SDLK_UNKNOWN; | 495 code = SDL_SCANCODE_UNKNOWN; |
375 } | 496 } |
376 | 497 |
377 switch ([event type]) { | 498 switch ([event type]) { |
378 case NSKeyDown: | 499 case NSKeyDown: |
379 if (![event isARepeat]) { | 500 if (![event isARepeat]) { |
380 SDL_SendKeyboardKey(data->keyboard, SDL_PRESSED, (Uint8)scancode, physicalKey); | 501 /* See if we need to rebuild the keyboard layout */ |
502 UpdateKeymap(data); | |
503 | |
504 SDL_SendKeyboardKey(data->keyboard, SDL_PRESSED, code); | |
381 #if 1 | 505 #if 1 |
382 if (physicalKey == SDLK_UNKNOWN) { | 506 if (code == SDL_SCANCODE_UNKNOWN) { |
383 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); | 507 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); |
384 } | 508 } |
385 #endif | 509 #endif |
386 } | 510 } |
387 if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) { | 511 if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) { |
393 [data->fieldEdit setString:@""]; | 517 [data->fieldEdit setString:@""]; |
394 } | 518 } |
395 } | 519 } |
396 break; | 520 break; |
397 case NSKeyUp: | 521 case NSKeyUp: |
398 SDL_SendKeyboardKey(data->keyboard, SDL_RELEASED, (Uint8)scancode, physicalKey); | 522 SDL_SendKeyboardKey(data->keyboard, SDL_RELEASED, code); |
399 break; | 523 break; |
400 case NSFlagsChanged: | 524 case NSFlagsChanged: |
401 /* FIXME CW 2007-08-14: check if this whole mess that takes up half of this file is really necessary */ | 525 /* FIXME CW 2007-08-14: check if this whole mess that takes up half of this file is really necessary */ |
402 HandleModifiers(_this, scancode, [event modifierFlags]); | 526 HandleModifiers(_this, scancode, [event modifierFlags]); |
403 break; | 527 break; |
404 default: /* just to avoid compiler warnings */ | 528 default: /* just to avoid compiler warnings */ |
405 break; | 529 break; |
406 } | 530 } |
407 } | 531 } |
408 | 532 |
409 SDLKey | |
410 Cocoa_GetLayoutKey(_THIS, SDLKey physicalKey) | |
411 { | |
412 switch (physicalKey) { | |
413 /* Many of these keys would generate a character in the translation by keyboard layout, but an inappropriate one, so we catch them before. */ | |
414 case SDLK_UNKNOWN: | |
415 case SDLK_RETURN: | |
416 case SDLK_ESCAPE: | |
417 case SDLK_BACKSPACE: | |
418 case SDLK_TAB: | |
419 case SDLK_SPACE: | |
420 case SDLK_CAPSLOCK: | |
421 case SDLK_F1: | |
422 case SDLK_F2: | |
423 case SDLK_F3: | |
424 case SDLK_F4: | |
425 case SDLK_F5: | |
426 case SDLK_F6: | |
427 case SDLK_F7: | |
428 case SDLK_F8: | |
429 case SDLK_F9: | |
430 case SDLK_F10: | |
431 case SDLK_F11: | |
432 case SDLK_F12: | |
433 case SDLK_PRINTSCREEN: | |
434 case SDLK_SCROLLLOCK: | |
435 case SDLK_PAUSE: | |
436 case SDLK_INSERT: | |
437 case SDLK_HOME: | |
438 case SDLK_PAGEUP: | |
439 case SDLK_DELETE: | |
440 case SDLK_END: | |
441 case SDLK_PAGEDOWN: | |
442 case SDLK_RIGHT: | |
443 case SDLK_LEFT: | |
444 case SDLK_DOWN: | |
445 case SDLK_UP: | |
446 case SDLK_KP_NUMLOCKCLEAR: | |
447 case SDLK_KP_ENTER: | |
448 case SDLK_APPLICATION: | |
449 case SDLK_POWER: | |
450 case SDLK_F13: | |
451 case SDLK_F14: | |
452 case SDLK_F15: | |
453 case SDLK_F16: | |
454 case SDLK_LCTRL: | |
455 case SDLK_LSHIFT: | |
456 case SDLK_LALT: | |
457 case SDLK_LMETA: | |
458 case SDLK_RCTRL: | |
459 case SDLK_RSHIFT: | |
460 case SDLK_RALT: | |
461 case SDLK_RMETA: | |
462 return physicalKey; | |
463 | |
464 /* For the rest, we try the translation first. */ | |
465 default: { | |
466 UInt16 vkey = 0; | |
467 KeyboardLayoutRef layout; | |
468 KeyboardLayoutKind kind; | |
469 UInt32 keyboardType = LMGetKbdType(); | |
470 | |
471 /* Look up pkey to get a Mac virtual key code - linear search isn't terribly efficient, this might have to be optimized. */ | |
472 while (vkey < 128 && physicalKey != macToSDLKey[vkey]) vkey++; | |
473 if (vkey == 128) return physicalKey; | |
474 if ((vkey == 10 || vkey == 50) && KBGetLayoutType(keyboardType) == kKeyboardISO) vkey = 60 - vkey; /* see comments in SDL_cocoakeys.h */ | |
475 | |
476 if (KLGetCurrentKeyboardLayout(&layout) != noErr) return physicalKey; | |
477 if (KLGetKeyboardLayoutProperty(layout, kKLKind, (const void **)&kind) != noErr) return physicalKey; | |
478 if (kind == kKLKCHRuchrKind || kind == kKLuchrKind) { | |
479 UniChar utf16String[4]; | |
480 UInt32 deadKeyState = 0; | |
481 UniCharCount actualStringLength; | |
482 const UCKeyboardLayout *uchrData; | |
483 | |
484 if (KLGetKeyboardLayoutProperty(layout, kKLuchrData, (const void **)&uchrData) != noErr) return physicalKey; | |
485 if (UCKeyTranslate(uchrData, vkey, kUCKeyActionDisplay, 0, keyboardType, 0, &deadKeyState, 4, &actualStringLength, utf16String) != noErr) return physicalKey; | |
486 /* 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 */ | |
487 | |
488 if (actualStringLength == 0) return physicalKey; | |
489 | |
490 /* 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. */ | |
491 if (utf16String[0] < 0xD800 || utf16String[0] > 0xDFFF) { | |
492 return utf16String[0]; | |
493 } | |
494 else if (utf16String[0] > 0xDBFF || utf16String[1] < 0xDC00 || utf16String[1] > 0xDFFF) { | |
495 /* invalid UTF-16 */ | |
496 return physicalKey; | |
497 } | |
498 else { | |
499 return (((utf16String[0] & 0x3FF) << 10) | (utf16String[1] & 0x3FF)) + 0x10000; | |
500 } | |
501 } | |
502 else { /* kind == kKLKCHRKind */ | |
503 const void *kchrData; | |
504 UInt32 state = 0; | |
505 UInt8 charCode; | |
506 SInt32 scriptCode; | |
507 TextEncoding keyboardEncoding; | |
508 CFStringRef conversionString; | |
509 UniChar codepoint; | |
510 | |
511 if (KLGetKeyboardLayoutProperty(layout, kKLKCHRData, &kchrData) != noErr) return physicalKey; | |
512 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 */ | |
513 if (charCode == 0) { | |
514 /* It's a dead key, so simulate a second key press */ | |
515 charCode = KeyTranslate(kchrData, vkey, &state) & 0xFF; | |
516 /* Still zero? Give up. */ | |
517 if (charCode == 0) return physicalKey; | |
518 } | |
519 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> */ | |
520 if (UpgradeScriptInfoToTextEncoding(scriptCode, kTextLanguageDontCare, kTextRegionDontCare, NULL, &keyboardEncoding) != noErr) return physicalKey; | |
521 | |
522 conversionString = CFStringCreateWithBytes(kCFAllocatorDefault, &charCode, 1, keyboardEncoding, FALSE); | |
523 codepoint = CFStringGetCharacterAtIndex(conversionString, 0); | |
524 CFRelease(conversionString); | |
525 return codepoint; | |
526 } | |
527 } | |
528 } | |
529 } | |
530 | |
531 void | 533 void |
532 Cocoa_QuitKeyboard(_THIS) | 534 Cocoa_QuitKeyboard(_THIS) |
533 { | 535 { |
534 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; | 536 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; |
535 NSAutoreleasePool *pool; | 537 NSAutoreleasePool *pool; |