Commit 7b88c898 authored by Sam Lantinga's avatar Sam Lantinga

Lots of cleanups by Darrell, added the ability to resize Cocoa windows.

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40502
parent 2ac69739
This diff is collapsed.
......@@ -22,9 +22,9 @@
/*
@file SDL_QuartzVideo.h
@author Darrell Walisser
@author Darrell Walisser, Max Horn, et al.
@abstract SDL video driver for MacOS X.
@abstract SDL video driver for Mac OS X.
@discussion
......@@ -33,17 +33,17 @@
- Keyboard repeat/mouse speed adjust (if needed)
- Multiple monitor support (currently only main display)
- Accelerated blitting support
- Fix white OpenGL window on minimize (fixed)
- Find out what events should be sent/ignored if window is mimimized
- Fix white OpenGL window on minimize (fixed) (update: broken again on 10.2)
- Find out what events should be sent/ignored if window is minimized
- Find a way to deal with external resolution/depth switch while app is running
- Resizeable windows
- Resizeable windows (done)
- Check accuracy of QZ_SetGamma()
Problems:
- OGL not working in full screen with software renderer
- SetColors sets palette correctly but clears framebuffer
- Crash in CG after several mode switches (I think this has been fixed)
- Retained windows don't draw their title bar quite right (OS Bug) (not using retained windows)
- Cursor in 8 bit modes is screwy (might just be Radeon PCI bug)
- Cursor in 8 bit modes is screwy (might just be Radeon PCI bug) (update: not just Radeon)
- Warping cursor delays mouse events for a fraction of a second,
there is a hack around this that helps a bit
*/
......@@ -79,8 +79,10 @@
}
@end
/* This is a workaround to directly access NSOpenGLContext's CGL context */
/* We need to do this in order to check for errors */
/*
This is a workaround to directly access NSOpenGLContext's CGL context
We need this to check for errors NSOpenGLContext doesn't support
*/
@interface NSOpenGLContext (CGLContextAccess)
- (CGLContextObj) cglContext;
@end
......@@ -92,8 +94,10 @@
}
@end
/* Structure for rez switch gamma fades */
/* We can hide the monitor flicker by setting the gamma tables to 0 */
/*
Structure for rez switch gamma fades
We can hide the monitor flicker by setting the gamma tables to 0
*/
#define QZ_GAMMA_TABLE_SIZE 256
typedef struct {
......@@ -112,14 +116,22 @@ typedef struct SDL_PrivateVideoData {
CFDictionaryRef save_mode; /* original mode of the display */
CFArrayRef mode_list; /* list of available fullscreen modes */
CGDirectPaletteRef palette; /* palette of an 8-bit display */
NSOpenGLContext *gl_context; /* object that represents an OpenGL rendering context */
NSOpenGLContext *gl_context; /* OpenGL rendering context */
Uint32 width, height, bpp; /* frequently used data about the display */
Uint32 flags; /* flags for mode, for teardown purposes */
Uint32 flags; /* flags for current mode, for teardown purposes */
Uint32 video_set; /* boolean; indicates if video was set correctly */
Uint32 warp_flag; /* boolean; notify to event loop that a warp just occured */
Uint32 warp_ticks; /* timestamp when the warp occured */
NSWindow *window; /* Cocoa window to implement the SDL window */
NSQuickDrawView *view; /* the window's view; draw 2D into this view */
NSQuickDrawView *view; /* the window's view; draw 2D and OpenGL into this view */
SDL_Surface *resize_icon; /* icon for the resize badge, we have to draw it by hand */
SDL_GrabMode current_grab_mode; /* default value is SDL_GRAB_OFF */
BOOL in_foreground; /* boolean; indicate if app is in foreground or not */
SDL_Rect **client_mode_list; /* resolution list to pass back to client */
SDLKey keymap[256]; /* Mac OS X to SDL key mapping */
Uint32 current_mods; /* current keyboard modifiers, to track modifier state */
Uint32 last_virtual_button;/* last virtual mouse button pressed */
ImageDescriptionHandle yuv_idh;
MatrixRecordPtr yuv_matrix;
DecompressorComponent yuv_codec;
......@@ -146,6 +158,14 @@ typedef struct SDL_PrivateVideoData {
#define video_set (this->hidden->video_set)
#define warp_ticks (this->hidden->warp_ticks)
#define warp_flag (this->hidden->warp_flag)
#define resize_icon (this->hidden->resize_icon)
#define current_grab_mode (this->hidden->current_grab_mode)
#define in_foreground (this->hidden->in_foreground)
#define client_mode_list (this->hidden->client_mode_list)
#define keymap (this->hidden->keymap)
#define current_mods (this->hidden->current_mods)
#define last_virtual_button (this->hidden->last_virtual_button)
#define yuv_idh (this->hidden->yuv_idh)
#define yuv_matrix (this->hidden->yuv_matrix)
#define yuv_codec (this->hidden->yuv_codec)
......@@ -156,7 +176,13 @@ typedef struct SDL_PrivateVideoData {
#define yuv_height (this->hidden->yuv_height)
#define yuv_port (this->hidden->yuv_port)
/* Obscuring code: maximum number of windows above ours (inclusive) */
/*
Obscuring code: maximum number of windows above ours (inclusive)
Note: this doesn't work too well in practice and should be
phased out when we add OpenGL 2D acceleration. It was never
enabled in the first place, so this shouldn't be a problem ;-)
*/
#define kMaxWindows 256
/* Some of the Core Graphics Server API for obscuring code */
......@@ -171,10 +197,11 @@ typedef struct SDL_PrivateVideoData {
#define kCGSWindowLevelUtility 3
#define kCGSWindowLevelNormal 0
/* For completeness; We never use these window levels, they are always below us
#define kCGSWindowLevelMBarShadow -20
#define kCGSWindowLevelDesktopPicture -2147483647
#define kCGSWindowLevelDesktop -2147483648
/*
For completeness; We never use these window levels, they are always below us
#define kCGSWindowLevelMBarShadow -20
#define kCGSWindowLevelDesktopPicture -2147483647
#define kCGSWindowLevelDesktop -2147483648
*/
typedef CGError CGSError;
......@@ -280,4 +307,3 @@ static SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode);
/* YUV functions */
static SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height,
Uint32 format, SDL_Surface *display);
\ No newline at end of file
This diff is collapsed.
......@@ -87,13 +87,13 @@ static int QZ_ShowWMCursor (_THIS, WMcursor *cursor) {
return 1;
}
/**
* Coordinate conversion functions, for convenience
* Cocoa sets the origin at the lower left corner of the window/screen
* SDL, CoreGraphics/WindowServer, and QuickDraw use the origin at the upper left corner
* The routines were written so they could be called before SetVideoMode() has finished;
* this might have limited usefulness at the moment, but the extra cost is trivial.
**/
/*
Coordinate conversion functions, for convenience
Cocoa sets the origin at the lower left corner of the window/screen
SDL, CoreGraphics/WindowServer, and QuickDraw use the origin at the upper left corner
The routines were written so they could be called before SetVideoMode() has finished;
this might have limited usefulness at the moment, but the extra cost is trivial.
*/
/* Convert Cocoa screen coordinate to Cocoa window coordinate */
static void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p) {
......@@ -190,7 +190,7 @@ static void QZ_PrivateWarpCursor (_THIS, int x, int y) {
static void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y) {
/* Only allow warping when in foreground */
if ( ! inForeground )
if ( ! in_foreground )
return;
/* Do the actual warp */
......@@ -227,8 +227,10 @@ static void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask)
NSAutoreleasePool *pool;
SDL_Rect rrect;
NSSize imgSize = {icon->w, icon->h};
pool = [ [ NSAutoreleasePool alloc ] init ];
SDL_GetClipRect(icon, &rrect);
/* create a big endian RGBA surface */
mergedSurface = SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_SRCALPHA,
icon->w, icon->h, 32, 0xff<<24, 0xff<<16, 0xff<<8, 0xff<<0);
......@@ -236,10 +238,12 @@ static void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask)
NSLog(@"Error creating surface for merge");
goto freePool;
}
if (SDL_BlitSurface(icon,&rrect,mergedSurface,&rrect)) {
NSLog(@"Error blitting to mergedSurface");
goto freePool;
}
if (mask) {
masksize=icon->w*icon->h;
surfPtr = (Uint8 *)mergedSurface->pixels;
......@@ -248,14 +252,18 @@ static void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask)
for (j=0;j<8;j++)
surfPtr[ALPHASHIFT+((i+j)<<2)]=(mask[i>>3]&(1<<(7-j)))?0xFF:0x00;
}
imgrep = [ [ NSBitmapImageRep alloc]
initWithBitmapDataPlanes:(unsigned char **)&mergedSurface->pixels
pixelsWide:icon->w pixelsHigh:icon->h bitsPerSample:8 samplesPerPixel:4
hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:icon->w<<2 bitsPerPixel:32 ];
img = [ [ NSImage alloc ] initWithSize:imgSize ];
[ img addRepresentation: imgrep ];
[ NSApp setApplicationIconImage:img ];
[ img release ];
[ imgrep release ];
SDL_FreeSurface(mergedSurface);
......@@ -265,13 +273,12 @@ freePool:
static int QZ_IconifyWindow (_THIS) {
/* Bug! minimize erases the framebuffer */
if ( ! [ qz_window isMiniaturized ] ) {
[ qz_window miniaturize:nil ];
return 1;
}
else {
SDL_SetError ("qz_window already iconified");
SDL_SetError ("window already iconified");
return 0;
}
}
......@@ -289,16 +296,94 @@ static SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) {
break;
case SDL_GRAB_OFF:
CGAssociateMouseAndMouseCursorPosition (1);
currentGrabMode = SDL_GRAB_OFF;
current_grab_mode = SDL_GRAB_OFF;
break;
case SDL_GRAB_ON:
QZ_WarpWMCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2);
CGAssociateMouseAndMouseCursorPosition (0);
currentGrabMode = SDL_GRAB_ON;
current_grab_mode = SDL_GRAB_ON;
break;
case SDL_GRAB_FULLSCREEN:
break;
}
return currentGrabMode;
return current_grab_mode;
}
/* Resize icon, BMP format */
static unsigned char QZ_ResizeIcon[] = {
0x42,0x4d,0x31,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00,
0x00,0x00,0x0d,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00,
0x00,0x00,0xfb,0x01,0x00,0x00,0x13,0x0b,0x00,0x00,0x13,0x0b,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff,
0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,
0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,
0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xda,0xda,0xda,0x87,
0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,
0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd5,0xd5,0xd5,0x87,0x87,0x87,0xe8,0xe8,0xe8,
0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,
0xda,0xda,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,
0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7,
0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,
0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8,
0xe8,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xd9,0xd9,0xd9,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xdc,
0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb,
0xdb,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb,0xdb,0x87,0x87,0x87,0xe8,
0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdc,
0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b
};
static void QZ_DrawResizeIcon (_THIS, RgnHandle dirtyRegion) {
/* Check if we should draw the resize icon */
if (SDL_VideoSurface->flags & SDL_RESIZABLE) {
Rect icon;
SetRect (&icon, SDL_VideoSurface->w - 13, SDL_VideoSurface->h - 13,
SDL_VideoSurface->w, SDL_VideoSurface->h);
if (RectInRgn (&icon, dirtyRegion)) {
SDL_Rect icon_rect;
/* Create the icon image */
if (resize_icon == NULL) {
SDL_RWops *rw;
SDL_Surface *tmp;
rw = SDL_RWFromMem (QZ_ResizeIcon, sizeof(QZ_ResizeIcon));
tmp = SDL_LoadBMP_RW (rw, SDL_TRUE);
resize_icon = SDL_ConvertSurface (tmp, SDL_VideoSurface->format, SDL_SRCCOLORKEY);
SDL_SetColorKey (resize_icon, SDL_SRCCOLORKEY, 0xFFFFFF);
SDL_FreeSurface (tmp);
}
icon_rect.x = SDL_VideoSurface->w - 13;
icon_rect.y = SDL_VideoSurface->h - 13;
icon_rect.w = 13;
icon_rect.h = 13;
SDL_BlitSurface (resize_icon, NULL, SDL_VideoSurface, &icon_rect);
}
}
}
\ No newline at end of file
/* Subclass of NSWindow to allow customization if we need it */
@interface SDL_QuartzWindow : NSWindow
{}
- (void)miniaturize:(id)sender;
- (void)deminiaturize:(id)sender;
- (void)display;
@end
/*
This function makes the *SDL region* of the window 100% opaque.
The genie effect uses the alpha component. Otherwise,
it doesn't seem to matter what value it has.
*/
static void QZ_SetPortAlphaOpaque () {
/**
* Function to set the opacity of window's pixels to 100%
* The opacity is only used by the window server code that does the minimize effect
**/
static void QZ_SetPortAlphaOpaque (CGrafPtr port, Uint32 noTitleBar) {
SDL_Surface *surface = current_video->screen;
int bpp;
Uint32 *pixels;
Uint32 rowPixels;
Uint32 width, height;
Uint32 bpp;
PixMapHandle pixMap;
Rect bounds;
int i, j;
pixMap = GetPortPixMap ( port );
bpp = GetPixDepth ( pixMap );
bpp = surface->format->BitsPerPixel;
if (bpp == 32) {
GetPortBounds ( port, &bounds );
width = bounds.right - bounds.left;
height = bounds.bottom - bounds.top;
LockPortBits (port);
pixels = (Uint32*) GetPixBaseAddr ( pixMap );
rowPixels = GetPixRowBytes ( pixMap ) / 4;
if (! noTitleBar) {
/* offset for title bar */
pixels += rowPixels * 22;
}
Uint32 *pixels = (Uint32*) surface->pixels;
Uint32 rowPixels = surface->pitch / 4;
Uint32 i, j;
for (i = 0; i < height; i++)
for (j = 0; j < width; j++) {
for (i = 0; i < surface->h; i++)
for (j = 0; j < surface->w; j++) {
pixels[ (i * rowPixels) + j ] |= 0xFF000000;
}
UnlockPortBits (port);
}
}
/* Subclass of NSWindow to fix genie effect and support resize events */
@interface SDL_QuartzWindow : NSWindow
{}
- (void)miniaturize:(id)sender;
- (void)display;
- (void)setFrame:(NSRect)frameRect display:(BOOL)flag;
@end
@implementation SDL_QuartzWindow
/* override these methods to fix the miniaturize animation/dock icon bug */
/* we override these methods to fix the miniaturize animation/dock icon bug */
- (void)miniaturize:(id)sender
{
if (SDL_VideoSurface->flags & SDL_OPENGL) {
/* Grab framebuffer and put into NSImage */
/* [ qz_window setMiniwindowImage:image ]; */
/*
Future: Grab framebuffer and put into NSImage
[ qz_window setMiniwindowImage:image ];
*/
}
else {
QZ_SetPortAlphaOpaque ([ [ self contentView ] qdPort ],
[ self styleMask ] & NSBorderlessWindowMask);
/* make the alpha channel opaque so anim won't have holes in it */
QZ_SetPortAlphaOpaque ();
}
[ super miniaturize:sender ];
}
/* this routine fires *after* deminiaturizing, so it might be useless to us */
- (void)deminiaturize:(id)sender
- (void)display
{
[ super deminiaturize:sender ];
/*
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.
*/
if ( (SDL_VideoSurface->flags & SDL_OPENGL) == 0)
QZ_SetPortAlphaOpaque ();
}
- (void)display
- (void)setFrame:(NSRect)frameRect display:(BOOL)flag
{
/* Do nothing to keep pinstripe pattern from drawing */
/*
If the video surface is NULL, this originated from QZ_SetVideoMode,
so don't send the resize event.
*/
if (SDL_VideoSurface == NULL) {
[ super setFrame:frameRect display:flag ];
}
else {
SDL_VideoDevice *this = (SDL_VideoDevice*)current_video;
NSRect sdlRect = [ NSWindow contentRectForFrameRect:frameRect styleMask:[self styleMask] ];
[ super setFrame:frameRect display:flag ];
SDL_PrivateResize (sdlRect.size.width, sdlRect.size.height);
/* If not OpenGL, we have to update the pixels and pitch */
if ( ! this->screen->flags & SDL_OPENGL ) {
LockPortBits ( [ window_view qdPort ] );
SDL_VideoSurface->pixels = GetPixBaseAddr ( GetPortPixMap ( [ window_view qdPort ] ) );
SDL_VideoSurface->pitch = GetPixRowBytes ( GetPortPixMap ( [ window_view qdPort ] ) );
SDL_VideoSurface->pixels += ((int)[ self frame ].size.height - (int)sdlRect.size.height) * SDL_VideoSurface->pitch;
UnlockPortBits ( [ window_view qdPort ] );
}
}
}
@end
/* Delegate for our NSWindow to send SDLQuit() on close */
......@@ -90,19 +109,17 @@ static void QZ_SetPortAlphaOpaque (CGrafPtr port, Uint32 noTitleBar) {
@end
@implementation SDL_QuartzWindowDelegate
- (BOOL)windowShouldClose:(id)sender {
- (BOOL)windowShouldClose:(id)sender
{
SDL_PrivateQuit();
return NO;
}
@end
/* empty class; probably could be used to fix bugs in the future */
/* Subclass of NSQuickDrawView for the window's subview */
@interface SDL_QuartzWindowView : NSQuickDrawView
{}
@end
@implementation SDL_QuartzWindowView
@end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment