Date: Sat, 9 Aug 2003 20:14:06 -0400
authorSam Lantinga <slouken@libsdl.org>
Sun, 10 Aug 2003 07:21:43 +0000
changeset 683 5d2f027b3349
parent 682 8b2b97e466bc
child 684 9dcfc694a1e4
Date: Sat, 9 Aug 2003 20:14:06 -0400 From: Darrell Walisser Subject: Re: Updated projects? >> Did you get a chance to look at my "Custom Cocoa" demo? I have a few >> minor patches that enable SDL/Cocoa integration, and a project >> template. > > I didn't yet, but go ahead and send me the patches. :) > I updated the patch for current CVS. There are a lot of changes, but I don't think I've broken anything. This patch also improves the behavior of window minimize/deminimize.
src/video/quartz/SDL_QuartzEvents.m
src/video/quartz/SDL_QuartzVideo.m
src/video/quartz/SDL_QuartzWM.m
src/video/quartz/SDL_QuartzWindow.m
--- a/src/video/quartz/SDL_QuartzEvents.m	Sat Aug 09 22:49:28 2003 +0000
+++ b/src/video/quartz/SDL_QuartzEvents.m	Sun Aug 10 07:21:43 2003 +0000
@@ -251,6 +251,9 @@
             SDL_PrivateKeyboard (state, &key);
         }
     }
+    
+    if (getenv ("SDL_ENABLEAPPEVENTS"))
+        [ NSApp sendEvent:event ];
 }
 
 static void QZ_DoModifiers (_THIS, unsigned int newMods) {
@@ -464,7 +467,7 @@
             
             type = [ event type ];
             isForGameWin = (qz_window == [ event window ]);
-            isInGameWin = (mode_flags & SDL_FULLSCREEN) ? true : NSPointInRect([event locationInWindow], winRect);
+            isInGameWin = (mode_flags & SDL_FULLSCREEN) ? true : NSPointInRect([event locationInWindow], [ window_view frame ]);
             switch (type) {
                 case NSLeftMouseDown:
                     if ( getenv("SDL_HAS3BUTTONMOUSE") ) {
--- a/src/video/quartz/SDL_QuartzVideo.m	Sat Aug 09 22:49:28 2003 +0000
+++ b/src/video/quartz/SDL_QuartzVideo.m	Sun Aug 10 07:21:43 2003 +0000
@@ -396,7 +396,6 @@
         CGDisplaySwitchToMode (display_id, save_mode);
         CGReleaseAllDisplays ();
         ShowMenuBar ();
-
         /* 
             Reset the main screen's rectangle
             See comment in QZ_SetVideoFullscreen for why we do this
@@ -580,6 +579,7 @@
                                          int height, int bpp, Uint32 flags) {
     unsigned int style;
     NSRect contentRect;
+    BOOL isCustom = NO;
     int center_window = 1;
     int origin_x, origin_y;
 
@@ -602,7 +602,41 @@
              (mode_flags & SDL_OPENGL) || 
              (flags & SDL_OPENGL) )
             QZ_UnsetVideoMode (this);
-        
+    
+    /* Check for user-specified window and view */
+    {
+        char *windowPtrString = getenv ("SDL_NSWindowPointer");
+        char *viewPtrString = getenv ("SDL_NSQuickDrawViewPointer");
+    
+        if (windowPtrString && viewPtrString) {
+            
+            /* Release any previous window */
+            if ( qz_window ) {
+                [ qz_window release ];
+                qz_window = nil;
+            }
+            
+            qz_window = (NSWindow*)atoi(windowPtrString);
+            window_view = (NSQuickDrawView*)atoi(viewPtrString);
+            isCustom = YES;
+            
+            /* 
+                Retain reference to window because we
+                might release it in QZ_UnsetVideoMode
+            */
+            [ qz_window retain ];
+            
+            style = [ qz_window styleMask ];
+            /* Check resizability */
+            if ( style & NSResizableWindowMask )
+                current->flags |= SDL_RESIZABLE;
+            
+            /* Check frame */
+            if ( style & NSBorderlessWindowMask )
+                current->flags |= SDL_NOFRAME;
+        }
+    }
+    
     /* Check if we should recreate the window */
     if (qz_window == nil) {
     
@@ -650,8 +684,10 @@
     /* We already have a window, just change its size */
     else {
     
-        [ qz_window setContentSize:contentRect.size ];
-        current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags;
+        if (!isCustom) {
+            [ qz_window setContentSize:contentRect.size ];
+            current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags;
+        }
     }
 
     /* For OpenGL, we bind the context to a subview */
@@ -692,9 +728,18 @@
         current->flags |= SDL_PREALLOC;
         current->flags |= SDL_ASYNCBLIT;
         
-        /* Offset below the title bar to fill the full content region */
-        current->pixels += ((int)([ qz_window frame ].size.height) - height) * current->pitch;
-
+        /* 
+            current->pixels now points to the window's pixels
+            We want it to point to the *view's* pixels 
+        */
+        { 
+            int vOffset = [ qz_window frame ].size.height - 
+                [ window_view frame ].size.height - [ window_view frame ].origin.y;
+            
+            int hOffset = [ window_view frame ].origin.x;
+                    
+            current->pixels += (vOffset * current->pitch) + hOffset * (device_bpp/8);
+        }
         this->UpdateRects     = QZ_UpdateRects;
         this->LockHWSurface   = QZ_LockWindow;
         this->UnlockHWSurface = QZ_UnlockWindow;
--- a/src/video/quartz/SDL_QuartzWM.m	Sat Aug 09 22:49:28 2003 +0000
+++ b/src/video/quartz/SDL_QuartzWM.m	Sun Aug 10 07:21:43 2003 +0000
@@ -119,28 +119,35 @@
 /* Convert SDL coordinate to Cocoa coordinate */
 static void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) {
 
-    int height;
-    
     if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */
     
-        height = CGDisplayPixelsHigh (display_id);
+        p->y = CGDisplayPixelsHigh (display_id) - p->y - 1;
     }
     else {
         
-        height = NSHeight ( [ qz_window frame ] );
-        if ( [ qz_window styleMask ] & NSTitledWindowMask ) {
+        NSPoint newPoint;
         
-            height -= 22;
-        }
+        newPoint = [ window_view convertPoint:*p toView:[ qz_window contentView ] ];
+        
+        *p = newPoint;
     }
-    
-    p->y = height - p->y - 1;
 }
 
 /* Convert Cocoa coordinate to SDL coordinate */
 static void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) {
 
-    QZ_PrivateSDLToCocoa (this, p);
+    if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */
+    
+        p->y = CGDisplayPixelsHigh (display_id) - p->y - 1;
+    }
+    else {
+        
+        NSPoint newPoint;
+        
+        newPoint = [ window_view convertPoint:*p fromView:[ qz_window contentView ] ];
+        
+        *p = newPoint;
+    }
 }
 
 /* Convert SDL coordinate to window server (CoreGraphics) coordinate */
@@ -165,6 +172,7 @@
     return cgp;
 }
 
+#if 0 /* Dead code */
 /* Convert window server (CoreGraphics) coordinate to SDL coordinate */
 static void QZ_PrivateCGToSDL (_THIS, NSPoint *p) {
             
@@ -180,6 +188,7 @@
         QZ_PrivateCocoaToSDL (this, p);
     }
 }
+#endif /* Dead code */
 
 static void  QZ_PrivateWarpCursor (_THIS, int x, int y) {
     
@@ -188,7 +197,6 @@
     
     p = NSMakePoint (x, y);
     cgp = QZ_PrivateSDLToCG (this, &p);
-    QZ_PrivateCGToSDL (this, &p);
     
     /* this is the magic call that fixes cursor "freezing" after warp */
     CGSetLocalEventsSuppressionInterval (0.0);
--- a/src/video/quartz/SDL_QuartzWindow.m	Sat Aug 09 22:49:28 2003 +0000
+++ b/src/video/quartz/SDL_QuartzWindow.m	Sun Aug 10 07:21:43 2003 +0000
@@ -32,6 +32,7 @@
 - (void)display;
 - (void)setFrame:(NSRect)frameRect display:(BOOL)flag;
 - (void)appDidHide:(NSNotification*)note;
+- (void)appWillUnhide:(NSNotification*)note;
 - (void)appDidUnhide:(NSNotification*)note;
 - (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag;
 @end
@@ -63,13 +64,27 @@
 - (void)display
 {    
     /* 
-        This method fires just before the window deminaturizes.
-        So, it's just the right place to fixup the alpha channel - which
-        makes the deminiaturize animation look right.
+        This method fires just before the window deminaturizes from the Dock.
+        
+        We'll save the current visible surface, let the window manager redraw any
+        UI elements, and restore the SDL surface. This way, no expose event 
+        is required, and the deminiaturize works perfectly.
     */
-    if ( (SDL_VideoSurface->flags & SDL_OPENGL) == 0)
+     SDL_VideoDevice *this = (SDL_VideoDevice*)current_video;
+    
+    /* make sure pixels are fully opaque */
+    if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) )
         QZ_SetPortAlphaOpaque ();
-
+    
+    /* save current visible SDL surface */
+    [ self cacheImageInRect:[ window_view frame ] ];
+    
+    /* let the window manager redraw controls, border, etc */
+    [ super display ];
+    
+    /* restore visible SDL surface */
+    [ self restoreCachedImage ];
+    
     /* window is visible again */
     SDL_PrivateAppActive (1, SDL_APPACTIVE);
 }
@@ -81,30 +96,45 @@
         If the video surface is NULL, this originated from QZ_SetVideoMode,
         so don't send the resize event. 
     */
-    if (SDL_VideoSurface == NULL) {
+    SDL_VideoDevice *this = (SDL_VideoDevice*)current_video;
+    
+    if (this && SDL_VideoSurface == NULL) {
 
         [ super setFrame:frameRect display:flag ];
     }
-    else {
+    else if (this && qz_window) {
 
-        SDL_VideoDevice *this = (SDL_VideoDevice*)current_video;
+        NSRect newViewFrame;
         
-        NSRect sdlRect = [ NSWindow contentRectForFrameRect:frameRect styleMask:[self styleMask] ];
-
         [ super setFrame:frameRect display:flag ];
-        SDL_PrivateResize (sdlRect.size.width, sdlRect.size.height);
+        
+        newViewFrame = [ window_view frame ];
+        
+        SDL_PrivateResize (newViewFrame.size.width, newViewFrame.size.height);
 
         /* If not OpenGL, we have to update the pixels and pitch */
-        if ( ! this->screen->flags & SDL_OPENGL ) {
+        if ( ! ( SDL_VideoSurface->flags & SDL_OPENGL ) ) {
             
-            LockPortBits ( [ window_view qdPort ] );
+            CGrafPtr thePort = [ window_view qdPort ];
+            LockPortBits ( thePort );
             
-            SDL_VideoSurface->pixels = GetPixBaseAddr ( GetPortPixMap ( [ window_view qdPort ] ) );
-            SDL_VideoSurface->pitch  = GetPixRowBytes ( GetPortPixMap ( [ window_view qdPort ] ) );
+            SDL_VideoSurface->pixels = GetPixBaseAddr ( GetPortPixMap ( thePort ) );
+            SDL_VideoSurface->pitch  = GetPixRowBytes ( GetPortPixMap ( thePort ) );
+                        
+            /* 
+                SDL_VideoSurface->pixels now points to the window's pixels
+                We want it to point to the *view's* pixels 
+            */
+            { 
+                int vOffset = [ qz_window frame ].size.height - 
+                    newViewFrame.size.height - newViewFrame.origin.y;
+                
+                int hOffset = newViewFrame.origin.x;
+                        
+                SDL_VideoSurface->pixels += (vOffset * SDL_VideoSurface->pitch) + hOffset * (device_bpp/8);
+            }
             
-            SDL_VideoSurface->pixels += ((int)[ self frame ].size.height - (int)sdlRect.size.height) * SDL_VideoSurface->pitch;
-    
-            UnlockPortBits ( [ window_view qdPort ] );
+            UnlockPortBits ( thePort );
         }
     }
 }
@@ -114,8 +144,28 @@
     SDL_PrivateAppActive (0, SDL_APPACTIVE);
 }
 
+- (void)appWillUnhide:(NSNotification*)note
+{
+    SDL_VideoDevice *this = (SDL_VideoDevice*)current_video;
+    
+    if ( this ) {
+    
+        /* make sure pixels are fully opaque */
+        if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) )
+            QZ_SetPortAlphaOpaque ();
+          
+        /* save current visible SDL surface */
+        [ self cacheImageInRect:[ window_view frame ] ];
+    }
+}
+
 - (void)appDidUnhide:(NSNotification*)note
 {
+    /* restore cached image, since it may not be current, post expose event too */
+    [ self restoreCachedImage ];
+    
+    //SDL_PrivateExpose ();
+    
     SDL_PrivateAppActive (1, SDL_APPACTIVE);
 }
 
@@ -127,6 +177,9 @@
     
     [ [ NSNotificationCenter defaultCenter ] addObserver:self
         selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ];
+   
+    [ [ NSNotificationCenter defaultCenter ] addObserver:self
+        selector:@selector(appWillUnhide:) name:NSApplicationWillUnhideNotification object:NSApp ];
         
     return [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ];
 }