zenilib  0.5.1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups
SDL_QuartzEvents.m
Go to the documentation of this file.
1 /*
2  SDL - Simple DirectMedia Layer
3  Copyright (C) 1997-2012 Sam Lantinga
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public
16  License along with this library; if not, write to the Free
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 
19  Sam Lantinga
20  slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23 
24 #include "SDL_QuartzVideo.h"
25 #include "SDL_QuartzWM.h"
26 
27 #include <IOKit/IOMessage.h> /* For wake from sleep detection */
28 #include <IOKit/pwr_mgt/IOPMLib.h> /* For wake from sleep detection */
29 #include "SDL_QuartzKeys.h"
30 
31 /*
32  * On Leopard, this is missing from the 64-bit headers
33  */
34 #if defined(__LP64__) && !defined(__POWER__)
35 /*
36  * Workaround for a bug in the 10.5 SDK: By accident, OSService.h does
37  * not include Power.h at all when compiling in 64bit mode. This has
38  * been fixed in 10.6, but for 10.5, we manually define UsrActivity
39  * to ensure compilation works.
40  */
41 #define UsrActivity 1
42 #endif
43 
44 /*
45  * In Panther, this header defines device dependent masks for
46  * right side keys. These definitions only exist in Panther, but
47  * the header seems to exist at least in Jaguar and probably earlier
48  * versions of the OS, so this should't break anything.
49  */
50 #include <IOKit/hidsystem/IOLLEvent.h>
51 /*
52  * These are not defined before Panther. To keep the code compiling
53  * on systems without these, I will define if they don't exist.
54  */
55 #ifndef NX_DEVICERCTLKEYMASK
56  #define NX_DEVICELCTLKEYMASK 0x00000001
57 #endif
58 #ifndef NX_DEVICELSHIFTKEYMASK
59  #define NX_DEVICELSHIFTKEYMASK 0x00000002
60 #endif
61 #ifndef NX_DEVICERSHIFTKEYMASK
62  #define NX_DEVICERSHIFTKEYMASK 0x00000004
63 #endif
64 #ifndef NX_DEVICELCMDKEYMASK
65  #define NX_DEVICELCMDKEYMASK 0x00000008
66 #endif
67 #ifndef NX_DEVICERCMDKEYMASK
68  #define NX_DEVICERCMDKEYMASK 0x00000010
69 #endif
70 #ifndef NX_DEVICELALTKEYMASK
71  #define NX_DEVICELALTKEYMASK 0x00000020
72 #endif
73 #ifndef NX_DEVICERALTKEYMASK
74  #define NX_DEVICERALTKEYMASK 0x00000040
75 #endif
76 #ifndef NX_DEVICERCTLKEYMASK
77  #define NX_DEVICERCTLKEYMASK 0x00002000
78 #endif
79 
81  BOOL saw_layout = NO;
82  UInt32 state;
83  UInt32 value;
84  Uint16 i;
85  int world = SDLK_WORLD_0;
86 
87  for ( i=0; i<SDL_TABLESIZE(keymap); ++i )
88  keymap[i] = SDLK_UNKNOWN;
89 
90  /* This keymap is almost exactly the same as the OS 9 one */
91  keymap[QZ_ESCAPE] = SDLK_ESCAPE;
92  keymap[QZ_F1] = SDLK_F1;
93  keymap[QZ_F2] = SDLK_F2;
94  keymap[QZ_F3] = SDLK_F3;
95  keymap[QZ_F4] = SDLK_F4;
96  keymap[QZ_F5] = SDLK_F5;
97  keymap[QZ_F6] = SDLK_F6;
98  keymap[QZ_F7] = SDLK_F7;
99  keymap[QZ_F8] = SDLK_F8;
100  keymap[QZ_F9] = SDLK_F9;
101  keymap[QZ_F10] = SDLK_F10;
102  keymap[QZ_F11] = SDLK_F11;
103  keymap[QZ_F12] = SDLK_F12;
104  keymap[QZ_F13] = SDLK_F13;
105  keymap[QZ_F14] = SDLK_F14;
106  keymap[QZ_F15] = SDLK_F15;
107 /*
108  keymap[QZ_PRINT] = SDLK_PRINT;
109  keymap[QZ_SCROLLOCK] = SDLK_SCROLLOCK;
110  keymap[QZ_PAUSE] = SDLK_PAUSE;
111 */
112  keymap[QZ_POWER] = SDLK_POWER;
113  keymap[QZ_BACKQUOTE] = SDLK_BACKQUOTE;
114  keymap[QZ_1] = SDLK_1;
115  keymap[QZ_2] = SDLK_2;
116  keymap[QZ_3] = SDLK_3;
117  keymap[QZ_4] = SDLK_4;
118  keymap[QZ_5] = SDLK_5;
119  keymap[QZ_6] = SDLK_6;
120  keymap[QZ_7] = SDLK_7;
121  keymap[QZ_8] = SDLK_8;
122  keymap[QZ_9] = SDLK_9;
123  keymap[QZ_0] = SDLK_0;
124  keymap[QZ_MINUS] = SDLK_MINUS;
125  keymap[QZ_EQUALS] = SDLK_EQUALS;
126  keymap[QZ_BACKSPACE] = SDLK_BACKSPACE;
127  keymap[QZ_INSERT] = SDLK_INSERT;
128  keymap[QZ_HOME] = SDLK_HOME;
129  keymap[QZ_PAGEUP] = SDLK_PAGEUP;
130  keymap[QZ_NUMLOCK] = SDLK_NUMLOCK;
131  keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS;
132  keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE;
133  keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
134  keymap[QZ_TAB] = SDLK_TAB;
135  keymap[QZ_q] = SDLK_q;
136  keymap[QZ_w] = SDLK_w;
137  keymap[QZ_e] = SDLK_e;
138  keymap[QZ_r] = SDLK_r;
139  keymap[QZ_t] = SDLK_t;
140  keymap[QZ_y] = SDLK_y;
141  keymap[QZ_u] = SDLK_u;
142  keymap[QZ_i] = SDLK_i;
143  keymap[QZ_o] = SDLK_o;
144  keymap[QZ_p] = SDLK_p;
145  keymap[QZ_LEFTBRACKET] = SDLK_LEFTBRACKET;
146  keymap[QZ_RIGHTBRACKET] = SDLK_RIGHTBRACKET;
147  keymap[QZ_BACKSLASH] = SDLK_BACKSLASH;
148  keymap[QZ_DELETE] = SDLK_DELETE;
149  keymap[QZ_END] = SDLK_END;
150  keymap[QZ_PAGEDOWN] = SDLK_PAGEDOWN;
151  keymap[QZ_KP7] = SDLK_KP7;
152  keymap[QZ_KP8] = SDLK_KP8;
153  keymap[QZ_KP9] = SDLK_KP9;
154  keymap[QZ_KP_MINUS] = SDLK_KP_MINUS;
155  keymap[QZ_CAPSLOCK] = SDLK_CAPSLOCK;
156  keymap[QZ_a] = SDLK_a;
157  keymap[QZ_s] = SDLK_s;
158  keymap[QZ_d] = SDLK_d;
159  keymap[QZ_f] = SDLK_f;
160  keymap[QZ_g] = SDLK_g;
161  keymap[QZ_h] = SDLK_h;
162  keymap[QZ_j] = SDLK_j;
163  keymap[QZ_k] = SDLK_k;
164  keymap[QZ_l] = SDLK_l;
165  keymap[QZ_SEMICOLON] = SDLK_SEMICOLON;
166  keymap[QZ_QUOTE] = SDLK_QUOTE;
167  keymap[QZ_RETURN] = SDLK_RETURN;
168  keymap[QZ_KP4] = SDLK_KP4;
169  keymap[QZ_KP5] = SDLK_KP5;
170  keymap[QZ_KP6] = SDLK_KP6;
171  keymap[QZ_KP_PLUS] = SDLK_KP_PLUS;
172  keymap[QZ_LSHIFT] = SDLK_LSHIFT;
173  keymap[QZ_RSHIFT] = SDLK_RSHIFT;
174  keymap[QZ_z] = SDLK_z;
175  keymap[QZ_x] = SDLK_x;
176  keymap[QZ_c] = SDLK_c;
177  keymap[QZ_v] = SDLK_v;
178  keymap[QZ_b] = SDLK_b;
179  keymap[QZ_n] = SDLK_n;
180  keymap[QZ_m] = SDLK_m;
181  keymap[QZ_COMMA] = SDLK_COMMA;
182  keymap[QZ_PERIOD] = SDLK_PERIOD;
183  keymap[QZ_SLASH] = SDLK_SLASH;
184  keymap[QZ_UP] = SDLK_UP;
185  keymap[QZ_KP1] = SDLK_KP1;
186  keymap[QZ_KP2] = SDLK_KP2;
187  keymap[QZ_KP3] = SDLK_KP3;
188  keymap[QZ_KP_ENTER] = SDLK_KP_ENTER;
189  keymap[QZ_LCTRL] = SDLK_LCTRL;
190  keymap[QZ_LALT] = SDLK_LALT;
191  keymap[QZ_LMETA] = SDLK_LMETA;
192  keymap[QZ_RCTRL] = SDLK_RCTRL;
193  keymap[QZ_RALT] = SDLK_RALT;
194  keymap[QZ_RMETA] = SDLK_RMETA;
195  keymap[QZ_SPACE] = SDLK_SPACE;
196  keymap[QZ_LEFT] = SDLK_LEFT;
197  keymap[QZ_DOWN] = SDLK_DOWN;
198  keymap[QZ_RIGHT] = SDLK_RIGHT;
199  keymap[QZ_KP0] = SDLK_KP0;
200  keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD;
201  keymap[QZ_IBOOK_ENTER] = SDLK_KP_ENTER;
202  keymap[QZ_IBOOK_RIGHT] = SDLK_RIGHT;
203  keymap[QZ_IBOOK_DOWN] = SDLK_DOWN;
204  keymap[QZ_IBOOK_UP] = SDLK_UP;
205  keymap[QZ_IBOOK_LEFT] = SDLK_LEFT;
206 
207  /*
208  Up there we setup a static scancode->keysym map. However, it will not
209  work very well on international keyboard. Hence we now query MacOS
210  for its own keymap to adjust our own mapping table. However, this is
211  basically only useful for ascii char keys. This is also the reason
212  why we keep the static table, too.
213  */
214 
215 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
216  if (TISCopyCurrentKeyboardLayoutInputSource != NULL) {
217  TISInputSourceRef src = TISCopyCurrentKeyboardLayoutInputSource();
218  if (src != NULL) {
219  CFDataRef data = (CFDataRef)
220  TISGetInputSourceProperty(src,
221  kTISPropertyUnicodeKeyLayoutData);
222  if (data != NULL) {
223  const UCKeyboardLayout *layout = (const UCKeyboardLayout *)
224  CFDataGetBytePtr(data);
225  if (layout != NULL) {
226  const UInt32 kbdtype = LMGetKbdType();
227  saw_layout = YES;
228 
229  /* Loop over all 127 possible scan codes */
230  for (i = 0; i < 0x7F; i++) {
231  UniChar buf[16];
232  UniCharCount count = 0;
233 
234  /* We pretend a clean start to begin with (i.e. no dead keys active */
235  state = 0;
236 
237  if (UCKeyTranslate(layout, i, kUCKeyActionDown, 0, kbdtype,
238  0, &state, 16, &count, buf) != noErr) {
239  continue;
240  }
241 
242  /* If the state become 0, it was a dead key. We need to
243  translate again, passing in the new state, to get
244  the actual key value */
245  if (state != 0) {
246  if (UCKeyTranslate(layout, i, kUCKeyActionDown, 0, kbdtype,
247  0, &state, 16, &count, buf) != noErr) {
248  continue;
249  }
250  }
251 
252  if (count != 1) {
253  continue; /* no multi-char. Use SDL 1.3 instead. :) */
254  }
255 
256  value = (UInt32) buf[0];
257  if (value >= 128) {
258  /* Some non-ASCII char, map it to SDLK_WORLD_* */
259  if (world < 0xFF) {
260  keymap[i] = world++;
261  }
262  } else if (value >= 32) { /* non-control ASCII char */
263  keymap[i] = value;
264  }
265  }
266  }
267  }
268  CFRelease(src);
269  }
270  }
271 #endif
272 
273 #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1050)
274  if (!saw_layout) {
275  /* Get a pointer to the systems cached KCHR */
276  const void *KCHRPtr = (const void *)GetScriptManagerVariable(smKCHRCache);
277  if (KCHRPtr)
278  {
279  /* Loop over all 127 possible scan codes */
280  for (i = 0; i < 0x7F; i++)
281  {
282  /* We pretend a clean start to begin with (i.e. no dead keys active */
283  state = 0;
284 
285  /* Now translate the key code to a key value */
286  value = KeyTranslate(KCHRPtr, i, &state) & 0xff;
287 
288  /* If the state become 0, it was a dead key. We need to translate again,
289  passing in the new state, to get the actual key value */
290  if (state != 0)
291  value = KeyTranslate(KCHRPtr, i, &state) & 0xff;
292 
293  /* Now we should have an ascii value, or 0. Try to figure out to which SDL symbol it maps */
294  if (value >= 128) { /* Some non-ASCII char, map it to SDLK_WORLD_* */
295  if (world < 0xFF) {
296  keymap[i] = world++;
297  }
298  } else if (value >= 32) { /* non-control ASCII char */
299  keymap[i] = value;
300  }
301  }
302  }
303  }
304 #endif
305 
306  /*
307  The keypad codes are re-setup here, because the loop above cannot
308  distinguish between a key on the keypad and a regular key. We maybe
309  could get around this problem in another fashion: NSEvent's flags
310  include a "NSNumericPadKeyMask" bit; we could check that and modify
311  the symbol we return on the fly. However, this flag seems to exhibit
312  some weird behaviour related to the num lock key
313  */
314  keymap[QZ_KP0] = SDLK_KP0;
315  keymap[QZ_KP1] = SDLK_KP1;
316  keymap[QZ_KP2] = SDLK_KP2;
317  keymap[QZ_KP3] = SDLK_KP3;
318  keymap[QZ_KP4] = SDLK_KP4;
319  keymap[QZ_KP5] = SDLK_KP5;
320  keymap[QZ_KP6] = SDLK_KP6;
321  keymap[QZ_KP7] = SDLK_KP7;
322  keymap[QZ_KP8] = SDLK_KP8;
323  keymap[QZ_KP9] = SDLK_KP9;
324  keymap[QZ_KP_MINUS] = SDLK_KP_MINUS;
325  keymap[QZ_KP_PLUS] = SDLK_KP_PLUS;
326  keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD;
327  keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS;
328  keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE;
329  keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
330  keymap[QZ_KP_ENTER] = SDLK_KP_ENTER;
331 }
332 
333 static void QZ_DoKey (_THIS, int state, NSEvent *event) {
334 
335  NSString *chars = NULL;
336  unsigned int i, numChars;
337  SDL_keysym key;
338 
339  /*
340  A key event can contain multiple characters,
341  or no characters at all. In most cases, it
342  will contain a single character. If it contains
343  0 characters, we'll use 0 as the unicode. If it
344  contains multiple characters, we'll use 0 as
345  the scancode/keysym.
346  */
347  if (SDL_TranslateUNICODE && state == SDL_PRESSED) {
348  [field_edit interpretKeyEvents:[NSArray arrayWithObject:event]];
349  chars = [ event characters ];
350  numChars = [ chars length ];
351  if (numChars > 0)
352  [field_edit setString:@""];
353  } else {
354  numChars = 0;
355  }
356 
357  if (numChars == 0) {
358 
359  key.scancode = [ event keyCode ];
360  key.sym = keymap [ key.scancode ];
361  key.unicode = 0;
362  key.mod = KMOD_NONE;
363 
364  SDL_PrivateKeyboard (state, &key);
365  }
366  else if (numChars >= 1) {
367 
368  key.scancode = [ event keyCode ];
369  key.sym = keymap [ key.scancode ];
370  key.unicode = [ chars characterAtIndex:0 ];
371  key.mod = KMOD_NONE;
372 
373  SDL_PrivateKeyboard (state, &key);
374 
375  for (i = 1; i < numChars; i++) {
376 
377  key.scancode = 0;
378  key.sym = 0;
379  key.unicode = [ chars characterAtIndex:i];
380  key.mod = KMOD_NONE;
381 
382  SDL_PrivateKeyboard (state, &key);
383  }
384  }
385 
386  if (SDL_getenv ("SDL_ENABLEAPPEVENTS"))
387  [ NSApp sendEvent:event ];
388 }
389 
390 /* This is the original behavior, before support was added for
391  * differentiating between left and right versions of the keys.
392  */
393 static void QZ_DoUnsidedModifiers (_THIS, unsigned int newMods) {
394 
396 
397  int i;
398  int bit;
399  SDL_keysym key;
400 
401  key.scancode = 0;
402  key.sym = SDLK_UNKNOWN;
403  key.unicode = 0;
404  key.mod = KMOD_NONE;
405 
406  /* Iterate through the bits, testing each against the current modifiers */
407  for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
408 
409  unsigned int currentMask, newMask;
410 
411  currentMask = current_mods & bit;
412  newMask = newMods & bit;
413 
414  if ( currentMask &&
415  currentMask != newMask ) { /* modifier up event */
416 
417  key.sym = mapping[i];
418  /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
419  if (bit == NSAlphaShiftKeyMask)
422  }
423  else if ( newMask &&
424  currentMask != newMask ) { /* modifier down event */
425 
426  key.sym = mapping[i];
428  /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
429  if (bit == NSAlphaShiftKeyMask)
431  }
432  }
433 }
434 
435 /* This is a helper function for QZ_HandleModifierSide. This
436  * function reverts back to behavior before the distinction between
437  * sides was made.
438  */
439 static void QZ_HandleNonDeviceModifier ( _THIS, unsigned int device_independent_mask, unsigned int newMods, unsigned int key_sym) {
440  unsigned int currentMask, newMask;
441  SDL_keysym key;
442 
443  key.scancode = 0;
444  key.sym = key_sym;
445  key.unicode = 0;
446  key.mod = KMOD_NONE;
447 
448  /* Isolate just the bits we care about in the depedent bits so we can
449  * figure out what changed
450  */
451  currentMask = current_mods & device_independent_mask;
452  newMask = newMods & device_independent_mask;
453 
454  if ( currentMask &&
455  currentMask != newMask ) { /* modifier up event */
457  }
458  else if ( newMask &&
459  currentMask != newMask ) { /* modifier down event */
461  }
462 }
463 
464 /* This is a helper function for QZ_HandleModifierSide.
465  * This function sets the actual SDL_PrivateKeyboard event.
466  */
467 static void QZ_HandleModifierOneSide ( _THIS, unsigned int newMods,
468  unsigned int key_sym,
469  unsigned int sided_device_dependent_mask ) {
470 
471  SDL_keysym key;
472  unsigned int current_dep_mask, new_dep_mask;
473 
474  key.scancode = 0;
475  key.sym = key_sym;
476  key.unicode = 0;
477  key.mod = KMOD_NONE;
478 
479  /* Isolate just the bits we care about in the depedent bits so we can
480  * figure out what changed
481  */
482  current_dep_mask = current_mods & sided_device_dependent_mask;
483  new_dep_mask = newMods & sided_device_dependent_mask;
484 
485  /* We now know that this side bit flipped. But we don't know if
486  * it went pressed to released or released to pressed, so we must
487  * find out which it is.
488  */
489  if( new_dep_mask &&
490  current_dep_mask != new_dep_mask ) {
491  /* Modifier down event */
493  }
494  else /* Modifier up event */ {
496  }
497 }
498 
499 /* This is a helper function for QZ_DoSidedModifiers.
500  * This function will figure out if the modifier key is the left or right side,
501  * e.g. left-shift vs right-shift.
502  */
503 static void QZ_HandleModifierSide ( _THIS, int device_independent_mask,
504  unsigned int newMods,
505  unsigned int left_key_sym,
506  unsigned int right_key_sym,
507  unsigned int left_device_dependent_mask,
508  unsigned int right_device_dependent_mask ) {
509  unsigned int device_dependent_mask = 0;
510  unsigned int diff_mod = 0;
511 
512  device_dependent_mask = left_device_dependent_mask | right_device_dependent_mask;
513  /* On the basis that the device independent mask is set, but there are
514  * no device dependent flags set, we'll assume that we can't detect this
515  * keyboard and revert to the unsided behavior.
516  */
517  if ( (device_dependent_mask & newMods) == 0 ) {
518  /* Revert to the old behavior */
519  QZ_HandleNonDeviceModifier ( this, device_independent_mask, newMods, left_key_sym );
520  return;
521  }
522 
523  /* XOR the previous state against the new state to see if there's a change */
524  diff_mod = (device_dependent_mask & current_mods)
525  ^ (device_dependent_mask & newMods);
526 
527  if ( diff_mod ) {
528  /* A change in state was found. Isolate the left and right bits
529  * to handle them separately just in case the values can simulataneously
530  * change or if the bits don't both exist.
531  */
532  if ( left_device_dependent_mask & diff_mod ) {
533  QZ_HandleModifierOneSide ( this, newMods, left_key_sym, left_device_dependent_mask );
534  }
535  if ( right_device_dependent_mask & diff_mod ) {
536  QZ_HandleModifierOneSide ( this, newMods, right_key_sym, right_device_dependent_mask );
537  }
538  }
539 }
540 
541 /* This is a helper function for QZ_DoSidedModifiers.
542  * This function will release a key press in the case that
543  * it is clear that the modifier has been released (i.e. one side
544  * can't still be down).
545  */
547  unsigned int device_independent_mask,
548  unsigned int newMods,
549  unsigned int left_key_sym,
550  unsigned int right_key_sym,
551  unsigned int left_device_dependent_mask,
552  unsigned int right_device_dependent_mask ) {
553  unsigned int device_dependent_mask = 0;
554  SDL_keysym key;
555 
556  key.scancode = 0;
557  key.sym = SDLK_UNKNOWN;
558  key.unicode = 0;
559  key.mod = KMOD_NONE;
560 
561  device_dependent_mask = left_device_dependent_mask | right_device_dependent_mask;
562  /* On the basis that the device independent mask is set, but there are
563  * no device dependent flags set, we'll assume that we can't detect this
564  * keyboard and revert to the unsided behavior.
565  */
566  if ( (device_dependent_mask & current_mods) == 0 ) {
567  /* In this case, we can't detect the keyboard, so use the left side
568  * to represent both, and release it.
569  */
570  key.sym = left_key_sym;
572 
573  return;
574  }
575 
576 
577  /*
578  * This could have been done in an if-else case because at this point,
579  * we know that all keys have been released when calling this function.
580  * But I'm being paranoid so I want to handle each separately,
581  * so I hope this doesn't cause other problems.
582  */
583  if ( left_device_dependent_mask & current_mods ) {
584  key.sym = left_key_sym;
586  }
587  if ( right_device_dependent_mask & current_mods ) {
588  key.sym = right_key_sym;
590  }
591 }
592 
593 /* This is a helper function for QZ_DoSidedModifiers.
594  * This function handles the CapsLock case.
595  */
596 static void QZ_HandleCapsLock (_THIS, unsigned int newMods) {
597  unsigned int currentMask, newMask;
598  SDL_keysym key;
599 
600  key.scancode = 0;
601  key.sym = SDLK_CAPSLOCK;
602  key.unicode = 0;
603  key.mod = KMOD_NONE;
604 
605  currentMask = current_mods & NSAlphaShiftKeyMask;
606  newMask = newMods & NSAlphaShiftKeyMask;
607 
608  if ( currentMask &&
609  currentMask != newMask ) { /* modifier up event */
610  /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
613  }
614  else if ( newMask &&
615  currentMask != newMask ) { /* modifier down event */
616  /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
619  }
620 }
621 
622 /* This function will handle the modifier keys and also determine the
623  * correct side of the key.
624  */
625 static void QZ_DoSidedModifiers (_THIS, unsigned int newMods) {
626  /* Set up arrays for the key syms for the left and right side. */
627  const unsigned int left_mapping[] = { SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA };
628  const unsigned int right_mapping[] = { SDLK_RSHIFT, SDLK_RCTRL, SDLK_RALT, SDLK_RMETA };
629  /* Set up arrays for the device dependent masks with indices that
630  * correspond to the _mapping arrays
631  */
632  const unsigned int left_device_mapping[] = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK };
633  const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK };
634 
635  unsigned int i;
636  unsigned int bit;
637 
638  /* Handle CAPSLOCK separately because it doesn't have a left/right side */
639  QZ_HandleCapsLock ( this, newMods );
640 
641  /* Iterate through the bits, testing each against the current modifiers */
642  for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
643 
644  unsigned int currentMask, newMask;
645 
646  currentMask = current_mods & bit;
647  newMask = newMods & bit;
648 
649  /* If the bit is set, we must always examine it because the left
650  * and right side keys may alternate or both may be pressed.
651  */
652  if ( newMask ) {
653  QZ_HandleModifierSide ( this, bit, newMods,
654  left_mapping[i],
655  right_mapping[i],
656  left_device_mapping[i],
657  right_device_mapping[i] );
658  }
659  /* If the state changed from pressed to unpressed, we must examine
660  * the device dependent bits to release the correct keys.
661  */
662  else if ( currentMask &&
663  currentMask != newMask ) { /* modifier up event */
664  QZ_ReleaseModifierSide ( this, bit, newMods,
665  left_mapping[i],
666  right_mapping[i],
667  left_device_mapping[i],
668  right_device_mapping[i] );
669  }
670  }
671 }
672 
673 /* This function is called to handle the modifiers.
674  * It will try to distinguish between the left side and right side
675  * of the keyboard for those modifiers that qualify if the
676  * operating system version supports it. Otherwise, the code
677  * will not try to make the distinction.
678  */
679 static void QZ_DoModifiers (_THIS, unsigned int newMods) {
680 
681  if (current_mods == newMods)
682  return;
683 
684  /*
685  * Starting with Panther (10.3.0), the ability to distinguish between
686  * left side and right side modifiers is available.
687  */
688  if( system_version >= 0x1030 ) {
689  QZ_DoSidedModifiers (this, newMods);
690  }
691  else {
692  QZ_DoUnsidedModifiers (this, newMods);
693  }
694 
695  current_mods = newMods;
696 }
697 
698 static void QZ_GetMouseLocation (_THIS, NSPoint *p) {
699  *p = [ NSEvent mouseLocation ]; /* global coordinates */
700  if (qz_window)
701  QZ_PrivateGlobalToLocal (this, p);
702  QZ_PrivateCocoaToSDL (this, p);
703 }
704 
706 
708 
709  QZ_UpdateCursor(this);
710 
711  /* Regrab input, only if it was previously grabbed */
712  if ( current_grab_mode == SDL_GRAB_ON ) {
713 
714  /* Restore cursor location if input was grabbed */
717  }
718  else {
719  /* Update SDL's mouse location */
720  NSPoint p;
721  QZ_GetMouseLocation (this, &p);
722  SDL_PrivateMouseMotion (0, 0, p.x, p.y);
723  }
724 
725  QZ_UpdateCursor(this);
726 }
727 
729 
731 
732  /* Get the current cursor location, for restore on activate */
734 
735  /* Reassociate mouse and cursor */
736  CGAssociateMouseAndMouseCursorPosition (1);
737 
738  QZ_UpdateCursor(this);
739 }
740 
741 void QZ_SleepNotificationHandler (void * refcon,
742  io_service_t service,
743  natural_t messageType,
744  void * messageArgument )
745 {
746  SDL_VideoDevice *this = (SDL_VideoDevice*)refcon;
747 
748  switch(messageType)
749  {
750  case kIOMessageSystemWillSleep:
751  IOAllowPowerChange(power_connection, (long) messageArgument);
752  break;
753  case kIOMessageCanSystemSleep:
754  IOAllowPowerChange(power_connection, (long) messageArgument);
755  break;
756  case kIOMessageSystemHasPoweredOn:
757  /* awake */
759  break;
760  }
761 }
762 
764 {
765  CFRunLoopSourceRef rls;
766  IONotificationPortRef thePortRef;
767  io_object_t notifier;
768 
769  power_connection = IORegisterForSystemPower (this, &thePortRef, QZ_SleepNotificationHandler, &notifier);
770 
771  if (power_connection == 0)
772  NSLog(@"SDL: QZ_SleepNotificationHandler() IORegisterForSystemPower failed.");
773 
774  rls = IONotificationPortGetRunLoopSource (thePortRef);
775  CFRunLoopAddSource (CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
776  CFRelease (rls);
777 }
778 
779 
780 /* Try to map Quartz mouse buttons to SDL's lingo... */
781 static int QZ_OtherMouseButtonToSDL(int button)
782 {
783  switch (button)
784  {
785  case 0:
786  return(SDL_BUTTON_LEFT); /* 1 */
787  case 1:
788  return(SDL_BUTTON_RIGHT); /* 3 */
789  case 2:
790  return(SDL_BUTTON_MIDDLE); /* 2 */
791  }
792 
793  /* >= 3: skip 4 & 5, since those are the SDL mousewheel buttons. */
794  return(button + 3);
795 }
796 
797 
799 {
800  int32_t dx, dy;
801 
802  NSDate *distantPast;
803  NSEvent *event;
804  NSRect winRect;
805  NSAutoreleasePool *pool;
806 
807  if (!SDL_VideoSurface)
808  return; /* don't do anything if there's no screen surface. */
809 
810  /* Update activity every five seconds to prevent screensaver. --ryan. */
811  if (!allow_screensaver) {
812  static Uint32 screensaverTicks;
813  Uint32 nowTicks = SDL_GetTicks();
814  if ((nowTicks - screensaverTicks) > 5000)
815  {
816  UpdateSystemActivity(UsrActivity);
817  screensaverTicks = nowTicks;
818  }
819  }
820 
821  pool = [ [ NSAutoreleasePool alloc ] init ];
822  distantPast = [ NSDate distantPast ];
823 
824  winRect = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
825 
826  /* while grabbed, accumulate all mouse moved events into one SDL mouse event */
827  dx = 0;
828  dy = 0;
829 
830  do {
831 
832  /* Poll for an event. This will not block */
833  event = [ NSApp nextEventMatchingMask:NSAnyEventMask
834  untilDate:distantPast
835  inMode: NSDefaultRunLoopMode dequeue:YES ];
836  if (event != nil) {
837 
838  int button;
839  unsigned int type;
840  BOOL isInGameWin;
841 
842  #define DO_MOUSE_DOWN(button) do { \
843  if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { \
844  SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0); \
845  expect_mouse_up |= 1<<button; \
846  } \
847  [ NSApp sendEvent:event ]; \
848  } while(0)
849 
850  #define DO_MOUSE_UP(button) do { \
851  if ( expect_mouse_up & (1<<button) ) { \
852  SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0); \
853  expect_mouse_up &= ~(1<<button); \
854  } \
855  [ NSApp sendEvent:event ]; \
856  } while(0)
857 
858  type = [ event type ];
859  isInGameWin = QZ_IsMouseInWindow (this);
860 
861  QZ_DoModifiers(this, [ event modifierFlags ] );
862 
863  switch (type) {
864  case NSLeftMouseDown:
865  if ( SDL_getenv("SDL_HAS3BUTTONMOUSE") ) {
867  } else {
868  if ( NSCommandKeyMask & current_mods ) {
871  }
872  else if ( NSAlternateKeyMask & current_mods ) {
875  }
876  else {
878  }
879  }
880  break;
881 
882  case NSLeftMouseUp:
883  if ( last_virtual_button != 0 ) {
886  }
887  else {
889  }
890  break;
891 
892  case NSOtherMouseDown:
893  case NSRightMouseDown:
894  button = QZ_OtherMouseButtonToSDL([ event buttonNumber ]);
895  DO_MOUSE_DOWN (button);
896  break;
897 
898  case NSOtherMouseUp:
899  case NSRightMouseUp:
900  button = QZ_OtherMouseButtonToSDL([ event buttonNumber ]);
901  DO_MOUSE_UP (button);
902  break;
903 
904  case NSSystemDefined:
905  /*
906  Future: up to 32 "mouse" buttons can be handled.
907  if ([event subtype] == 7) {
908  unsigned int buttons;
909  buttons = [ event data2 ];
910  */
911  break;
912  case NSLeftMouseDragged:
913  case NSRightMouseDragged:
914  case NSOtherMouseDragged: /* usually middle mouse dragged */
915  case NSMouseMoved:
916  if ( grab_state == QZ_INVISIBLE_GRAB ) {
917 
918  /*
919  If input is grabbed+hidden, the cursor doesn't move,
920  so we have to call the lowlevel window server
921  function. This is less accurate but works OK.
922  */
923  int32_t dx1, dy1;
924  CGGetLastMouseDelta (&dx1, &dy1);
925  dx += dx1;
926  dy += dy1;
927  }
928  else {
929 
930  /*
931  Get the absolute mouse location. This is not the
932  mouse location after the currently processed event,
933  but the *current* mouse location, i.e. after all
934  pending events. This means that if there are
935  multiple mouse moved events in the queue, we make
936  multiple identical calls to SDL_PrivateMouseMotion(),
937  but that's no problem since the latter only
938  generates SDL events for nonzero movements. In my
939  experience on PBG4/10.4.8, this rarely happens anyway.
940  */
941  NSPoint p;
942  QZ_GetMouseLocation (this, &p);
943  SDL_PrivateMouseMotion (0, 0, p.x, p.y);
944  }
945 
946  /*
947  Handle grab input+cursor visible by warping the cursor back
948  into the game window. This still generates a mouse moved event,
949  but not as a result of the warp (so it's in the right direction).
950  */
951  if ( grab_state == QZ_VISIBLE_GRAB && !isInGameWin ) {
952 
953  NSPoint p;
954  QZ_GetMouseLocation (this, &p);
955 
956  if ( p.x < 0.0 )
957  p.x = 0.0;
958 
959  if ( p.y < 0.0 )
960  p.y = 0.0;
961 
962  if ( p.x >= winRect.size.width )
963  p.x = winRect.size.width-1;
964 
965  if ( p.y >= winRect.size.height )
966  p.y = winRect.size.height-1;
967 
968  QZ_PrivateWarpCursor (this, p.x, p.y);
969  }
970  else
971  if ( !isInGameWin && (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) {
972 
974 
976  /*The cursor has left the window even though it is
977  disassociated from the mouse (and therefore
978  shouldn't move): this can happen with Wacom
979  tablets, and it effectively breaks the grab, since
980  mouse down events now go to background
981  applications. The only possibility to avoid this
982  seems to be talking to the tablet driver
983  (AppleEvents) to constrain its mapped area to the
984  window, which may not be worth the effort. For
985  now, handle the condition more gracefully than
986  before by reassociating cursor and mouse until the
987  cursor enters the window again, making it obvious
988  to the user that the grab is broken.*/
989  CGAssociateMouseAndMouseCursorPosition (1);
990 
991  QZ_UpdateCursor(this);
992  }
993  else
994  if ( isInGameWin && (SDL_GetAppState() & (SDL_APPMOUSEFOCUS | SDL_APPINPUTFOCUS)) == SDL_APPINPUTFOCUS ) {
995 
997 
998  QZ_UpdateCursor(this);
999 
1000  if (grab_state == QZ_INVISIBLE_GRAB) { /*see comment above*/
1002  CGAssociateMouseAndMouseCursorPosition (0);
1003  }
1004  }
1005  break;
1006  case NSScrollWheel:
1007  if ( isInGameWin ) {
1008  float dy, dx;
1009  Uint8 button;
1010  dy = [ event deltaY ];
1011  dx = [ event deltaX ];
1012  if ( dy > 0.0 ) /* Scroll up */
1013  button = SDL_BUTTON_WHEELUP;
1014  else if ( dy < 0.0 ) /* Scroll down */
1015  button = SDL_BUTTON_WHEELDOWN;
1016  else
1017  break; /* Horizontal scroll */
1018  /* For now, wheel is sent as a quick down+up */
1019  SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0);
1020  SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0);
1021  }
1022  break;
1023  case NSKeyUp:
1024  QZ_DoKey (this, SDL_RELEASED, event);
1025  break;
1026  case NSKeyDown:
1027  QZ_DoKey (this, SDL_PRESSED, event);
1028  break;
1029  case NSFlagsChanged:
1030  break;
1031  case NSAppKitDefined:
1032  [ NSApp sendEvent:event ];
1033  if ([ event subtype ] == NSApplicationActivatedEventType && (mode_flags & SDL_FULLSCREEN)) {
1034  /* the default handling of this event seems to reset any cursor set by [NSCursor set] (used by SDL_SetCursor() in fullscreen mode) to the default system arrow cursor */
1035  SDL_Cursor *sdlc = SDL_GetCursor();
1036  if (sdlc != NULL && sdlc->wm_cursor != NULL) {
1037  [ sdlc->wm_cursor->nscursor set ];
1038  }
1039  }
1040  break;
1041  /* case NSApplicationDefined: break; */
1042  /* case NSPeriodic: break; */
1043  /* case NSCursorUpdate: break; */
1044  default:
1045  [ NSApp sendEvent:event ];
1046  }
1047  }
1048  } while (event != nil);
1049 
1050  /* handle accumulated mouse moved events */
1051  if (dx != 0 || dy != 0)
1052  SDL_PrivateMouseMotion (0, 1, dx, dy);
1053 
1054  [ pool release ];
1055 }
1056 
1058 {
1059  NSPoint p;
1060  QZ_GetMouseLocation (this, &p);
1062  SDL_PrivateMouseMotion (0, 0, p.x, p.y);
1063 }