diff options
Diffstat (limited to 'apps/plugins/sdl/src/video/quartz/SDL_QuartzEvents.m')
-rw-r--r-- | apps/plugins/sdl/src/video/quartz/SDL_QuartzEvents.m | 1063 |
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 | |||
80 | void 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 | |||
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 | |||
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 | */ | ||
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 */ | ||
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 | */ | ||
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 */ | ||
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 | */ | ||
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 | */ | ||
546 | static 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 | */ | ||
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 */ | ||
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 | */ | ||
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 | |||
705 | void 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 | |||
728 | void 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 | |||
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 */ | ||
758 | SDL_PrivateExpose(); | ||
759 | break; | ||
760 | } | ||
761 | } | ||
762 | |||
763 | void QZ_RegisterForSleepNotifications (_THIS) | ||
764 | { | ||
765 | CFRunLoopSourceRef rls; | ||
766 | IONotificationPortRef thePortRef; | ||
767 | io_object_t notifier; | ||
768 | |||
769 | power_connection = IORegisterForSystemPower (this, &thePortRef, QZ_SleepNotificationHandler, ¬ifier); | ||
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 | |||
798 | void 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 | |||
1057 | void 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 | } | ||