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 (at) 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 232