Date: Sat, 9 Aug 2003 20:14:06 -0400
authorSam Lantinga <slouken@libsdl.org>
Sun, 10 Aug 2003 07:21:43 +0000
changeset 6835d2f027b3349
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
     1.1 --- a/src/video/quartz/SDL_QuartzEvents.m	Sat Aug 09 22:49:28 2003 +0000
     1.2 +++ b/src/video/quartz/SDL_QuartzEvents.m	Sun Aug 10 07:21:43 2003 +0000
     1.3 @@ -251,6 +251,9 @@
     1.4              SDL_PrivateKeyboard (state, &key);
     1.5          }
     1.6      }
     1.7 +    
     1.8 +    if (getenv ("SDL_ENABLEAPPEVENTS"))
     1.9 +        [ NSApp sendEvent:event ];
    1.10  }
    1.11  
    1.12  static void QZ_DoModifiers (_THIS, unsigned int newMods) {
    1.13 @@ -464,7 +467,7 @@
    1.14              
    1.15              type = [ event type ];
    1.16              isForGameWin = (qz_window == [ event window ]);
    1.17 -            isInGameWin = (mode_flags & SDL_FULLSCREEN) ? true : NSPointInRect([event locationInWindow], winRect);
    1.18 +            isInGameWin = (mode_flags & SDL_FULLSCREEN) ? true : NSPointInRect([event locationInWindow], [ window_view frame ]);
    1.19              switch (type) {
    1.20                  case NSLeftMouseDown:
    1.21                      if ( getenv("SDL_HAS3BUTTONMOUSE") ) {
     2.1 --- a/src/video/quartz/SDL_QuartzVideo.m	Sat Aug 09 22:49:28 2003 +0000
     2.2 +++ b/src/video/quartz/SDL_QuartzVideo.m	Sun Aug 10 07:21:43 2003 +0000
     2.3 @@ -396,7 +396,6 @@
     2.4          CGDisplaySwitchToMode (display_id, save_mode);
     2.5          CGReleaseAllDisplays ();
     2.6          ShowMenuBar ();
     2.7 -
     2.8          /* 
     2.9              Reset the main screen's rectangle
    2.10              See comment in QZ_SetVideoFullscreen for why we do this
    2.11 @@ -580,6 +579,7 @@
    2.12                                           int height, int bpp, Uint32 flags) {
    2.13      unsigned int style;
    2.14      NSRect contentRect;
    2.15 +    BOOL isCustom = NO;
    2.16      int center_window = 1;
    2.17      int origin_x, origin_y;
    2.18  
    2.19 @@ -602,7 +602,41 @@
    2.20               (mode_flags & SDL_OPENGL) || 
    2.21               (flags & SDL_OPENGL) )
    2.22              QZ_UnsetVideoMode (this);
    2.23 -        
    2.24 +    
    2.25 +    /* Check for user-specified window and view */
    2.26 +    {
    2.27 +        char *windowPtrString = getenv ("SDL_NSWindowPointer");
    2.28 +        char *viewPtrString = getenv ("SDL_NSQuickDrawViewPointer");
    2.29 +    
    2.30 +        if (windowPtrString && viewPtrString) {
    2.31 +            
    2.32 +            /* Release any previous window */
    2.33 +            if ( qz_window ) {
    2.34 +                [ qz_window release ];
    2.35 +                qz_window = nil;
    2.36 +            }
    2.37 +            
    2.38 +            qz_window = (NSWindow*)atoi(windowPtrString);
    2.39 +            window_view = (NSQuickDrawView*)atoi(viewPtrString);
    2.40 +            isCustom = YES;
    2.41 +            
    2.42 +            /* 
    2.43 +                Retain reference to window because we
    2.44 +                might release it in QZ_UnsetVideoMode
    2.45 +            */
    2.46 +            [ qz_window retain ];
    2.47 +            
    2.48 +            style = [ qz_window styleMask ];
    2.49 +            /* Check resizability */
    2.50 +            if ( style & NSResizableWindowMask )
    2.51 +                current->flags |= SDL_RESIZABLE;
    2.52 +            
    2.53 +            /* Check frame */
    2.54 +            if ( style & NSBorderlessWindowMask )
    2.55 +                current->flags |= SDL_NOFRAME;
    2.56 +        }
    2.57 +    }
    2.58 +    
    2.59      /* Check if we should recreate the window */
    2.60      if (qz_window == nil) {
    2.61      
    2.62 @@ -650,8 +684,10 @@
    2.63      /* We already have a window, just change its size */
    2.64      else {
    2.65      
    2.66 -        [ qz_window setContentSize:contentRect.size ];
    2.67 -        current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags;
    2.68 +        if (!isCustom) {
    2.69 +            [ qz_window setContentSize:contentRect.size ];
    2.70 +            current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags;
    2.71 +        }
    2.72      }
    2.73  
    2.74      /* For OpenGL, we bind the context to a subview */
    2.75 @@ -692,9 +728,18 @@
    2.76          current->flags |= SDL_PREALLOC;
    2.77          current->flags |= SDL_ASYNCBLIT;
    2.78          
    2.79 -        /* Offset below the title bar to fill the full content region */
    2.80 -        current->pixels += ((int)([ qz_window frame ].size.height) - height) * current->pitch;
    2.81 -
    2.82 +        /* 
    2.83 +            current->pixels now points to the window's pixels
    2.84 +            We want it to point to the *view's* pixels 
    2.85 +        */
    2.86 +        { 
    2.87 +            int vOffset = [ qz_window frame ].size.height - 
    2.88 +                [ window_view frame ].size.height - [ window_view frame ].origin.y;
    2.89 +            
    2.90 +            int hOffset = [ window_view frame ].origin.x;
    2.91 +                    
    2.92 +            current->pixels += (vOffset * current->pitch) + hOffset * (device_bpp/8);
    2.93 +        }
    2.94          this->UpdateRects     = QZ_UpdateRects;
    2.95          this->LockHWSurface   = QZ_LockWindow;
    2.96          this->UnlockHWSurface = QZ_UnlockWindow;
     3.1 --- a/src/video/quartz/SDL_QuartzWM.m	Sat Aug 09 22:49:28 2003 +0000
     3.2 +++ b/src/video/quartz/SDL_QuartzWM.m	Sun Aug 10 07:21:43 2003 +0000
     3.3 @@ -119,28 +119,35 @@
     3.4  /* Convert SDL coordinate to Cocoa coordinate */
     3.5  static void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) {
     3.6  
     3.7 -    int height;
     3.8 -    
     3.9      if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */
    3.10      
    3.11 -        height = CGDisplayPixelsHigh (display_id);
    3.12 +        p->y = CGDisplayPixelsHigh (display_id) - p->y - 1;
    3.13      }
    3.14      else {
    3.15          
    3.16 -        height = NSHeight ( [ qz_window frame ] );
    3.17 -        if ( [ qz_window styleMask ] & NSTitledWindowMask ) {
    3.18 +        NSPoint newPoint;
    3.19          
    3.20 -            height -= 22;
    3.21 -        }
    3.22 +        newPoint = [ window_view convertPoint:*p toView:[ qz_window contentView ] ];
    3.23 +        
    3.24 +        *p = newPoint;
    3.25      }
    3.26 -    
    3.27 -    p->y = height - p->y - 1;
    3.28  }
    3.29  
    3.30  /* Convert Cocoa coordinate to SDL coordinate */
    3.31  static void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) {
    3.32  
    3.33 -    QZ_PrivateSDLToCocoa (this, p);
    3.34 +    if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */
    3.35 +    
    3.36 +        p->y = CGDisplayPixelsHigh (display_id) - p->y - 1;
    3.37 +    }
    3.38 +    else {
    3.39 +        
    3.40 +        NSPoint newPoint;
    3.41 +        
    3.42 +        newPoint = [ window_view convertPoint:*p fromView:[ qz_window contentView ] ];
    3.43 +        
    3.44 +        *p = newPoint;
    3.45 +    }
    3.46  }
    3.47  
    3.48  /* Convert SDL coordinate to window server (CoreGraphics) coordinate */
    3.49 @@ -165,6 +172,7 @@
    3.50      return cgp;
    3.51  }
    3.52  
    3.53 +#if 0 /* Dead code */
    3.54  /* Convert window server (CoreGraphics) coordinate to SDL coordinate */
    3.55  static void QZ_PrivateCGToSDL (_THIS, NSPoint *p) {
    3.56              
    3.57 @@ -180,6 +188,7 @@
    3.58          QZ_PrivateCocoaToSDL (this, p);
    3.59      }
    3.60  }
    3.61 +#endif /* Dead code */
    3.62  
    3.63  static void  QZ_PrivateWarpCursor (_THIS, int x, int y) {
    3.64      
    3.65 @@ -188,7 +197,6 @@
    3.66      
    3.67      p = NSMakePoint (x, y);
    3.68      cgp = QZ_PrivateSDLToCG (this, &p);
    3.69 -    QZ_PrivateCGToSDL (this, &p);
    3.70      
    3.71      /* this is the magic call that fixes cursor "freezing" after warp */
    3.72      CGSetLocalEventsSuppressionInterval (0.0);
     4.1 --- a/src/video/quartz/SDL_QuartzWindow.m	Sat Aug 09 22:49:28 2003 +0000
     4.2 +++ b/src/video/quartz/SDL_QuartzWindow.m	Sun Aug 10 07:21:43 2003 +0000
     4.3 @@ -32,6 +32,7 @@
     4.4  - (void)display;
     4.5  - (void)setFrame:(NSRect)frameRect display:(BOOL)flag;
     4.6  - (void)appDidHide:(NSNotification*)note;
     4.7 +- (void)appWillUnhide:(NSNotification*)note;
     4.8  - (void)appDidUnhide:(NSNotification*)note;
     4.9  - (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag;
    4.10  @end
    4.11 @@ -63,13 +64,27 @@
    4.12  - (void)display
    4.13  {    
    4.14      /* 
    4.15 -        This method fires just before the window deminaturizes.
    4.16 -        So, it's just the right place to fixup the alpha channel - which
    4.17 -        makes the deminiaturize animation look right.
    4.18 +        This method fires just before the window deminaturizes from the Dock.
    4.19 +        
    4.20 +        We'll save the current visible surface, let the window manager redraw any
    4.21 +        UI elements, and restore the SDL surface. This way, no expose event 
    4.22 +        is required, and the deminiaturize works perfectly.
    4.23      */
    4.24 -    if ( (SDL_VideoSurface->flags & SDL_OPENGL) == 0)
    4.25 +     SDL_VideoDevice *this = (SDL_VideoDevice*)current_video;
    4.26 +    
    4.27 +    /* make sure pixels are fully opaque */
    4.28 +    if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) )
    4.29          QZ_SetPortAlphaOpaque ();
    4.30 -
    4.31 +    
    4.32 +    /* save current visible SDL surface */
    4.33 +    [ self cacheImageInRect:[ window_view frame ] ];
    4.34 +    
    4.35 +    /* let the window manager redraw controls, border, etc */
    4.36 +    [ super display ];
    4.37 +    
    4.38 +    /* restore visible SDL surface */
    4.39 +    [ self restoreCachedImage ];
    4.40 +    
    4.41      /* window is visible again */
    4.42      SDL_PrivateAppActive (1, SDL_APPACTIVE);
    4.43  }
    4.44 @@ -81,30 +96,45 @@
    4.45          If the video surface is NULL, this originated from QZ_SetVideoMode,
    4.46          so don't send the resize event. 
    4.47      */
    4.48 -    if (SDL_VideoSurface == NULL) {
    4.49 +    SDL_VideoDevice *this = (SDL_VideoDevice*)current_video;
    4.50 +    
    4.51 +    if (this && SDL_VideoSurface == NULL) {
    4.52  
    4.53          [ super setFrame:frameRect display:flag ];
    4.54      }
    4.55 -    else {
    4.56 +    else if (this && qz_window) {
    4.57  
    4.58 -        SDL_VideoDevice *this = (SDL_VideoDevice*)current_video;
    4.59 +        NSRect newViewFrame;
    4.60          
    4.61 -        NSRect sdlRect = [ NSWindow contentRectForFrameRect:frameRect styleMask:[self styleMask] ];
    4.62 -
    4.63          [ super setFrame:frameRect display:flag ];
    4.64 -        SDL_PrivateResize (sdlRect.size.width, sdlRect.size.height);
    4.65 +        
    4.66 +        newViewFrame = [ window_view frame ];
    4.67 +        
    4.68 +        SDL_PrivateResize (newViewFrame.size.width, newViewFrame.size.height);
    4.69  
    4.70          /* If not OpenGL, we have to update the pixels and pitch */
    4.71 -        if ( ! this->screen->flags & SDL_OPENGL ) {
    4.72 +        if ( ! ( SDL_VideoSurface->flags & SDL_OPENGL ) ) {
    4.73              
    4.74 -            LockPortBits ( [ window_view qdPort ] );
    4.75 +            CGrafPtr thePort = [ window_view qdPort ];
    4.76 +            LockPortBits ( thePort );
    4.77              
    4.78 -            SDL_VideoSurface->pixels = GetPixBaseAddr ( GetPortPixMap ( [ window_view qdPort ] ) );
    4.79 -            SDL_VideoSurface->pitch  = GetPixRowBytes ( GetPortPixMap ( [ window_view qdPort ] ) );
    4.80 +            SDL_VideoSurface->pixels = GetPixBaseAddr ( GetPortPixMap ( thePort ) );
    4.81 +            SDL_VideoSurface->pitch  = GetPixRowBytes ( GetPortPixMap ( thePort ) );
    4.82 +                        
    4.83 +            /* 
    4.84 +                SDL_VideoSurface->pixels now points to the window's pixels
    4.85 +                We want it to point to the *view's* pixels 
    4.86 +            */
    4.87 +            { 
    4.88 +                int vOffset = [ qz_window frame ].size.height - 
    4.89 +                    newViewFrame.size.height - newViewFrame.origin.y;
    4.90 +                
    4.91 +                int hOffset = newViewFrame.origin.x;
    4.92 +                        
    4.93 +                SDL_VideoSurface->pixels += (vOffset * SDL_VideoSurface->pitch) + hOffset * (device_bpp/8);
    4.94 +            }
    4.95              
    4.96 -            SDL_VideoSurface->pixels += ((int)[ self frame ].size.height - (int)sdlRect.size.height) * SDL_VideoSurface->pitch;
    4.97 -    
    4.98 -            UnlockPortBits ( [ window_view qdPort ] );
    4.99 +            UnlockPortBits ( thePort );
   4.100          }
   4.101      }
   4.102  }
   4.103 @@ -114,8 +144,28 @@
   4.104      SDL_PrivateAppActive (0, SDL_APPACTIVE);
   4.105  }
   4.106  
   4.107 +- (void)appWillUnhide:(NSNotification*)note
   4.108 +{
   4.109 +    SDL_VideoDevice *this = (SDL_VideoDevice*)current_video;
   4.110 +    
   4.111 +    if ( this ) {
   4.112 +    
   4.113 +        /* make sure pixels are fully opaque */
   4.114 +        if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) )
   4.115 +            QZ_SetPortAlphaOpaque ();
   4.116 +          
   4.117 +        /* save current visible SDL surface */
   4.118 +        [ self cacheImageInRect:[ window_view frame ] ];
   4.119 +    }
   4.120 +}
   4.121 +
   4.122  - (void)appDidUnhide:(NSNotification*)note
   4.123  {
   4.124 +    /* restore cached image, since it may not be current, post expose event too */
   4.125 +    [ self restoreCachedImage ];
   4.126 +    
   4.127 +    //SDL_PrivateExpose ();
   4.128 +    
   4.129      SDL_PrivateAppActive (1, SDL_APPACTIVE);
   4.130  }
   4.131  
   4.132 @@ -127,6 +177,9 @@
   4.133      
   4.134      [ [ NSNotificationCenter defaultCenter ] addObserver:self
   4.135          selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ];
   4.136 +   
   4.137 +    [ [ NSNotificationCenter defaultCenter ] addObserver:self
   4.138 +        selector:@selector(appWillUnhide:) name:NSApplicationWillUnhideNotification object:NSApp ];
   4.139          
   4.140      return [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ];
   4.141  }