summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/src/video/quartz
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
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')
-rw-r--r--apps/plugins/sdl/src/video/quartz/CGS.h84
-rw-r--r--apps/plugins/sdl/src/video/quartz/SDL_QuartzEvents.m1063
-rw-r--r--apps/plugins/sdl/src/video/quartz/SDL_QuartzGL.m292
-rw-r--r--apps/plugins/sdl/src/video/quartz/SDL_QuartzKeys.h146
-rw-r--r--apps/plugins/sdl/src/video/quartz/SDL_QuartzVideo.h229
-rw-r--r--apps/plugins/sdl/src/video/quartz/SDL_QuartzVideo.m1689
-rw-r--r--apps/plugins/sdl/src/video/quartz/SDL_QuartzWM.h27
-rw-r--r--apps/plugins/sdl/src/video/quartz/SDL_QuartzWM.m444
-rw-r--r--apps/plugins/sdl/src/video/quartz/SDL_QuartzWindow.h51
-rw-r--r--apps/plugins/sdl/src/video/quartz/SDL_QuartzWindow.m231
10 files changed, 0 insertions, 4256 deletions
diff --git a/apps/plugins/sdl/src/video/quartz/CGS.h b/apps/plugins/sdl/src/video/quartz/CGS.h
deleted file mode 100644
index abe47f7320..0000000000
--- a/apps/plugins/sdl/src/video/quartz/CGS.h
+++ /dev/null
@@ -1,84 +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/*
25 Obscuring code: maximum number of windows above ours (inclusive)
26
27 Note: this doesn't work too well in practice and should be
28 phased out when we add OpenGL 2D acceleration. It was never
29 enabled in the first place, so this shouldn't be a problem ;-)
30*/
31#define kMaxWindows 256
32
33/* Some of the Core Graphics Server API for obscuring code */
34#define kCGSWindowLevelTop 2147483632
35#define kCGSWindowLevelDockIconDrag 500
36#define kCGSWindowLevelDockMenu 101
37#define kCGSWindowLevelMenuIgnore 21
38#define kCGSWindowLevelMenu 20
39#define kCGSWindowLevelDockLabel 12
40#define kCGSWindowLevelDockIcon 11
41#define kCGSWindowLevelDock 10
42#define kCGSWindowLevelUtility 3
43#define kCGSWindowLevelNormal 0
44
45/*
46 For completeness; We never use these window levels, they are always below us
47 #define kCGSWindowLevelMBarShadow -20
48 #define kCGSWindowLevelDesktopPicture -2147483647
49 #define kCGSWindowLevelDesktop -2147483648
50*/
51
52typedef CGError CGSError;
53typedef long CGSWindowCount;
54typedef void * CGSConnectionID;
55typedef int CGSWindowID;
56typedef CGSWindowID* CGSWindowIDList;
57typedef CGWindowLevel CGSWindowLevel;
58typedef NSRect CGSRect;
59
60extern CGSConnectionID _CGSDefaultConnection ();
61
62extern CGSError CGSGetOnScreenWindowList (CGSConnectionID cid,
63 CGSConnectionID owner,
64 CGSWindowCount listCapacity,
65 CGSWindowIDList list,
66 CGSWindowCount *listCount);
67
68extern CGSError CGSGetScreenRectForWindow (CGSConnectionID cid,
69 CGSWindowID wid,
70 CGSRect *rect);
71
72extern CGWindowLevel CGSGetWindowLevel (CGSConnectionID cid,
73 CGSWindowID wid,
74 CGSWindowLevel *level);
75
76extern CGSError CGSDisplayHWFill (CGDirectDisplayID id, unsigned int x, unsigned int y,
77 unsigned int w, unsigned int h, unsigned int color);
78
79extern CGSError CGSDisplayCanHWFill (CGDirectDisplayID id);
80
81extern CGSError CGSGetMouseEnabledFlags (CGSConnectionID cid, CGSWindowID wid, int *flags);
82
83int CGSDisplayHWSync (CGDirectDisplayID id);
84
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}
diff --git a/apps/plugins/sdl/src/video/quartz/SDL_QuartzGL.m b/apps/plugins/sdl/src/video/quartz/SDL_QuartzGL.m
deleted file mode 100644
index d38dceb56b..0000000000
--- a/apps/plugins/sdl/src/video/quartz/SDL_QuartzGL.m
+++ /dev/null
@@ -1,292 +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
26/*
27 * GL_ARB_Multisample is supposed to be available in 10.1, according to Apple:
28 *
29 * http://developer.apple.com/graphicsimaging/opengl/extensions.html#GL_ARB_multisample
30 *
31 * ...but it isn't in the system headers, according to Sam:
32 *
33 * http://lists.libsdl.org/pipermail/sdl-libsdl.org/2003-December/039794.html
34 *
35 * These are normally enums and not #defines in the system headers.
36 *
37 * --ryan.
38 */
39#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1020)
40#define NSOpenGLPFASampleBuffers ((NSOpenGLPixelFormatAttribute) 55)
41#define NSOpenGLPFASamples ((NSOpenGLPixelFormatAttribute) 56)
42#endif
43
44#ifdef __powerpc__ /* we lost this in 10.6, which has no PPC support. */
45@implementation NSOpenGLContext (CGLContextAccess)
46- (CGLContextObj) cglContext;
47{
48 return _contextAuxiliary;
49}
50@end
51CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx)
52{
53 return [nsctx cglContext];
54}
55#else
56CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx)
57{
58 return (CGLContextObj) [nsctx CGLContextObj];
59}
60#endif
61
62
63/* OpenGL helper functions (used internally) */
64
65int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
66
67 NSOpenGLPixelFormatAttribute attr[32];
68 NSOpenGLPixelFormat *fmt;
69 int i = 0;
70 int colorBits = bpp;
71
72 /* if a GL library hasn't been loaded at this point, load the default. */
73 if (!this->gl_config.driver_loaded) {
74 if (QZ_GL_LoadLibrary(this, NULL) == -1)
75 return 0;
76 }
77
78 if ( flags & SDL_FULLSCREEN ) {
79
80 attr[i++] = NSOpenGLPFAFullScreen;
81 }
82 /* In windowed mode, the OpenGL pixel depth must match device pixel depth */
83 else if ( colorBits != device_bpp ) {
84
85 colorBits = device_bpp;
86 }
87
88 attr[i++] = NSOpenGLPFAColorSize;
89 attr[i++] = colorBits;
90
91 attr[i++] = NSOpenGLPFADepthSize;
92 attr[i++] = this->gl_config.depth_size;
93
94 if ( this->gl_config.double_buffer ) {
95 attr[i++] = NSOpenGLPFADoubleBuffer;
96 }
97
98 if ( this->gl_config.stereo ) {
99 attr[i++] = NSOpenGLPFAStereo;
100 }
101
102 if ( this->gl_config.stencil_size != 0 ) {
103 attr[i++] = NSOpenGLPFAStencilSize;
104 attr[i++] = this->gl_config.stencil_size;
105 }
106
107 if ( (this->gl_config.accum_red_size +
108 this->gl_config.accum_green_size +
109 this->gl_config.accum_blue_size +
110 this->gl_config.accum_alpha_size) > 0 ) {
111 attr[i++] = NSOpenGLPFAAccumSize;
112 attr[i++] = this->gl_config.accum_red_size + this->gl_config.accum_green_size + this->gl_config.accum_blue_size + this->gl_config.accum_alpha_size;
113 }
114
115 if ( this->gl_config.multisamplebuffers != 0 ) {
116 attr[i++] = NSOpenGLPFASampleBuffers;
117 attr[i++] = this->gl_config.multisamplebuffers;
118 }
119
120 if ( this->gl_config.multisamplesamples != 0 ) {
121 attr[i++] = NSOpenGLPFASamples;
122 attr[i++] = this->gl_config.multisamplesamples;
123 attr[i++] = NSOpenGLPFANoRecovery;
124 }
125
126 if ( this->gl_config.accelerated > 0 ) {
127 attr[i++] = NSOpenGLPFAAccelerated;
128 }
129
130 attr[i++] = NSOpenGLPFAScreenMask;
131 attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
132 attr[i] = 0;
133
134 fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
135 if (fmt == nil) {
136 SDL_SetError ("Failed creating OpenGL pixel format");
137 return 0;
138 }
139
140 gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
141 shareContext:nil];
142
143 [ fmt release ];
144
145 if (gl_context == nil) {
146 SDL_SetError ("Failed creating OpenGL context");
147 return 0;
148 }
149
150 /* Synchronize QZ_GL_SwapBuffers() to vertical retrace.
151 * (Apple's documentation is not completely clear about what this setting
152 * exactly does, IMHO - for a detailed explanation see
153 * http://lists.apple.com/archives/mac-opengl/2006/Jan/msg00080.html )
154 */
155 if ( this->gl_config.swap_control >= 0 ) {
156 GLint value;
157 value = this->gl_config.swap_control;
158 [ gl_context setValues: &value forParameter: NSOpenGLCPSwapInterval ];
159 }
160
161 /*
162 * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
163 * "You are blowing a couple of the internal OpenGL function caches. This
164 * appears to be happening in the VAO case. You can tell OpenGL to up
165 * the cache size by issuing the following calls right after you create
166 * the OpenGL context. The default cache size is 16." --ryan.
167 */
168
169 #ifndef GLI_ARRAY_FUNC_CACHE_MAX
170 #define GLI_ARRAY_FUNC_CACHE_MAX 284
171 #endif
172
173 #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
174 #define GLI_SUBMIT_FUNC_CACHE_MAX 280
175 #endif
176
177 {
178 GLint cache_max = 64;
179 CGLContextObj ctx = QZ_GetCGLContextObj(gl_context);
180 CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
181 CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
182 }
183
184 /* End Wisdom from Apple Engineer section. --ryan. */
185
186 return 1;
187}
188
189void QZ_TearDownOpenGL (_THIS) {
190
191 [ NSOpenGLContext clearCurrentContext ];
192 [ gl_context clearDrawable ];
193 [ gl_context release ];
194}
195
196
197/* SDL OpenGL functions */
198static const char *DEFAULT_OPENGL_LIB_NAME =
199 "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib";
200
201int QZ_GL_LoadLibrary (_THIS, const char *location) {
202 if ( gl_context != NULL ) {
203 SDL_SetError("OpenGL context already created");
204 return -1;
205 }
206
207 if (opengl_library != NULL)
208 SDL_UnloadObject(opengl_library);
209
210 if (location == NULL)
211 location = DEFAULT_OPENGL_LIB_NAME;
212
213 opengl_library = SDL_LoadObject(location);
214 if (opengl_library != NULL) {
215 this->gl_config.driver_loaded = 1;
216 return 0;
217 }
218
219 this->gl_config.driver_loaded = 0;
220 return -1;
221}
222
223void* QZ_GL_GetProcAddress (_THIS, const char *proc) {
224 return SDL_LoadFunction(opengl_library, proc);
225}
226
227int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value) {
228
229 GLenum attr = 0;
230
231 QZ_GL_MakeCurrent (this);
232
233 switch (attrib) {
234 case SDL_GL_RED_SIZE: attr = GL_RED_BITS; break;
235 case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS; break;
236 case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break;
237 case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break;
238 case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break;
239 case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS; break;
240 case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break;
241 case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break;
242 case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break;
243 case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break;
244 case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break;
245 case SDL_GL_STEREO: attr = GL_STEREO; break;
246 case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break;
247 case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break;
248 case SDL_GL_BUFFER_SIZE:
249 {
250 GLint bits = 0;
251 GLint component;
252
253 /* there doesn't seem to be a single flag in OpenGL for this! */
254 glGetIntegerv (GL_RED_BITS, &component); bits += component;
255 glGetIntegerv (GL_GREEN_BITS,&component); bits += component;
256 glGetIntegerv (GL_BLUE_BITS, &component); bits += component;
257 glGetIntegerv (GL_ALPHA_BITS, &component); bits += component;
258
259 *value = bits;
260 return 0;
261 }
262 case SDL_GL_ACCELERATED_VISUAL:
263 {
264 GLint val;
265 /* FIXME: How do we get this information here?
266 [fmt getValues: &val forAttribute: NSOpenGLPFAAccelerated attr forVirtualScreen: 0];
267 */
268 val = (this->gl_config.accelerated != 0);;
269 *value = val;
270 return 0;
271 }
272 case SDL_GL_SWAP_CONTROL:
273 {
274 GLint val;
275 [ gl_context getValues: &val forParameter: NSOpenGLCPSwapInterval ];
276 *value = val;
277 return 0;
278 }
279 }
280
281 glGetIntegerv (attr, (GLint *)value);
282 return 0;
283}
284
285int QZ_GL_MakeCurrent (_THIS) {
286 [ gl_context makeCurrentContext ];
287 return 0;
288}
289
290void QZ_GL_SwapBuffers (_THIS) {
291 [ gl_context flushBuffer ];
292}
diff --git a/apps/plugins/sdl/src/video/quartz/SDL_QuartzKeys.h b/apps/plugins/sdl/src/video/quartz/SDL_QuartzKeys.h
deleted file mode 100644
index 82b78595e3..0000000000
--- a/apps/plugins/sdl/src/video/quartz/SDL_QuartzKeys.h
+++ /dev/null
@@ -1,146 +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/* These are the Macintosh key scancode constants -- from Inside Macintosh */
25
26#define QZ_ESCAPE 0x35
27#define QZ_F1 0x7A
28#define QZ_F2 0x78
29#define QZ_F3 0x63
30#define QZ_F4 0x76
31#define QZ_F5 0x60
32#define QZ_F6 0x61
33#define QZ_F7 0x62
34#define QZ_F8 0x64
35#define QZ_F9 0x65
36#define QZ_F10 0x6D
37#define QZ_F11 0x67
38#define QZ_F12 0x6F
39#define QZ_F13 0x69
40#define QZ_F14 0x6B
41#define QZ_F15 0x71
42/*
43#define QZ_PRINT 0x69
44#define QZ_SCROLLOCK 0x6B
45#define QZ_PAUSE 0x71
46*/
47#define QZ_POWER 0x7F
48#define QZ_BACKQUOTE 0x32
49#define QZ_1 0x12
50#define QZ_2 0x13
51#define QZ_3 0x14
52#define QZ_4 0x15
53#define QZ_5 0x17
54#define QZ_6 0x16
55#define QZ_7 0x1A
56#define QZ_8 0x1C
57#define QZ_9 0x19
58#define QZ_0 0x1D
59#define QZ_MINUS 0x1B
60#define QZ_EQUALS 0x18
61#define QZ_BACKSPACE 0x33
62#define QZ_INSERT 0x72
63#define QZ_HOME 0x73
64#define QZ_PAGEUP 0x74
65#define QZ_NUMLOCK 0x47
66#define QZ_KP_EQUALS 0x51
67#define QZ_KP_DIVIDE 0x4B
68#define QZ_KP_MULTIPLY 0x43
69#define QZ_TAB 0x30
70#define QZ_q 0x0C
71#define QZ_w 0x0D
72#define QZ_e 0x0E
73#define QZ_r 0x0F
74#define QZ_t 0x11
75#define QZ_y 0x10
76#define QZ_u 0x20
77#define QZ_i 0x22
78#define QZ_o 0x1F
79#define QZ_p 0x23
80#define QZ_LEFTBRACKET 0x21
81#define QZ_RIGHTBRACKET 0x1E
82#define QZ_BACKSLASH 0x2A
83#define QZ_DELETE 0x75
84#define QZ_END 0x77
85#define QZ_PAGEDOWN 0x79
86#define QZ_KP7 0x59
87#define QZ_KP8 0x5B
88#define QZ_KP9 0x5C
89#define QZ_KP_MINUS 0x4E
90#define QZ_CAPSLOCK 0x39
91#define QZ_a 0x00
92#define QZ_s 0x01
93#define QZ_d 0x02
94#define QZ_f 0x03
95#define QZ_g 0x05
96#define QZ_h 0x04
97#define QZ_j 0x26
98#define QZ_k 0x28
99#define QZ_l 0x25
100#define QZ_SEMICOLON 0x29
101#define QZ_QUOTE 0x27
102#define QZ_RETURN 0x24
103#define QZ_KP4 0x56
104#define QZ_KP5 0x57
105#define QZ_KP6 0x58
106#define QZ_KP_PLUS 0x45
107#define QZ_LSHIFT 0x38
108#define QZ_z 0x06
109#define QZ_x 0x07
110#define QZ_c 0x08
111#define QZ_v 0x09
112#define QZ_b 0x0B
113#define QZ_n 0x2D
114#define QZ_m 0x2E
115#define QZ_COMMA 0x2B
116#define QZ_PERIOD 0x2F
117#define QZ_SLASH 0x2C
118#if 1 /* Panther now defines right side keys */
119#define QZ_RSHIFT 0x3C
120#endif
121#define QZ_UP 0x7E
122#define QZ_KP1 0x53
123#define QZ_KP2 0x54
124#define QZ_KP3 0x55
125#define QZ_KP_ENTER 0x4C
126#define QZ_LCTRL 0x3B
127#define QZ_LALT 0x3A
128#define QZ_LMETA 0x37
129#define QZ_SPACE 0x31
130#if 1 /* Panther now defines right side keys */
131#define QZ_RMETA 0x36
132#define QZ_RALT 0x3D
133#define QZ_RCTRL 0x3E
134#endif
135#define QZ_LEFT 0x7B
136#define QZ_DOWN 0x7D
137#define QZ_RIGHT 0x7C
138#define QZ_KP0 0x52
139#define QZ_KP_PERIOD 0x41
140
141/* Wierd, these keys are on my iBook under Mac OS X */
142#define QZ_IBOOK_ENTER 0x34
143#define QZ_IBOOK_LEFT 0x3B
144#define QZ_IBOOK_RIGHT 0x3C
145#define QZ_IBOOK_DOWN 0x3D
146#define QZ_IBOOK_UP 0x3E
diff --git a/apps/plugins/sdl/src/video/quartz/SDL_QuartzVideo.h b/apps/plugins/sdl/src/video/quartz/SDL_QuartzVideo.h
deleted file mode 100644
index 7506e0cd10..0000000000
--- a/apps/plugins/sdl/src/video/quartz/SDL_QuartzVideo.h
+++ /dev/null
@@ -1,229 +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/*
25 @file SDL_QuartzVideo.h
26 @author Darrell Walisser, Max Horn, et al.
27
28 @abstract SDL video driver for Mac OS X.
29
30 @discussion
31
32 TODO
33 - Hardware Cursor support with NSCursor instead of Carbon
34 - Keyboard repeat/mouse speed adjust (if needed)
35 - Multiple monitor support (currently only main display)
36 - Accelerated blitting support
37 - Fix white OpenGL window on minimize (fixed) (update: broken again on 10.2)
38 - Find out what events should be sent/ignored if window is minimized
39 - Find a way to deal with external resolution/depth switch while app is running
40 - Check accuracy of QZ_SetGamma()
41 Problems:
42 - OGL not working in full screen with software renderer
43 - SetColors sets palette correctly but clears framebuffer
44 - Crash in CG after several mode switches (I think this has been fixed)
45 - Retained windows don't draw their title bar quite right (OS Bug) (not using retained windows)
46 - Cursor in 8 bit modes is screwy (might just be Radeon PCI bug) (update: not just Radeon)
47 - Warping cursor delays mouse events for a fraction of a second,
48 there is a hack around this that helps a bit
49*/
50
51/* Needs to be first, so QuickTime.h doesn't include glext.h (10.4) */
52#include "SDL_opengl.h"
53
54#include <Cocoa/Cocoa.h>
55#include <Carbon/Carbon.h>
56#include <OpenGL/OpenGL.h> /* For CGL functions and types */
57#include <IOKit/IOKitLib.h> /* For powersave handling */
58#include <pthread.h>
59
60#include "SDL_thread.h"
61#include "SDL_video.h"
62#include "SDL_error.h"
63#include "SDL_timer.h"
64#include "SDL_loadso.h"
65#include "SDL_syswm.h"
66#include "../SDL_sysvideo.h"
67#include "../SDL_pixels_c.h"
68#include "../../events/SDL_events_c.h"
69
70
71#ifdef __powerpc__
72/*
73 This is a workaround to directly access NSOpenGLContext's CGL context
74 We need this to check for errors NSOpenGLContext doesn't support
75 Please note this is only used on PowerPC (Intel Macs are guaranteed to
76 have a better API for this, since it showed up in Mac OS X 10.3).
77*/
78@interface NSOpenGLContext (CGLContextAccess)
79- (CGLContextObj) cglContext;
80@end
81#endif
82
83/* use this to get the CGLContext; it handles Cocoa interface changes. */
84CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx);
85
86
87/* Main driver structure to store required state information */
88typedef struct SDL_PrivateVideoData {
89 BOOL use_new_mode_apis; /* 1 == >= 10.6 APIs available */
90 BOOL allow_screensaver; /* 0 == disable screensaver */
91 CGDirectDisplayID display; /* 0 == main display (only support single display) */
92 const void *mode; /* current mode of the display */
93 const void *save_mode; /* original mode of the display */
94 CGDirectPaletteRef palette; /* palette of an 8-bit display */
95 NSOpenGLContext *gl_context; /* OpenGL rendering context */
96 NSGraphicsContext *nsgfx_context; /* Cocoa graphics context */
97 Uint32 width, height, bpp; /* frequently used data about the display */
98 Uint32 flags; /* flags for current mode, for teardown purposes */
99 Uint32 video_set; /* boolean; indicates if video was set correctly */
100 Uint32 warp_flag; /* boolean; notify to event loop that a warp just occured */
101 Uint32 warp_ticks; /* timestamp when the warp occured */
102 NSWindow *window; /* Cocoa window to implement the SDL window */
103 NSView *view; /* the window's view; draw 2D and OpenGL into this view */
104 CGContextRef cg_context; /* CoreGraphics rendering context */
105 SDL_Surface *resize_icon; /* icon for the resize badge, we have to draw it by hand */
106 SDL_GrabMode current_grab_mode; /* default value is SDL_GRAB_OFF */
107 SDL_Rect **client_mode_list; /* resolution list to pass back to client */
108 SDLKey keymap[256]; /* Mac OS X to SDL key mapping */
109 Uint32 current_mods; /* current keyboard modifiers, to track modifier state */
110 NSText *field_edit; /* a field editor for keyboard composition processing */
111 Uint32 last_virtual_button;/* last virtual mouse button pressed */
112 io_connect_t power_connection; /* used with IOKit to detect wake from sleep */
113 Uint8 expect_mouse_up; /* used to determine when to send mouse up events */
114 Uint8 grab_state; /* used to manage grab behavior */
115 NSPoint cursor_loc; /* saved cursor coords, for activate/deactivate when grabbed */
116 BOOL cursor_should_be_visible; /* tells if cursor is supposed to be visible (SDL_ShowCursor) */
117 BOOL cursor_visible; /* tells if cursor is *actually* visible or not */
118 Uint8* sw_buffers[2]; /* pointers to the two software buffers for double-buffer emulation */
119 SDL_Thread *thread; /* thread for async updates to the screen */
120 SDL_sem *sem1, *sem2; /* synchronization for async screen updates */
121 Uint8 *current_buffer; /* the buffer being copied to the screen */
122 BOOL quit_thread; /* used to quit the async blitting thread */
123 SInt32 system_version; /* used to dis-/enable workarounds depending on the system version */
124
125 void *opengl_library; /* dynamically loaded OpenGL library. */
126} SDL_PrivateVideoData;
127
128#define _THIS SDL_VideoDevice *this
129#define display_id (this->hidden->display)
130#define mode (this->hidden->mode)
131#define save_mode (this->hidden->save_mode)
132#define use_new_mode_apis (this->hidden->use_new_mode_apis)
133#define allow_screensaver (this->hidden->allow_screensaver)
134#define palette (this->hidden->palette)
135#define gl_context (this->hidden->gl_context)
136#define nsgfx_context (this->hidden->nsgfx_context)
137#define device_width (this->hidden->width)
138#define device_height (this->hidden->height)
139#define device_bpp (this->hidden->bpp)
140#define mode_flags (this->hidden->flags)
141#define qz_window (this->hidden->window)
142#define window_view (this->hidden->view)
143#define cg_context (this->hidden->cg_context)
144#define video_set (this->hidden->video_set)
145#define warp_ticks (this->hidden->warp_ticks)
146#define warp_flag (this->hidden->warp_flag)
147#define resize_icon (this->hidden->resize_icon)
148#define current_grab_mode (this->hidden->current_grab_mode)
149#define client_mode_list (this->hidden->client_mode_list)
150#define keymap (this->hidden->keymap)
151#define current_mods (this->hidden->current_mods)
152#define field_edit (this->hidden->field_edit)
153#define last_virtual_button (this->hidden->last_virtual_button)
154#define power_connection (this->hidden->power_connection)
155#define expect_mouse_up (this->hidden->expect_mouse_up)
156#define grab_state (this->hidden->grab_state)
157#define cursor_loc (this->hidden->cursor_loc)
158#define cursor_should_be_visible (this->hidden->cursor_should_be_visible)
159#define cursor_visible (this->hidden->cursor_visible)
160#define sw_buffers (this->hidden->sw_buffers)
161#define sw_contexts (this->hidden->sw_contexts)
162#define thread (this->hidden->thread)
163#define sem1 (this->hidden->sem1)
164#define sem2 (this->hidden->sem2)
165#define current_buffer (this->hidden->current_buffer)
166#define quit_thread (this->hidden->quit_thread)
167#define system_version (this->hidden->system_version)
168#define opengl_library (this->hidden->opengl_library)
169
170/* grab states - the input is in one of these states */
171enum {
172 QZ_UNGRABBED = 0,
173 QZ_VISIBLE_GRAB,
174 QZ_INVISIBLE_GRAB
175};
176
177/* grab actions - these can change the grabbed state */
178enum {
179 QZ_ENABLE_GRAB = 0,
180 QZ_DISABLE_GRAB,
181 QZ_HIDECURSOR,
182 QZ_SHOWCURSOR
183};
184
185/* Gamma Functions */
186int QZ_SetGamma (_THIS, float red, float green, float blue);
187int QZ_GetGamma (_THIS, float *red, float *green, float *blue);
188int QZ_SetGammaRamp (_THIS, Uint16 *ramp);
189int QZ_GetGammaRamp (_THIS, Uint16 *ramp);
190
191/* OpenGL functions */
192int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags);
193void QZ_TearDownOpenGL (_THIS);
194void* QZ_GL_GetProcAddress (_THIS, const char *proc);
195int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value);
196int QZ_GL_MakeCurrent (_THIS);
197void QZ_GL_SwapBuffers (_THIS);
198int QZ_GL_LoadLibrary (_THIS, const char *location);
199
200/* Cursor and Mouse functions */
201void QZ_FreeWMCursor (_THIS, WMcursor *cursor);
202WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask,
203 int w, int h, int hot_x, int hot_y);
204int QZ_ShowWMCursor (_THIS, WMcursor *cursor);
205void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y);
206void QZ_MoveWMCursor (_THIS, int x, int y);
207void QZ_CheckMouseMode (_THIS);
208void QZ_UpdateMouse (_THIS);
209
210/* Event functions */
211void QZ_InitOSKeymap (_THIS);
212void QZ_PumpEvents (_THIS);
213
214/* Window Manager functions */
215void QZ_SetCaption (_THIS, const char *title, const char *icon);
216void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask);
217int QZ_IconifyWindow (_THIS);
218SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode);
219/*int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info);*/
220
221/* Private functions (used internally) */
222void QZ_PrivateWarpCursor (_THIS, int x, int y);
223void QZ_ChangeGrabState (_THIS, int action);
224void QZ_RegisterForSleepNotifications (_THIS);
225void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p);
226void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p);
227BOOL QZ_IsMouseInWindow (_THIS);
228void QZ_DoActivate (_THIS);
229void QZ_DoDeactivate (_THIS);
diff --git a/apps/plugins/sdl/src/video/quartz/SDL_QuartzVideo.m b/apps/plugins/sdl/src/video/quartz/SDL_QuartzVideo.m
deleted file mode 100644
index fa04e9d107..0000000000
--- a/apps/plugins/sdl/src/video/quartz/SDL_QuartzVideo.m
+++ /dev/null
@@ -1,1689 +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_QuartzWindow.h"
26
27/* These APIs aren't just deprecated; they're gone from the headers in the
28 10.7 SDK. If we're using a >= 10.7 SDK, but targeting < 10.7, then we
29 force these function declarations. */
30#if ((MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1070))
31CG_EXTERN void *CGDisplayBaseAddress(CGDirectDisplayID display)
32 CG_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_6,
33 __IPHONE_NA, __IPHONE_NA);
34CG_EXTERN size_t CGDisplayBytesPerRow(CGDirectDisplayID display)
35 CG_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_6,
36 __IPHONE_NA, __IPHONE_NA);
37#endif
38
39
40static inline BOOL IS_LION_OR_LATER(_THIS)
41{
42 return (system_version >= 0x1070);
43}
44
45static inline BOOL IS_SNOW_LEOPARD_OR_LATER(_THIS)
46{
47 return (system_version >= 0x1060);
48}
49
50#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1060) && !defined(__LP64__) /* Fixed in Snow Leopard */
51/*
52 Add methods to get at private members of NSScreen.
53 Since there is a bug in Apple's screen switching code
54 that does not update this variable when switching
55 to fullscreen, we'll set it manually (but only for the
56 main screen).
57*/
58@interface NSScreen (NSScreenAccess)
59- (void) setFrame:(NSRect)frame;
60@end
61
62@implementation NSScreen (NSScreenAccess)
63- (void) setFrame:(NSRect)frame;
64{
65 _frame = frame;
66}
67@end
68static inline void QZ_SetFrame(_THIS, NSScreen *nsscreen, NSRect frame)
69{
70 if (!IS_SNOW_LEOPARD_OR_LATER(this)) {
71 [nsscreen setFrame:frame];
72 }
73}
74#else
75static inline void QZ_SetFrame(_THIS, NSScreen *nsscreen, NSRect frame)
76{
77}
78#endif
79
80@interface SDLTranslatorResponder : NSTextView
81{
82}
83- (void) doCommandBySelector:(SEL)myselector;
84@end
85
86@implementation SDLTranslatorResponder
87- (void) doCommandBySelector:(SEL) myselector {}
88@end
89
90/* absent in 10.3.9. */
91CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef);
92
93/* Bootstrap functions */
94static int QZ_Available ();
95static SDL_VideoDevice* QZ_CreateDevice (int device_index);
96static void QZ_DeleteDevice (SDL_VideoDevice *device);
97
98/* Initialization, Query, Setup, and Redrawing functions */
99static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format);
100
101static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format,
102 Uint32 flags);
103static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop, BOOL save_gl);
104
105static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current,
106 int width, int height, int bpp,
107 Uint32 flags);
108static int QZ_ToggleFullScreen (_THIS, int on);
109static int QZ_SetColors (_THIS, int first_color,
110 int num_colors, SDL_Color *colors);
111
112#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
113static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface);
114static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface);
115static int QZ_ThreadFlip (_THIS);
116static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface);
117static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects);
118static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects);
119#endif
120
121static void QZ_UpdateRects (_THIS, int num_rects, SDL_Rect *rects);
122static void QZ_VideoQuit (_THIS);
123
124static int QZ_LockHWSurface(_THIS, SDL_Surface *surface);
125static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface);
126static int QZ_AllocHWSurface(_THIS, SDL_Surface *surface);
127static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface);
128
129/* Bootstrap binding, enables entry point into the driver */
130VideoBootStrap QZ_bootstrap = {
131 "Quartz", "Mac OS X CoreGraphics", QZ_Available, QZ_CreateDevice
132};
133
134/* Disable compiler warnings we can't avoid. */
135#if (defined(__GNUC__) && (__GNUC__ >= 4))
136# if (MAC_OS_X_VERSION_MAX_ALLOWED <= 1070)
137# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
138# endif
139#endif
140
141static void QZ_ReleaseDisplayMode(_THIS, const void *moderef)
142{
143 /* we only own these references in the 10.6+ API. */
144#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
145 if (use_new_mode_apis) {
146 CGDisplayModeRelease((CGDisplayModeRef) moderef);
147 }
148#endif
149}
150
151static void QZ_ReleaseDisplayModeList(_THIS, CFArrayRef mode_list)
152{
153 /* we only own these references in the 10.6+ API. */
154#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
155 if (use_new_mode_apis) {
156 CFRelease(mode_list);
157 }
158#endif
159}
160
161
162/* Bootstrap functions */
163static int QZ_Available ()
164{
165 return 1;
166}
167
168static SDL_VideoDevice* QZ_CreateDevice (int device_index)
169{
170#pragma unused (device_index)
171
172 SDL_VideoDevice *device;
173 SDL_PrivateVideoData *hidden;
174
175 device = (SDL_VideoDevice*) SDL_malloc (sizeof (*device) );
176 hidden = (SDL_PrivateVideoData*) SDL_malloc (sizeof (*hidden) );
177
178 if (device == NULL || hidden == NULL)
179 SDL_OutOfMemory ();
180
181 SDL_memset (device, 0, sizeof (*device) );
182 SDL_memset (hidden, 0, sizeof (*hidden) );
183
184 device->hidden = hidden;
185
186 device->VideoInit = QZ_VideoInit;
187 device->ListModes = QZ_ListModes;
188 device->SetVideoMode = QZ_SetVideoMode;
189 device->ToggleFullScreen = QZ_ToggleFullScreen;
190 device->UpdateMouse = QZ_UpdateMouse;
191 device->SetColors = QZ_SetColors;
192 /* device->UpdateRects = QZ_UpdateRects; this is determined by SetVideoMode() */
193 device->VideoQuit = QZ_VideoQuit;
194
195 device->LockHWSurface = QZ_LockHWSurface;
196 device->UnlockHWSurface = QZ_UnlockHWSurface;
197 device->AllocHWSurface = QZ_AllocHWSurface;
198 device->FreeHWSurface = QZ_FreeHWSurface;
199
200 device->SetGamma = QZ_SetGamma;
201 device->GetGamma = QZ_GetGamma;
202 device->SetGammaRamp = QZ_SetGammaRamp;
203 device->GetGammaRamp = QZ_GetGammaRamp;
204
205 device->GL_GetProcAddress = QZ_GL_GetProcAddress;
206 device->GL_GetAttribute = QZ_GL_GetAttribute;
207 device->GL_MakeCurrent = QZ_GL_MakeCurrent;
208 device->GL_SwapBuffers = QZ_GL_SwapBuffers;
209 device->GL_LoadLibrary = QZ_GL_LoadLibrary;
210
211 device->FreeWMCursor = QZ_FreeWMCursor;
212 device->CreateWMCursor = QZ_CreateWMCursor;
213 device->ShowWMCursor = QZ_ShowWMCursor;
214 device->WarpWMCursor = QZ_WarpWMCursor;
215 device->MoveWMCursor = QZ_MoveWMCursor;
216 device->CheckMouseMode = QZ_CheckMouseMode;
217 device->InitOSKeymap = QZ_InitOSKeymap;
218 device->PumpEvents = QZ_PumpEvents;
219
220 device->SetCaption = QZ_SetCaption;
221 device->SetIcon = QZ_SetIcon;
222 device->IconifyWindow = QZ_IconifyWindow;
223 /*device->GetWMInfo = QZ_GetWMInfo;*/
224 device->GrabInput = QZ_GrabInput;
225
226 /*
227 * This is a big hassle, needing QuickDraw and QuickTime on older
228 * systems, and god knows what on 10.6, so we immediately fail here,
229 * which causes SDL to make an RGB surface and manage the YUV overlay
230 * in software. Sorry. Use SDL 1.3 if you want YUV rendering in a pixel
231 * shader. :)
232 */
233 /*device->CreateYUVOverlay = QZ_CreateYUVOverlay;*/
234
235 device->free = QZ_DeleteDevice;
236
237 return device;
238}
239
240static void QZ_DeleteDevice (SDL_VideoDevice *device)
241{
242 _THIS = device;
243 QZ_ReleaseDisplayMode(this, save_mode);
244 QZ_ReleaseDisplayMode(this, mode);
245 SDL_free (device->hidden);
246 SDL_free (device);
247}
248
249static void QZ_GetModeInfo(_THIS, const void *_mode, Uint32 *w, Uint32 *h, Uint32 *bpp)
250{
251 *w = *h = *bpp = 0;
252 if (_mode == NULL) {
253 return;
254 }
255
256#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
257 if (use_new_mode_apis) {
258 CGDisplayModeRef vidmode = (CGDisplayModeRef) _mode;
259 CFStringRef fmt = CGDisplayModeCopyPixelEncoding(vidmode);
260
261 *w = (Uint32) CGDisplayModeGetWidth(vidmode);
262 *h = (Uint32) CGDisplayModeGetHeight(vidmode);
263
264 /* we only care about the 32-bit modes... */
265 if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels),
266 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
267 *bpp = 32;
268 }
269
270 CFRelease(fmt);
271 }
272#endif
273
274#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060)
275 if (!use_new_mode_apis) {
276 CFDictionaryRef vidmode = (CFDictionaryRef) _mode;
277 CFNumberGetValue (
278 CFDictionaryGetValue (vidmode, kCGDisplayBitsPerPixel),
279 kCFNumberSInt32Type, bpp);
280
281 CFNumberGetValue (
282 CFDictionaryGetValue (vidmode, kCGDisplayWidth),
283 kCFNumberSInt32Type, w);
284
285 CFNumberGetValue (
286 CFDictionaryGetValue (vidmode, kCGDisplayHeight),
287 kCFNumberSInt32Type, h);
288 }
289#endif
290
291 /* we only care about the 32-bit modes... */
292 if (*bpp != 32) {
293 *bpp = 0;
294 }
295}
296
297static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format)
298{
299 NSRect r = NSMakeRect(0.0, 0.0, 0.0, 0.0);
300 const char *env = NULL;
301
302 if ( Gestalt(gestaltSystemVersion, &system_version) != noErr )
303 system_version = 0;
304
305 use_new_mode_apis = NO;
306
307#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
308 use_new_mode_apis = IS_SNOW_LEOPARD_OR_LATER(this);
309#endif
310
311 /* Initialize the video settings; this data persists between mode switches */
312 display_id = kCGDirectMainDisplay;
313
314#if 0 /* The mouse event code needs to take this into account... */
315 env = getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
316 if ( env ) {
317 int monitor = SDL_atoi(env);
318 CGDirectDisplayID activeDspys [3];
319 CGDisplayCount dspyCnt;
320 CGGetActiveDisplayList (3, activeDspys, &dspyCnt);
321 if ( monitor >= 0 && monitor < dspyCnt ) {
322 display_id = activeDspys[monitor];
323 }
324 }
325#endif
326
327#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
328 if (use_new_mode_apis) {
329 save_mode = CGDisplayCopyDisplayMode(display_id);
330 }
331#endif
332
333#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060)
334 if (!use_new_mode_apis) {
335 save_mode = CGDisplayCurrentMode(display_id);
336 }
337#endif
338
339#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
340 if (!IS_LION_OR_LATER(this)) {
341 palette = CGPaletteCreateDefaultColorPalette();
342 }
343#endif
344
345 if (save_mode == NULL) {
346 SDL_SetError("Couldn't figure out current display mode.");
347 return -1;
348 }
349
350 /* Allow environment override of screensaver disable. */
351 env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
352 if ( env ) {
353 allow_screensaver = SDL_atoi(env);
354 } else {
355#ifdef SDL_VIDEO_DISABLE_SCREENSAVER
356 allow_screensaver = 0;
357#else
358 allow_screensaver = 1;
359#endif
360 }
361
362 /* Gather some information that is useful to know about the display */
363 QZ_GetModeInfo(this, save_mode, &device_width, &device_height, &device_bpp);
364 if (device_bpp == 0) {
365 QZ_ReleaseDisplayMode(this, save_mode);
366 save_mode = NULL;
367 SDL_SetError("Unsupported display mode");
368 return -1;
369 }
370
371 /* Determine the current screen size */
372 this->info.current_w = device_width;
373 this->info.current_h = device_height;
374
375 /* Determine the default screen depth */
376 video_format->BitsPerPixel = device_bpp;
377
378 /* Set misc globals */
379 current_grab_mode = SDL_GRAB_OFF;
380 cursor_should_be_visible = YES;
381 cursor_visible = YES;
382 current_mods = 0;
383 field_edit = [[SDLTranslatorResponder alloc] initWithFrame:r];
384
385 /* register for sleep notifications so wake from sleep generates SDL_VIDEOEXPOSE */
386 QZ_RegisterForSleepNotifications (this);
387
388 /* Fill in some window manager capabilities */
389 this->info.wm_available = 1;
390
391 return 0;
392}
393
394static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags)
395{
396 CFArrayRef mode_list = NULL; /* list of available fullscreen modes */
397 CFIndex num_modes;
398 CFIndex i;
399
400 int list_size = 0;
401
402 /* Any windowed mode is acceptable */
403 if ( (flags & SDL_FULLSCREEN) == 0 )
404 return (SDL_Rect**)-1;
405
406 /* Free memory from previous call, if any */
407 if ( client_mode_list != NULL ) {
408 int i;
409
410 for (i = 0; client_mode_list[i] != NULL; i++)
411 SDL_free (client_mode_list[i]);
412
413 SDL_free (client_mode_list);
414 client_mode_list = NULL;
415 }
416
417#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
418 if (use_new_mode_apis) {
419 mode_list = CGDisplayCopyAllDisplayModes(display_id, NULL);
420 }
421#endif
422
423#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060)
424 if (!use_new_mode_apis) {
425 mode_list = CGDisplayAvailableModes(display_id);
426 }
427#endif
428
429 num_modes = CFArrayGetCount (mode_list);
430
431 /* Build list of modes with the requested bpp */
432 for (i = 0; i < num_modes; i++) {
433 Uint32 width, height, bpp;
434 const void *onemode = CFArrayGetValueAtIndex(mode_list, i);
435
436 QZ_GetModeInfo(this, onemode, &width, &height, &bpp);
437
438 if (bpp && (bpp == format->BitsPerPixel)) {
439 int hasMode = SDL_FALSE;
440 int i;
441
442 /* Check if mode is already in the list */
443 for (i = 0; i < list_size; i++) {
444 if (client_mode_list[i]->w == width &&
445 client_mode_list[i]->h == height) {
446 hasMode = SDL_TRUE;
447 break;
448 }
449 }
450
451 /* Grow the list and add mode to the list */
452 if ( ! hasMode ) {
453 SDL_Rect *rect;
454
455 list_size++;
456
457 if (client_mode_list == NULL)
458 client_mode_list = (SDL_Rect**)
459 SDL_malloc (sizeof(*client_mode_list) * (list_size+1) );
460 else {
461 /* !!! FIXME: this leaks memory if SDL_realloc() fails! */
462 client_mode_list = (SDL_Rect**)
463 SDL_realloc (client_mode_list, sizeof(*client_mode_list) * (list_size+1));
464 }
465
466 rect = (SDL_Rect*) SDL_malloc (sizeof(**client_mode_list));
467
468 if (client_mode_list == NULL || rect == NULL) {
469 QZ_ReleaseDisplayModeList(this, mode_list);
470 SDL_OutOfMemory ();
471 return NULL;
472 }
473
474 rect->x = rect->y = 0;
475 rect->w = width;
476 rect->h = height;
477
478 client_mode_list[list_size-1] = rect;
479 client_mode_list[list_size] = NULL;
480 }
481 }
482 }
483
484 QZ_ReleaseDisplayModeList(this, mode_list);
485
486 /* Sort list largest to smallest (by area) */
487 {
488 int i, j;
489 for (i = 0; i < list_size; i++) {
490 for (j = 0; j < list_size-1; j++) {
491
492 int area1, area2;
493 area1 = client_mode_list[j]->w * client_mode_list[j]->h;
494 area2 = client_mode_list[j+1]->w * client_mode_list[j+1]->h;
495
496 if (area1 < area2) {
497 SDL_Rect *tmp = client_mode_list[j];
498 client_mode_list[j] = client_mode_list[j+1];
499 client_mode_list[j+1] = tmp;
500 }
501 }
502 }
503 }
504
505 return client_mode_list;
506}
507
508static SDL_bool QZ_WindowPosition(_THIS, int *x, int *y)
509{
510 const char *window = getenv("SDL_VIDEO_WINDOW_POS");
511 if ( window ) {
512 if ( sscanf(window, "%d,%d", x, y) == 2 ) {
513 return SDL_TRUE;
514 }
515 }
516 return SDL_FALSE;
517}
518
519static CGError QZ_SetDisplayMode(_THIS, const void *vidmode)
520{
521#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
522 if (use_new_mode_apis) {
523 return CGDisplaySetDisplayMode(display_id, (CGDisplayModeRef) vidmode, NULL);
524 }
525#endif
526
527#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060)
528 if (!use_new_mode_apis) {
529 return CGDisplaySwitchToMode(display_id, (CFDictionaryRef) vidmode);
530 }
531#endif
532
533 return kCGErrorFailure;
534}
535
536static inline CGError QZ_RestoreDisplayMode(_THIS)
537{
538 return QZ_SetDisplayMode(this, save_mode);
539}
540
541static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop, BOOL save_gl)
542{
543 /* Reset values that may change between switches */
544 this->info.blit_fill = 0;
545 this->FillHWRect = NULL;
546 this->UpdateRects = NULL;
547 this->LockHWSurface = NULL;
548 this->UnlockHWSurface = NULL;
549
550 if (cg_context) {
551 CGContextFlush (cg_context);
552 CGContextRelease (cg_context);
553 cg_context = nil;
554 }
555
556 /* Release fullscreen resources */
557 if ( mode_flags & SDL_FULLSCREEN ) {
558
559 NSRect screen_rect;
560
561 /* Release double buffer stuff */
562#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
563 if ( !IS_LION_OR_LATER(this) && (mode_flags & SDL_DOUBLEBUF) ) {
564 quit_thread = YES;
565 SDL_SemPost (sem1);
566 SDL_WaitThread (thread, NULL);
567 SDL_DestroySemaphore (sem1);
568 SDL_DestroySemaphore (sem2);
569 SDL_free (sw_buffers[0]);
570 }
571#endif
572
573 /* If we still have a valid window, close it. */
574 if ( qz_window ) {
575 NSCAssert([ qz_window delegate ] == nil, @"full screen window shouldn't have a delegate"); /* if that should ever change, we'd have to release it here */
576 [ qz_window close ]; /* includes release because [qz_window isReleasedWhenClosed] */
577 qz_window = nil;
578 window_view = nil;
579 }
580 /*
581 Release the OpenGL context
582 Do this first to avoid trash on the display before fade
583 */
584 if ( mode_flags & SDL_OPENGL ) {
585 if (!save_gl) {
586 QZ_TearDownOpenGL (this);
587 }
588
589 #ifdef __powerpc__ /* we only use this for pre-10.3 compatibility. */
590 CGLSetFullScreen (NULL);
591 #endif
592 }
593 if (to_desktop) {
594 /* !!! FIXME: keep an eye on this.
595 * This API is officially unavailable for 64-bit binaries.
596 * It happens to work, as of 10.7, but we're going to see if
597 * we can just simply do without it on newer OSes...
598 */
599 #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__)
600 if ( !IS_LION_OR_LATER(this) ) {
601 ShowMenuBar ();
602 }
603 #endif
604
605 /* Restore original screen resolution/bpp */
606 QZ_RestoreDisplayMode (this);
607 CGReleaseAllDisplays ();
608 /*
609 Reset the main screen's rectangle
610 See comment in QZ_SetVideoFullscreen for why we do this
611 */
612 screen_rect = NSMakeRect(0,0,device_width,device_height);
613 QZ_SetFrame(this, [ NSScreen mainScreen ], screen_rect);
614 }
615 }
616 /* Release window mode resources */
617 else {
618 id delegate = [ qz_window delegate ];
619 [ qz_window close ]; /* includes release because [qz_window isReleasedWhenClosed] */
620 if (delegate != nil) [ delegate release ];
621 qz_window = nil;
622 window_view = nil;
623
624 /* Release the OpenGL context */
625 if ( mode_flags & SDL_OPENGL ) {
626 if (!save_gl) {
627 QZ_TearDownOpenGL (this);
628 }
629 }
630 }
631
632 /* Signal successful teardown */
633 video_set = SDL_FALSE;
634}
635
636static const void *QZ_BestMode(_THIS, const int bpp, const int w, const int h)
637{
638 const void *best = NULL;
639
640 if (bpp == 0) {
641 return NULL;
642 }
643
644#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
645 if (use_new_mode_apis) {
646 /* apparently, we have to roll our own now. :/ */
647 CFArrayRef mode_list = CGDisplayCopyAllDisplayModes(display_id, NULL);
648 if (mode_list != NULL) {
649 const CFIndex num_modes = CFArrayGetCount(mode_list);
650 CFIndex i;
651 for (i = 0; i < num_modes; i++) {
652 const void *vidmode = CFArrayGetValueAtIndex(mode_list, i);
653 Uint32 thisw, thish, thisbpp;
654 QZ_GetModeInfo(this, vidmode, &thisw, &thish, &thisbpp);
655
656 /* We only care about exact matches, apparently. */
657 if ((thisbpp == bpp) && (thisw == w) && (thish == h)) {
658 best = vidmode;
659 break; /* got it! */
660 }
661 }
662 CGDisplayModeRetain((CGDisplayModeRef) best); /* NULL is ok */
663 CFRelease(mode_list);
664 }
665 }
666#endif
667
668#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060)
669 if (!use_new_mode_apis) {
670 boolean_t exact = 0;
671 best = CGDisplayBestModeForParameters(display_id, bpp, w, h, &exact);
672 if (!exact) {
673 best = NULL;
674 }
675 }
676#endif
677
678 return best;
679}
680
681static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width,
682 int height, int bpp, Uint32 flags,
683 const BOOL save_gl)
684{
685 const BOOL isLion = IS_LION_OR_LATER(this);
686 NSRect screen_rect;
687 CGError error;
688 NSRect contentRect;
689 CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
690
691 current->flags = SDL_FULLSCREEN;
692 current->w = width;
693 current->h = height;
694
695 contentRect = NSMakeRect (0, 0, width, height);
696
697 /* Fade to black to hide resolution-switching flicker (and garbage
698 that is displayed by a destroyed OpenGL context, if applicable) */
699 if ( CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess ) {
700 CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
701 }
702
703 /* Destroy any previous mode */
704 if (video_set == SDL_TRUE)
705 QZ_UnsetVideoMode (this, FALSE, save_gl);
706
707 /* Sorry, QuickDraw was ripped out. */
708 if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) {
709 SDL_SetError ("Embedded QuickDraw windows are no longer supported");
710 goto ERR_NO_MATCH;
711 }
712
713 QZ_ReleaseDisplayMode(this, mode); /* NULL is okay. */
714
715 /* See if requested mode exists */
716 mode = QZ_BestMode(this, bpp, width, height);
717
718 /* Require an exact match to the requested mode */
719 if ( mode == NULL ) {
720 SDL_SetError ("Failed to find display resolution: %dx%dx%d", width, height, bpp);
721 goto ERR_NO_MATCH;
722 }
723
724 /* Put up the blanking window (a window above all other windows) */
725 if (getenv ("SDL_SINGLEDISPLAY"))
726 error = CGDisplayCapture (display_id);
727 else
728 error = CGCaptureAllDisplays ();
729
730 if ( CGDisplayNoErr != error ) {
731 SDL_SetError ("Failed capturing display");
732 goto ERR_NO_CAPTURE;
733 }
734
735 /* Do the physical switch */
736 if ( CGDisplayNoErr != QZ_SetDisplayMode(this, mode) ) {
737 SDL_SetError ("Failed switching display resolution");
738 goto ERR_NO_SWITCH;
739 }
740
741#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
742 if ( !isLion ) {
743 current->pixels = (Uint32*) CGDisplayBaseAddress (display_id);
744 current->pitch = CGDisplayBytesPerRow (display_id);
745
746 current->flags |= SDL_HWSURFACE;
747 current->flags |= SDL_PREALLOC;
748 /* current->hwdata = (void *) CGDisplayGetDrawingContext (display_id); */
749
750 this->UpdateRects = QZ_DirectUpdate;
751 this->LockHWSurface = QZ_LockHWSurface;
752 this->UnlockHWSurface = QZ_UnlockHWSurface;
753
754 /* Setup double-buffer emulation */
755 if ( flags & SDL_DOUBLEBUF ) {
756
757 /*
758 Setup a software backing store for reasonable results when
759 double buffering is requested (since a single-buffered hardware
760 surface looks hideous).
761
762 The actual screen blit occurs in a separate thread to allow
763 other blitting while waiting on the VBL (and hence results in higher framerates).
764 */
765 this->LockHWSurface = NULL;
766 this->UnlockHWSurface = NULL;
767 this->UpdateRects = NULL;
768
769 current->flags |= (SDL_HWSURFACE|SDL_DOUBLEBUF);
770 this->UpdateRects = QZ_DoubleBufferUpdate;
771 this->LockHWSurface = QZ_LockDoubleBuffer;
772 this->UnlockHWSurface = QZ_UnlockDoubleBuffer;
773 this->FlipHWSurface = QZ_FlipDoubleBuffer;
774
775 current->pixels = SDL_malloc (current->pitch * current->h * 2);
776 if (current->pixels == NULL) {
777 SDL_OutOfMemory ();
778 goto ERR_DOUBLEBUF;
779 }
780
781 sw_buffers[0] = current->pixels;
782 sw_buffers[1] = (Uint8*)current->pixels + current->pitch * current->h;
783
784 quit_thread = NO;
785 sem1 = SDL_CreateSemaphore (0);
786 sem2 = SDL_CreateSemaphore (1);
787 thread = SDL_CreateThread ((int (*)(void *))QZ_ThreadFlip, this);
788 }
789
790 if ( CGDisplayCanSetPalette (display_id) )
791 current->flags |= SDL_HWPALETTE;
792 }
793#endif
794
795 /* Check if we should recreate the window */
796 if (qz_window == nil) {
797 /* Manually create a window, avoids having a nib file resource */
798 qz_window = [ [ SDL_QuartzWindow alloc ]
799 initWithContentRect:contentRect
800 styleMask:(isLion ? NSBorderlessWindowMask : 0)
801 backing:NSBackingStoreBuffered
802 defer:NO ];
803
804 if (qz_window != nil) {
805 [ qz_window setAcceptsMouseMovedEvents:YES ];
806 [ qz_window setViewsNeedDisplay:NO ];
807 if (isLion) {
808 [ qz_window setContentView: [ [ [ SDL_QuartzView alloc ] init ] autorelease ] ];
809 }
810 }
811 }
812 /* We already have a window, just change its size */
813 else {
814 [ qz_window setContentSize:contentRect.size ];
815 current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags;
816 [ window_view setFrameSize:contentRect.size ];
817 }
818
819 /* Setup OpenGL for a fullscreen context */
820 if (flags & SDL_OPENGL) {
821
822 if ( ! save_gl ) {
823 if ( ! QZ_SetupOpenGL (this, bpp, flags) ) {
824 goto ERR_NO_GL;
825 }
826 }
827
828 /* Initialize the NSView and add it to our window. The presence of a valid window and
829 view allow the cursor to be changed whilst in fullscreen.*/
830 window_view = [ [ NSView alloc ] initWithFrame:contentRect ];
831
832 if ( isLion ) {
833 [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
834 }
835
836 [ [ qz_window contentView ] addSubview:window_view ];
837
838 /* Apparently Lion checks some version flag set by the linker
839 and changes API behavior. Annoying. */
840 if ( isLion ) {
841 [ qz_window setLevel:CGShieldingWindowLevel() ];
842 [ gl_context setView: window_view ];
843 //[ gl_context setFullScreen ];
844 [ gl_context update ];
845 }
846
847#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
848 if ( !isLion ) {
849 CGLError err;
850 CGLContextObj ctx;
851
852 [ qz_window setLevel:NSNormalWindowLevel ];
853 ctx = QZ_GetCGLContextObj (gl_context);
854 err = CGLSetFullScreen (ctx);
855
856 if (err) {
857 SDL_SetError ("Error setting OpenGL fullscreen: %s", CGLErrorString(err));
858 goto ERR_NO_GL;
859 }
860 }
861#endif
862
863 [ window_view release ];
864 [ gl_context makeCurrentContext];
865
866 glClear (GL_COLOR_BUFFER_BIT);
867
868 [ gl_context flushBuffer ];
869
870 current->flags |= SDL_OPENGL;
871 } else if (isLion) { /* For 2D, we build a CGBitmapContext */
872 CGColorSpaceRef cgColorspace;
873
874 /* Only recreate the view if it doesn't already exist */
875 if (window_view == nil) {
876 window_view = [ [ NSView alloc ] initWithFrame:contentRect ];
877 [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
878 [ [ qz_window contentView ] addSubview:window_view ];
879 [ window_view release ];
880 }
881
882 cgColorspace = CGColorSpaceCreateDeviceRGB();
883 current->pitch = 4 * current->w;
884 current->pixels = SDL_malloc (current->h * current->pitch);
885
886 cg_context = CGBitmapContextCreate (current->pixels, current->w, current->h,
887 8, current->pitch, cgColorspace,
888 kCGImageAlphaNoneSkipFirst);
889 CGColorSpaceRelease (cgColorspace);
890
891 current->flags |= SDL_SWSURFACE;
892 current->flags |= SDL_ASYNCBLIT;
893 current->hwdata = (void *) cg_context;
894
895 /* Force this window to draw above _everything_. */
896 [ qz_window setLevel:CGShieldingWindowLevel() ];
897
898 this->UpdateRects = QZ_UpdateRects;
899 this->LockHWSurface = QZ_LockHWSurface;
900 this->UnlockHWSurface = QZ_UnlockHWSurface;
901 }
902
903 if (isLion) {
904 [ qz_window setHasShadow:NO];
905 [ qz_window setOpaque:YES];
906 [ qz_window makeKeyAndOrderFront:nil ];
907 }
908
909 /* !!! FIXME: keep an eye on this.
910 * This API is officially unavailable for 64-bit binaries.
911 * It happens to work, as of 10.7, but we're going to see if
912 * we can just simply do without it on newer OSes...
913 */
914 #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__)
915 if ( !isLion ) {
916 /* If we don't hide menu bar, it will get events and interrupt the program */
917 HideMenuBar ();
918 }
919 #endif
920
921 /* Fade in again (asynchronously) */
922 if ( fade_token != kCGDisplayFadeReservationInvalidToken ) {
923 CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
924 CGReleaseDisplayFadeReservation(fade_token);
925 }
926
927 /*
928 There is a bug in Cocoa where NSScreen doesn't synchronize
929 with CGDirectDisplay, so the main screen's frame is wrong.
930 As a result, coordinate translation produces incorrect results.
931 We can hack around this bug by setting the screen rect
932 ourselves. This hack should be removed if/when the bug is fixed.
933 */
934 screen_rect = NSMakeRect(0,0,width,height);
935 QZ_SetFrame(this, [ NSScreen mainScreen ], screen_rect);
936
937 /* Save the flags to ensure correct tear-down */
938 mode_flags = current->flags;
939
940 /* Set app state, hide cursor if necessary, ... */
941 QZ_DoActivate(this);
942
943 return current;
944
945 /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
946ERR_NO_GL: goto ERR_DOUBLEBUF; /* this goto is to stop a compiler warning on newer SDKs. */
947ERR_DOUBLEBUF: QZ_RestoreDisplayMode(this);
948ERR_NO_SWITCH: CGReleaseAllDisplays ();
949ERR_NO_CAPTURE:
950ERR_NO_MATCH: if ( fade_token != kCGDisplayFadeReservationInvalidToken ) {
951 CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
952 CGReleaseDisplayFadeReservation (fade_token);
953 }
954 return NULL;
955}
956
957static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
958 int height, int *bpp, Uint32 flags,
959 const BOOL save_gl)
960{
961 unsigned int style;
962 NSRect contentRect;
963 int center_window = 1;
964 int origin_x, origin_y;
965 CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
966
967 current->flags = 0;
968 current->w = width;
969 current->h = height;
970
971 contentRect = NSMakeRect (0, 0, width, height);
972
973 /*
974 Check if we should completely destroy the previous mode
975 - If it is fullscreen
976 - If it has different noframe or resizable attribute
977 - If it is OpenGL (since gl attributes could be different)
978 - If new mode is OpenGL, but previous mode wasn't
979 */
980 if (video_set == SDL_TRUE) {
981 if (mode_flags & SDL_FULLSCREEN) {
982 /* Fade to black to hide resolution-switching flicker (and garbage
983 that is displayed by a destroyed OpenGL context, if applicable) */
984 if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) {
985 CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
986 }
987 QZ_UnsetVideoMode (this, TRUE, save_gl);
988 }
989 else if ( ((mode_flags ^ flags) & (SDL_NOFRAME|SDL_RESIZABLE)) ||
990 (mode_flags & SDL_OPENGL) ||
991 (flags & SDL_OPENGL) ) {
992 QZ_UnsetVideoMode (this, TRUE, save_gl);
993 }
994 }
995
996 /* Sorry, QuickDraw was ripped out. */
997 if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) {
998 SDL_SetError ("Embedded QuickDraw windows are no longer supported");
999 if (fade_token != kCGDisplayFadeReservationInvalidToken) {
1000 CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
1001 CGReleaseDisplayFadeReservation (fade_token);
1002 }
1003 return NULL;
1004 }
1005
1006 /* Check if we should recreate the window */
1007 if (qz_window == nil) {
1008
1009 /* Set the window style based on input flags */
1010 if ( flags & SDL_NOFRAME ) {
1011 style = NSBorderlessWindowMask;
1012 current->flags |= SDL_NOFRAME;
1013 } else {
1014 style = NSTitledWindowMask;
1015 style |= (NSMiniaturizableWindowMask | NSClosableWindowMask);
1016 if ( flags & SDL_RESIZABLE ) {
1017 style |= NSResizableWindowMask;
1018 current->flags |= SDL_RESIZABLE;
1019 }
1020 }
1021
1022 /* Manually create a window, avoids having a nib file resource */
1023 qz_window = [ [ SDL_QuartzWindow alloc ]
1024 initWithContentRect:contentRect
1025 styleMask:style
1026 backing:NSBackingStoreBuffered
1027 defer:NO ];
1028
1029 if (qz_window == nil) {
1030 SDL_SetError ("Could not create the Cocoa window");
1031 if (fade_token != kCGDisplayFadeReservationInvalidToken) {
1032 CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
1033 CGReleaseDisplayFadeReservation (fade_token);
1034 }
1035 return NULL;
1036 }
1037
1038 /*[ qz_window setReleasedWhenClosed:YES ];*/ /* no need to set this as it's the default for NSWindows */
1039 QZ_SetCaption(this, this->wm_title, this->wm_icon);
1040 [ qz_window setAcceptsMouseMovedEvents:YES ];
1041 [ qz_window setViewsNeedDisplay:NO ];
1042
1043 if ( QZ_WindowPosition(this, &origin_x, &origin_y) ) {
1044 /* have to flip the Y value (NSPoint is lower left corner origin) */
1045 [ qz_window setFrameTopLeftPoint:NSMakePoint((float) origin_x, (float) (this->info.current_h - origin_y))];
1046 center_window = 0;
1047 } else if ( center_window ) {
1048 [ qz_window center ];
1049 }
1050
1051 [ qz_window setDelegate:
1052 [ [ SDL_QuartzWindowDelegate alloc ] init ] ];
1053 [ qz_window setContentView: [ [ [ SDL_QuartzView alloc ] init ] autorelease ] ];
1054 }
1055 /* We already have a window, just change its size */
1056 else {
1057 [ qz_window setContentSize:contentRect.size ];
1058 current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags;
1059 [ window_view setFrameSize:contentRect.size ];
1060 }
1061
1062 /* For OpenGL, we bind the context to a subview */
1063 if ( flags & SDL_OPENGL ) {
1064
1065 if ( ! save_gl ) {
1066 if ( ! QZ_SetupOpenGL (this, *bpp, flags) ) {
1067 if (fade_token != kCGDisplayFadeReservationInvalidToken) {
1068 CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
1069 CGReleaseDisplayFadeReservation (fade_token);
1070 }
1071 return NULL;
1072 }
1073 }
1074
1075 window_view = [ [ NSView alloc ] initWithFrame:contentRect ];
1076 [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
1077 [ [ qz_window contentView ] addSubview:window_view ];
1078 [ gl_context setView: window_view ];
1079 [ window_view release ];
1080 [ gl_context makeCurrentContext];
1081 [ qz_window makeKeyAndOrderFront:nil ];
1082 current->flags |= SDL_OPENGL;
1083 }
1084 /* For 2D, we build a CGBitmapContext */
1085 else {
1086 CGColorSpaceRef cgColorspace;
1087
1088 /* Only recreate the view if it doesn't already exist */
1089 if (window_view == nil) {
1090
1091 window_view = [ [ NSView alloc ] initWithFrame:contentRect ];
1092 [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
1093 [ [ qz_window contentView ] addSubview:window_view ];
1094 [ window_view release ];
1095 [ qz_window makeKeyAndOrderFront:nil ];
1096 }
1097
1098 cgColorspace = CGColorSpaceCreateDeviceRGB();
1099 current->pitch = 4 * current->w;
1100 current->pixels = SDL_malloc (current->h * current->pitch);
1101
1102 cg_context = CGBitmapContextCreate (current->pixels, current->w, current->h,
1103 8, current->pitch, cgColorspace,
1104 kCGImageAlphaNoneSkipFirst);
1105 CGColorSpaceRelease (cgColorspace);
1106
1107 current->flags |= SDL_SWSURFACE;
1108 current->flags |= SDL_ASYNCBLIT;
1109 current->hwdata = (void *) cg_context;
1110
1111 this->UpdateRects = QZ_UpdateRects;
1112 this->LockHWSurface = QZ_LockHWSurface;
1113 this->UnlockHWSurface = QZ_UnlockHWSurface;
1114 }
1115
1116 /* Save flags to ensure correct teardown */
1117 mode_flags = current->flags;
1118
1119 /* Fade in again (asynchronously) if we came from a fullscreen mode and faded to black */
1120 if (fade_token != kCGDisplayFadeReservationInvalidToken) {
1121 CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
1122 CGReleaseDisplayFadeReservation (fade_token);
1123 }
1124
1125 return current;
1126}
1127
1128
1129static SDL_Surface* QZ_SetVideoModeInternal (_THIS, SDL_Surface *current,
1130 int width, int height, int bpp,
1131 Uint32 flags, BOOL save_gl)
1132{
1133 const BOOL isLion = IS_LION_OR_LATER(this);
1134
1135 current->flags = 0;
1136 current->pixels = NULL;
1137
1138 /* Setup full screen video */
1139 if ( flags & SDL_FULLSCREEN ) {
1140 if ( isLion ) {
1141 bpp = 32;
1142 }
1143 current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags, save_gl );
1144 if (current == NULL)
1145 return NULL;
1146 }
1147 /* Setup windowed video */
1148 else {
1149 /* Force bpp to 32 */
1150 bpp = 32;
1151 current = QZ_SetVideoWindowed (this, current, width, height, &bpp, flags, save_gl );
1152 if (current == NULL)
1153 return NULL;
1154 }
1155
1156 if (qz_window != nil) {
1157 nsgfx_context = [NSGraphicsContext graphicsContextWithWindow:qz_window];
1158 [NSGraphicsContext setCurrentContext:nsgfx_context];
1159 }
1160
1161 /* Setup the new pixel format */
1162 {
1163 int amask = 0,
1164 rmask = 0,
1165 gmask = 0,
1166 bmask = 0;
1167
1168 switch (bpp) {
1169 case 16: /* (1)-5-5-5 RGB */
1170 amask = 0;
1171 rmask = 0x7C00;
1172 gmask = 0x03E0;
1173 bmask = 0x001F;
1174 break;
1175 case 24:
1176 SDL_SetError ("24bpp is not available");
1177 return NULL;
1178 case 32: /* (8)-8-8-8 ARGB */
1179 amask = 0x00000000;
1180 if ( (!isLion) && (flags & SDL_FULLSCREEN) ) {
1181 rmask = 0x00FF0000;
1182 gmask = 0x0000FF00;
1183 bmask = 0x000000FF;
1184 } else {
1185#if SDL_BYTEORDER == SDL_LIL_ENDIAN
1186 rmask = 0x0000FF00;
1187 gmask = 0x00FF0000;
1188 bmask = 0xFF000000;
1189#else
1190 rmask = 0x00FF0000;
1191 gmask = 0x0000FF00;
1192 bmask = 0x000000FF;
1193#endif
1194 break;
1195 }
1196 }
1197
1198 if ( ! SDL_ReallocFormat (current, bpp,
1199 rmask, gmask, bmask, amask ) ) {
1200 SDL_SetError ("Couldn't reallocate pixel format");
1201 return NULL;
1202 }
1203 }
1204
1205 /* Signal successful completion (used internally) */
1206 video_set = SDL_TRUE;
1207
1208 return current;
1209}
1210
1211static SDL_Surface* QZ_SetVideoMode(_THIS, SDL_Surface *current,
1212 int width, int height, int bpp,
1213 Uint32 flags)
1214{
1215 /* Don't throw away the GL context if we can just resize the current one. */
1216#if 0 /* !!! FIXME: half-finished side project. Reenable this if you ever debug the corner cases. */
1217 const BOOL save_gl = ( (video_set == SDL_TRUE) && ((flags & SDL_OPENGL) == (current->flags & SDL_OPENGL)) && (bpp == current->format->BitsPerPixel) );
1218#else
1219 const BOOL save_gl = NO;
1220#endif
1221
1222 NSOpenGLContext *glctx = gl_context;
1223 SDL_Surface* retval = NULL;
1224
1225 if (save_gl) {
1226 [glctx retain]; /* just so we don't lose this when killing old views, etc */
1227 }
1228
1229 retval = QZ_SetVideoModeInternal (this, current, width, height, bpp, flags, save_gl);
1230
1231 if (save_gl) {
1232 [glctx release]; /* something else should own this now, or we legitimately release it. */
1233 }
1234
1235 return retval;
1236}
1237
1238
1239static int QZ_ToggleFullScreen (_THIS, int on)
1240{
1241 return 0;
1242}
1243
1244static int QZ_SetColors (_THIS, int first_color, int num_colors,
1245 SDL_Color *colors)
1246{
1247#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
1248 /* we shouldn't have an 8-bit mode on Lion! */
1249 if (!IS_LION_OR_LATER(this)) {
1250 CGTableCount index;
1251 CGDeviceColor color;
1252
1253 for (index = first_color; index < first_color+num_colors; index++) {
1254
1255 /* Clamp colors between 0.0 and 1.0 */
1256 color.red = colors->r / 255.0;
1257 color.blue = colors->b / 255.0;
1258 color.green = colors->g / 255.0;
1259
1260 colors++;
1261
1262 CGPaletteSetColorAtIndex (palette, color, index);
1263 }
1264
1265 return ( CGDisplayNoErr == CGDisplaySetPalette (display_id, palette) );
1266 }
1267#endif
1268
1269 return 0;
1270}
1271
1272#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
1273static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface)
1274{
1275 return 1;
1276}
1277
1278static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface)
1279{
1280}
1281
1282/* The VBL delay is based on code by Ian R Ollmann's RezLib <iano@cco.caltech.edu> */
1283static AbsoluteTime QZ_SecondsToAbsolute ( double seconds )
1284{
1285 union
1286 {
1287 UInt64 i;
1288 Nanoseconds ns;
1289 } temp;
1290
1291 temp.i = seconds * 1000000000.0;
1292
1293 return NanosecondsToAbsolute ( temp.ns );
1294}
1295
1296static int QZ_ThreadFlip (_THIS)
1297{
1298 Uint8 *src, *dst;
1299 int skip, len, h;
1300
1301 /*
1302 Give this thread the highest scheduling priority possible,
1303 in the hopes that it will immediately run after the VBL delay
1304 */
1305 {
1306 pthread_t current_thread;
1307 int policy;
1308 struct sched_param param;
1309
1310 current_thread = pthread_self ();
1311 pthread_getschedparam (current_thread, &policy, &param);
1312 policy = SCHED_RR;
1313 param.sched_priority = sched_get_priority_max (policy);
1314 pthread_setschedparam (current_thread, policy, &param);
1315 }
1316
1317 while (1) {
1318
1319 SDL_SemWait (sem1);
1320 if (quit_thread)
1321 return 0;
1322
1323 /*
1324 * We have to add SDL_VideoSurface->offset here, since we might be a
1325 * smaller surface in the center of the framebuffer (you asked for
1326 * a fullscreen resolution smaller than the hardware could supply
1327 * so SDL is centering it in a bigger resolution)...
1328 */
1329 dst = ((Uint8 *)((size_t)CGDisplayBaseAddress (display_id))) + SDL_VideoSurface->offset;
1330 src = current_buffer + SDL_VideoSurface->offset;
1331 len = SDL_VideoSurface->w * SDL_VideoSurface->format->BytesPerPixel;
1332 h = SDL_VideoSurface->h;
1333 skip = SDL_VideoSurface->pitch;
1334
1335 /* Wait for the VBL to occur (estimated since we don't have a hardware interrupt) */
1336 {
1337
1338 /* The VBL delay is based on Ian Ollmann's RezLib <iano@cco.caltech.edu> */
1339 double refreshRate;
1340 double linesPerSecond;
1341 double target;
1342 double position;
1343 double adjustment;
1344 AbsoluteTime nextTime;
1345 CFNumberRef refreshRateCFNumber;
1346
1347 refreshRateCFNumber = CFDictionaryGetValue (mode, kCGDisplayRefreshRate);
1348 if ( NULL == refreshRateCFNumber ) {
1349 SDL_SetError ("Mode has no refresh rate");
1350 goto ERROR;
1351 }
1352
1353 if ( 0 == CFNumberGetValue (refreshRateCFNumber, kCFNumberDoubleType, &refreshRate) ) {
1354 SDL_SetError ("Error getting refresh rate");
1355 goto ERROR;
1356 }
1357
1358 if ( 0 == refreshRate ) {
1359
1360 SDL_SetError ("Display has no refresh rate, using 60hz");
1361
1362 /* ok, for LCD's we'll emulate a 60hz refresh, which may or may not look right */
1363 refreshRate = 60.0;
1364 }
1365
1366 linesPerSecond = refreshRate * h;
1367 target = h;
1368
1369 /* Figure out the first delay so we start off about right */
1370 position = CGDisplayBeamPosition (display_id);
1371 if (position > target)
1372 position = 0;
1373
1374 adjustment = (target - position) / linesPerSecond;
1375
1376 nextTime = AddAbsoluteToAbsolute (UpTime (), QZ_SecondsToAbsolute (adjustment));
1377
1378 MPDelayUntil (&nextTime);
1379 }
1380
1381
1382 /* On error, skip VBL delay */
1383 ERROR:
1384
1385 /* TODO: use CGContextDrawImage here too! Create two CGContextRefs the same way we
1386 create two buffers, replace current_buffer with current_context and set it
1387 appropriately in QZ_FlipDoubleBuffer. */
1388 while ( h-- ) {
1389
1390 SDL_memcpy (dst, src, len);
1391 src += skip;
1392 dst += skip;
1393 }
1394
1395 /* signal flip completion */
1396 SDL_SemPost (sem2);
1397 }
1398
1399 return 0;
1400}
1401
1402static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface)
1403{
1404 /* wait for previous flip to complete */
1405 SDL_SemWait (sem2);
1406
1407 current_buffer = surface->pixels;
1408
1409 if (surface->pixels == sw_buffers[0])
1410 surface->pixels = sw_buffers[1];
1411 else
1412 surface->pixels = sw_buffers[0];
1413
1414 /* signal worker thread to do the flip */
1415 SDL_SemPost (sem1);
1416
1417 return 0;
1418}
1419
1420static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects)
1421{
1422 /* perform a flip if someone calls updaterects on a doublebuferred surface */
1423 this->FlipHWSurface (this, SDL_VideoSurface);
1424}
1425
1426static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects)
1427{
1428#pragma unused(this,num_rects,rects)
1429}
1430#endif
1431
1432/* Resize icon, BMP format */
1433static const unsigned char QZ_ResizeIcon[] = {
1434 0x42,0x4d,0x31,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00,
1435 0x00,0x00,0x0d,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00,
1436 0x00,0x00,0xfb,0x01,0x00,0x00,0x13,0x0b,0x00,0x00,0x13,0x0b,0x00,0x00,0x00,0x00,
1437 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1438 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1439 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff,
1440 0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,
1441 0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,
1442 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xda,0xda,0xda,0x87,
1443 0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,
1444 0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff,
1445 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd5,0xd5,0xd5,0x87,0x87,0x87,0xe8,0xe8,0xe8,
1446 0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,
1447 0xda,0xda,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1448 0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,
1449 0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff,
1450 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7,
1451 0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,
1452 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1453 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8,
1454 0xe8,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff,
1455 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1456 0xff,0xff,0xff,0xd9,0xd9,0xd9,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xdc,
1457 0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1458 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb,
1459 0xdb,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff,
1460 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1461 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb,0xdb,0x87,0x87,0x87,0xe8,
1462 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1463 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1464 0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff,
1465 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1466 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdc,
1467 0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1468 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1469 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b
1470};
1471
1472static void QZ_DrawResizeIcon (_THIS)
1473{
1474 /* Check if we should draw the resize icon */
1475 if (SDL_VideoSurface->flags & SDL_RESIZABLE) {
1476
1477 SDL_Rect icon_rect;
1478
1479 /* Create the icon image */
1480 if (resize_icon == NULL) {
1481
1482 SDL_RWops *rw;
1483 SDL_Surface *tmp;
1484
1485 rw = SDL_RWFromConstMem (QZ_ResizeIcon, sizeof(QZ_ResizeIcon));
1486 tmp = SDL_LoadBMP_RW (rw, SDL_TRUE);
1487
1488 resize_icon = SDL_ConvertSurface (tmp, SDL_VideoSurface->format, SDL_SRCCOLORKEY);
1489 SDL_SetColorKey (resize_icon, SDL_SRCCOLORKEY, 0xFFFFFF);
1490
1491 SDL_FreeSurface (tmp);
1492 }
1493
1494 icon_rect.x = SDL_VideoSurface->w - 13;
1495 icon_rect.y = SDL_VideoSurface->h - 13;
1496 icon_rect.w = 13;
1497 icon_rect.h = 13;
1498
1499 SDL_BlitSurface (resize_icon, NULL, SDL_VideoSurface, &icon_rect);
1500 }
1501}
1502
1503static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects)
1504{
1505 if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) {
1506 QZ_GL_SwapBuffers (this);
1507 }
1508 else if ( [ qz_window isMiniaturized ] ) {
1509
1510 /* Do nothing if miniaturized */
1511 }
1512
1513 else {
1514 NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
1515 if (ctx != nsgfx_context) { /* uhoh, you might be rendering from another thread... */
1516 [NSGraphicsContext setCurrentContext:nsgfx_context];
1517 ctx = nsgfx_context;
1518 }
1519 CGContextRef cgc = (CGContextRef) [ctx graphicsPort];
1520 QZ_DrawResizeIcon (this);
1521 CGContextFlush (cg_context);
1522 CGImageRef image = CGBitmapContextCreateImage (cg_context);
1523 CGRect rectangle = CGRectMake (0,0,[window_view frame].size.width,[window_view frame].size.height);
1524
1525 CGContextDrawImage (cgc, rectangle, image);
1526 CGImageRelease(image);
1527 CGContextFlush (cgc);
1528 }
1529}
1530
1531static void QZ_VideoQuit (_THIS)
1532{
1533 CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
1534
1535 /* Restore gamma settings */
1536 CGDisplayRestoreColorSyncSettings ();
1537
1538 /* Ensure the cursor will be visible and working when we quit */
1539 CGDisplayShowCursor (display_id);
1540 CGAssociateMouseAndMouseCursorPosition (1);
1541
1542 if (mode_flags & SDL_FULLSCREEN) {
1543 /* Fade to black to hide resolution-switching flicker (and garbage
1544 that is displayed by a destroyed OpenGL context, if applicable) */
1545 if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) {
1546 CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
1547 }
1548 QZ_UnsetVideoMode (this, TRUE, FALSE);
1549 if (fade_token != kCGDisplayFadeReservationInvalidToken) {
1550 CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
1551 CGReleaseDisplayFadeReservation (fade_token);
1552 }
1553 }
1554 else
1555 QZ_UnsetVideoMode (this, TRUE, FALSE);
1556
1557#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
1558 if (!IS_LION_OR_LATER(this)) {
1559 CGPaletteRelease(palette);
1560 }
1561#endif
1562
1563 if (opengl_library) {
1564 SDL_UnloadObject(opengl_library);
1565 opengl_library = NULL;
1566 }
1567 this->gl_config.driver_loaded = 0;
1568
1569 if (field_edit) {
1570 [field_edit release];
1571 field_edit = NULL;
1572 }
1573}
1574
1575static int QZ_LockHWSurface(_THIS, SDL_Surface *surface)
1576{
1577 return 1;
1578}
1579
1580static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface)
1581{
1582}
1583
1584static int QZ_AllocHWSurface(_THIS, SDL_Surface *surface)
1585{
1586 return(-1); /* unallowed (no HWSURFACE support here). */
1587}
1588
1589static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface)
1590{
1591}
1592
1593/* Gamma functions */
1594int QZ_SetGamma (_THIS, float red, float green, float blue)
1595{
1596 const CGGammaValue min = 0.0, max = 1.0;
1597
1598 if (red == 0.0)
1599 red = FLT_MAX;
1600 else
1601 red = 1.0 / red;
1602
1603 if (green == 0.0)
1604 green = FLT_MAX;
1605 else
1606 green = 1.0 / green;
1607
1608 if (blue == 0.0)
1609 blue = FLT_MAX;
1610 else
1611 blue = 1.0 / blue;
1612
1613 if ( CGDisplayNoErr == CGSetDisplayTransferByFormula
1614 (display_id, min, max, red, min, max, green, min, max, blue) ) {
1615
1616 return 0;
1617 }
1618 else {
1619
1620 return -1;
1621 }
1622}
1623
1624int QZ_GetGamma (_THIS, float *red, float *green, float *blue)
1625{
1626 CGGammaValue dummy;
1627 if ( CGDisplayNoErr == CGGetDisplayTransferByFormula
1628 (display_id, &dummy, &dummy, red,
1629 &dummy, &dummy, green, &dummy, &dummy, blue) )
1630
1631 return 0;
1632 else
1633 return -1;
1634}
1635
1636int QZ_SetGammaRamp (_THIS, Uint16 *ramp)
1637{
1638 const uint32_t tableSize = 255;
1639 CGGammaValue redTable[tableSize];
1640 CGGammaValue greenTable[tableSize];
1641 CGGammaValue blueTable[tableSize];
1642
1643 int i;
1644
1645 /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */
1646 for (i = 0; i < 256; i++)
1647 redTable[i % 256] = ramp[i] / 65535.0;
1648
1649 for (i=256; i < 512; i++)
1650 greenTable[i % 256] = ramp[i] / 65535.0;
1651
1652 for (i=512; i < 768; i++)
1653 blueTable[i % 256] = ramp[i] / 65535.0;
1654
1655 if ( CGDisplayNoErr == CGSetDisplayTransferByTable
1656 (display_id, tableSize, redTable, greenTable, blueTable) )
1657 return 0;
1658 else
1659 return -1;
1660}
1661
1662int QZ_GetGammaRamp (_THIS, Uint16 *ramp)
1663{
1664 const uint32_t tableSize = 255;
1665 CGGammaValue redTable[tableSize];
1666 CGGammaValue greenTable[tableSize];
1667 CGGammaValue blueTable[tableSize];
1668 uint32_t actual;
1669 int i;
1670
1671 if ( CGDisplayNoErr != CGGetDisplayTransferByTable
1672 (display_id, tableSize, redTable, greenTable, blueTable, &actual) ||
1673 actual != tableSize)
1674
1675 return -1;
1676
1677 /* Pack tables into one array, with values from 0 to 65535 */
1678 for (i = 0; i < 256; i++)
1679 ramp[i] = redTable[i % 256] * 65535.0;
1680
1681 for (i=256; i < 512; i++)
1682 ramp[i] = greenTable[i % 256] * 65535.0;
1683
1684 for (i=512; i < 768; i++)
1685 ramp[i] = blueTable[i % 256] * 65535.0;
1686
1687 return 0;
1688}
1689
diff --git a/apps/plugins/sdl/src/video/quartz/SDL_QuartzWM.h b/apps/plugins/sdl/src/video/quartz/SDL_QuartzWM.h
deleted file mode 100644
index 0b0767e8e2..0000000000
--- a/apps/plugins/sdl/src/video/quartz/SDL_QuartzWM.h
+++ /dev/null
@@ -1,27 +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
23struct WMcursor {
24 NSCursor *nscursor;
25};
26
27void QZ_UpdateCursor(_THIS);
diff --git a/apps/plugins/sdl/src/video/quartz/SDL_QuartzWM.m b/apps/plugins/sdl/src/video/quartz/SDL_QuartzWM.m
deleted file mode 100644
index d526424d4c..0000000000
--- a/apps/plugins/sdl/src/video/quartz/SDL_QuartzWM.m
+++ /dev/null
@@ -1,444 +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
28void QZ_FreeWMCursor (_THIS, WMcursor *cursor) {
29
30 if ( cursor != NULL ) {
31 [ cursor->nscursor release ];
32 free (cursor);
33 }
34}
35
36WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask,
37 int w, int h, int hot_x, int hot_y) {
38 WMcursor *cursor;
39 NSBitmapImageRep *imgrep;
40 NSImage *img;
41 unsigned char *planes[5];
42 int i;
43 NSAutoreleasePool *pool;
44
45 pool = [ [ NSAutoreleasePool alloc ] init ];
46
47 /* Allocate the cursor memory */
48 cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor));
49 if (cursor == NULL) goto outOfMemory;
50
51 /* create the image representation and get the pointers to its storage */
52 imgrep = [ [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes: NULL pixelsWide: w pixelsHigh: h bitsPerSample: 1 samplesPerPixel: 2 hasAlpha: YES isPlanar: YES colorSpaceName: NSDeviceWhiteColorSpace bytesPerRow: (w+7)/8 bitsPerPixel: 0 ] autorelease ];
53 if (imgrep == nil) goto outOfMemory;
54 [ imgrep getBitmapDataPlanes: planes ];
55
56 /* copy data and mask, extending the mask to all black pixels because the inversion effect doesn't work with Cocoa's alpha-blended cursors */
57 for (i = 0; i < (w+7)/8*h; i++) {
58 planes[0][i] = data[i] ^ 0xFF;
59 planes[1][i] = mask[i] | data[i];
60 }
61
62 /* create image and cursor */
63 img = [ [ [ NSImage alloc ] initWithSize: NSMakeSize(w, h) ] autorelease ];
64 if (img == nil) goto outOfMemory;
65 [ img addRepresentation: imgrep ];
66 if (system_version < 0x1030) { /* on 10.2, cursors must be 16*16 */
67 if (w > 16 || h > 16) { /* too big: scale it down */
68 [ img setScalesWhenResized: YES ];
69 hot_x = hot_x*16/w;
70 hot_y = hot_y*16/h;
71 }
72 else { /* too small (or just right): extend it (from the bottom left corner, so hot_y must be adjusted) */
73 hot_y += 16 - h;
74 }
75 [ img setSize: NSMakeSize(16, 16) ];
76 }
77 cursor->nscursor = [ [ NSCursor alloc ] initWithImage: img hotSpot: NSMakePoint(hot_x, hot_y) ];
78 if (cursor->nscursor == nil) goto outOfMemory;
79
80 [ pool release ];
81 return(cursor);
82
83outOfMemory:
84 [ pool release ];
85 if (cursor != NULL) SDL_free(cursor);
86 SDL_OutOfMemory();
87 return(NULL);
88}
89
90void QZ_UpdateCursor (_THIS) {
91 BOOL state;
92
93 if (cursor_should_be_visible || !(SDL_GetAppState() & SDL_APPMOUSEFOCUS)) {
94 state = YES;
95 } else {
96 state = NO;
97 }
98 if (state != cursor_visible) {
99 if (state) {
100 [ NSCursor unhide ];
101 } else {
102 [ NSCursor hide ];
103 }
104 cursor_visible = state;
105 }
106}
107
108BOOL QZ_IsMouseInWindow (_THIS) {
109 if (qz_window == nil || (mode_flags & SDL_FULLSCREEN)) return YES; /*fullscreen*/
110 else {
111 NSPoint p = [ qz_window mouseLocationOutsideOfEventStream ];
112 p.y -= 1.0f; /* Apparently y goes from 1 to h, not from 0 to h-1 (i.e. the "location of the mouse" seems to be defined as "the location of the top left corner of the mouse pointer's hot pixel" */
113 return NSPointInRect(p, [ window_view frame ]);
114 }
115}
116
117int QZ_ShowWMCursor (_THIS, WMcursor *cursor) {
118
119 if ( cursor == NULL) {
120 if ( cursor_should_be_visible ) {
121 cursor_should_be_visible = NO;
122 QZ_ChangeGrabState (this, QZ_HIDECURSOR);
123 }
124 QZ_UpdateCursor(this);
125 }
126 else {
127 if ( qz_window != nil && !(mode_flags & SDL_FULLSCREEN) ) {
128 [ qz_window invalidateCursorRectsForView: [ qz_window contentView ] ];
129 }
130 if ( ! cursor_should_be_visible ) {
131 cursor_should_be_visible = YES;
132 QZ_ChangeGrabState (this, QZ_SHOWCURSOR);
133 }
134 [ cursor->nscursor performSelectorOnMainThread:@selector(set) withObject:nil waitUntilDone:NO ];
135 QZ_UpdateCursor(this);
136 }
137
138 return 1;
139}
140
141/*
142 Coordinate conversion functions, for convenience
143 Cocoa sets the origin at the lower left corner of the window/screen
144 SDL, CoreGraphics/WindowServer, and QuickDraw use the origin at the upper left corner
145 The routines were written so they could be called before SetVideoMode() has finished;
146 this might have limited usefulness at the moment, but the extra cost is trivial.
147*/
148
149/* Convert Cocoa screen coordinate to Cocoa window coordinate */
150void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p) {
151
152 if ( ! CGDisplayIsCaptured (display_id) )
153 *p = [ qz_window convertScreenToBase:*p ];
154}
155
156
157/* Convert Cocoa window coordinate to Cocoa screen coordinate */
158void QZ_PrivateLocalToGlobal (_THIS, NSPoint *p) {
159
160 if ( ! CGDisplayIsCaptured (display_id) )
161 *p = [ qz_window convertBaseToScreen:*p ];
162}
163
164/* Convert SDL coordinate to Cocoa coordinate */
165void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) {
166
167 if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */
168
169 p->y = CGDisplayPixelsHigh (display_id) - p->y;
170 }
171 else {
172
173 *p = [ window_view convertPoint:*p toView: nil ];
174 p->y = [window_view frame].size.height - p->y;
175 }
176}
177
178/* Convert Cocoa coordinate to SDL coordinate */
179void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) {
180
181 if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */
182
183 p->y = CGDisplayPixelsHigh (display_id) - p->y;
184 }
185 else {
186
187 *p = [ window_view convertPoint:*p fromView: nil ];
188 p->y = [window_view frame].size.height - p->y;
189 }
190}
191
192/* Convert SDL coordinate to window server (CoreGraphics) coordinate */
193CGPoint QZ_PrivateSDLToCG (_THIS, NSPoint *p) {
194
195 CGPoint cgp;
196
197 if ( ! CGDisplayIsCaptured (display_id) ) { /* not captured => not fullscreen => local coord */
198
199 int height;
200
201 QZ_PrivateSDLToCocoa (this, p);
202 QZ_PrivateLocalToGlobal (this, p);
203
204 height = CGDisplayPixelsHigh (display_id);
205 p->y = height - p->y;
206 }
207
208 cgp.x = p->x;
209 cgp.y = p->y;
210
211 return cgp;
212}
213
214#if 0 /* Dead code */
215/* Convert window server (CoreGraphics) coordinate to SDL coordinate */
216void QZ_PrivateCGToSDL (_THIS, NSPoint *p) {
217
218 if ( ! CGDisplayIsCaptured (display_id) ) { /* not captured => not fullscreen => local coord */
219
220 int height;
221
222 /* Convert CG Global to Cocoa Global */
223 height = CGDisplayPixelsHigh (display_id);
224 p->y = height - p->y;
225
226 QZ_PrivateGlobalToLocal (this, p);
227 QZ_PrivateCocoaToSDL (this, p);
228 }
229}
230#endif /* Dead code */
231
232void QZ_PrivateWarpCursor (_THIS, int x, int y) {
233 NSPoint p;
234 CGPoint cgp;
235
236 p = NSMakePoint (x, y);
237 cgp = QZ_PrivateSDLToCG (this, &p);
238
239 /* this is the magic call that fixes cursor "freezing" after warp */
240 CGAssociateMouseAndMouseCursorPosition (0);
241 CGWarpMouseCursorPosition (cgp);
242 if (grab_state != QZ_INVISIBLE_GRAB) { /* can't leave it disassociated? */
243 CGAssociateMouseAndMouseCursorPosition (1);
244 }
245 SDL_PrivateAppActive (QZ_IsMouseInWindow (this), SDL_APPMOUSEFOCUS);
246}
247
248void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y) {
249
250 /* Only allow warping when in foreground */
251 if ( ! [ NSApp isActive ] )
252 return;
253
254 /* Do the actual warp */
255 if (grab_state != QZ_INVISIBLE_GRAB) QZ_PrivateWarpCursor (this, x, y);
256
257 /* Generate the mouse moved event */
258 SDL_PrivateMouseMotion (0, 0, x, y);
259}
260
261void QZ_MoveWMCursor (_THIS, int x, int y) { }
262void QZ_CheckMouseMode (_THIS) { }
263
264void QZ_SetCaption (_THIS, const char *title, const char *icon) {
265
266 if ( qz_window != nil ) {
267 NSString *string;
268 if ( title != NULL ) {
269 string = [ [ NSString alloc ] initWithUTF8String:title ];
270 [ qz_window setTitle:string ];
271 [ string release ];
272 }
273 if ( icon != NULL ) {
274 string = [ [ NSString alloc ] initWithUTF8String:icon ];
275 [ qz_window setMiniwindowTitle:string ];
276 [ string release ];
277 }
278 }
279}
280
281void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask)
282{
283 NSBitmapImageRep *imgrep;
284 NSImage *img;
285 SDL_Surface *mergedSurface;
286 NSAutoreleasePool *pool;
287 Uint8 *pixels;
288 SDL_bool iconSrcAlpha;
289 Uint8 iconAlphaValue;
290 int i, j, maskPitch, index;
291
292 pool = [ [ NSAutoreleasePool alloc ] init ];
293
294 imgrep = [ [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes: NULL pixelsWide: icon->w pixelsHigh: icon->h bitsPerSample: 8 samplesPerPixel: 4 hasAlpha: YES isPlanar: NO colorSpaceName: NSDeviceRGBColorSpace bytesPerRow: 4*icon->w bitsPerPixel: 32 ] autorelease ];
295 if (imgrep == nil) goto freePool;
296 pixels = [ imgrep bitmapData ];
297 SDL_memset(pixels, 0, 4*icon->w*icon->h); /* make the background, which will survive in colorkeyed areas, completely transparent */
298
299#if SDL_BYTEORDER == SDL_BIG_ENDIAN
300#define BYTEORDER_DEPENDENT_RGBA_MASKS 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF
301#else
302#define BYTEORDER_DEPENDENT_RGBA_MASKS 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
303#endif
304 mergedSurface = SDL_CreateRGBSurfaceFrom(pixels, icon->w, icon->h, 32, 4*icon->w, BYTEORDER_DEPENDENT_RGBA_MASKS);
305 if (mergedSurface == NULL) goto freePool;
306
307 /* blit, with temporarily cleared SRCALPHA flag because we want to copy, not alpha-blend */
308 iconSrcAlpha = ((icon->flags & SDL_SRCALPHA) != 0);
309 iconAlphaValue = icon->format->alpha;
310 SDL_SetAlpha(icon, 0, 255);
311 SDL_BlitSurface(icon, NULL, mergedSurface, NULL);
312 if (iconSrcAlpha) SDL_SetAlpha(icon, SDL_SRCALPHA, iconAlphaValue);
313
314 SDL_FreeSurface(mergedSurface);
315
316 /* apply mask, source alpha, and premultiply color values by alpha */
317 maskPitch = (icon->w+7)/8;
318 for (i = 0; i < icon->h; i++) {
319 for (j = 0; j < icon->w; j++) {
320 index = i*4*icon->w + j*4;
321 if (!(mask[i*maskPitch + j/8] & (128 >> j%8))) {
322 pixels[index + 3] = 0;
323 }
324 else {
325 if (iconSrcAlpha) {
326 if (icon->format->Amask == 0) pixels[index + 3] = icon->format->alpha;
327 }
328 else {
329 pixels[index + 3] = 255;
330 }
331 }
332 if (pixels[index + 3] < 255) {
333 pixels[index + 0] = (Uint16)pixels[index + 0]*pixels[index + 3]/255;
334 pixels[index + 1] = (Uint16)pixels[index + 1]*pixels[index + 3]/255;
335 pixels[index + 2] = (Uint16)pixels[index + 2]*pixels[index + 3]/255;
336 }
337 }
338 }
339
340 img = [ [ [ NSImage alloc ] initWithSize: NSMakeSize(icon->w, icon->h) ] autorelease ];
341 if (img == nil) goto freePool;
342 [ img addRepresentation: imgrep ];
343 [ NSApp setApplicationIconImage:img ];
344
345freePool:
346 [ pool release ];
347}
348
349int QZ_IconifyWindow (_THIS) {
350
351 if ( ! [ qz_window isMiniaturized ] ) {
352 [ qz_window miniaturize:nil ];
353 if ( ! [ qz_window isMiniaturized ] ) {
354 SDL_SetError ("window iconification failed");
355 return 0;
356 }
357 return 1;
358 }
359 else {
360 SDL_SetError ("window already iconified");
361 return 0;
362 }
363}
364
365/*
366int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) {
367 info->nsWindowPtr = qz_window;
368 return 0;
369}*/
370
371void QZ_ChangeGrabState (_THIS, int action) {
372
373 /*
374 Figure out what the next state should be based on the action.
375 Ignore actions that can't change the current state.
376 */
377 if ( grab_state == QZ_UNGRABBED ) {
378 if ( action == QZ_ENABLE_GRAB ) {
379 if ( cursor_should_be_visible )
380 grab_state = QZ_VISIBLE_GRAB;
381 else
382 grab_state = QZ_INVISIBLE_GRAB;
383 }
384 }
385 else if ( grab_state == QZ_VISIBLE_GRAB ) {
386 if ( action == QZ_DISABLE_GRAB )
387 grab_state = QZ_UNGRABBED;
388 else if ( action == QZ_HIDECURSOR )
389 grab_state = QZ_INVISIBLE_GRAB;
390 }
391 else {
392 assert( grab_state == QZ_INVISIBLE_GRAB );
393
394 if ( action == QZ_DISABLE_GRAB )
395 grab_state = QZ_UNGRABBED;
396 else if ( action == QZ_SHOWCURSOR )
397 grab_state = QZ_VISIBLE_GRAB;
398 }
399
400 /* now apply the new state */
401 if (grab_state == QZ_UNGRABBED) {
402
403 CGAssociateMouseAndMouseCursorPosition (1);
404 }
405 else if (grab_state == QZ_VISIBLE_GRAB) {
406
407 CGAssociateMouseAndMouseCursorPosition (1);
408 }
409 else {
410 assert( grab_state == QZ_INVISIBLE_GRAB );
411
412 QZ_PrivateWarpCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2);
413 CGAssociateMouseAndMouseCursorPosition (0);
414 }
415}
416
417SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) {
418
419 int doGrab = grab_mode & SDL_GRAB_ON;
420 /*int fullscreen = grab_mode & SDL_GRAB_FULLSCREEN;*/
421
422 if ( this->screen == NULL ) {
423 SDL_SetError ("QZ_GrabInput: screen is NULL");
424 return SDL_GRAB_OFF;
425 }
426
427 if ( ! video_set ) {
428 /*SDL_SetError ("QZ_GrabInput: video is not set, grab will take effect on mode switch"); */
429 current_grab_mode = grab_mode;
430 return grab_mode; /* Will be set later on mode switch */
431 }
432
433 if ( grab_mode != SDL_GRAB_QUERY ) {
434 if ( doGrab )
435 QZ_ChangeGrabState (this, QZ_ENABLE_GRAB);
436 else
437 QZ_ChangeGrabState (this, QZ_DISABLE_GRAB);
438
439 current_grab_mode = doGrab ? SDL_GRAB_ON : SDL_GRAB_OFF;
440 QZ_UpdateCursor(this);
441 }
442
443 return current_grab_mode;
444}
diff --git a/apps/plugins/sdl/src/video/quartz/SDL_QuartzWindow.h b/apps/plugins/sdl/src/video/quartz/SDL_QuartzWindow.h
deleted file mode 100644
index d19375b747..0000000000
--- a/apps/plugins/sdl/src/video/quartz/SDL_QuartzWindow.h
+++ /dev/null
@@ -1,51 +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#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1050)
25typedef unsigned int NSUInteger;
26#endif
27
28/* Subclass of NSWindow to fix genie effect and support resize events */
29@interface SDL_QuartzWindow : NSWindow
30{
31 BOOL watchForMouseUp;
32}
33
34- (void)miniaturize:(id)sender;
35- (void)display;
36- (void)setFrame:(NSRect)frameRect display:(BOOL)flag;
37- (void)appDidHide:(NSNotification*)note;
38- (void)appWillUnhide:(NSNotification*)note;
39- (void)appDidUnhide:(NSNotification*)note;
40- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag;
41@end
42
43/* Delegate for our NSWindow to send SDLQuit() on close */
44@interface SDL_QuartzWindowDelegate : NSObject
45- (BOOL)windowShouldClose:(id)sender;
46@end
47
48/* Subclass of NSView to set cursor rectangle */
49@interface SDL_QuartzView : NSView
50- (void)resetCursorRects;
51@end
diff --git a/apps/plugins/sdl/src/video/quartz/SDL_QuartzWindow.m b/apps/plugins/sdl/src/video/quartz/SDL_QuartzWindow.m
deleted file mode 100644
index 375833fb7b..0000000000
--- a/apps/plugins/sdl/src/video/quartz/SDL_QuartzWindow.m
+++ /dev/null
@@ -1,231 +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#include "SDL_QuartzWindow.h"
27
28/*
29 This function makes the *SDL region* of the window 100% opaque.
30 The genie effect uses the alpha component. Otherwise,
31 it doesn't seem to matter what value it has.
32*/
33static void QZ_SetPortAlphaOpaque () {
34
35 SDL_Surface *surface = current_video->screen;
36 int bpp;
37
38 bpp = surface->format->BitsPerPixel;
39
40 if (bpp == 32) {
41
42 Uint32 *pixels = (Uint32*) surface->pixels;
43 Uint32 rowPixels = surface->pitch / 4;
44 Uint32 i, j;
45
46 for (i = 0; i < surface->h; i++)
47 for (j = 0; j < surface->w; j++) {
48
49 pixels[ (i * rowPixels) + j ] |= 0xFF000000;
50 }
51 }
52}
53
54@implementation SDL_QuartzWindow
55
56/* we override these methods to fix the miniaturize animation/dock icon bug */
57- (void)miniaturize:(id)sender
58{
59 if (SDL_VideoSurface->flags & SDL_OPENGL) {
60
61 /*
62 Future: Grab framebuffer and put into NSImage
63 [ qz_window setMiniwindowImage:image ];
64 */
65 }
66 else {
67
68 /* make the alpha channel opaque so anim won't have holes in it */
69 QZ_SetPortAlphaOpaque ();
70 }
71
72 /* window is hidden now */
73 SDL_PrivateAppActive (0, SDL_APPACTIVE);
74
75 [ super miniaturize:sender ];
76}
77
78- (void)display
79{
80 /*
81 This method fires just before the window deminaturizes from the Dock.
82
83 We'll save the current visible surface, let the window manager redraw any
84 UI elements, and restore the SDL surface. This way, no expose event
85 is required, and the deminiaturize works perfectly.
86 */
87 SDL_VideoDevice *this = (SDL_VideoDevice*)current_video;
88
89 /* make sure pixels are fully opaque */
90 if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) )
91 QZ_SetPortAlphaOpaque ();
92
93 /* save current visible SDL surface */
94 [ self cacheImageInRect:[ window_view frame ] ];
95
96 /* let the window manager redraw controls, border, etc */
97 [ super display ];
98
99 /* restore visible SDL surface */
100 [ self restoreCachedImage ];
101
102 /* window is visible again */
103 SDL_PrivateAppActive (1, SDL_APPACTIVE);
104}
105
106- (void)setFrame:(NSRect)frameRect display:(BOOL)flag
107{
108
109 /*
110 If the video surface is NULL, this originated from QZ_SetVideoMode,
111 so don't send the resize event.
112 */
113 SDL_VideoDevice *this = (SDL_VideoDevice*)current_video;
114
115 if (this && SDL_VideoSurface == NULL) {
116
117 [ super setFrame:frameRect display:flag ];
118 }
119 else if (this && qz_window) {
120
121 NSRect newViewFrame;
122
123 [ super setFrame:frameRect display:flag ];
124
125 newViewFrame = [ window_view frame ];
126
127 SDL_PrivateResize (newViewFrame.size.width, newViewFrame.size.height);
128 }
129}
130
131/* QZ_DoActivate() calls a low-level CoreGraphics routine to adjust
132 the cursor position, if input is being grabbed. If app activation is
133 triggered by a mouse click in the title bar, then the window manager
134 gets confused and thinks we're dragging the window. The solution
135 below postpones the activate event to avoid this scenario. */
136- (void)becomeKeyWindow
137{
138 NSEvent *event = [self currentEvent];
139 if ([event type] == NSLeftMouseDown && [event window] == self)
140 watchForMouseUp = YES;
141 else
142 [super becomeKeyWindow];
143}
144
145- (void)sendEvent:(NSEvent *)event
146{
147 [super sendEvent:event];
148 if (watchForMouseUp && [event type] == NSLeftMouseUp)
149 {
150 watchForMouseUp = NO;
151 [super becomeKeyWindow];
152 }
153}
154
155- (void)appDidHide:(NSNotification*)note
156{
157 SDL_PrivateAppActive (0, SDL_APPACTIVE);
158}
159
160- (void)appWillUnhide:(NSNotification*)note
161{
162 SDL_VideoDevice *this = (SDL_VideoDevice*)current_video;
163
164 if ( this ) {
165
166 /* make sure pixels are fully opaque */
167 if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) )
168 QZ_SetPortAlphaOpaque ();
169
170 /* save current visible SDL surface */
171 [ self cacheImageInRect:[ window_view frame ] ];
172 }
173}
174
175- (void)appDidUnhide:(NSNotification*)note
176{
177 /* restore cached image, since it may not be current, post expose event too */
178 [ self restoreCachedImage ];
179
180 /*SDL_PrivateExpose ();*/
181
182 SDL_PrivateAppActive (1, SDL_APPACTIVE);
183}
184
185- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag
186{
187 /* Make our window subclass receive these application notifications */
188 [ [ NSNotificationCenter defaultCenter ] addObserver:self
189 selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ];
190
191 [ [ NSNotificationCenter defaultCenter ] addObserver:self
192 selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ];
193
194 [ [ NSNotificationCenter defaultCenter ] addObserver:self
195 selector:@selector(appWillUnhide:) name:NSApplicationWillUnhideNotification object:NSApp ];
196
197 return [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ];
198}
199
200@end
201
202@implementation SDL_QuartzWindowDelegate
203- (BOOL)windowShouldClose:(id)sender
204{
205 SDL_PrivateQuit();
206 return NO;
207}
208
209- (void)windowDidBecomeKey:(NSNotification *)aNotification
210{
211 QZ_DoActivate (current_video);
212}
213
214- (void)windowDidResignKey:(NSNotification *)aNotification
215{
216 QZ_DoDeactivate (current_video);
217}
218
219@end
220
221@implementation SDL_QuartzView
222
223- (void)resetCursorRects
224{
225 SDL_Cursor *sdlc = SDL_GetCursor();
226 if (sdlc != NULL && sdlc->wm_cursor != NULL) {
227 [self addCursorRect: [self visibleRect] cursor: sdlc->wm_cursor->nscursor];
228 }
229}
230
231@end