diff -Nur SDL-1.2.14/src/video/quartz/CGS.h SDL-1.2.15/src/video/quartz/CGS.h --- SDL-1.2.14/src/video/quartz/CGS.h 2009-10-13 01:07:14.000000000 +0200 +++ SDL-1.2.15/src/video/quartz/CGS.h 2012-01-19 07:30:06.000000000 +0100 @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2009 Sam Lantinga + Copyright (C) 1997-2012 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public diff -Nur SDL-1.2.14/src/video/quartz/SDL_QuartzEvents.m SDL-1.2.15/src/video/quartz/SDL_QuartzEvents.m --- SDL-1.2.14/src/video/quartz/SDL_QuartzEvents.m 2009-10-13 01:07:14.000000000 +0200 +++ SDL-1.2.15/src/video/quartz/SDL_QuartzEvents.m 2012-01-19 07:30:06.000000000 +0100 @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2009 Sam Lantinga + Copyright (C) 1997-2012 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -78,10 +78,10 @@ #endif void QZ_InitOSKeymap (_THIS) { - const void *KCHRPtr; + BOOL saw_layout = NO; UInt32 state; UInt32 value; - int i; + Uint16 i; int world = SDLK_WORLD_0; for ( i=0; i= 1050) + if (TISCopyCurrentKeyboardLayoutInputSource != NULL) { + TISInputSourceRef src = TISCopyCurrentKeyboardLayoutInputSource(); + if (src != NULL) { + CFDataRef data = (CFDataRef) + TISGetInputSourceProperty(src, + kTISPropertyUnicodeKeyLayoutData); + if (data != NULL) { + const UCKeyboardLayout *layout = (const UCKeyboardLayout *) + CFDataGetBytePtr(data); + if (layout != NULL) { + const UInt32 kbdtype = LMGetKbdType(); + saw_layout = YES; + + /* Loop over all 127 possible scan codes */ + for (i = 0; i < 0x7F; i++) { + UniChar buf[16]; + UniCharCount count = 0; + + /* We pretend a clean start to begin with (i.e. no dead keys active */ + state = 0; + + if (UCKeyTranslate(layout, i, kUCKeyActionDown, 0, kbdtype, + 0, &state, 16, &count, buf) != noErr) { + continue; + } + + /* If the state become 0, it was a dead key. We need to + translate again, passing in the new state, to get + the actual key value */ + if (state != 0) { + if (UCKeyTranslate(layout, i, kUCKeyActionDown, 0, kbdtype, + 0, &state, 16, &count, buf) != noErr) { + continue; + } + } - /* Now translate the key code to a key value */ - value = KeyTranslate(KCHRPtr, i, &state) & 0xff; + if (count != 1) { + continue; /* no multi-char. Use SDL 1.3 instead. :) */ + } - /* If the state become 0, it was a dead key. We need to translate again, - passing in the new state, to get the actual key value */ - if (state != 0) + value = (UInt32) buf[0]; + if (value >= 128) { + /* Some non-ASCII char, map it to SDLK_WORLD_* */ + if (world < 0xFF) { + keymap[i] = world++; + } + } else if (value >= 32) { /* non-control ASCII char */ + keymap[i] = value; + } + } + } + } + CFRelease(src); + } + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1050) + if (!saw_layout) { + /* Get a pointer to the systems cached KCHR */ + const void *KCHRPtr = (const void *)GetScriptManagerVariable(smKCHRCache); + if (KCHRPtr) + { + /* Loop over all 127 possible scan codes */ + for (i = 0; i < 0x7F; i++) + { + /* We pretend a clean start to begin with (i.e. no dead keys active */ + state = 0; + + /* Now translate the key code to a key value */ value = KeyTranslate(KCHRPtr, i, &state) & 0xff; - /* Now we should have an ascii value, or 0. Try to figure out to which SDL symbol it maps */ - if (value >= 128) /* Some non-ASCII char, map it to SDLK_WORLD_* */ - keymap[i] = world++; - else if (value >= 32) /* non-control ASCII char */ - keymap[i] = value; + /* If the state become 0, it was a dead key. We need to translate again, + passing in the new state, to get the actual key value */ + if (state != 0) + value = KeyTranslate(KCHRPtr, i, &state) & 0xff; + + /* Now we should have an ascii value, or 0. Try to figure out to which SDL symbol it maps */ + if (value >= 128) { /* Some non-ASCII char, map it to SDLK_WORLD_* */ + if (world < 0xFF) { + keymap[i] = world++; + } + } else if (value >= 32) { /* non-control ASCII char */ + keymap[i] = value; + } + } } } +#endif /* The keypad codes are re-setup here, because the loop above cannot @@ -656,6 +721,8 @@ QZ_GetMouseLocation (this, &p); SDL_PrivateMouseMotion (0, 0, p.x, p.y); } + + QZ_UpdateCursor(this); } void QZ_DoDeactivate (_THIS) { @@ -730,7 +797,7 @@ void QZ_PumpEvents (_THIS) { - CGMouseDelta dx, dy; + int32_t dx, dy; NSDate *distantPast; NSEvent *event; @@ -853,7 +920,7 @@ so we have to call the lowlevel window server function. This is less accurate but works OK. */ - CGMouseDelta dx1, dy1; + int32_t dx1, dy1; CGGetLastMouseDelta (&dx1, &dy1); dx += dx1; dy += dy1; diff -Nur SDL-1.2.14/src/video/quartz/SDL_QuartzGL.m SDL-1.2.15/src/video/quartz/SDL_QuartzGL.m --- SDL-1.2.14/src/video/quartz/SDL_QuartzGL.m 2009-10-13 01:07:14.000000000 +0200 +++ SDL-1.2.15/src/video/quartz/SDL_QuartzGL.m 2012-01-19 07:30:06.000000000 +0100 @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2009 Sam Lantinga + Copyright (C) 1997-2012 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -153,7 +153,7 @@ * http://lists.apple.com/archives/mac-opengl/2006/Jan/msg00080.html ) */ if ( this->gl_config.swap_control >= 0 ) { - long value; + GLint value; value = this->gl_config.swap_control; [ gl_context setValues: &value forParameter: NSOpenGLCPSwapInterval ]; } @@ -175,7 +175,7 @@ #endif { - long cache_max = 64; + GLint cache_max = 64; CGLContextObj ctx = QZ_GetCGLContextObj(gl_context); CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max); CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max); @@ -261,7 +261,7 @@ } case SDL_GL_ACCELERATED_VISUAL: { - long val; + GLint val; /* FIXME: How do we get this information here? [fmt getValues: &val forAttribute: NSOpenGLPFAAccelerated attr forVirtualScreen: 0]; */ @@ -271,7 +271,7 @@ } case SDL_GL_SWAP_CONTROL: { - long val; + GLint val; [ gl_context getValues: &val forParameter: NSOpenGLCPSwapInterval ]; *value = val; return 0; diff -Nur SDL-1.2.14/src/video/quartz/SDL_QuartzKeys.h SDL-1.2.15/src/video/quartz/SDL_QuartzKeys.h --- SDL-1.2.14/src/video/quartz/SDL_QuartzKeys.h 2009-10-13 01:07:14.000000000 +0200 +++ SDL-1.2.15/src/video/quartz/SDL_QuartzKeys.h 2012-01-19 07:30:06.000000000 +0100 @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2009 Sam Lantinga + Copyright (C) 1997-2012 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public diff -Nur SDL-1.2.14/src/video/quartz/SDL_QuartzVideo.h SDL-1.2.15/src/video/quartz/SDL_QuartzVideo.h --- SDL-1.2.14/src/video/quartz/SDL_QuartzVideo.h 2009-10-13 01:07:14.000000000 +0200 +++ SDL-1.2.15/src/video/quartz/SDL_QuartzVideo.h 2012-01-19 07:30:06.000000000 +0100 @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2009 Sam Lantinga + Copyright (C) 1997-2012 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -86,14 +86,14 @@ /* Main driver structure to store required state information */ typedef struct SDL_PrivateVideoData { - + BOOL use_new_mode_apis; /* 1 == >= 10.6 APIs available */ BOOL allow_screensaver; /* 0 == disable screensaver */ CGDirectDisplayID display; /* 0 == main display (only support single display) */ - CFDictionaryRef mode; /* current mode of the display */ - CFDictionaryRef save_mode; /* original mode of the display */ - CFArrayRef mode_list; /* list of available fullscreen modes */ + const void *mode; /* current mode of the display */ + const void *save_mode; /* original mode of the display */ CGDirectPaletteRef palette; /* palette of an 8-bit display */ NSOpenGLContext *gl_context; /* OpenGL rendering context */ + NSGraphicsContext *nsgfx_context; /* Cocoa graphics context */ Uint32 width, height, bpp; /* frequently used data about the display */ Uint32 flags; /* flags for current mode, for teardown purposes */ Uint32 video_set; /* boolean; indicates if video was set correctly */ @@ -129,10 +129,11 @@ #define display_id (this->hidden->display) #define mode (this->hidden->mode) #define save_mode (this->hidden->save_mode) +#define use_new_mode_apis (this->hidden->use_new_mode_apis) #define allow_screensaver (this->hidden->allow_screensaver) -#define mode_list (this->hidden->mode_list) #define palette (this->hidden->palette) #define gl_context (this->hidden->gl_context) +#define nsgfx_context (this->hidden->nsgfx_context) #define device_width (this->hidden->width) #define device_height (this->hidden->height) #define device_bpp (this->hidden->bpp) diff -Nur SDL-1.2.14/src/video/quartz/SDL_QuartzVideo.m SDL-1.2.15/src/video/quartz/SDL_QuartzVideo.m --- SDL-1.2.14/src/video/quartz/SDL_QuartzVideo.m 2009-10-17 09:45:42.000000000 +0200 +++ SDL-1.2.15/src/video/quartz/SDL_QuartzVideo.m 2012-01-19 07:30:06.000000000 +0100 @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2009 Sam Lantinga + Copyright (C) 1997-2012 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -24,7 +24,30 @@ #include "SDL_QuartzVideo.h" #include "SDL_QuartzWindow.h" -#ifdef __powerpc__ /* I'm gambling they fixed this by 10.4. --ryan. */ +/* These APIs aren't just deprecated; they're gone from the headers in the + 10.7 SDK. If we're using a >= 10.7 SDK, but targeting < 10.7, then we + force these function declarations. */ +#if ((MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1070)) +CG_EXTERN void *CGDisplayBaseAddress(CGDirectDisplayID display) + CG_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_6, + __IPHONE_NA, __IPHONE_NA); +CG_EXTERN size_t CGDisplayBytesPerRow(CGDirectDisplayID display) + CG_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_6, + __IPHONE_NA, __IPHONE_NA); +#endif + + +static inline BOOL IS_LION_OR_LATER(_THIS) +{ + return (system_version >= 0x1070); +} + +static inline BOOL IS_SNOW_LEOPARD_OR_LATER(_THIS) +{ + return (system_version >= 0x1060); +} + +#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1060) && !defined(__LP64__) /* Fixed in Snow Leopard */ /* Add methods to get at private members of NSScreen. Since there is a bug in Apple's screen switching code @@ -42,12 +65,14 @@ _frame = frame; } @end -static inline void QZ_SetFrame(NSScreen *nsscreen, NSRect frame) +static inline void QZ_SetFrame(_THIS, NSScreen *nsscreen, NSRect frame) { - [nsscreen setFrame:frame]; + if (!IS_SNOW_LEOPARD_OR_LATER(this)) { + [nsscreen setFrame:frame]; + } } #else -static inline void QZ_SetFrame(NSScreen *nsscreen, NSRect frame) +static inline void QZ_SetFrame(_THIS, NSScreen *nsscreen, NSRect frame) { } #endif @@ -75,7 +100,7 @@ static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags); -static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop); +static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop, BOOL save_gl); static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, int height, int bpp, @@ -84,31 +109,55 @@ static int QZ_SetColors (_THIS, int first_color, int num_colors, SDL_Color *colors); +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface); static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface); static int QZ_ThreadFlip (_THIS); static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface); static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects); - static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects); +#endif + static void QZ_UpdateRects (_THIS, int num_rects, SDL_Rect *rects); static void QZ_VideoQuit (_THIS); -/* Hardware surface functions (for fullscreen mode only) */ -#if 0 /* Not used (apparently, it's really slow) */ -static int QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color); -#endif static int QZ_LockHWSurface(_THIS, SDL_Surface *surface); static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface); static int QZ_AllocHWSurface(_THIS, SDL_Surface *surface); static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface); -/* static int QZ_FlipHWSurface (_THIS, SDL_Surface *surface); */ /* Bootstrap binding, enables entry point into the driver */ VideoBootStrap QZ_bootstrap = { "Quartz", "Mac OS X CoreGraphics", QZ_Available, QZ_CreateDevice }; +/* Disable compiler warnings we can't avoid. */ +#if (defined(__GNUC__) && (__GNUC__ >= 4)) +# if (MAC_OS_X_VERSION_MAX_ALLOWED <= 1070) +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +# endif +#endif + +static void QZ_ReleaseDisplayMode(_THIS, const void *moderef) +{ + /* we only own these references in the 10.6+ API. */ +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + CGDisplayModeRelease((CGDisplayModeRef) moderef); + } +#endif +} + +static void QZ_ReleaseDisplayModeList(_THIS, CFArrayRef mode_list) +{ + /* we only own these references in the 10.6+ API. */ +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + CFRelease(mode_list); + } +#endif +} + /* Bootstrap functions */ static int QZ_Available () @@ -147,7 +196,6 @@ device->UnlockHWSurface = QZ_UnlockHWSurface; device->AllocHWSurface = QZ_AllocHWSurface; device->FreeHWSurface = QZ_FreeHWSurface; - /* device->FlipHWSurface = QZ_FlipHWSurface */; device->SetGamma = QZ_SetGamma; device->GetGamma = QZ_GetGamma; @@ -191,15 +239,75 @@ static void QZ_DeleteDevice (SDL_VideoDevice *device) { + _THIS = device; + QZ_ReleaseDisplayMode(this, save_mode); + QZ_ReleaseDisplayMode(this, mode); SDL_free (device->hidden); SDL_free (device); } +static void QZ_GetModeInfo(_THIS, const void *_mode, Uint32 *w, Uint32 *h, Uint32 *bpp) +{ + *w = *h = *bpp = 0; + if (_mode == NULL) { + return; + } + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + CGDisplayModeRef vidmode = (CGDisplayModeRef) _mode; + CFStringRef fmt = CGDisplayModeCopyPixelEncoding(vidmode); + + *w = (Uint32) CGDisplayModeGetWidth(vidmode); + *h = (Uint32) CGDisplayModeGetHeight(vidmode); + + /* we only care about the 32-bit modes... */ + if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels), + kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + *bpp = 32; + } + + CFRelease(fmt); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + CFDictionaryRef vidmode = (CFDictionaryRef) _mode; + CFNumberGetValue ( + CFDictionaryGetValue (vidmode, kCGDisplayBitsPerPixel), + kCFNumberSInt32Type, bpp); + + CFNumberGetValue ( + CFDictionaryGetValue (vidmode, kCGDisplayWidth), + kCFNumberSInt32Type, w); + + CFNumberGetValue ( + CFDictionaryGetValue (vidmode, kCGDisplayHeight), + kCFNumberSInt32Type, h); + } +#endif + + /* we only care about the 32-bit modes... */ + if (*bpp != 32) { + *bpp = 0; + } +} + static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) { NSRect r = NSMakeRect(0.0, 0.0, 0.0, 0.0); const char *env = NULL; - + + if ( Gestalt(gestaltSystemVersion, &system_version) != noErr ) + system_version = 0; + + use_new_mode_apis = NO; + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + use_new_mode_apis = IS_SNOW_LEOPARD_OR_LATER(this); +#endif + /* Initialize the video settings; this data persists between mode switches */ display_id = kCGDirectMainDisplay; @@ -216,9 +324,28 @@ } #endif - save_mode = CGDisplayCurrentMode (display_id); - mode_list = CGDisplayAvailableModes (display_id); - palette = CGPaletteCreateDefaultColorPalette (); +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + save_mode = CGDisplayCopyDisplayMode(display_id); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + save_mode = CGDisplayCurrentMode(display_id); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if (!IS_LION_OR_LATER(this)) { + palette = CGPaletteCreateDefaultColorPalette(); + } +#endif + + if (save_mode == NULL) { + SDL_SetError("Couldn't figure out current display mode."); + return -1; + } /* Allow environment override of screensaver disable. */ env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER"); @@ -233,14 +360,13 @@ } /* Gather some information that is useful to know about the display */ - CFNumberGetValue (CFDictionaryGetValue (save_mode, kCGDisplayBitsPerPixel), - kCFNumberSInt32Type, &device_bpp); - - CFNumberGetValue (CFDictionaryGetValue (save_mode, kCGDisplayWidth), - kCFNumberSInt32Type, &device_width); - - CFNumberGetValue (CFDictionaryGetValue (save_mode, kCGDisplayHeight), - kCFNumberSInt32Type, &device_height); + QZ_GetModeInfo(this, save_mode, &device_width, &device_height, &device_bpp); + if (device_bpp == 0) { + QZ_ReleaseDisplayMode(this, save_mode); + save_mode = NULL; + SDL_SetError("Unsupported display mode"); + return -1; + } /* Determine the current screen size */ this->info.current_w = device_width; @@ -255,10 +381,7 @@ cursor_visible = YES; current_mods = 0; field_edit = [[SDLTranslatorResponder alloc] initWithFrame:r]; - - if ( Gestalt(gestaltSystemVersion, &system_version) != noErr ) - system_version = 0; - + /* register for sleep notifications so wake from sleep generates SDL_VIDEOEXPOSE */ QZ_RegisterForSleepNotifications (this); @@ -270,6 +393,7 @@ static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) { + CFArrayRef mode_list = NULL; /* list of available fullscreen modes */ CFIndex num_modes; CFIndex i; @@ -281,7 +405,6 @@ /* Free memory from previous call, if any */ if ( client_mode_list != NULL ) { - int i; for (i = 0; client_mode_list[i] != NULL; i++) @@ -291,49 +414,42 @@ client_mode_list = NULL; } +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + mode_list = CGDisplayCopyAllDisplayModes(display_id, NULL); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + mode_list = CGDisplayAvailableModes(display_id); + } +#endif + num_modes = CFArrayGetCount (mode_list); /* Build list of modes with the requested bpp */ for (i = 0; i < num_modes; i++) { + Uint32 width, height, bpp; + const void *onemode = CFArrayGetValueAtIndex(mode_list, i); - CFDictionaryRef onemode; - CFNumberRef number; - int bpp; - - onemode = CFArrayGetValueAtIndex (mode_list, i); - number = CFDictionaryGetValue (onemode, kCGDisplayBitsPerPixel); - CFNumberGetValue (number, kCFNumberSInt32Type, &bpp); - - if (bpp == format->BitsPerPixel) { - - int intvalue; - int hasMode; - int width, height; - - number = CFDictionaryGetValue (onemode, kCGDisplayWidth); - CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue); - width = (Uint16) intvalue; - - number = CFDictionaryGetValue (onemode, kCGDisplayHeight); - CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue); - height = (Uint16) intvalue; + QZ_GetModeInfo(this, onemode, &width, &height, &bpp); + + if (bpp && (bpp == format->BitsPerPixel)) { + int hasMode = SDL_FALSE; + int i; /* Check if mode is already in the list */ - { - int i; - hasMode = SDL_FALSE; - for (i = 0; i < list_size; i++) { - if (client_mode_list[i]->w == width && - client_mode_list[i]->h == height) { + for (i = 0; i < list_size; i++) { + if (client_mode_list[i]->w == width && + client_mode_list[i]->h == height) { hasMode = SDL_TRUE; break; - } } } /* Grow the list and add mode to the list */ if ( ! hasMode ) { - SDL_Rect *rect; list_size++; @@ -341,13 +457,16 @@ if (client_mode_list == NULL) client_mode_list = (SDL_Rect**) SDL_malloc (sizeof(*client_mode_list) * (list_size+1) ); - else - client_mode_list = (SDL_Rect**) + else { + /* !!! FIXME: this leaks memory if SDL_realloc() fails! */ + client_mode_list = (SDL_Rect**) SDL_realloc (client_mode_list, sizeof(*client_mode_list) * (list_size+1)); + } rect = (SDL_Rect*) SDL_malloc (sizeof(**client_mode_list)); if (client_mode_list == NULL || rect == NULL) { + QZ_ReleaseDisplayModeList(this, mode_list); SDL_OutOfMemory (); return NULL; } @@ -362,6 +481,8 @@ } } + QZ_ReleaseDisplayModeList(this, mode_list); + /* Sort list largest to smallest (by area) */ { int i, j; @@ -380,6 +501,7 @@ } } } + return client_mode_list; } @@ -394,7 +516,29 @@ return SDL_FALSE; } -static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) +static CGError QZ_SetDisplayMode(_THIS, const void *vidmode) +{ +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + return CGDisplaySetDisplayMode(display_id, (CGDisplayModeRef) vidmode, NULL); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + return CGDisplaySwitchToMode(display_id, (CFDictionaryRef) vidmode); + } +#endif + + return kCGErrorFailure; +} + +static inline CGError QZ_RestoreDisplayMode(_THIS) +{ + return QZ_SetDisplayMode(this, save_mode); +} + +static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop, BOOL save_gl) { /* Reset values that may change between switches */ this->info.blit_fill = 0; @@ -402,7 +546,7 @@ this->UpdateRects = NULL; this->LockHWSurface = NULL; this->UnlockHWSurface = NULL; - + if (cg_context) { CGContextFlush (cg_context); CGContextRelease (cg_context); @@ -413,9 +557,10 @@ if ( mode_flags & SDL_FULLSCREEN ) { NSRect screen_rect; - + /* Release double buffer stuff */ - if ( mode_flags & SDL_DOUBLEBUF) { +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if ( !IS_LION_OR_LATER(this) && (mode_flags & SDL_DOUBLEBUF) ) { quit_thread = YES; SDL_SemPost (sem1); SDL_WaitThread (thread, NULL); @@ -423,7 +568,8 @@ SDL_DestroySemaphore (sem2); SDL_free (sw_buffers[0]); } - +#endif + /* If we still have a valid window, close it. */ if ( qz_window ) { NSCAssert([ qz_window delegate ] == nil, @"full screen window shouldn't have a delegate"); /* if that should ever change, we'd have to release it here */ @@ -436,21 +582,35 @@ Do this first to avoid trash on the display before fade */ if ( mode_flags & SDL_OPENGL ) { - - QZ_TearDownOpenGL (this); + if (!save_gl) { + QZ_TearDownOpenGL (this); + } + + #ifdef __powerpc__ /* we only use this for pre-10.3 compatibility. */ CGLSetFullScreen (NULL); + #endif } if (to_desktop) { - ShowMenuBar (); + /* !!! FIXME: keep an eye on this. + * This API is officially unavailable for 64-bit binaries. + * It happens to work, as of 10.7, but we're going to see if + * we can just simply do without it on newer OSes... + */ + #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__) + if ( !IS_LION_OR_LATER(this) ) { + ShowMenuBar (); + } + #endif + /* Restore original screen resolution/bpp */ - CGDisplaySwitchToMode (display_id, save_mode); + QZ_RestoreDisplayMode (this); CGReleaseAllDisplays (); /* Reset the main screen's rectangle See comment in QZ_SetVideoFullscreen for why we do this */ screen_rect = NSMakeRect(0,0,device_width,device_height); - QZ_SetFrame([ NSScreen mainScreen ], screen_rect); + QZ_SetFrame(this, [ NSScreen mainScreen ], screen_rect); } } /* Release window mode resources */ @@ -462,23 +622,78 @@ window_view = nil; /* Release the OpenGL context */ - if ( mode_flags & SDL_OPENGL ) - QZ_TearDownOpenGL (this); + if ( mode_flags & SDL_OPENGL ) { + if (!save_gl) { + QZ_TearDownOpenGL (this); + } + } } /* Signal successful teardown */ video_set = SDL_FALSE; } +static const void *QZ_BestMode(_THIS, const int bpp, const int w, const int h) +{ + const void *best = NULL; + + if (bpp == 0) { + return NULL; + } + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + /* apparently, we have to roll our own now. :/ */ + CFArrayRef mode_list = CGDisplayCopyAllDisplayModes(display_id, NULL); + if (mode_list != NULL) { + const CFIndex num_modes = CFArrayGetCount(mode_list); + CFIndex i; + for (i = 0; i < num_modes; i++) { + const void *vidmode = CFArrayGetValueAtIndex(mode_list, i); + Uint32 thisw, thish, thisbpp; + QZ_GetModeInfo(this, vidmode, &thisw, &thish, &thisbpp); + + /* We only care about exact matches, apparently. */ + if ((thisbpp == bpp) && (thisw == w) && (thish == h)) { + best = vidmode; + break; /* got it! */ + } + } + CGDisplayModeRetain((CGDisplayModeRef) best); /* NULL is ok */ + CFRelease(mode_list); + } + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + boolean_t exact = 0; + best = CGDisplayBestModeForParameters(display_id, bpp, w, h, &exact); + if (!exact) { + best = NULL; + } + } +#endif + + return best; +} + static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width, - int height, int bpp, Uint32 flags) + int height, int bpp, Uint32 flags, + const BOOL save_gl) { - boolean_t exact_match = 0; + const BOOL isLion = IS_LION_OR_LATER(this); NSRect screen_rect; CGError error; NSRect contentRect; CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; + current->flags = SDL_FULLSCREEN; + current->w = width; + current->h = height; + + contentRect = NSMakeRect (0, 0, width, height); + /* Fade to black to hide resolution-switching flicker (and garbage that is displayed by a destroyed OpenGL context, if applicable) */ if ( CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess ) { @@ -487,7 +702,7 @@ /* Destroy any previous mode */ if (video_set == SDL_TRUE) - QZ_UnsetVideoMode (this, FALSE); + QZ_UnsetVideoMode (this, FALSE, save_gl); /* Sorry, QuickDraw was ripped out. */ if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) { @@ -495,12 +710,13 @@ goto ERR_NO_MATCH; } + QZ_ReleaseDisplayMode(this, mode); /* NULL is okay. */ + /* See if requested mode exists */ - mode = CGDisplayBestModeForParameters (display_id, bpp, width, - height, &exact_match); + mode = QZ_BestMode(this, bpp, width, height); /* Require an exact match to the requested mode */ - if ( ! exact_match ) { + if ( mode == NULL ) { SDL_SetError ("Failed to find display resolution: %dx%dx%d", width, height, bpp); goto ERR_NO_MATCH; } @@ -517,77 +733,80 @@ } /* Do the physical switch */ - if ( CGDisplayNoErr != CGDisplaySwitchToMode (display_id, mode) ) { + if ( CGDisplayNoErr != QZ_SetDisplayMode(this, mode) ) { SDL_SetError ("Failed switching display resolution"); goto ERR_NO_SWITCH; } - current->pixels = (Uint32*) CGDisplayBaseAddress (display_id); - current->pitch = CGDisplayBytesPerRow (display_id); +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if ( !isLion ) { + current->pixels = (Uint32*) CGDisplayBaseAddress (display_id); + current->pitch = CGDisplayBytesPerRow (display_id); + + current->flags |= SDL_HWSURFACE; + current->flags |= SDL_PREALLOC; + /* current->hwdata = (void *) CGDisplayGetDrawingContext (display_id); */ - current->flags = 0; - current->w = width; - current->h = height; - current->flags |= SDL_FULLSCREEN; - current->flags |= SDL_HWSURFACE; - current->flags |= SDL_PREALLOC; - /* current->hwdata = (void *) CGDisplayGetDrawingContext (display_id); */ - - this->UpdateRects = QZ_DirectUpdate; - this->LockHWSurface = QZ_LockHWSurface; - this->UnlockHWSurface = QZ_UnlockHWSurface; + this->UpdateRects = QZ_DirectUpdate; + this->LockHWSurface = QZ_LockHWSurface; + this->UnlockHWSurface = QZ_UnlockHWSurface; - /* Setup double-buffer emulation */ - if ( flags & SDL_DOUBLEBUF ) { + /* Setup double-buffer emulation */ + if ( flags & SDL_DOUBLEBUF ) { - /* + /* Setup a software backing store for reasonable results when double buffering is requested (since a single-buffered hardware surface looks hideous). The actual screen blit occurs in a separate thread to allow other blitting while waiting on the VBL (and hence results in higher framerates). - */ - this->LockHWSurface = NULL; - this->UnlockHWSurface = NULL; - this->UpdateRects = NULL; - - current->flags |= (SDL_HWSURFACE|SDL_DOUBLEBUF); - this->UpdateRects = QZ_DoubleBufferUpdate; - this->LockHWSurface = QZ_LockDoubleBuffer; - this->UnlockHWSurface = QZ_UnlockDoubleBuffer; - this->FlipHWSurface = QZ_FlipDoubleBuffer; - - current->pixels = SDL_malloc (current->pitch * current->h * 2); - if (current->pixels == NULL) { - SDL_OutOfMemory (); - goto ERR_DOUBLEBUF; - } + */ + this->LockHWSurface = NULL; + this->UnlockHWSurface = NULL; + this->UpdateRects = NULL; + + current->flags |= (SDL_HWSURFACE|SDL_DOUBLEBUF); + this->UpdateRects = QZ_DoubleBufferUpdate; + this->LockHWSurface = QZ_LockDoubleBuffer; + this->UnlockHWSurface = QZ_UnlockDoubleBuffer; + this->FlipHWSurface = QZ_FlipDoubleBuffer; + + current->pixels = SDL_malloc (current->pitch * current->h * 2); + if (current->pixels == NULL) { + SDL_OutOfMemory (); + goto ERR_DOUBLEBUF; + } - sw_buffers[0] = current->pixels; - sw_buffers[1] = (Uint8*)current->pixels + current->pitch * current->h; + sw_buffers[0] = current->pixels; + sw_buffers[1] = (Uint8*)current->pixels + current->pitch * current->h; - quit_thread = NO; - sem1 = SDL_CreateSemaphore (0); - sem2 = SDL_CreateSemaphore (1); - thread = SDL_CreateThread ((int (*)(void *))QZ_ThreadFlip, this); - } + quit_thread = NO; + sem1 = SDL_CreateSemaphore (0); + sem2 = SDL_CreateSemaphore (1); + thread = SDL_CreateThread ((int (*)(void *))QZ_ThreadFlip, this); + } - if ( CGDisplayCanSetPalette (display_id) ) - current->flags |= SDL_HWPALETTE; + if ( CGDisplayCanSetPalette (display_id) ) + current->flags |= SDL_HWPALETTE; + } +#endif /* Check if we should recreate the window */ if (qz_window == nil) { /* Manually create a window, avoids having a nib file resource */ qz_window = [ [ SDL_QuartzWindow alloc ] initWithContentRect:contentRect - styleMask:0 + styleMask:(isLion ? NSBorderlessWindowMask : 0) backing:NSBackingStoreBuffered defer:NO ]; if (qz_window != nil) { [ qz_window setAcceptsMouseMovedEvents:YES ]; [ qz_window setViewsNeedDisplay:NO ]; + if (isLion) { + [ qz_window setContentView: [ [ [ SDL_QuartzView alloc ] init ] autorelease ] ]; + } } } /* We already have a window, just change its size */ @@ -600,27 +819,48 @@ /* Setup OpenGL for a fullscreen context */ if (flags & SDL_OPENGL) { - CGLError err; - CGLContextObj ctx; - - if ( ! QZ_SetupOpenGL (this, bpp, flags) ) { - goto ERR_NO_GL; + if ( ! save_gl ) { + if ( ! QZ_SetupOpenGL (this, bpp, flags) ) { + goto ERR_NO_GL; + } } /* Initialize the NSView and add it to our window. The presence of a valid window and view allow the cursor to be changed whilst in fullscreen.*/ window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; - [ [ qz_window contentView ] addSubview:window_view ]; - [ window_view release ]; - ctx = QZ_GetCGLContextObj (gl_context); - err = CGLSetFullScreen (ctx); + if ( isLion ) { + [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; + } + + [ [ qz_window contentView ] addSubview:window_view ]; - if (err) { - SDL_SetError ("Error setting OpenGL fullscreen: %s", CGLErrorString(err)); - goto ERR_NO_GL; + /* Apparently Lion checks some version flag set by the linker + and changes API behavior. Annoying. */ + if ( isLion ) { + [ qz_window setLevel:CGShieldingWindowLevel() ]; + [ gl_context setView: window_view ]; + //[ gl_context setFullScreen ]; + [ gl_context update ]; + } + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if ( !isLion ) { + CGLError err; + CGLContextObj ctx; + + [ qz_window setLevel:NSNormalWindowLevel ]; + ctx = QZ_GetCGLContextObj (gl_context); + err = CGLSetFullScreen (ctx); + + if (err) { + SDL_SetError ("Error setting OpenGL fullscreen: %s", CGLErrorString(err)); + goto ERR_NO_GL; + } } +#endif + [ window_view release ]; [ gl_context makeCurrentContext]; glClear (GL_COLOR_BUFFER_BIT); @@ -628,10 +868,55 @@ [ gl_context flushBuffer ]; current->flags |= SDL_OPENGL; + } else if (isLion) { /* For 2D, we build a CGBitmapContext */ + CGColorSpaceRef cgColorspace; + + /* Only recreate the view if it doesn't already exist */ + if (window_view == nil) { + window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; + [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; + [ [ qz_window contentView ] addSubview:window_view ]; + [ window_view release ]; + } + + cgColorspace = CGColorSpaceCreateDeviceRGB(); + current->pitch = 4 * current->w; + current->pixels = SDL_malloc (current->h * current->pitch); + + cg_context = CGBitmapContextCreate (current->pixels, current->w, current->h, + 8, current->pitch, cgColorspace, + kCGImageAlphaNoneSkipFirst); + CGColorSpaceRelease (cgColorspace); + + current->flags |= SDL_SWSURFACE; + current->flags |= SDL_ASYNCBLIT; + current->hwdata = (void *) cg_context; + + /* Force this window to draw above _everything_. */ + [ qz_window setLevel:CGShieldingWindowLevel() ]; + + this->UpdateRects = QZ_UpdateRects; + this->LockHWSurface = QZ_LockHWSurface; + this->UnlockHWSurface = QZ_UnlockHWSurface; } - /* If we don't hide menu bar, it will get events and interrupt the program */ - HideMenuBar (); + if (isLion) { + [ qz_window setHasShadow:NO]; + [ qz_window setOpaque:YES]; + [ qz_window makeKeyAndOrderFront:nil ]; + } + + /* !!! FIXME: keep an eye on this. + * This API is officially unavailable for 64-bit binaries. + * It happens to work, as of 10.7, but we're going to see if + * we can just simply do without it on newer OSes... + */ + #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__) + if ( !isLion ) { + /* If we don't hide menu bar, it will get events and interrupt the program */ + HideMenuBar (); + } + #endif /* Fade in again (asynchronously) */ if ( fade_token != kCGDisplayFadeReservationInvalidToken ) { @@ -647,7 +932,7 @@ ourselves. This hack should be removed if/when the bug is fixed. */ screen_rect = NSMakeRect(0,0,width,height); - QZ_SetFrame([ NSScreen mainScreen ], screen_rect); + QZ_SetFrame(this, [ NSScreen mainScreen ], screen_rect); /* Save the flags to ensure correct tear-down */ mode_flags = current->flags; @@ -658,8 +943,8 @@ return current; /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */ -ERR_NO_GL: -ERR_DOUBLEBUF: CGDisplaySwitchToMode (display_id, save_mode); +ERR_NO_GL: goto ERR_DOUBLEBUF; /* this goto is to stop a compiler warning on newer SDKs. */ +ERR_DOUBLEBUF: QZ_RestoreDisplayMode(this); ERR_NO_SWITCH: CGReleaseAllDisplays (); ERR_NO_CAPTURE: ERR_NO_MATCH: if ( fade_token != kCGDisplayFadeReservationInvalidToken ) { @@ -670,7 +955,8 @@ } static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, - int height, int *bpp, Uint32 flags) + int height, int *bpp, Uint32 flags, + const BOOL save_gl) { unsigned int style; NSRect contentRect; @@ -698,12 +984,12 @@ if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) { CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); } - QZ_UnsetVideoMode (this, TRUE); + QZ_UnsetVideoMode (this, TRUE, save_gl); } else if ( ((mode_flags ^ flags) & (SDL_NOFRAME|SDL_RESIZABLE)) || (mode_flags & SDL_OPENGL) || (flags & SDL_OPENGL) ) { - QZ_UnsetVideoMode (this, TRUE); + QZ_UnsetVideoMode (this, TRUE, save_gl); } } @@ -776,12 +1062,14 @@ /* For OpenGL, we bind the context to a subview */ if ( flags & SDL_OPENGL ) { - if ( ! QZ_SetupOpenGL (this, *bpp, flags) ) { - if (fade_token != kCGDisplayFadeReservationInvalidToken) { - CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); - CGReleaseDisplayFadeReservation (fade_token); + if ( ! save_gl ) { + if ( ! QZ_SetupOpenGL (this, *bpp, flags) ) { + if (fade_token != kCGDisplayFadeReservationInvalidToken) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation (fade_token); + } + return NULL; } - return NULL; } window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; @@ -819,7 +1107,7 @@ current->flags |= SDL_SWSURFACE; current->flags |= SDL_ASYNCBLIT; current->hwdata = (void *) cg_context; - + this->UpdateRects = QZ_UpdateRects; this->LockHWSurface = QZ_LockHWSurface; this->UnlockHWSurface = QZ_UnlockHWSurface; @@ -837,15 +1125,22 @@ return current; } -static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, - int height, int bpp, Uint32 flags) + +static SDL_Surface* QZ_SetVideoModeInternal (_THIS, SDL_Surface *current, + int width, int height, int bpp, + Uint32 flags, BOOL save_gl) { + const BOOL isLion = IS_LION_OR_LATER(this); + current->flags = 0; current->pixels = NULL; /* Setup full screen video */ if ( flags & SDL_FULLSCREEN ) { - current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags ); + if ( isLion ) { + bpp = 32; + } + current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags, save_gl ); if (current == NULL) return NULL; } @@ -853,11 +1148,16 @@ else { /* Force bpp to 32 */ bpp = 32; - current = QZ_SetVideoWindowed (this, current, width, height, &bpp, flags); + current = QZ_SetVideoWindowed (this, current, width, height, &bpp, flags, save_gl ); if (current == NULL) return NULL; } + if (qz_window != nil) { + nsgfx_context = [NSGraphicsContext graphicsContextWithWindow:qz_window]; + [NSGraphicsContext setCurrentContext:nsgfx_context]; + } + /* Setup the new pixel format */ { int amask = 0, @@ -877,25 +1177,22 @@ return NULL; case 32: /* (8)-8-8-8 ARGB */ amask = 0x00000000; - if ( flags & SDL_FULLSCREEN ) - { - rmask = 0x00FF0000; - gmask = 0x0000FF00; - bmask = 0x000000FF; - } - else - { + if ( (!isLion) && (flags & SDL_FULLSCREEN) ) { + rmask = 0x00FF0000; + gmask = 0x0000FF00; + bmask = 0x000000FF; + } else { #if SDL_BYTEORDER == SDL_LIL_ENDIAN - rmask = 0x0000FF00; - gmask = 0x00FF0000; - bmask = 0xFF000000; + rmask = 0x0000FF00; + gmask = 0x00FF0000; + bmask = 0xFF000000; #else - rmask = 0x00FF0000; - gmask = 0x0000FF00; - bmask = 0x000000FF; + rmask = 0x00FF0000; + gmask = 0x0000FF00; + bmask = 0x000000FF; #endif - } - break; + break; + } } if ( ! SDL_ReallocFormat (current, bpp, @@ -911,6 +1208,34 @@ return current; } +static SDL_Surface* QZ_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, + Uint32 flags) +{ + /* Don't throw away the GL context if we can just resize the current one. */ +#if 0 /* !!! FIXME: half-finished side project. Reenable this if you ever debug the corner cases. */ + const BOOL save_gl = ( (video_set == SDL_TRUE) && ((flags & SDL_OPENGL) == (current->flags & SDL_OPENGL)) && (bpp == current->format->BitsPerPixel) ); +#else + const BOOL save_gl = NO; +#endif + + NSOpenGLContext *glctx = gl_context; + SDL_Surface* retval = NULL; + + if (save_gl) { + [glctx retain]; /* just so we don't lose this when killing old views, etc */ + } + + retval = QZ_SetVideoModeInternal (this, current, width, height, bpp, flags, save_gl); + + if (save_gl) { + [glctx release]; /* something else should own this now, or we legitimately release it. */ + } + + return retval; +} + + static int QZ_ToggleFullScreen (_THIS, int on) { return 0; @@ -919,27 +1244,32 @@ static int QZ_SetColors (_THIS, int first_color, int num_colors, SDL_Color *colors) { - CGTableCount index; - CGDeviceColor color; +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + /* we shouldn't have an 8-bit mode on Lion! */ + if (!IS_LION_OR_LATER(this)) { + CGTableCount index; + CGDeviceColor color; - for (index = first_color; index < first_color+num_colors; index++) { + for (index = first_color; index < first_color+num_colors; index++) { - /* Clamp colors between 0.0 and 1.0 */ - color.red = colors->r / 255.0; - color.blue = colors->b / 255.0; - color.green = colors->g / 255.0; + /* Clamp colors between 0.0 and 1.0 */ + color.red = colors->r / 255.0; + color.blue = colors->b / 255.0; + color.green = colors->g / 255.0; - colors++; + colors++; - CGPaletteSetColorAtIndex (palette, color, index); - } + CGPaletteSetColorAtIndex (palette, color, index); + } - if ( CGDisplayNoErr != CGDisplaySetPalette (display_id, palette) ) - return 0; + return ( CGDisplayNoErr == CGDisplaySetPalette (display_id, palette) ); + } +#endif - return 1; + return 0; } +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface) { return 1; @@ -996,7 +1326,7 @@ * a fullscreen resolution smaller than the hardware could supply * so SDL is centering it in a bigger resolution)... */ - dst = (Uint8 *)CGDisplayBaseAddress (display_id) + SDL_VideoSurface->offset; + dst = ((Uint8 *)((size_t)CGDisplayBaseAddress (display_id))) + SDL_VideoSurface->offset; src = current_buffer + SDL_VideoSurface->offset; len = SDL_VideoSurface->w * SDL_VideoSurface->format->BytesPerPixel; h = SDL_VideoSurface->h; @@ -1097,7 +1427,7 @@ { #pragma unused(this,num_rects,rects) } - +#endif /* Resize icon, BMP format */ static const unsigned char QZ_ResizeIcon[] = { @@ -1181,9 +1511,12 @@ } else { - CGContextRef cgc = (CGContextRef) - [[NSGraphicsContext graphicsContextWithWindow: qz_window] - graphicsPort]; + NSGraphicsContext *ctx = [NSGraphicsContext currentContext]; + if (ctx != nsgfx_context) { /* uhoh, you might be rendering from another thread... */ + [NSGraphicsContext setCurrentContext:nsgfx_context]; + ctx = nsgfx_context; + } + CGContextRef cgc = (CGContextRef) [ctx graphicsPort]; QZ_DrawResizeIcon (this); CGContextFlush (cg_context); CGImageRef image = CGBitmapContextCreateImage (cg_context); @@ -1192,7 +1525,6 @@ CGContextDrawImage (cgc, rectangle, image); CGImageRelease(image); CGContextFlush (cgc); - CGContextRelease (cgc); } } @@ -1213,16 +1545,20 @@ if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) { CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); } - QZ_UnsetVideoMode (this, TRUE); + QZ_UnsetVideoMode (this, TRUE, FALSE); if (fade_token != kCGDisplayFadeReservationInvalidToken) { CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); CGReleaseDisplayFadeReservation (fade_token); } } else - QZ_UnsetVideoMode (this, TRUE); - - CGPaletteRelease (palette); + QZ_UnsetVideoMode (this, TRUE, FALSE); + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if (!IS_LION_OR_LATER(this)) { + CGPaletteRelease(palette); + } +#endif if (opengl_library) { SDL_UnloadObject(opengl_library); @@ -1236,15 +1572,6 @@ } } -#if 0 /* Not used (apparently, it's really slow) */ -static int QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) -{ - CGSDisplayHWFill (display_id, rect->x, rect->y, rect->w, rect->h, color); - - return 0; -} -#endif - static int QZ_LockHWSurface(_THIS, SDL_Surface *surface) { return 1; @@ -1263,12 +1590,6 @@ { } -/* - int QZ_FlipHWSurface (_THIS, SDL_Surface *surface) { - return 0; - } - */ - /* Gamma functions */ int QZ_SetGamma (_THIS, float red, float green, float blue) { @@ -1314,7 +1635,7 @@ int QZ_SetGammaRamp (_THIS, Uint16 *ramp) { - const CGTableCount tableSize = 255; + const uint32_t tableSize = 255; CGGammaValue redTable[tableSize]; CGGammaValue greenTable[tableSize]; CGGammaValue blueTable[tableSize]; @@ -1340,11 +1661,11 @@ int QZ_GetGammaRamp (_THIS, Uint16 *ramp) { - const CGTableCount tableSize = 255; + const uint32_t tableSize = 255; CGGammaValue redTable[tableSize]; CGGammaValue greenTable[tableSize]; CGGammaValue blueTable[tableSize]; - CGTableCount actual; + uint32_t actual; int i; if ( CGDisplayNoErr != CGGetDisplayTransferByTable diff -Nur SDL-1.2.14/src/video/quartz/SDL_QuartzWindow.h SDL-1.2.15/src/video/quartz/SDL_QuartzWindow.h --- SDL-1.2.14/src/video/quartz/SDL_QuartzWindow.h 2009-10-13 01:07:14.000000000 +0200 +++ SDL-1.2.15/src/video/quartz/SDL_QuartzWindow.h 2012-01-19 07:30:06.000000000 +0100 @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2009 Sam Lantinga + Copyright (C) 1997-2012 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -21,7 +21,7 @@ */ #include "SDL_config.h" -#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1050 +#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1050) typedef unsigned int NSUInteger; #endif diff -Nur SDL-1.2.14/src/video/quartz/SDL_QuartzWindow.m SDL-1.2.15/src/video/quartz/SDL_QuartzWindow.m --- SDL-1.2.14/src/video/quartz/SDL_QuartzWindow.m 2009-10-13 01:07:14.000000000 +0200 +++ SDL-1.2.15/src/video/quartz/SDL_QuartzWindow.m 2012-01-19 07:30:06.000000000 +0100 @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2009 Sam Lantinga + Copyright (C) 1997-2012 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public diff -Nur SDL-1.2.14/src/video/quartz/SDL_QuartzWM.h SDL-1.2.15/src/video/quartz/SDL_QuartzWM.h --- SDL-1.2.14/src/video/quartz/SDL_QuartzWM.h 2009-10-13 01:07:14.000000000 +0200 +++ SDL-1.2.15/src/video/quartz/SDL_QuartzWM.h 2012-01-19 07:30:06.000000000 +0100 @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2009 Sam Lantinga + Copyright (C) 1997-2012 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public diff -Nur SDL-1.2.14/src/video/quartz/SDL_QuartzWM.m SDL-1.2.15/src/video/quartz/SDL_QuartzWM.m --- SDL-1.2.14/src/video/quartz/SDL_QuartzWM.m 2009-10-13 01:07:14.000000000 +0200 +++ SDL-1.2.15/src/video/quartz/SDL_QuartzWM.m 2012-01-19 07:30:06.000000000 +0100 @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2009 Sam Lantinga + Copyright (C) 1997-2012 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -47,18 +47,18 @@ /* Allocate the cursor memory */ cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor)); if (cursor == NULL) goto outOfMemory; - + /* create the image representation and get the pointers to its storage */ - imgrep = [ [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes: NULL pixelsWide: w pixelsHigh: h bitsPerSample: 1 samplesPerPixel: 2 hasAlpha: YES isPlanar: YES colorSpaceName: NSDeviceBlackColorSpace bytesPerRow: (w+7)/8 bitsPerPixel: 0 ] autorelease ]; + imgrep = [ [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes: NULL pixelsWide: w pixelsHigh: h bitsPerSample: 1 samplesPerPixel: 2 hasAlpha: YES isPlanar: YES colorSpaceName: NSDeviceWhiteColorSpace bytesPerRow: (w+7)/8 bitsPerPixel: 0 ] autorelease ]; if (imgrep == nil) goto outOfMemory; [ imgrep getBitmapDataPlanes: planes ]; /* copy data and mask, extending the mask to all black pixels because the inversion effect doesn't work with Cocoa's alpha-blended cursors */ for (i = 0; i < (w+7)/8*h; i++) { - planes[0][i] = data[i]; + planes[0][i] = data[i] ^ 0xFF; planes[1][i] = mask[i] | data[i]; } - + /* create image and cursor */ img = [ [ [ NSImage alloc ] initWithSize: NSMakeSize(w, h) ] autorelease ]; if (img == nil) goto outOfMemory; @@ -124,16 +124,14 @@ QZ_UpdateCursor(this); } else { - if (qz_window ==nil || (mode_flags & SDL_FULLSCREEN)) { - [ cursor->nscursor set ]; - } - else { + if ( qz_window != nil && !(mode_flags & SDL_FULLSCREEN) ) { [ qz_window invalidateCursorRectsForView: [ qz_window contentView ] ]; } if ( ! cursor_should_be_visible ) { cursor_should_be_visible = YES; QZ_ChangeGrabState (this, QZ_SHOWCURSOR); } + [ cursor->nscursor performSelectorOnMainThread:@selector(set) withObject:nil waitUntilDone:NO ]; QZ_UpdateCursor(this); } @@ -151,14 +149,16 @@ /* Convert Cocoa screen coordinate to Cocoa window coordinate */ void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p) { - *p = [ qz_window convertScreenToBase:*p ]; + if ( ! CGDisplayIsCaptured (display_id) ) + *p = [ qz_window convertScreenToBase:*p ]; } /* Convert Cocoa window coordinate to Cocoa screen coordinate */ void QZ_PrivateLocalToGlobal (_THIS, NSPoint *p) { - *p = [ qz_window convertBaseToScreen:*p ]; + if ( ! CGDisplayIsCaptured (display_id) ) + *p = [ qz_window convertBaseToScreen:*p ]; } /* Convert SDL coordinate to Cocoa coordinate */ @@ -230,7 +230,6 @@ #endif /* Dead code */ void QZ_PrivateWarpCursor (_THIS, int x, int y) { - NSPoint p; CGPoint cgp; @@ -238,8 +237,12 @@ cgp = QZ_PrivateSDLToCG (this, &p); /* this is the magic call that fixes cursor "freezing" after warp */ - CGSetLocalEventsSuppressionInterval (0.0); + CGAssociateMouseAndMouseCursorPosition (0); CGWarpMouseCursorPosition (cgp); + if (grab_state != QZ_INVISIBLE_GRAB) { /* can't leave it disassociated? */ + CGAssociateMouseAndMouseCursorPosition (1); + } + SDL_PrivateAppActive (QZ_IsMouseInWindow (this), SDL_APPMOUSEFOCUS); } void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y) { @@ -434,6 +437,7 @@ QZ_ChangeGrabState (this, QZ_DISABLE_GRAB); current_grab_mode = doGrab ? SDL_GRAB_ON : SDL_GRAB_OFF; + QZ_UpdateCursor(this); } return current_grab_mode;