e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 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 |