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 = surface->format->BitsPerPixel; 37 Uint32 amask = surface->format->Amask; 38 39 if (bpp == 32 && amask != 0) { 40 41 Uint32 *pixels = (Uint32*) surface->pixels; 42 Uint32 rowPixels = surface->pitch / 4; 43 Uint32 i, j; 44 45 for (i = 0; i < surface->h; i++) 46 for (j = 0; j < surface->w; j++) { 47 48 pixels[ (i * rowPixels) + j ] |= amask; 49 } 50 } 51 } 52 53 @implementation SDL_QuartzWindow 54 55 /* we override these methods to fix the miniaturize animation/dock icon bug */ 56 - (void)miniaturize:(id)sender 57 { 58 if (SDL_VideoSurface->flags & SDL_OPENGL) { 59 60 /* 61 Future: Grab framebuffer and put into NSImage 62 [ qz_window setMiniwindowImage:image ]; 63 */ 64 } 65 else { 66 67 /* make the alpha channel opaque so anim won't have holes in it */ 68 QZ_SetPortAlphaOpaque (); 69 } 70 71 /* window is hidden now */ 72 SDL_PrivateAppActive (0, SDL_APPACTIVE); 73 74 [ super miniaturize:sender ]; 75 } 76 77 - (void)display 78 { 79 /* 80 This method fires just before the window deminaturizes from the Dock. 81 82 We'll save the current visible surface, let the window manager redraw any 83 UI elements, and restore the SDL surface. This way, no expose event 84 is required, and the deminiaturize works perfectly. 85 */ 86 SDL_VideoDevice *this = (SDL_VideoDevice*)current_video; 87 88 /* make sure pixels are fully opaque */ 89 if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) ) 90 QZ_SetPortAlphaOpaque (); 91 92 /* save current visible SDL surface */ 93 [ self cacheImageInRect:[ window_view frame ] ]; 94 95 /* let the window manager redraw controls, border, etc */ 96 [ super display ]; 97 98 /* restore visible SDL surface */ 99 [ self restoreCachedImage ]; 100 101 /* window is visible again */ 102 SDL_PrivateAppActive (1, SDL_APPACTIVE); 103 } 104 105 - (void)setFrame:(NSRect)frameRect display:(BOOL)flag 106 { 107 108 /* 109 If the video surface is NULL, this originated from QZ_SetVideoMode, 110 so don't send the resize event. 111 */ 112 SDL_VideoDevice *this = (SDL_VideoDevice*)current_video; 113 114 if (this && SDL_VideoSurface == NULL) { 115 116 [ super setFrame:frameRect display:flag ]; 117 } 118 else if (this && qz_window) { 119 120 NSRect newViewFrame; 121 122 [ super setFrame:frameRect display:flag ]; 123 124 newViewFrame = [ window_view frame ]; 125 126 SDL_PrivateResize (newViewFrame.size.width, newViewFrame.size.height); 127 } 128 } 129 130 /* QZ_DoActivate() calls a low-level CoreGraphics routine to adjust 131 the cursor position, if input is being grabbed. If app activation is 132 triggered by a mouse click in the title bar, then the window manager 133 gets confused and thinks we're dragging the window. The solution 134 below postpones the activate event to avoid this scenario. */ 135 - (void)becomeKeyWindow 136 { 137 NSEvent *event = [self currentEvent]; 138 if ([event type] == NSLeftMouseDown && [event window] == self) 139 watchForMouseUp = YES; 140 else 141 [super becomeKeyWindow]; 142 } 143 144 - (void)sendEvent:(NSEvent *)event 145 { 146 [super sendEvent:event]; 147 if (watchForMouseUp && [event type] == NSLeftMouseUp) 148 { 149 watchForMouseUp = NO; 150 [super becomeKeyWindow]; 151 } 152 } 153 154 - (void)appDidHide:(NSNotification*)note 155 { 156 SDL_PrivateAppActive (0, SDL_APPACTIVE); 157 } 158 159 - (void)appWillUnhide:(NSNotification*)note 160 { 161 SDL_VideoDevice *this = (SDL_VideoDevice*)current_video; 162 163 if ( this ) { 164 165 /* make sure pixels are fully opaque */ 166 if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) ) 167 QZ_SetPortAlphaOpaque (); 168 169 /* save current visible SDL surface */ 170 [ self cacheImageInRect:[ window_view frame ] ]; 171 } 172 } 173 174 - (void)appDidUnhide:(NSNotification*)note 175 { 176 /* restore cached image, since it may not be current, post expose event too */ 177 [ self restoreCachedImage ]; 178 179 /*SDL_PrivateExpose ();*/ 180 181 SDL_PrivateAppActive (1, SDL_APPACTIVE); 182 } 183 184 - (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag 185 { 186 /* Make our window subclass receive these application notifications */ 187 [ [ NSNotificationCenter defaultCenter ] addObserver:self 188 selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ]; 189 190 [ [ NSNotificationCenter defaultCenter ] addObserver:self 191 selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ]; 192 193 [ [ NSNotificationCenter defaultCenter ] addObserver:self 194 selector:@selector(appWillUnhide:) name:NSApplicationWillUnhideNotification object:NSApp ]; 195 196 return [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ]; 197 } 198 199 @end 200 201 @implementation SDL_QuartzWindowDelegate 202 - (BOOL)windowShouldClose:(id)sender 203 { 204 SDL_PrivateQuit(); 205 return NO; 206 } 207 208 - (void)windowDidBecomeKey:(NSNotification *)aNotification 209 { 210 QZ_DoActivate (current_video); 211 } 212 213 - (void)windowDidResignKey:(NSNotification *)aNotification 214 { 215 QZ_DoDeactivate (current_video); 216 } 217 218 @end 219 220 @implementation SDL_QuartzView 221 222 - (void)resetCursorRects 223 { 224 SDL_Cursor *sdlc = SDL_GetCursor(); 225 if (sdlc != NULL && sdlc->wm_cursor != NULL) { 226 [self addCursorRect: [self visibleRect] cursor: sdlc->wm_cursor->nscursor]; 227 } 228 } 229 230 @end 231