summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/src/video/quartz/SDL_QuartzEvents.m
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2018-02-07 20:04:46 -0500
committerFranklin Wei <git@fwei.tk>2018-03-12 20:52:01 -0400
commit6039eb05ba6d82ef56f2868c96654c552d117bf9 (patch)
tree9db7016bcbf66cfdf7b9bc998d84c6eaff9c8378 /apps/plugins/sdl/src/video/quartz/SDL_QuartzEvents.m
parentef373c03b96b0be08babca581d9f10bccfd4931f (diff)
downloadrockbox-6039eb05ba6d82ef56f2868c96654c552d117bf9.tar.gz
rockbox-6039eb05ba6d82ef56f2868c96654c552d117bf9.zip
sdl: remove non-rockbox drivers
We never use any of these other drivers, so having them around just takes up space. Change-Id: Iced812162df1fef3fd55522b7e700acb6c3bcd41
Diffstat (limited to 'apps/plugins/sdl/src/video/quartz/SDL_QuartzEvents.m')
-rw-r--r--apps/plugins/sdl/src/video/quartz/SDL_QuartzEvents.m1063
1 files changed, 0 insertions, 1063 deletions
diff --git a/apps/plugins/sdl/src/video/quartz/SDL_QuartzEvents.m b/apps/plugins/sdl/src/video/quartz/SDL_QuartzEvents.m
deleted file mode 100644
index 773eb010be..0000000000
--- a/apps/plugins/sdl/src/video/quartz/SDL_QuartzEvents.m
+++ /dev/null
@@ -1,1063 +0,0 @@
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
80void QZ_InitOSKeymap (_THIS) {
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
333static 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 */
393static void QZ_DoUnsidedModifiers (_THIS, unsigned int newMods) {
394
395 const int mapping[] = { SDLK_CAPSLOCK, SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA };
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)
420 SDL_PrivateKeyboard (SDL_PRESSED, &key);
421 SDL_PrivateKeyboard (SDL_RELEASED, &key);
422 }
423 else if ( newMask &&
424 currentMask != newMask ) { /* modifier down event */
425
426 key.sym = mapping[i];
427 SDL_PrivateKeyboard (SDL_PRESSED, &key);
428 /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
429 if (bit == NSAlphaShiftKeyMask)
430 SDL_PrivateKeyboard (SDL_RELEASED, &key);
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 */
439static 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 */
456 SDL_PrivateKeyboard (SDL_RELEASED, &key);
457 }
458 else if ( newMask &&
459 currentMask != newMask ) { /* modifier down event */
460 SDL_PrivateKeyboard (SDL_PRESSED, &key);
461 }
462}
463
464/* This is a helper function for QZ_HandleModifierSide.
465 * This function sets the actual SDL_PrivateKeyboard event.
466 */
467static 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 */
492 SDL_PrivateKeyboard (SDL_PRESSED, &key);
493 }
494 else /* Modifier up event */ {
495 SDL_PrivateKeyboard (SDL_RELEASED, &key);
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 */
503static 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 */
546static void QZ_ReleaseModifierSide ( _THIS,
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;
571 SDL_PrivateKeyboard (SDL_RELEASED, &key);
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;
585 SDL_PrivateKeyboard (SDL_RELEASED, &key);
586 }
587 if ( right_device_dependent_mask & current_mods ) {
588 key.sym = right_key_sym;
589 SDL_PrivateKeyboard (SDL_RELEASED, &key);
590 }
591}
592
593/* This is a helper function for QZ_DoSidedModifiers.
594 * This function handles the CapsLock case.
595 */
596static 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 */
611 SDL_PrivateKeyboard (SDL_PRESSED, &key);
612 SDL_PrivateKeyboard (SDL_RELEASED, &key);
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 */
617 SDL_PrivateKeyboard (SDL_PRESSED, &key);
618 SDL_PrivateKeyboard (SDL_RELEASED, &key);
619 }
620}
621
622/* This function will handle the modifier keys and also determine the
623 * correct side of the key.
624 */
625static 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 */
679static 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
698static 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
705void QZ_DoActivate (_THIS) {
706
707 SDL_PrivateAppActive (1, SDL_APPINPUTFOCUS | (QZ_IsMouseInWindow (this) ? SDL_APPMOUSEFOCUS : 0));
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 */
715 QZ_PrivateWarpCursor (this, cursor_loc.x, cursor_loc.y);
716 QZ_ChangeGrabState (this, QZ_ENABLE_GRAB);
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
728void QZ_DoDeactivate (_THIS) {
729
730 SDL_PrivateAppActive (0, SDL_APPINPUTFOCUS | SDL_APPMOUSEFOCUS);
731
732 /* Get the current cursor location, for restore on activate */
733 QZ_GetMouseLocation (this, &cursor_loc);
734
735 /* Reassociate mouse and cursor */
736 CGAssociateMouseAndMouseCursorPosition (1);
737
738 QZ_UpdateCursor(this);
739}
740
741void 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 */
758 SDL_PrivateExpose();
759 break;
760 }
761}
762
763void QZ_RegisterForSleepNotifications (_THIS)
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... */
781static 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
798void QZ_PumpEvents (_THIS)
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") ) {
866 DO_MOUSE_DOWN (SDL_BUTTON_LEFT);
867 } else {
868 if ( NSCommandKeyMask & current_mods ) {
869 last_virtual_button = SDL_BUTTON_RIGHT;
870 DO_MOUSE_DOWN (SDL_BUTTON_RIGHT);
871 }
872 else if ( NSAlternateKeyMask & current_mods ) {
873 last_virtual_button = SDL_BUTTON_MIDDLE;
874 DO_MOUSE_DOWN (SDL_BUTTON_MIDDLE);
875 }
876 else {
877 DO_MOUSE_DOWN (SDL_BUTTON_LEFT);
878 }
879 }
880 break;
881
882 case NSLeftMouseUp:
883 if ( last_virtual_button != 0 ) {
884 DO_MOUSE_UP (last_virtual_button);
885 last_virtual_button = 0;
886 }
887 else {
888 DO_MOUSE_UP (SDL_BUTTON_LEFT);
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
973 SDL_PrivateAppActive (0, SDL_APPMOUSEFOCUS);
974
975 if (grab_state == QZ_INVISIBLE_GRAB)
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
996 SDL_PrivateAppActive (1, SDL_APPMOUSEFOCUS);
997
998 QZ_UpdateCursor(this);
999
1000 if (grab_state == QZ_INVISIBLE_GRAB) { /*see comment above*/
1001 QZ_PrivateWarpCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2);
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
1057void QZ_UpdateMouse (_THIS)
1058{
1059 NSPoint p;
1060 QZ_GetMouseLocation (this, &p);
1061 SDL_PrivateAppActive (QZ_IsMouseInWindow (this), SDL_APPMOUSEFOCUS);
1062 SDL_PrivateMouseMotion (0, 0, p.x, p.y);
1063}