diff options
author | Franklin Wei <git@fwei.tk> | 2018-02-07 20:04:46 -0500 |
---|---|---|
committer | Franklin Wei <git@fwei.tk> | 2018-03-12 20:52:01 -0400 |
commit | 6039eb05ba6d82ef56f2868c96654c552d117bf9 (patch) | |
tree | 9db7016bcbf66cfdf7b9bc998d84c6eaff9c8378 /apps/plugins/sdl/src/video/quartz | |
parent | ef373c03b96b0be08babca581d9f10bccfd4931f (diff) | |
download | rockbox-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.h | 84 | ||||
-rw-r--r-- | apps/plugins/sdl/src/video/quartz/SDL_QuartzEvents.m | 1063 | ||||
-rw-r--r-- | apps/plugins/sdl/src/video/quartz/SDL_QuartzGL.m | 292 | ||||
-rw-r--r-- | apps/plugins/sdl/src/video/quartz/SDL_QuartzKeys.h | 146 | ||||
-rw-r--r-- | apps/plugins/sdl/src/video/quartz/SDL_QuartzVideo.h | 229 | ||||
-rw-r--r-- | apps/plugins/sdl/src/video/quartz/SDL_QuartzVideo.m | 1689 | ||||
-rw-r--r-- | apps/plugins/sdl/src/video/quartz/SDL_QuartzWM.h | 27 | ||||
-rw-r--r-- | apps/plugins/sdl/src/video/quartz/SDL_QuartzWM.m | 444 | ||||
-rw-r--r-- | apps/plugins/sdl/src/video/quartz/SDL_QuartzWindow.h | 51 | ||||
-rw-r--r-- | apps/plugins/sdl/src/video/quartz/SDL_QuartzWindow.m | 231 |
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 | |||
52 | typedef CGError CGSError; | ||
53 | typedef long CGSWindowCount; | ||
54 | typedef void * CGSConnectionID; | ||
55 | typedef int CGSWindowID; | ||
56 | typedef CGSWindowID* CGSWindowIDList; | ||
57 | typedef CGWindowLevel CGSWindowLevel; | ||
58 | typedef NSRect CGSRect; | ||
59 | |||
60 | extern CGSConnectionID _CGSDefaultConnection (); | ||
61 | |||
62 | extern CGSError CGSGetOnScreenWindowList (CGSConnectionID cid, | ||
63 | CGSConnectionID owner, | ||
64 | CGSWindowCount listCapacity, | ||
65 | CGSWindowIDList list, | ||
66 | CGSWindowCount *listCount); | ||
67 | |||
68 | extern CGSError CGSGetScreenRectForWindow (CGSConnectionID cid, | ||
69 | CGSWindowID wid, | ||
70 | CGSRect *rect); | ||
71 | |||
72 | extern CGWindowLevel CGSGetWindowLevel (CGSConnectionID cid, | ||
73 | CGSWindowID wid, | ||
74 | CGSWindowLevel *level); | ||
75 | |||
76 | extern CGSError CGSDisplayHWFill (CGDirectDisplayID id, unsigned int x, unsigned int y, | ||
77 | unsigned int w, unsigned int h, unsigned int color); | ||
78 | |||
79 | extern CGSError CGSDisplayCanHWFill (CGDirectDisplayID id); | ||
80 | |||
81 | extern CGSError CGSGetMouseEnabledFlags (CGSConnectionID cid, CGSWindowID wid, int *flags); | ||
82 | |||
83 | int 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 | |||
80 | void QZ_InitOSKeymap (_THIS) { | ||
81 | BOOL saw_layout = NO; | ||
82 | UInt32 state; | ||
83 | UInt32 value; | ||
84 | Uint16 i; | ||
85 | int world = SDLK_WORLD_0; | ||
86 | |||
87 | for ( i=0; i<SDL_TABLESIZE(keymap); ++i ) | ||
88 | keymap[i] = SDLK_UNKNOWN; | ||
89 | |||
90 | /* This keymap is almost exactly the same as the OS 9 one */ | ||
91 | keymap[QZ_ESCAPE] = SDLK_ESCAPE; | ||
92 | keymap[QZ_F1] = SDLK_F1; | ||
93 | keymap[QZ_F2] = SDLK_F2; | ||
94 | keymap[QZ_F3] = SDLK_F3; | ||
95 | keymap[QZ_F4] = SDLK_F4; | ||
96 | keymap[QZ_F5] = SDLK_F5; | ||
97 | keymap[QZ_F6] = SDLK_F6; | ||
98 | keymap[QZ_F7] = SDLK_F7; | ||
99 | keymap[QZ_F8] = SDLK_F8; | ||
100 | keymap[QZ_F9] = SDLK_F9; | ||
101 | keymap[QZ_F10] = SDLK_F10; | ||
102 | keymap[QZ_F11] = SDLK_F11; | ||
103 | keymap[QZ_F12] = SDLK_F12; | ||
104 | keymap[QZ_F13] = SDLK_F13; | ||
105 | keymap[QZ_F14] = SDLK_F14; | ||
106 | keymap[QZ_F15] = SDLK_F15; | ||
107 | /* | ||
108 | keymap[QZ_PRINT] = SDLK_PRINT; | ||
109 | keymap[QZ_SCROLLOCK] = SDLK_SCROLLOCK; | ||
110 | keymap[QZ_PAUSE] = SDLK_PAUSE; | ||
111 | */ | ||
112 | keymap[QZ_POWER] = SDLK_POWER; | ||
113 | keymap[QZ_BACKQUOTE] = SDLK_BACKQUOTE; | ||
114 | keymap[QZ_1] = SDLK_1; | ||
115 | keymap[QZ_2] = SDLK_2; | ||
116 | keymap[QZ_3] = SDLK_3; | ||
117 | keymap[QZ_4] = SDLK_4; | ||
118 | keymap[QZ_5] = SDLK_5; | ||
119 | keymap[QZ_6] = SDLK_6; | ||
120 | keymap[QZ_7] = SDLK_7; | ||
121 | keymap[QZ_8] = SDLK_8; | ||
122 | keymap[QZ_9] = SDLK_9; | ||
123 | keymap[QZ_0] = SDLK_0; | ||
124 | keymap[QZ_MINUS] = SDLK_MINUS; | ||
125 | keymap[QZ_EQUALS] = SDLK_EQUALS; | ||
126 | keymap[QZ_BACKSPACE] = SDLK_BACKSPACE; | ||
127 | keymap[QZ_INSERT] = SDLK_INSERT; | ||
128 | keymap[QZ_HOME] = SDLK_HOME; | ||
129 | keymap[QZ_PAGEUP] = SDLK_PAGEUP; | ||
130 | keymap[QZ_NUMLOCK] = SDLK_NUMLOCK; | ||
131 | keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS; | ||
132 | keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE; | ||
133 | keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY; | ||
134 | keymap[QZ_TAB] = SDLK_TAB; | ||
135 | keymap[QZ_q] = SDLK_q; | ||
136 | keymap[QZ_w] = SDLK_w; | ||
137 | keymap[QZ_e] = SDLK_e; | ||
138 | keymap[QZ_r] = SDLK_r; | ||
139 | keymap[QZ_t] = SDLK_t; | ||
140 | keymap[QZ_y] = SDLK_y; | ||
141 | keymap[QZ_u] = SDLK_u; | ||
142 | keymap[QZ_i] = SDLK_i; | ||
143 | keymap[QZ_o] = SDLK_o; | ||
144 | keymap[QZ_p] = SDLK_p; | ||
145 | keymap[QZ_LEFTBRACKET] = SDLK_LEFTBRACKET; | ||
146 | keymap[QZ_RIGHTBRACKET] = SDLK_RIGHTBRACKET; | ||
147 | keymap[QZ_BACKSLASH] = SDLK_BACKSLASH; | ||
148 | keymap[QZ_DELETE] = SDLK_DELETE; | ||
149 | keymap[QZ_END] = SDLK_END; | ||
150 | keymap[QZ_PAGEDOWN] = SDLK_PAGEDOWN; | ||
151 | keymap[QZ_KP7] = SDLK_KP7; | ||
152 | keymap[QZ_KP8] = SDLK_KP8; | ||
153 | keymap[QZ_KP9] = SDLK_KP9; | ||
154 | keymap[QZ_KP_MINUS] = SDLK_KP_MINUS; | ||
155 | keymap[QZ_CAPSLOCK] = SDLK_CAPSLOCK; | ||
156 | keymap[QZ_a] = SDLK_a; | ||
157 | keymap[QZ_s] = SDLK_s; | ||
158 | keymap[QZ_d] = SDLK_d; | ||
159 | keymap[QZ_f] = SDLK_f; | ||
160 | keymap[QZ_g] = SDLK_g; | ||
161 | keymap[QZ_h] = SDLK_h; | ||
162 | keymap[QZ_j] = SDLK_j; | ||
163 | keymap[QZ_k] = SDLK_k; | ||
164 | keymap[QZ_l] = SDLK_l; | ||
165 | keymap[QZ_SEMICOLON] = SDLK_SEMICOLON; | ||
166 | keymap[QZ_QUOTE] = SDLK_QUOTE; | ||
167 | keymap[QZ_RETURN] = SDLK_RETURN; | ||
168 | keymap[QZ_KP4] = SDLK_KP4; | ||
169 | keymap[QZ_KP5] = SDLK_KP5; | ||
170 | keymap[QZ_KP6] = SDLK_KP6; | ||
171 | keymap[QZ_KP_PLUS] = SDLK_KP_PLUS; | ||
172 | keymap[QZ_LSHIFT] = SDLK_LSHIFT; | ||
173 | keymap[QZ_RSHIFT] = SDLK_RSHIFT; | ||
174 | keymap[QZ_z] = SDLK_z; | ||
175 | keymap[QZ_x] = SDLK_x; | ||
176 | keymap[QZ_c] = SDLK_c; | ||
177 | keymap[QZ_v] = SDLK_v; | ||
178 | keymap[QZ_b] = SDLK_b; | ||
179 | keymap[QZ_n] = SDLK_n; | ||
180 | keymap[QZ_m] = SDLK_m; | ||
181 | keymap[QZ_COMMA] = SDLK_COMMA; | ||
182 | keymap[QZ_PERIOD] = SDLK_PERIOD; | ||
183 | keymap[QZ_SLASH] = SDLK_SLASH; | ||
184 | keymap[QZ_UP] = SDLK_UP; | ||
185 | keymap[QZ_KP1] = SDLK_KP1; | ||
186 | keymap[QZ_KP2] = SDLK_KP2; | ||
187 | keymap[QZ_KP3] = SDLK_KP3; | ||
188 | keymap[QZ_KP_ENTER] = SDLK_KP_ENTER; | ||
189 | keymap[QZ_LCTRL] = SDLK_LCTRL; | ||
190 | keymap[QZ_LALT] = SDLK_LALT; | ||
191 | keymap[QZ_LMETA] = SDLK_LMETA; | ||
192 | keymap[QZ_RCTRL] = SDLK_RCTRL; | ||
193 | keymap[QZ_RALT] = SDLK_RALT; | ||
194 | keymap[QZ_RMETA] = SDLK_RMETA; | ||
195 | keymap[QZ_SPACE] = SDLK_SPACE; | ||
196 | keymap[QZ_LEFT] = SDLK_LEFT; | ||
197 | keymap[QZ_DOWN] = SDLK_DOWN; | ||
198 | keymap[QZ_RIGHT] = SDLK_RIGHT; | ||
199 | keymap[QZ_KP0] = SDLK_KP0; | ||
200 | keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD; | ||
201 | keymap[QZ_IBOOK_ENTER] = SDLK_KP_ENTER; | ||
202 | keymap[QZ_IBOOK_RIGHT] = SDLK_RIGHT; | ||
203 | keymap[QZ_IBOOK_DOWN] = SDLK_DOWN; | ||
204 | keymap[QZ_IBOOK_UP] = SDLK_UP; | ||
205 | keymap[QZ_IBOOK_LEFT] = SDLK_LEFT; | ||
206 | |||
207 | /* | ||
208 | Up there we setup a static scancode->keysym map. However, it will not | ||
209 | work very well on international keyboard. Hence we now query MacOS | ||
210 | for its own keymap to adjust our own mapping table. However, this is | ||
211 | basically only useful for ascii char keys. This is also the reason | ||
212 | why we keep the static table, too. | ||
213 | */ | ||
214 | |||
215 | #if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1050) | ||
216 | if (TISCopyCurrentKeyboardLayoutInputSource != NULL) { | ||
217 | TISInputSourceRef src = TISCopyCurrentKeyboardLayoutInputSource(); | ||
218 | if (src != NULL) { | ||
219 | CFDataRef data = (CFDataRef) | ||
220 | TISGetInputSourceProperty(src, | ||
221 | kTISPropertyUnicodeKeyLayoutData); | ||
222 | if (data != NULL) { | ||
223 | const UCKeyboardLayout *layout = (const UCKeyboardLayout *) | ||
224 | CFDataGetBytePtr(data); | ||
225 | if (layout != NULL) { | ||
226 | const UInt32 kbdtype = LMGetKbdType(); | ||
227 | saw_layout = YES; | ||
228 | |||
229 | /* Loop over all 127 possible scan codes */ | ||
230 | for (i = 0; i < 0x7F; i++) { | ||
231 | UniChar buf[16]; | ||
232 | UniCharCount count = 0; | ||
233 | |||
234 | /* We pretend a clean start to begin with (i.e. no dead keys active */ | ||
235 | state = 0; | ||
236 | |||
237 | if (UCKeyTranslate(layout, i, kUCKeyActionDown, 0, kbdtype, | ||
238 | 0, &state, 16, &count, buf) != noErr) { | ||
239 | continue; | ||
240 | } | ||
241 | |||
242 | /* If the state become 0, it was a dead key. We need to | ||
243 | translate again, passing in the new state, to get | ||
244 | the actual key value */ | ||
245 | if (state != 0) { | ||
246 | if (UCKeyTranslate(layout, i, kUCKeyActionDown, 0, kbdtype, | ||
247 | 0, &state, 16, &count, buf) != noErr) { | ||
248 | continue; | ||
249 | } | ||
250 | } | ||
251 | |||
252 | if (count != 1) { | ||
253 | continue; /* no multi-char. Use SDL 1.3 instead. :) */ | ||
254 | } | ||
255 | |||
256 | value = (UInt32) buf[0]; | ||
257 | if (value >= 128) { | ||
258 | /* Some non-ASCII char, map it to SDLK_WORLD_* */ | ||
259 | if (world < 0xFF) { | ||
260 | keymap[i] = world++; | ||
261 | } | ||
262 | } else if (value >= 32) { /* non-control ASCII char */ | ||
263 | keymap[i] = value; | ||
264 | } | ||
265 | } | ||
266 | } | ||
267 | } | ||
268 | CFRelease(src); | ||
269 | } | ||
270 | } | ||
271 | #endif | ||
272 | |||
273 | #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1050) | ||
274 | if (!saw_layout) { | ||
275 | /* Get a pointer to the systems cached KCHR */ | ||
276 | const void *KCHRPtr = (const void *)GetScriptManagerVariable(smKCHRCache); | ||
277 | if (KCHRPtr) | ||
278 | { | ||
279 | /* Loop over all 127 possible scan codes */ | ||
280 | for (i = 0; i < 0x7F; i++) | ||
281 | { | ||
282 | /* We pretend a clean start to begin with (i.e. no dead keys active */ | ||
283 | state = 0; | ||
284 | |||
285 | /* Now translate the key code to a key value */ | ||
286 | value = KeyTranslate(KCHRPtr, i, &state) & 0xff; | ||
287 | |||
288 | /* If the state become 0, it was a dead key. We need to translate again, | ||
289 | passing in the new state, to get the actual key value */ | ||
290 | if (state != 0) | ||
291 | value = KeyTranslate(KCHRPtr, i, &state) & 0xff; | ||
292 | |||
293 | /* Now we should have an ascii value, or 0. Try to figure out to which SDL symbol it maps */ | ||
294 | if (value >= 128) { /* Some non-ASCII char, map it to SDLK_WORLD_* */ | ||
295 | if (world < 0xFF) { | ||
296 | keymap[i] = world++; | ||
297 | } | ||
298 | } else if (value >= 32) { /* non-control ASCII char */ | ||
299 | keymap[i] = value; | ||
300 | } | ||
301 | } | ||
302 | } | ||
303 | } | ||
304 | #endif | ||
305 | |||
306 | /* | ||
307 | The keypad codes are re-setup here, because the loop above cannot | ||
308 | distinguish between a key on the keypad and a regular key. We maybe | ||
309 | could get around this problem in another fashion: NSEvent's flags | ||
310 | include a "NSNumericPadKeyMask" bit; we could check that and modify | ||
311 | the symbol we return on the fly. However, this flag seems to exhibit | ||
312 | some weird behaviour related to the num lock key | ||
313 | */ | ||
314 | keymap[QZ_KP0] = SDLK_KP0; | ||
315 | keymap[QZ_KP1] = SDLK_KP1; | ||
316 | keymap[QZ_KP2] = SDLK_KP2; | ||
317 | keymap[QZ_KP3] = SDLK_KP3; | ||
318 | keymap[QZ_KP4] = SDLK_KP4; | ||
319 | keymap[QZ_KP5] = SDLK_KP5; | ||
320 | keymap[QZ_KP6] = SDLK_KP6; | ||
321 | keymap[QZ_KP7] = SDLK_KP7; | ||
322 | keymap[QZ_KP8] = SDLK_KP8; | ||
323 | keymap[QZ_KP9] = SDLK_KP9; | ||
324 | keymap[QZ_KP_MINUS] = SDLK_KP_MINUS; | ||
325 | keymap[QZ_KP_PLUS] = SDLK_KP_PLUS; | ||
326 | keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD; | ||
327 | keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS; | ||
328 | keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE; | ||
329 | keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY; | ||
330 | keymap[QZ_KP_ENTER] = SDLK_KP_ENTER; | ||
331 | } | ||
332 | |||
333 | static void QZ_DoKey (_THIS, int state, NSEvent *event) { | ||
334 | |||
335 | NSString *chars = NULL; | ||
336 | unsigned int i, numChars; | ||
337 | SDL_keysym key; | ||
338 | |||
339 | /* | ||
340 | A key event can contain multiple characters, | ||
341 | or no characters at all. In most cases, it | ||
342 | will contain a single character. If it contains | ||
343 | 0 characters, we'll use 0 as the unicode. If it | ||
344 | contains multiple characters, we'll use 0 as | ||
345 | the scancode/keysym. | ||
346 | */ | ||
347 | if (SDL_TranslateUNICODE && state == SDL_PRESSED) { | ||
348 | [field_edit interpretKeyEvents:[NSArray arrayWithObject:event]]; | ||
349 | chars = [ event characters ]; | ||
350 | numChars = [ chars length ]; | ||
351 | if (numChars > 0) | ||
352 | [field_edit setString:@""]; | ||
353 | } else { | ||
354 | numChars = 0; | ||
355 | } | ||
356 | |||
357 | if (numChars == 0) { | ||
358 | |||
359 | key.scancode = [ event keyCode ]; | ||
360 | key.sym = keymap [ key.scancode ]; | ||
361 | key.unicode = 0; | ||
362 | key.mod = KMOD_NONE; | ||
363 | |||
364 | SDL_PrivateKeyboard (state, &key); | ||
365 | } | ||
366 | else if (numChars >= 1) { | ||
367 | |||
368 | key.scancode = [ event keyCode ]; | ||
369 | key.sym = keymap [ key.scancode ]; | ||
370 | key.unicode = [ chars characterAtIndex:0 ]; | ||
371 | key.mod = KMOD_NONE; | ||
372 | |||
373 | SDL_PrivateKeyboard (state, &key); | ||
374 | |||
375 | for (i = 1; i < numChars; i++) { | ||
376 | |||
377 | key.scancode = 0; | ||
378 | key.sym = 0; | ||
379 | key.unicode = [ chars characterAtIndex:i]; | ||
380 | key.mod = KMOD_NONE; | ||
381 | |||
382 | SDL_PrivateKeyboard (state, &key); | ||
383 | } | ||
384 | } | ||
385 | |||
386 | if (SDL_getenv ("SDL_ENABLEAPPEVENTS")) | ||
387 | [ NSApp sendEvent:event ]; | ||
388 | } | ||
389 | |||
390 | /* This is the original behavior, before support was added for | ||
391 | * differentiating between left and right versions of the keys. | ||
392 | */ | ||
393 | static void QZ_DoUnsidedModifiers (_THIS, unsigned int newMods) { | ||
394 | |||
395 | const int mapping[] = { SDLK_CAPSLOCK, SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA }; | ||
396 | |||
397 | int i; | ||
398 | int bit; | ||
399 | SDL_keysym key; | ||
400 | |||
401 | key.scancode = 0; | ||
402 | key.sym = SDLK_UNKNOWN; | ||
403 | key.unicode = 0; | ||
404 | key.mod = KMOD_NONE; | ||
405 | |||
406 | /* Iterate through the bits, testing each against the current modifiers */ | ||
407 | for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) { | ||
408 | |||
409 | unsigned int currentMask, newMask; | ||
410 | |||
411 | currentMask = current_mods & bit; | ||
412 | newMask = newMods & bit; | ||
413 | |||
414 | if ( currentMask && | ||
415 | currentMask != newMask ) { /* modifier up event */ | ||
416 | |||
417 | key.sym = mapping[i]; | ||
418 | /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ | ||
419 | if (bit == NSAlphaShiftKeyMask) | ||
420 | SDL_PrivateKeyboard (SDL_PRESSED, &key); | ||
421 | SDL_PrivateKeyboard (SDL_RELEASED, &key); | ||
422 | } | ||
423 | else if ( newMask && | ||
424 | currentMask != newMask ) { /* modifier down event */ | ||
425 | |||
426 | key.sym = mapping[i]; | ||
427 | SDL_PrivateKeyboard (SDL_PRESSED, &key); | ||
428 | /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ | ||
429 | if (bit == NSAlphaShiftKeyMask) | ||
430 | SDL_PrivateKeyboard (SDL_RELEASED, &key); | ||
431 | } | ||
432 | } | ||
433 | } | ||
434 | |||
435 | /* This is a helper function for QZ_HandleModifierSide. This | ||
436 | * function reverts back to behavior before the distinction between | ||
437 | * sides was made. | ||
438 | */ | ||
439 | static void QZ_HandleNonDeviceModifier ( _THIS, unsigned int device_independent_mask, unsigned int newMods, unsigned int key_sym) { | ||
440 | unsigned int currentMask, newMask; | ||
441 | SDL_keysym key; | ||
442 | |||
443 | key.scancode = 0; | ||
444 | key.sym = key_sym; | ||
445 | key.unicode = 0; | ||
446 | key.mod = KMOD_NONE; | ||
447 | |||
448 | /* Isolate just the bits we care about in the depedent bits so we can | ||
449 | * figure out what changed | ||
450 | */ | ||
451 | currentMask = current_mods & device_independent_mask; | ||
452 | newMask = newMods & device_independent_mask; | ||
453 | |||
454 | if ( currentMask && | ||
455 | currentMask != newMask ) { /* modifier up event */ | ||
456 | SDL_PrivateKeyboard (SDL_RELEASED, &key); | ||
457 | } | ||
458 | else if ( newMask && | ||
459 | currentMask != newMask ) { /* modifier down event */ | ||
460 | SDL_PrivateKeyboard (SDL_PRESSED, &key); | ||
461 | } | ||
462 | } | ||
463 | |||
464 | /* This is a helper function for QZ_HandleModifierSide. | ||
465 | * This function sets the actual SDL_PrivateKeyboard event. | ||
466 | */ | ||
467 | static void QZ_HandleModifierOneSide ( _THIS, unsigned int newMods, | ||
468 | unsigned int key_sym, | ||
469 | unsigned int sided_device_dependent_mask ) { | ||
470 | |||
471 | SDL_keysym key; | ||
472 | unsigned int current_dep_mask, new_dep_mask; | ||
473 | |||
474 | key.scancode = 0; | ||
475 | key.sym = key_sym; | ||
476 | key.unicode = 0; | ||
477 | key.mod = KMOD_NONE; | ||
478 | |||
479 | /* Isolate just the bits we care about in the depedent bits so we can | ||
480 | * figure out what changed | ||
481 | */ | ||
482 | current_dep_mask = current_mods & sided_device_dependent_mask; | ||
483 | new_dep_mask = newMods & sided_device_dependent_mask; | ||
484 | |||
485 | /* We now know that this side bit flipped. But we don't know if | ||
486 | * it went pressed to released or released to pressed, so we must | ||
487 | * find out which it is. | ||
488 | */ | ||
489 | if( new_dep_mask && | ||
490 | current_dep_mask != new_dep_mask ) { | ||
491 | /* Modifier down event */ | ||
492 | SDL_PrivateKeyboard (SDL_PRESSED, &key); | ||
493 | } | ||
494 | else /* Modifier up event */ { | ||
495 | SDL_PrivateKeyboard (SDL_RELEASED, &key); | ||
496 | } | ||
497 | } | ||
498 | |||
499 | /* This is a helper function for QZ_DoSidedModifiers. | ||
500 | * This function will figure out if the modifier key is the left or right side, | ||
501 | * e.g. left-shift vs right-shift. | ||
502 | */ | ||
503 | static void QZ_HandleModifierSide ( _THIS, int device_independent_mask, | ||
504 | unsigned int newMods, | ||
505 | unsigned int left_key_sym, | ||
506 | unsigned int right_key_sym, | ||
507 | unsigned int left_device_dependent_mask, | ||
508 | unsigned int right_device_dependent_mask ) { | ||
509 | unsigned int device_dependent_mask = 0; | ||
510 | unsigned int diff_mod = 0; | ||
511 | |||
512 | device_dependent_mask = left_device_dependent_mask | right_device_dependent_mask; | ||
513 | /* On the basis that the device independent mask is set, but there are | ||
514 | * no device dependent flags set, we'll assume that we can't detect this | ||
515 | * keyboard and revert to the unsided behavior. | ||
516 | */ | ||
517 | if ( (device_dependent_mask & newMods) == 0 ) { | ||
518 | /* Revert to the old behavior */ | ||
519 | QZ_HandleNonDeviceModifier ( this, device_independent_mask, newMods, left_key_sym ); | ||
520 | return; | ||
521 | } | ||
522 | |||
523 | /* XOR the previous state against the new state to see if there's a change */ | ||
524 | diff_mod = (device_dependent_mask & current_mods) | ||
525 | ^ (device_dependent_mask & newMods); | ||
526 | |||
527 | if ( diff_mod ) { | ||
528 | /* A change in state was found. Isolate the left and right bits | ||
529 | * to handle them separately just in case the values can simulataneously | ||
530 | * change or if the bits don't both exist. | ||
531 | */ | ||
532 | if ( left_device_dependent_mask & diff_mod ) { | ||
533 | QZ_HandleModifierOneSide ( this, newMods, left_key_sym, left_device_dependent_mask ); | ||
534 | } | ||
535 | if ( right_device_dependent_mask & diff_mod ) { | ||
536 | QZ_HandleModifierOneSide ( this, newMods, right_key_sym, right_device_dependent_mask ); | ||
537 | } | ||
538 | } | ||
539 | } | ||
540 | |||
541 | /* This is a helper function for QZ_DoSidedModifiers. | ||
542 | * This function will release a key press in the case that | ||
543 | * it is clear that the modifier has been released (i.e. one side | ||
544 | * can't still be down). | ||
545 | */ | ||
546 | static void QZ_ReleaseModifierSide ( _THIS, | ||
547 | unsigned int device_independent_mask, | ||
548 | unsigned int newMods, | ||
549 | unsigned int left_key_sym, | ||
550 | unsigned int right_key_sym, | ||
551 | unsigned int left_device_dependent_mask, | ||
552 | unsigned int right_device_dependent_mask ) { | ||
553 | unsigned int device_dependent_mask = 0; | ||
554 | SDL_keysym key; | ||
555 | |||
556 | key.scancode = 0; | ||
557 | key.sym = SDLK_UNKNOWN; | ||
558 | key.unicode = 0; | ||
559 | key.mod = KMOD_NONE; | ||
560 | |||
561 | device_dependent_mask = left_device_dependent_mask | right_device_dependent_mask; | ||
562 | /* On the basis that the device independent mask is set, but there are | ||
563 | * no device dependent flags set, we'll assume that we can't detect this | ||
564 | * keyboard and revert to the unsided behavior. | ||
565 | */ | ||
566 | if ( (device_dependent_mask & current_mods) == 0 ) { | ||
567 | /* In this case, we can't detect the keyboard, so use the left side | ||
568 | * to represent both, and release it. | ||
569 | */ | ||
570 | key.sym = left_key_sym; | ||
571 | SDL_PrivateKeyboard (SDL_RELEASED, &key); | ||
572 | |||
573 | return; | ||
574 | } | ||
575 | |||
576 | |||
577 | /* | ||
578 | * This could have been done in an if-else case because at this point, | ||
579 | * we know that all keys have been released when calling this function. | ||
580 | * But I'm being paranoid so I want to handle each separately, | ||
581 | * so I hope this doesn't cause other problems. | ||
582 | */ | ||
583 | if ( left_device_dependent_mask & current_mods ) { | ||
584 | key.sym = left_key_sym; | ||
585 | SDL_PrivateKeyboard (SDL_RELEASED, &key); | ||
586 | } | ||
587 | if ( right_device_dependent_mask & current_mods ) { | ||
588 | key.sym = right_key_sym; | ||
589 | SDL_PrivateKeyboard (SDL_RELEASED, &key); | ||
590 | } | ||
591 | } | ||
592 | |||
593 | /* This is a helper function for QZ_DoSidedModifiers. | ||
594 | * This function handles the CapsLock case. | ||
595 | */ | ||
596 | static void QZ_HandleCapsLock (_THIS, unsigned int newMods) { | ||
597 | unsigned int currentMask, newMask; | ||
598 | SDL_keysym key; | ||
599 | |||
600 | key.scancode = 0; | ||
601 | key.sym = SDLK_CAPSLOCK; | ||
602 | key.unicode = 0; | ||
603 | key.mod = KMOD_NONE; | ||
604 | |||
605 | currentMask = current_mods & NSAlphaShiftKeyMask; | ||
606 | newMask = newMods & NSAlphaShiftKeyMask; | ||
607 | |||
608 | if ( currentMask && | ||
609 | currentMask != newMask ) { /* modifier up event */ | ||
610 | /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ | ||
611 | SDL_PrivateKeyboard (SDL_PRESSED, &key); | ||
612 | SDL_PrivateKeyboard (SDL_RELEASED, &key); | ||
613 | } | ||
614 | else if ( newMask && | ||
615 | currentMask != newMask ) { /* modifier down event */ | ||
616 | /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ | ||
617 | SDL_PrivateKeyboard (SDL_PRESSED, &key); | ||
618 | SDL_PrivateKeyboard (SDL_RELEASED, &key); | ||
619 | } | ||
620 | } | ||
621 | |||
622 | /* This function will handle the modifier keys and also determine the | ||
623 | * correct side of the key. | ||
624 | */ | ||
625 | static void QZ_DoSidedModifiers (_THIS, unsigned int newMods) { | ||
626 | /* Set up arrays for the key syms for the left and right side. */ | ||
627 | const unsigned int left_mapping[] = { SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA }; | ||
628 | const unsigned int right_mapping[] = { SDLK_RSHIFT, SDLK_RCTRL, SDLK_RALT, SDLK_RMETA }; | ||
629 | /* Set up arrays for the device dependent masks with indices that | ||
630 | * correspond to the _mapping arrays | ||
631 | */ | ||
632 | const unsigned int left_device_mapping[] = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK }; | ||
633 | const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK }; | ||
634 | |||
635 | unsigned int i; | ||
636 | unsigned int bit; | ||
637 | |||
638 | /* Handle CAPSLOCK separately because it doesn't have a left/right side */ | ||
639 | QZ_HandleCapsLock ( this, newMods ); | ||
640 | |||
641 | /* Iterate through the bits, testing each against the current modifiers */ | ||
642 | for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) { | ||
643 | |||
644 | unsigned int currentMask, newMask; | ||
645 | |||
646 | currentMask = current_mods & bit; | ||
647 | newMask = newMods & bit; | ||
648 | |||
649 | /* If the bit is set, we must always examine it because the left | ||
650 | * and right side keys may alternate or both may be pressed. | ||
651 | */ | ||
652 | if ( newMask ) { | ||
653 | QZ_HandleModifierSide ( this, bit, newMods, | ||
654 | left_mapping[i], | ||
655 | right_mapping[i], | ||
656 | left_device_mapping[i], | ||
657 | right_device_mapping[i] ); | ||
658 | } | ||
659 | /* If the state changed from pressed to unpressed, we must examine | ||
660 | * the device dependent bits to release the correct keys. | ||
661 | */ | ||
662 | else if ( currentMask && | ||
663 | currentMask != newMask ) { /* modifier up event */ | ||
664 | QZ_ReleaseModifierSide ( this, bit, newMods, | ||
665 | left_mapping[i], | ||
666 | right_mapping[i], | ||
667 | left_device_mapping[i], | ||
668 | right_device_mapping[i] ); | ||
669 | } | ||
670 | } | ||
671 | } | ||
672 | |||
673 | /* This function is called to handle the modifiers. | ||
674 | * It will try to distinguish between the left side and right side | ||
675 | * of the keyboard for those modifiers that qualify if the | ||
676 | * operating system version supports it. Otherwise, the code | ||
677 | * will not try to make the distinction. | ||
678 | */ | ||
679 | static void QZ_DoModifiers (_THIS, unsigned int newMods) { | ||
680 | |||
681 | if (current_mods == newMods) | ||
682 | return; | ||
683 | |||
684 | /* | ||
685 | * Starting with Panther (10.3.0), the ability to distinguish between | ||
686 | * left side and right side modifiers is available. | ||
687 | */ | ||
688 | if( system_version >= 0x1030 ) { | ||
689 | QZ_DoSidedModifiers (this, newMods); | ||
690 | } | ||
691 | else { | ||
692 | QZ_DoUnsidedModifiers (this, newMods); | ||
693 | } | ||
694 | |||
695 | current_mods = newMods; | ||
696 | } | ||
697 | |||
698 | static void QZ_GetMouseLocation (_THIS, NSPoint *p) { | ||
699 | *p = [ NSEvent mouseLocation ]; /* global coordinates */ | ||
700 | if (qz_window) | ||
701 | QZ_PrivateGlobalToLocal (this, p); | ||
702 | QZ_PrivateCocoaToSDL (this, p); | ||
703 | } | ||
704 | |||
705 | void QZ_DoActivate (_THIS) { | ||
706 | |||
707 | SDL_PrivateAppActive (1, SDL_APPINPUTFOCUS | (QZ_IsMouseInWindow (this) ? SDL_APPMOUSEFOCUS : 0)); | ||
708 | |||
709 | QZ_UpdateCursor(this); | ||
710 | |||
711 | /* Regrab input, only if it was previously grabbed */ | ||
712 | if ( current_grab_mode == SDL_GRAB_ON ) { | ||
713 | |||
714 | /* Restore cursor location if input was grabbed */ | ||
715 | QZ_PrivateWarpCursor (this, cursor_loc.x, cursor_loc.y); | ||
716 | QZ_ChangeGrabState (this, QZ_ENABLE_GRAB); | ||
717 | } | ||
718 | else { | ||
719 | /* Update SDL's mouse location */ | ||
720 | NSPoint p; | ||
721 | QZ_GetMouseLocation (this, &p); | ||
722 | SDL_PrivateMouseMotion (0, 0, p.x, p.y); | ||
723 | } | ||
724 | |||
725 | QZ_UpdateCursor(this); | ||
726 | } | ||
727 | |||
728 | void QZ_DoDeactivate (_THIS) { | ||
729 | |||
730 | SDL_PrivateAppActive (0, SDL_APPINPUTFOCUS | SDL_APPMOUSEFOCUS); | ||
731 | |||
732 | /* Get the current cursor location, for restore on activate */ | ||
733 | QZ_GetMouseLocation (this, &cursor_loc); | ||
734 | |||
735 | /* Reassociate mouse and cursor */ | ||
736 | CGAssociateMouseAndMouseCursorPosition (1); | ||
737 | |||
738 | QZ_UpdateCursor(this); | ||
739 | } | ||
740 | |||
741 | void QZ_SleepNotificationHandler (void * refcon, | ||
742 | io_service_t service, | ||
743 | natural_t messageType, | ||
744 | void * messageArgument ) | ||
745 | { | ||
746 | SDL_VideoDevice *this = (SDL_VideoDevice*)refcon; | ||
747 | |||
748 | switch(messageType) | ||
749 | { | ||
750 | case kIOMessageSystemWillSleep: | ||
751 | IOAllowPowerChange(power_connection, (long) messageArgument); | ||
752 | break; | ||
753 | case kIOMessageCanSystemSleep: | ||
754 | IOAllowPowerChange(power_connection, (long) messageArgument); | ||
755 | break; | ||
756 | case kIOMessageSystemHasPoweredOn: | ||
757 | /* awake */ | ||
758 | SDL_PrivateExpose(); | ||
759 | break; | ||
760 | } | ||
761 | } | ||
762 | |||
763 | void QZ_RegisterForSleepNotifications (_THIS) | ||
764 | { | ||
765 | CFRunLoopSourceRef rls; | ||
766 | IONotificationPortRef thePortRef; | ||
767 | io_object_t notifier; | ||
768 | |||
769 | power_connection = IORegisterForSystemPower (this, &thePortRef, QZ_SleepNotificationHandler, ¬ifier); | ||
770 | |||
771 | if (power_connection == 0) | ||
772 | NSLog(@"SDL: QZ_SleepNotificationHandler() IORegisterForSystemPower failed."); | ||
773 | |||
774 | rls = IONotificationPortGetRunLoopSource (thePortRef); | ||
775 | CFRunLoopAddSource (CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); | ||
776 | CFRelease (rls); | ||
777 | } | ||
778 | |||
779 | |||
780 | /* Try to map Quartz mouse buttons to SDL's lingo... */ | ||
781 | static int QZ_OtherMouseButtonToSDL(int button) | ||
782 | { | ||
783 | switch (button) | ||
784 | { | ||
785 | case 0: | ||
786 | return(SDL_BUTTON_LEFT); /* 1 */ | ||
787 | case 1: | ||
788 | return(SDL_BUTTON_RIGHT); /* 3 */ | ||
789 | case 2: | ||
790 | return(SDL_BUTTON_MIDDLE); /* 2 */ | ||
791 | } | ||
792 | |||
793 | /* >= 3: skip 4 & 5, since those are the SDL mousewheel buttons. */ | ||
794 | return(button + 3); | ||
795 | } | ||
796 | |||
797 | |||
798 | void QZ_PumpEvents (_THIS) | ||
799 | { | ||
800 | int32_t dx, dy; | ||
801 | |||
802 | NSDate *distantPast; | ||
803 | NSEvent *event; | ||
804 | NSRect winRect; | ||
805 | NSAutoreleasePool *pool; | ||
806 | |||
807 | if (!SDL_VideoSurface) | ||
808 | return; /* don't do anything if there's no screen surface. */ | ||
809 | |||
810 | /* Update activity every five seconds to prevent screensaver. --ryan. */ | ||
811 | if (!allow_screensaver) { | ||
812 | static Uint32 screensaverTicks; | ||
813 | Uint32 nowTicks = SDL_GetTicks(); | ||
814 | if ((nowTicks - screensaverTicks) > 5000) | ||
815 | { | ||
816 | UpdateSystemActivity(UsrActivity); | ||
817 | screensaverTicks = nowTicks; | ||
818 | } | ||
819 | } | ||
820 | |||
821 | pool = [ [ NSAutoreleasePool alloc ] init ]; | ||
822 | distantPast = [ NSDate distantPast ]; | ||
823 | |||
824 | winRect = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h); | ||
825 | |||
826 | /* while grabbed, accumulate all mouse moved events into one SDL mouse event */ | ||
827 | dx = 0; | ||
828 | dy = 0; | ||
829 | |||
830 | do { | ||
831 | |||
832 | /* Poll for an event. This will not block */ | ||
833 | event = [ NSApp nextEventMatchingMask:NSAnyEventMask | ||
834 | untilDate:distantPast | ||
835 | inMode: NSDefaultRunLoopMode dequeue:YES ]; | ||
836 | if (event != nil) { | ||
837 | |||
838 | int button; | ||
839 | unsigned int type; | ||
840 | BOOL isInGameWin; | ||
841 | |||
842 | #define DO_MOUSE_DOWN(button) do { \ | ||
843 | if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { \ | ||
844 | SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0); \ | ||
845 | expect_mouse_up |= 1<<button; \ | ||
846 | } \ | ||
847 | [ NSApp sendEvent:event ]; \ | ||
848 | } while(0) | ||
849 | |||
850 | #define DO_MOUSE_UP(button) do { \ | ||
851 | if ( expect_mouse_up & (1<<button) ) { \ | ||
852 | SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0); \ | ||
853 | expect_mouse_up &= ~(1<<button); \ | ||
854 | } \ | ||
855 | [ NSApp sendEvent:event ]; \ | ||
856 | } while(0) | ||
857 | |||
858 | type = [ event type ]; | ||
859 | isInGameWin = QZ_IsMouseInWindow (this); | ||
860 | |||
861 | QZ_DoModifiers(this, [ event modifierFlags ] ); | ||
862 | |||
863 | switch (type) { | ||
864 | case NSLeftMouseDown: | ||
865 | if ( SDL_getenv("SDL_HAS3BUTTONMOUSE") ) { | ||
866 | DO_MOUSE_DOWN (SDL_BUTTON_LEFT); | ||
867 | } else { | ||
868 | if ( NSCommandKeyMask & current_mods ) { | ||
869 | last_virtual_button = SDL_BUTTON_RIGHT; | ||
870 | DO_MOUSE_DOWN (SDL_BUTTON_RIGHT); | ||
871 | } | ||
872 | else if ( NSAlternateKeyMask & current_mods ) { | ||
873 | last_virtual_button = SDL_BUTTON_MIDDLE; | ||
874 | DO_MOUSE_DOWN (SDL_BUTTON_MIDDLE); | ||
875 | } | ||
876 | else { | ||
877 | DO_MOUSE_DOWN (SDL_BUTTON_LEFT); | ||
878 | } | ||
879 | } | ||
880 | break; | ||
881 | |||
882 | case NSLeftMouseUp: | ||
883 | if ( last_virtual_button != 0 ) { | ||
884 | DO_MOUSE_UP (last_virtual_button); | ||
885 | last_virtual_button = 0; | ||
886 | } | ||
887 | else { | ||
888 | DO_MOUSE_UP (SDL_BUTTON_LEFT); | ||
889 | } | ||
890 | break; | ||
891 | |||
892 | case NSOtherMouseDown: | ||
893 | case NSRightMouseDown: | ||
894 | button = QZ_OtherMouseButtonToSDL([ event buttonNumber ]); | ||
895 | DO_MOUSE_DOWN (button); | ||
896 | break; | ||
897 | |||
898 | case NSOtherMouseUp: | ||
899 | case NSRightMouseUp: | ||
900 | button = QZ_OtherMouseButtonToSDL([ event buttonNumber ]); | ||
901 | DO_MOUSE_UP (button); | ||
902 | break; | ||
903 | |||
904 | case NSSystemDefined: | ||
905 | /* | ||
906 | Future: up to 32 "mouse" buttons can be handled. | ||
907 | if ([event subtype] == 7) { | ||
908 | unsigned int buttons; | ||
909 | buttons = [ event data2 ]; | ||
910 | */ | ||
911 | break; | ||
912 | case NSLeftMouseDragged: | ||
913 | case NSRightMouseDragged: | ||
914 | case NSOtherMouseDragged: /* usually middle mouse dragged */ | ||
915 | case NSMouseMoved: | ||
916 | if ( grab_state == QZ_INVISIBLE_GRAB ) { | ||
917 | |||
918 | /* | ||
919 | If input is grabbed+hidden, the cursor doesn't move, | ||
920 | so we have to call the lowlevel window server | ||
921 | function. This is less accurate but works OK. | ||
922 | */ | ||
923 | int32_t dx1, dy1; | ||
924 | CGGetLastMouseDelta (&dx1, &dy1); | ||
925 | dx += dx1; | ||
926 | dy += dy1; | ||
927 | } | ||
928 | else { | ||
929 | |||
930 | /* | ||
931 | Get the absolute mouse location. This is not the | ||
932 | mouse location after the currently processed event, | ||
933 | but the *current* mouse location, i.e. after all | ||
934 | pending events. This means that if there are | ||
935 | multiple mouse moved events in the queue, we make | ||
936 | multiple identical calls to SDL_PrivateMouseMotion(), | ||
937 | but that's no problem since the latter only | ||
938 | generates SDL events for nonzero movements. In my | ||
939 | experience on PBG4/10.4.8, this rarely happens anyway. | ||
940 | */ | ||
941 | NSPoint p; | ||
942 | QZ_GetMouseLocation (this, &p); | ||
943 | SDL_PrivateMouseMotion (0, 0, p.x, p.y); | ||
944 | } | ||
945 | |||
946 | /* | ||
947 | Handle grab input+cursor visible by warping the cursor back | ||
948 | into the game window. This still generates a mouse moved event, | ||
949 | but not as a result of the warp (so it's in the right direction). | ||
950 | */ | ||
951 | if ( grab_state == QZ_VISIBLE_GRAB && !isInGameWin ) { | ||
952 | |||
953 | NSPoint p; | ||
954 | QZ_GetMouseLocation (this, &p); | ||
955 | |||
956 | if ( p.x < 0.0 ) | ||
957 | p.x = 0.0; | ||
958 | |||
959 | if ( p.y < 0.0 ) | ||
960 | p.y = 0.0; | ||
961 | |||
962 | if ( p.x >= winRect.size.width ) | ||
963 | p.x = winRect.size.width-1; | ||
964 | |||
965 | if ( p.y >= winRect.size.height ) | ||
966 | p.y = winRect.size.height-1; | ||
967 | |||
968 | QZ_PrivateWarpCursor (this, p.x, p.y); | ||
969 | } | ||
970 | else | ||
971 | if ( !isInGameWin && (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { | ||
972 | |||
973 | SDL_PrivateAppActive (0, SDL_APPMOUSEFOCUS); | ||
974 | |||
975 | if (grab_state == QZ_INVISIBLE_GRAB) | ||
976 | /*The cursor has left the window even though it is | ||
977 | disassociated from the mouse (and therefore | ||
978 | shouldn't move): this can happen with Wacom | ||
979 | tablets, and it effectively breaks the grab, since | ||
980 | mouse down events now go to background | ||
981 | applications. The only possibility to avoid this | ||
982 | seems to be talking to the tablet driver | ||
983 | (AppleEvents) to constrain its mapped area to the | ||
984 | window, which may not be worth the effort. For | ||
985 | now, handle the condition more gracefully than | ||
986 | before by reassociating cursor and mouse until the | ||
987 | cursor enters the window again, making it obvious | ||
988 | to the user that the grab is broken.*/ | ||
989 | CGAssociateMouseAndMouseCursorPosition (1); | ||
990 | |||
991 | QZ_UpdateCursor(this); | ||
992 | } | ||
993 | else | ||
994 | if ( isInGameWin && (SDL_GetAppState() & (SDL_APPMOUSEFOCUS | SDL_APPINPUTFOCUS)) == SDL_APPINPUTFOCUS ) { | ||
995 | |||
996 | SDL_PrivateAppActive (1, SDL_APPMOUSEFOCUS); | ||
997 | |||
998 | QZ_UpdateCursor(this); | ||
999 | |||
1000 | if (grab_state == QZ_INVISIBLE_GRAB) { /*see comment above*/ | ||
1001 | QZ_PrivateWarpCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2); | ||
1002 | CGAssociateMouseAndMouseCursorPosition (0); | ||
1003 | } | ||
1004 | } | ||
1005 | break; | ||
1006 | case NSScrollWheel: | ||
1007 | if ( isInGameWin ) { | ||
1008 | float dy, dx; | ||
1009 | Uint8 button; | ||
1010 | dy = [ event deltaY ]; | ||
1011 | dx = [ event deltaX ]; | ||
1012 | if ( dy > 0.0 ) /* Scroll up */ | ||
1013 | button = SDL_BUTTON_WHEELUP; | ||
1014 | else if ( dy < 0.0 ) /* Scroll down */ | ||
1015 | button = SDL_BUTTON_WHEELDOWN; | ||
1016 | else | ||
1017 | break; /* Horizontal scroll */ | ||
1018 | /* For now, wheel is sent as a quick down+up */ | ||
1019 | SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0); | ||
1020 | SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0); | ||
1021 | } | ||
1022 | break; | ||
1023 | case NSKeyUp: | ||
1024 | QZ_DoKey (this, SDL_RELEASED, event); | ||
1025 | break; | ||
1026 | case NSKeyDown: | ||
1027 | QZ_DoKey (this, SDL_PRESSED, event); | ||
1028 | break; | ||
1029 | case NSFlagsChanged: | ||
1030 | break; | ||
1031 | case NSAppKitDefined: | ||
1032 | [ NSApp sendEvent:event ]; | ||
1033 | if ([ event subtype ] == NSApplicationActivatedEventType && (mode_flags & SDL_FULLSCREEN)) { | ||
1034 | /* the default handling of this event seems to reset any cursor set by [NSCursor set] (used by SDL_SetCursor() in fullscreen mode) to the default system arrow cursor */ | ||
1035 | SDL_Cursor *sdlc = SDL_GetCursor(); | ||
1036 | if (sdlc != NULL && sdlc->wm_cursor != NULL) { | ||
1037 | [ sdlc->wm_cursor->nscursor set ]; | ||
1038 | } | ||
1039 | } | ||
1040 | break; | ||
1041 | /* case NSApplicationDefined: break; */ | ||
1042 | /* case NSPeriodic: break; */ | ||
1043 | /* case NSCursorUpdate: break; */ | ||
1044 | default: | ||
1045 | [ NSApp sendEvent:event ]; | ||
1046 | } | ||
1047 | } | ||
1048 | } while (event != nil); | ||
1049 | |||
1050 | /* handle accumulated mouse moved events */ | ||
1051 | if (dx != 0 || dy != 0) | ||
1052 | SDL_PrivateMouseMotion (0, 1, dx, dy); | ||
1053 | |||
1054 | [ pool release ]; | ||
1055 | } | ||
1056 | |||
1057 | void QZ_UpdateMouse (_THIS) | ||
1058 | { | ||
1059 | NSPoint p; | ||
1060 | QZ_GetMouseLocation (this, &p); | ||
1061 | SDL_PrivateAppActive (QZ_IsMouseInWindow (this), SDL_APPMOUSEFOCUS); | ||
1062 | SDL_PrivateMouseMotion (0, 0, p.x, p.y); | ||
1063 | } | ||
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 | ||
51 | CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx) | ||
52 | { | ||
53 | return [nsctx cglContext]; | ||
54 | } | ||
55 | #else | ||
56 | CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx) | ||
57 | { | ||
58 | return (CGLContextObj) [nsctx CGLContextObj]; | ||
59 | } | ||
60 | #endif | ||
61 | |||
62 | |||
63 | /* OpenGL helper functions (used internally) */ | ||
64 | |||
65 | int 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 | |||
189 | void QZ_TearDownOpenGL (_THIS) { | ||
190 | |||
191 | [ NSOpenGLContext clearCurrentContext ]; | ||
192 | [ gl_context clearDrawable ]; | ||
193 | [ gl_context release ]; | ||
194 | } | ||
195 | |||
196 | |||
197 | /* SDL OpenGL functions */ | ||
198 | static const char *DEFAULT_OPENGL_LIB_NAME = | ||
199 | "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"; | ||
200 | |||
201 | int 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 | |||
223 | void* QZ_GL_GetProcAddress (_THIS, const char *proc) { | ||
224 | return SDL_LoadFunction(opengl_library, proc); | ||
225 | } | ||
226 | |||
227 | int 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 | |||
285 | int QZ_GL_MakeCurrent (_THIS) { | ||
286 | [ gl_context makeCurrentContext ]; | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | void 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. */ | ||
84 | CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx); | ||
85 | |||
86 | |||
87 | /* Main driver structure to store required state information */ | ||
88 | typedef 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 */ | ||
171 | enum { | ||
172 | QZ_UNGRABBED = 0, | ||
173 | QZ_VISIBLE_GRAB, | ||
174 | QZ_INVISIBLE_GRAB | ||
175 | }; | ||
176 | |||
177 | /* grab actions - these can change the grabbed state */ | ||
178 | enum { | ||
179 | QZ_ENABLE_GRAB = 0, | ||
180 | QZ_DISABLE_GRAB, | ||
181 | QZ_HIDECURSOR, | ||
182 | QZ_SHOWCURSOR | ||
183 | }; | ||
184 | |||
185 | /* Gamma Functions */ | ||
186 | int QZ_SetGamma (_THIS, float red, float green, float blue); | ||
187 | int QZ_GetGamma (_THIS, float *red, float *green, float *blue); | ||
188 | int QZ_SetGammaRamp (_THIS, Uint16 *ramp); | ||
189 | int QZ_GetGammaRamp (_THIS, Uint16 *ramp); | ||
190 | |||
191 | /* OpenGL functions */ | ||
192 | int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags); | ||
193 | void QZ_TearDownOpenGL (_THIS); | ||
194 | void* QZ_GL_GetProcAddress (_THIS, const char *proc); | ||
195 | int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value); | ||
196 | int QZ_GL_MakeCurrent (_THIS); | ||
197 | void QZ_GL_SwapBuffers (_THIS); | ||
198 | int QZ_GL_LoadLibrary (_THIS, const char *location); | ||
199 | |||
200 | /* Cursor and Mouse functions */ | ||
201 | void QZ_FreeWMCursor (_THIS, WMcursor *cursor); | ||
202 | WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, | ||
203 | int w, int h, int hot_x, int hot_y); | ||
204 | int QZ_ShowWMCursor (_THIS, WMcursor *cursor); | ||
205 | void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y); | ||
206 | void QZ_MoveWMCursor (_THIS, int x, int y); | ||
207 | void QZ_CheckMouseMode (_THIS); | ||
208 | void QZ_UpdateMouse (_THIS); | ||
209 | |||
210 | /* Event functions */ | ||
211 | void QZ_InitOSKeymap (_THIS); | ||
212 | void QZ_PumpEvents (_THIS); | ||
213 | |||
214 | /* Window Manager functions */ | ||
215 | void QZ_SetCaption (_THIS, const char *title, const char *icon); | ||
216 | void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask); | ||
217 | int QZ_IconifyWindow (_THIS); | ||
218 | SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode); | ||
219 | /*int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info);*/ | ||
220 | |||
221 | /* Private functions (used internally) */ | ||
222 | void QZ_PrivateWarpCursor (_THIS, int x, int y); | ||
223 | void QZ_ChangeGrabState (_THIS, int action); | ||
224 | void QZ_RegisterForSleepNotifications (_THIS); | ||
225 | void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p); | ||
226 | void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p); | ||
227 | BOOL QZ_IsMouseInWindow (_THIS); | ||
228 | void QZ_DoActivate (_THIS); | ||
229 | void 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)) | ||
31 | CG_EXTERN void *CGDisplayBaseAddress(CGDirectDisplayID display) | ||
32 | CG_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_6, | ||
33 | __IPHONE_NA, __IPHONE_NA); | ||
34 | CG_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 | |||
40 | static inline BOOL IS_LION_OR_LATER(_THIS) | ||
41 | { | ||
42 | return (system_version >= 0x1070); | ||
43 | } | ||
44 | |||
45 | static 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 | ||
68 | static 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 | ||
75 | static 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. */ | ||
91 | CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef); | ||
92 | |||
93 | /* Bootstrap functions */ | ||
94 | static int QZ_Available (); | ||
95 | static SDL_VideoDevice* QZ_CreateDevice (int device_index); | ||
96 | static void QZ_DeleteDevice (SDL_VideoDevice *device); | ||
97 | |||
98 | /* Initialization, Query, Setup, and Redrawing functions */ | ||
99 | static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format); | ||
100 | |||
101 | static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, | ||
102 | Uint32 flags); | ||
103 | static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop, BOOL save_gl); | ||
104 | |||
105 | static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, | ||
106 | int width, int height, int bpp, | ||
107 | Uint32 flags); | ||
108 | static int QZ_ToggleFullScreen (_THIS, int on); | ||
109 | static int QZ_SetColors (_THIS, int first_color, | ||
110 | int num_colors, SDL_Color *colors); | ||
111 | |||
112 | #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) | ||
113 | static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface); | ||
114 | static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface); | ||
115 | static int QZ_ThreadFlip (_THIS); | ||
116 | static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface); | ||
117 | static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects); | ||
118 | static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects); | ||
119 | #endif | ||
120 | |||
121 | static void QZ_UpdateRects (_THIS, int num_rects, SDL_Rect *rects); | ||
122 | static void QZ_VideoQuit (_THIS); | ||
123 | |||
124 | static int QZ_LockHWSurface(_THIS, SDL_Surface *surface); | ||
125 | static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface); | ||
126 | static int QZ_AllocHWSurface(_THIS, SDL_Surface *surface); | ||
127 | static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface); | ||
128 | |||
129 | /* Bootstrap binding, enables entry point into the driver */ | ||
130 | VideoBootStrap 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 | |||
141 | static 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 | |||
151 | static 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 */ | ||
163 | static int QZ_Available () | ||
164 | { | ||
165 | return 1; | ||
166 | } | ||
167 | |||
168 | static 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 | |||
240 | static 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 | |||
249 | static 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 | |||
297 | static 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 | |||
394 | static 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 | |||
508 | static 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 | |||
519 | static 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 | |||
536 | static inline CGError QZ_RestoreDisplayMode(_THIS) | ||
537 | { | ||
538 | return QZ_SetDisplayMode(this, save_mode); | ||
539 | } | ||
540 | |||
541 | static 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 | |||
636 | static 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 | |||
681 | static 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 */ | ||
946 | ERR_NO_GL: goto ERR_DOUBLEBUF; /* this goto is to stop a compiler warning on newer SDKs. */ | ||
947 | ERR_DOUBLEBUF: QZ_RestoreDisplayMode(this); | ||
948 | ERR_NO_SWITCH: CGReleaseAllDisplays (); | ||
949 | ERR_NO_CAPTURE: | ||
950 | ERR_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 | |||
957 | static 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 | |||
1129 | static 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 | |||
1211 | static 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 | |||
1239 | static int QZ_ToggleFullScreen (_THIS, int on) | ||
1240 | { | ||
1241 | return 0; | ||
1242 | } | ||
1243 | |||
1244 | static 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) | ||
1273 | static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface) | ||
1274 | { | ||
1275 | return 1; | ||
1276 | } | ||
1277 | |||
1278 | static 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> */ | ||
1283 | static 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 | |||
1296 | static 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, ¶m); | ||
1312 | policy = SCHED_RR; | ||
1313 | param.sched_priority = sched_get_priority_max (policy); | ||
1314 | pthread_setschedparam (current_thread, policy, ¶m); | ||
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 | |||
1402 | static 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 | |||
1420 | static 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 | |||
1426 | static 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 */ | ||
1433 | static 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 | |||
1472 | static 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 | |||
1503 | static 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 | |||
1531 | static 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 | |||
1575 | static int QZ_LockHWSurface(_THIS, SDL_Surface *surface) | ||
1576 | { | ||
1577 | return 1; | ||
1578 | } | ||
1579 | |||
1580 | static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface) | ||
1581 | { | ||
1582 | } | ||
1583 | |||
1584 | static int QZ_AllocHWSurface(_THIS, SDL_Surface *surface) | ||
1585 | { | ||
1586 | return(-1); /* unallowed (no HWSURFACE support here). */ | ||
1587 | } | ||
1588 | |||
1589 | static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface) | ||
1590 | { | ||
1591 | } | ||
1592 | |||
1593 | /* Gamma functions */ | ||
1594 | int 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 | |||
1624 | int 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 | |||
1636 | int 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 | |||
1662 | int 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 | |||
23 | struct WMcursor { | ||
24 | NSCursor *nscursor; | ||
25 | }; | ||
26 | |||
27 | void 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 | |||
28 | void QZ_FreeWMCursor (_THIS, WMcursor *cursor) { | ||
29 | |||
30 | if ( cursor != NULL ) { | ||
31 | [ cursor->nscursor release ]; | ||
32 | free (cursor); | ||
33 | } | ||
34 | } | ||
35 | |||
36 | WMcursor* 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 | |||
83 | outOfMemory: | ||
84 | [ pool release ]; | ||
85 | if (cursor != NULL) SDL_free(cursor); | ||
86 | SDL_OutOfMemory(); | ||
87 | return(NULL); | ||
88 | } | ||
89 | |||
90 | void 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 | |||
108 | BOOL 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 | |||
117 | int 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 */ | ||
150 | void 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 */ | ||
158 | void 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 */ | ||
165 | void 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 */ | ||
179 | void 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 */ | ||
193 | CGPoint 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 */ | ||
216 | void 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 | |||
232 | void 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 | |||
248 | void 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 | |||
261 | void QZ_MoveWMCursor (_THIS, int x, int y) { } | ||
262 | void QZ_CheckMouseMode (_THIS) { } | ||
263 | |||
264 | void 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 | |||
281 | void 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 | |||
345 | freePool: | ||
346 | [ pool release ]; | ||
347 | } | ||
348 | |||
349 | int 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 | /* | ||
366 | int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) { | ||
367 | info->nsWindowPtr = qz_window; | ||
368 | return 0; | ||
369 | }*/ | ||
370 | |||
371 | void 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 | |||
417 | SDL_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) | ||
25 | typedef 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 | */ | ||
33 | static 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 | ||