1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2003 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 /* If not OpenGL, we have to update the pixels and pitch */ 130 if ( ! ( SDL_VideoSurface->flags & SDL_OPENGL ) ) { 131 132 CGrafPtr thePort = [ window_view qdPort ]; 133 LockPortBits ( thePort ); 134 135 SDL_VideoSurface->pixels = GetPixBaseAddr ( GetPortPixMap ( thePort ) ); 136 SDL_VideoSurface->pitch = GetPixRowBytes ( GetPortPixMap ( thePort ) ); 137 138 /* 139 SDL_VideoSurface->pixels now points to the window's pixels 140 We want it to point to the *view's* pixels 141 */ 142 { 143 int vOffset = [ qz_window frame ].size.height - 144 newViewFrame.size.height - newViewFrame.origin.y; 145 146 int hOffset = newViewFrame.origin.x; 147 148 SDL_VideoSurface->pixels = (Uint8 *)SDL_VideoSurface->pixels + (vOffset * SDL_VideoSurface->pitch) + hOffset * (device_bpp/8); 149 } 150 151 UnlockPortBits ( thePort ); 152 } 153 } 154 } 155 156 - (void)appDidHide:(NSNotification*)note 157 { 158 SDL_PrivateAppActive (0, SDL_APPACTIVE); 159 } 160 161 - (void)appWillUnhide:(NSNotification*)note 162 { 163 SDL_VideoDevice *this = (SDL_VideoDevice*)current_video; 164 165 if ( this ) { 166 167 /* make sure pixels are fully opaque */ 168 if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) ) 169 QZ_SetPortAlphaOpaque (); 170 171 /* save current visible SDL surface */ 172 [ self cacheImageInRect:[ window_view frame ] ]; 173 } 174 } 175 176 - (void)appDidUnhide:(NSNotification*)note 177 { 178 /* restore cached image, since it may not be current, post expose event too */ 179 [ self restoreCachedImage ]; 180 181 /*SDL_PrivateExpose ();*/ 182 183 SDL_PrivateAppActive (1, SDL_APPACTIVE); 184 } 185 186 - (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag 187 { 188 /* Make our window subclass receive these application notifications */ 189 [ [ NSNotificationCenter defaultCenter ] addObserver:self 190 selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ]; 191 192 [ [ NSNotificationCenter defaultCenter ] addObserver:self 193 selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ]; 194 195 [ [ NSNotificationCenter defaultCenter ] addObserver:self 196 selector:@selector(appWillUnhide:) name:NSApplicationWillUnhideNotification object:NSApp ]; 197 198 return [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ]; 199 } 200 201 @end 202 203 @implementation SDL_QuartzWindowDelegate 204 - (BOOL)windowShouldClose:(id)sender 205 { 206 SDL_PrivateQuit(); 207 return NO; 208 } 209 210 - (void)windowDidBecomeKey:(NSNotification *)aNotification 211 { 212 QZ_DoActivate (current_video); 213 } 214 215 - (void)windowDidResignKey:(NSNotification *)aNotification 216 { 217 QZ_DoDeactivate (current_video); 218 } 219 220 @end 221 222 @implementation SDL_QuartzView 223 224 - (void)resetCursorRects 225 { 226 SDL_Cursor *sdlc = SDL_GetCursor(); 227 if (sdlc != NULL && sdlc->wm_cursor != NULL) { 228 [self addCursorRect: [self visibleRect] cursor: sdlc->wm_cursor->nscursor]; 229 } 230 } 231 232 @end 233