Mercurial > sdl-ios-xcode
comparison src/video/quartz/SDL_QuartzEvents.m @ 934:af585d6efec8
Date: Thu, 17 Jun 2004 11:38:51 -0700 (PDT)
From: Eric Wing <ewing2121@yahoo.com>
Subject: New OS X patch (was Re: [SDL] Bug with inverted mouse coordinates in
I have a new patch for OS X I would like to submit.
First, it appears no further action has been taken on
my fix from Apple on the OpenGL windowed mode mouse
inversion problem. The fix would reunify the code, and
no longer require case checking for which version of
the OS you are running. This is probably a good fix
because the behavior with the old code could change
again with future versions of the OS, so those fixes
are included in this new patch.
But in addition, when I was at Apple, I asked them
about the ability to distinguish between the modifier
keys on the left and right sides of the keyboard (e.g.
Left Shift, Right Shift, Left/Right Alt, L/R Cmd, L/R
Ctrl). They told me that starting with Panther, the OS
began supporting this feature. This has always been a
source of annoyance for me when bringing a program
that comes from Windows or Linux to OS X when the
keybindings happened to need distinguishable left-side
and right-side keys. So the rest of the patch I am
submitting contains new code to support this feature
on Panther (and presumably later versions of the OS).
So after removing the OS version checks for the mouse
inversion problem, I reused the OS version checks to
activate the Left/Right detection of modifier keys. If
you are running Panther (or above), the new code will
attempt to distinguish between sides. For the older
OS's, the code path reverts to the original code.
I've tested with Panther on a G4 Cube, G5 dual
processor, and Powerbook Rev C. The Cube and G5
keyboards demonstrated the ability to distinguish
between sides. The Powerbook seems to only have
left-side keys, but the patch was still able to handle
it by producing the same results as before the patch.
I also wanted to test a non-Apple keyboard.
Unfortunately, I don't have any PC USB keyboards.
However, I was able to borrow a Sun Microsystems USB
keyboard, so I tried that out on the G5, and I got the
correct behavior for left and right sides. I'm
expecting that if it worked with a Sun keyboard, most
other keyboards should work with no problems.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Fri, 20 Aug 2004 22:35:23 +0000 |
parents | f221cadd6eda |
children | 8e1815fd9777 |
comparison
equal
deleted
inserted
replaced
933:4272450dd8d0 | 934:af585d6efec8 |
---|---|
24 | 24 |
25 #include <stdlib.h> // For getenv() | 25 #include <stdlib.h> // For getenv() |
26 #include <IOKit/IOMessage.h> // For wake from sleep detection | 26 #include <IOKit/IOMessage.h> // For wake from sleep detection |
27 #include <IOKit/pwr_mgt/IOPMLib.h> // For wake from sleep detection | 27 #include <IOKit/pwr_mgt/IOPMLib.h> // For wake from sleep detection |
28 #include "SDL_QuartzKeys.h" | 28 #include "SDL_QuartzKeys.h" |
29 | |
30 /* | |
31 * In Panther, this header defines device dependent masks for | |
32 * right side keys. These definitions only exist in Panther, but | |
33 * the header seems to exist at least in Jaguar and probably earlier | |
34 * versions of the OS, so this should't break anything. | |
35 */ | |
36 #include <IOKit/hidsystem/IOLLEvent.h> | |
37 /* | |
38 * These are not defined before Panther. To keep the code compiling | |
39 * on systems without these, I will define if they don't exist. | |
40 */ | |
41 #ifndef NX_DEVICERCTLKEYMASK | |
42 #define NX_DEVICELCTLKEYMASK 0x00000001 | |
43 #endif | |
44 #ifndef NX_DEVICELSHIFTKEYMASK | |
45 #define NX_DEVICELSHIFTKEYMASK 0x00000002 | |
46 #endif | |
47 #ifndef NX_DEVICERSHIFTKEYMASK | |
48 #define NX_DEVICERSHIFTKEYMASK 0x00000004 | |
49 #endif | |
50 #ifndef NX_DEVICELCMDKEYMASK | |
51 #define NX_DEVICELCMDKEYMASK 0x00000008 | |
52 #endif | |
53 #ifndef NX_DEVICERCMDKEYMASK | |
54 #define NX_DEVICERCMDKEYMASK 0x00000010 | |
55 #endif | |
56 #ifndef NX_DEVICELALTKEYMASK | |
57 #define NX_DEVICELALTKEYMASK 0x00000020 | |
58 #endif | |
59 #ifndef NX_DEVICERALTKEYMASK | |
60 #define NX_DEVICERALTKEYMASK 0x00000040 | |
61 #endif | |
62 #ifndef NX_DEVICERCTLKEYMASK | |
63 #define NX_DEVICERCTLKEYMASK 0x00002000 | |
64 #endif | |
29 | 65 |
30 void QZ_InitOSKeymap (_THIS) { | 66 void QZ_InitOSKeymap (_THIS) { |
31 const void *KCHRPtr; | 67 const void *KCHRPtr; |
32 UInt32 state; | 68 UInt32 state; |
33 UInt32 value; | 69 UInt32 value; |
113 keymap[QZ_KP4] = SDLK_KP4; | 149 keymap[QZ_KP4] = SDLK_KP4; |
114 keymap[QZ_KP5] = SDLK_KP5; | 150 keymap[QZ_KP5] = SDLK_KP5; |
115 keymap[QZ_KP6] = SDLK_KP6; | 151 keymap[QZ_KP6] = SDLK_KP6; |
116 keymap[QZ_KP_PLUS] = SDLK_KP_PLUS; | 152 keymap[QZ_KP_PLUS] = SDLK_KP_PLUS; |
117 keymap[QZ_LSHIFT] = SDLK_LSHIFT; | 153 keymap[QZ_LSHIFT] = SDLK_LSHIFT; |
154 keymap[QZ_RSHIFT] = SDLK_RSHIFT; | |
118 keymap[QZ_z] = SDLK_z; | 155 keymap[QZ_z] = SDLK_z; |
119 keymap[QZ_x] = SDLK_x; | 156 keymap[QZ_x] = SDLK_x; |
120 keymap[QZ_c] = SDLK_c; | 157 keymap[QZ_c] = SDLK_c; |
121 keymap[QZ_v] = SDLK_v; | 158 keymap[QZ_v] = SDLK_v; |
122 keymap[QZ_b] = SDLK_b; | 159 keymap[QZ_b] = SDLK_b; |
131 keymap[QZ_KP3] = SDLK_KP3; | 168 keymap[QZ_KP3] = SDLK_KP3; |
132 keymap[QZ_KP_ENTER] = SDLK_KP_ENTER; | 169 keymap[QZ_KP_ENTER] = SDLK_KP_ENTER; |
133 keymap[QZ_LCTRL] = SDLK_LCTRL; | 170 keymap[QZ_LCTRL] = SDLK_LCTRL; |
134 keymap[QZ_LALT] = SDLK_LALT; | 171 keymap[QZ_LALT] = SDLK_LALT; |
135 keymap[QZ_LMETA] = SDLK_LMETA; | 172 keymap[QZ_LMETA] = SDLK_LMETA; |
173 keymap[QZ_RCTRL] = SDLK_RCTRL; | |
174 keymap[QZ_RALT] = SDLK_RALT; | |
175 keymap[QZ_RMETA] = SDLK_RMETA; | |
136 keymap[QZ_SPACE] = SDLK_SPACE; | 176 keymap[QZ_SPACE] = SDLK_SPACE; |
137 keymap[QZ_LEFT] = SDLK_LEFT; | 177 keymap[QZ_LEFT] = SDLK_LEFT; |
138 keymap[QZ_DOWN] = SDLK_DOWN; | 178 keymap[QZ_DOWN] = SDLK_DOWN; |
139 keymap[QZ_RIGHT] = SDLK_RIGHT; | 179 keymap[QZ_RIGHT] = SDLK_RIGHT; |
140 keymap[QZ_KP0] = SDLK_KP0; | 180 keymap[QZ_KP0] = SDLK_KP0; |
257 | 297 |
258 if (getenv ("SDL_ENABLEAPPEVENTS")) | 298 if (getenv ("SDL_ENABLEAPPEVENTS")) |
259 [ NSApp sendEvent:event ]; | 299 [ NSApp sendEvent:event ]; |
260 } | 300 } |
261 | 301 |
262 static void QZ_DoModifiers (_THIS, unsigned int newMods) { | 302 /* This is the original behavior, before support was added for |
303 * differentiating between left and right versions of the keys. | |
304 */ | |
305 static void QZ_DoUnsidedModifiers (_THIS, unsigned int newMods) { | |
263 | 306 |
264 const int mapping[] = { SDLK_CAPSLOCK, SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA }; | 307 const int mapping[] = { SDLK_CAPSLOCK, SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA }; |
265 | 308 |
266 int i; | 309 int i; |
267 int bit; | 310 int bit; |
268 SDL_keysym key; | 311 SDL_keysym key; |
269 | 312 |
270 if (current_mods == newMods) | |
271 return; | |
272 | |
273 key.scancode = 0; | 313 key.scancode = 0; |
274 key.sym = SDLK_UNKNOWN; | 314 key.sym = SDLK_UNKNOWN; |
275 key.unicode = 0; | 315 key.unicode = 0; |
276 key.mod = KMOD_NONE; | 316 key.mod = KMOD_NONE; |
277 | 317 |
300 /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ | 340 /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ |
301 if (bit == NSAlphaShiftKeyMask) | 341 if (bit == NSAlphaShiftKeyMask) |
302 SDL_PrivateKeyboard (SDL_RELEASED, &key); | 342 SDL_PrivateKeyboard (SDL_RELEASED, &key); |
303 } | 343 } |
304 } | 344 } |
305 | 345 } |
346 | |
347 /* This is a helper function for QZ_HandleModifierSide. This | |
348 * function reverts back to behavior before the distinction between | |
349 * sides was made. | |
350 */ | |
351 static void QZ_HandleNonDeviceModifier ( _THIS, unsigned int device_independent_mask, unsigned int newMods, unsigned int key_sym) { | |
352 unsigned int currentMask, newMask; | |
353 SDL_keysym key; | |
354 | |
355 key.scancode = 0; | |
356 key.sym = key_sym; | |
357 key.unicode = 0; | |
358 key.mod = KMOD_NONE; | |
359 | |
360 /* Isolate just the bits we care about in the depedent bits so we can | |
361 * figure out what changed | |
362 */ | |
363 currentMask = current_mods & device_independent_mask; | |
364 newMask = newMods & device_independent_mask; | |
365 | |
366 if ( currentMask && | |
367 currentMask != newMask ) { /* modifier up event */ | |
368 SDL_PrivateKeyboard (SDL_RELEASED, &key); | |
369 } | |
370 else if ( newMask && | |
371 currentMask != newMask ) { /* modifier down event */ | |
372 SDL_PrivateKeyboard (SDL_PRESSED, &key); | |
373 } | |
374 } | |
375 | |
376 /* This is a helper function for QZ_HandleModifierSide. | |
377 * This function sets the actual SDL_PrivateKeyboard event. | |
378 */ | |
379 static void QZ_HandleModifierOneSide ( _THIS, unsigned int newMods, | |
380 unsigned int key_sym, | |
381 unsigned int sided_device_dependent_mask ) { | |
382 | |
383 SDL_keysym key; | |
384 unsigned int current_dep_mask, new_dep_mask; | |
385 | |
386 key.scancode = 0; | |
387 key.sym = key_sym; | |
388 key.unicode = 0; | |
389 key.mod = KMOD_NONE; | |
390 | |
391 /* Isolate just the bits we care about in the depedent bits so we can | |
392 * figure out what changed | |
393 */ | |
394 current_dep_mask = current_mods & sided_device_dependent_mask; | |
395 new_dep_mask = newMods & sided_device_dependent_mask; | |
396 | |
397 /* We now know that this side bit flipped. But we don't know if | |
398 * it went pressed to released or released to pressed, so we must | |
399 * find out which it is. | |
400 */ | |
401 if( new_dep_mask && | |
402 current_dep_mask != new_dep_mask ) { | |
403 /* Modifier down event */ | |
404 SDL_PrivateKeyboard (SDL_PRESSED, &key); | |
405 } | |
406 else /* Modifier up event */ { | |
407 SDL_PrivateKeyboard (SDL_RELEASED, &key); | |
408 } | |
409 } | |
410 | |
411 /* This is a helper function for QZ_DoSidedModifiers. | |
412 * This function will figure out if the modifier key is the left or right side, | |
413 * e.g. left-shift vs right-shift. | |
414 */ | |
415 static void QZ_HandleModifierSide ( _THIS, int device_independent_mask, | |
416 unsigned int newMods, | |
417 unsigned int left_key_sym, | |
418 unsigned int right_key_sym, | |
419 unsigned int left_device_dependent_mask, | |
420 unsigned int right_device_dependent_mask ) { | |
421 unsigned int device_dependent_mask = 0; | |
422 unsigned int diff_mod = 0; | |
423 | |
424 device_dependent_mask = left_device_dependent_mask | right_device_dependent_mask; | |
425 /* On the basis that the device independent mask is set, but there are | |
426 * no device dependent flags set, we'll assume that we can't detect this | |
427 * keyboard and revert to the unsided behavior. | |
428 */ | |
429 if ( (device_dependent_mask & newMods) == 0 ) { | |
430 /* Revert to the old behavior */ | |
431 QZ_HandleNonDeviceModifier ( this, device_independent_mask, newMods, left_key_sym ); | |
432 return; | |
433 } | |
434 | |
435 /* XOR the previous state against the new state to see if there's a change */ | |
436 diff_mod = (device_dependent_mask & current_mods) | |
437 ^ (device_dependent_mask & newMods); | |
438 | |
439 if ( diff_mod ) { | |
440 /* A change in state was found. Isolate the left and right bits | |
441 * to handle them separately just in case the values can simulataneously | |
442 * change or if the bits don't both exist. | |
443 */ | |
444 if ( left_device_dependent_mask & diff_mod ) { | |
445 QZ_HandleModifierOneSide ( this, newMods, left_key_sym, left_device_dependent_mask ); | |
446 } | |
447 if ( right_device_dependent_mask & diff_mod ) { | |
448 QZ_HandleModifierOneSide ( this, newMods, right_key_sym, right_device_dependent_mask ); | |
449 } | |
450 } | |
451 } | |
452 | |
453 /* This is a helper function for QZ_DoSidedModifiers. | |
454 * This function will release a key press in the case that | |
455 * it is clear that the modifier has been released (i.e. one side | |
456 * can't still be down). | |
457 */ | |
458 static void QZ_ReleaseModifierSide ( _THIS, | |
459 unsigned int device_independent_mask, | |
460 unsigned int newMods, | |
461 unsigned int left_key_sym, | |
462 unsigned int right_key_sym, | |
463 unsigned int left_device_dependent_mask, | |
464 unsigned int right_device_dependent_mask ) { | |
465 unsigned int device_dependent_mask = 0; | |
466 SDL_keysym key; | |
467 | |
468 key.scancode = 0; | |
469 key.sym = SDLK_UNKNOWN; | |
470 key.unicode = 0; | |
471 key.mod = KMOD_NONE; | |
472 | |
473 device_dependent_mask = left_device_dependent_mask | right_device_dependent_mask; | |
474 /* On the basis that the device independent mask is set, but there are | |
475 * no device dependent flags set, we'll assume that we can't detect this | |
476 * keyboard and revert to the unsided behavior. | |
477 */ | |
478 if ( (device_dependent_mask & current_mods) == 0 ) { | |
479 /* In this case, we can't detect the keyboard, so use the left side | |
480 * to represent both, and release it. | |
481 */ | |
482 key.sym = left_key_sym; | |
483 SDL_PrivateKeyboard (SDL_RELEASED, &key); | |
484 | |
485 return; | |
486 } | |
487 | |
488 | |
489 /* | |
490 * This could have been done in an if-else case because at this point, | |
491 * we know that all keys have been released when calling this function. | |
492 * But I'm being paranoid so I want to handle each separately, | |
493 * so I hope this doesn't cause other problems. | |
494 */ | |
495 if ( left_device_dependent_mask & current_mods ) { | |
496 key.sym = left_key_sym; | |
497 SDL_PrivateKeyboard (SDL_RELEASED, &key); | |
498 } | |
499 if ( right_device_dependent_mask & current_mods ) { | |
500 key.sym = right_key_sym; | |
501 SDL_PrivateKeyboard (SDL_RELEASED, &key); | |
502 } | |
503 } | |
504 | |
505 /* This is a helper function for QZ_DoSidedModifiers. | |
506 * This function handles the CapsLock case. | |
507 */ | |
508 static void QZ_HandleCapsLock (_THIS, unsigned int newMods) { | |
509 unsigned int currentMask, newMask; | |
510 SDL_keysym key; | |
511 | |
512 key.scancode = 0; | |
513 key.sym = SDLK_CAPSLOCK; | |
514 key.unicode = 0; | |
515 key.mod = KMOD_NONE; | |
516 | |
517 currentMask = current_mods & NSAlphaShiftKeyMask; | |
518 newMask = newMods & NSAlphaShiftKeyMask; | |
519 | |
520 if ( currentMask && | |
521 currentMask != newMask ) { /* modifier up event */ | |
522 /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ | |
523 SDL_PrivateKeyboard (SDL_PRESSED, &key); | |
524 SDL_PrivateKeyboard (SDL_RELEASED, &key); | |
525 } | |
526 else if ( newMask && | |
527 currentMask != newMask ) { /* modifier down event */ | |
528 /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ | |
529 SDL_PrivateKeyboard (SDL_PRESSED, &key); | |
530 SDL_PrivateKeyboard (SDL_RELEASED, &key); | |
531 } | |
532 } | |
533 | |
534 /* This function will handle the modifier keys and also determine the | |
535 * correct side of the key. | |
536 */ | |
537 static void QZ_DoSidedModifiers (_THIS, unsigned int newMods) { | |
538 /* Set up arrays for the key syms for the left and right side. */ | |
539 const unsigned int left_mapping[] = { SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA }; | |
540 const unsigned int right_mapping[] = { SDLK_RSHIFT, SDLK_RCTRL, SDLK_RALT, SDLK_RMETA }; | |
541 /* Set up arrays for the device dependent masks with indices that | |
542 * correspond to the _mapping arrays | |
543 */ | |
544 const unsigned int left_device_mapping[] = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK }; | |
545 const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK }; | |
546 | |
547 unsigned int i; | |
548 unsigned int bit; | |
549 | |
550 /* Handle CAPSLOCK separately because it doesn't have a left/right side */ | |
551 QZ_HandleCapsLock ( this, newMods ); | |
552 | |
553 /* Iterate through the bits, testing each against the current modifiers */ | |
554 for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) { | |
555 | |
556 unsigned int currentMask, newMask; | |
557 | |
558 currentMask = current_mods & bit; | |
559 newMask = newMods & bit; | |
560 | |
561 /* If the bit is set, we must always examine it because the left | |
562 * and right side keys may alternate or both may be pressed. | |
563 */ | |
564 if ( newMask ) { | |
565 QZ_HandleModifierSide ( this, bit, newMods, | |
566 left_mapping[i], | |
567 right_mapping[i], | |
568 left_device_mapping[i], | |
569 right_device_mapping[i] ); | |
570 } | |
571 /* If the state changed from pressed to unpressed, we must examine | |
572 * the device dependent bits to release the correct keys. | |
573 */ | |
574 else if ( currentMask && | |
575 currentMask != newMask ) { /* modifier up event */ | |
576 QZ_ReleaseModifierSide ( this, bit, newMods, | |
577 left_mapping[i], | |
578 right_mapping[i], | |
579 left_device_mapping[i], | |
580 right_device_mapping[i] ); | |
581 } | |
582 } | |
583 } | |
584 | |
585 /* This function is called to handle the modifiers. | |
586 * It will try to distinguish between the left side and right side | |
587 * of the keyboard for those modifiers that qualify if the | |
588 * operating system version supports it. Otherwise, the code | |
589 * will not try to make the distinction. | |
590 */ | |
591 static void QZ_DoModifiers (_THIS, unsigned int newMods) { | |
592 | |
593 if (current_mods == newMods) | |
594 return; | |
595 | |
596 /* | |
597 * Starting with Panther (10.3.0), the ability to distinguish between | |
598 * left side and right side modifiers is available. | |
599 */ | |
600 if( system_version >= 0x1030 ) { | |
601 QZ_DoSidedModifiers (this, newMods); | |
602 } | |
603 else { | |
604 QZ_DoUnsidedModifiers (this, newMods); | |
605 } | |
606 | |
306 current_mods = newMods; | 607 current_mods = newMods; |
307 } | 608 } |
308 | 609 |
309 static void QZ_GetMouseLocation (_THIS, NSPoint *p) { | 610 static void QZ_GetMouseLocation (_THIS, NSPoint *p) { |
310 *p = [ NSEvent mouseLocation ]; /* global coordinates */ | 611 *p = [ NSEvent mouseLocation ]; /* global coordinates */ |