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.
--- 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 ];
}