aboutsummaryrefslogtreecommitdiffstats
path: root/distrib/sdl-1.2.15/src/video/quartz
diff options
context:
space:
mode:
Diffstat (limited to 'distrib/sdl-1.2.15/src/video/quartz')
-rw-r--r--distrib/sdl-1.2.15/src/video/quartz/CGS.h84
-rw-r--r--distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzEvents.m1063
-rw-r--r--distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzGL.m292
-rw-r--r--distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzKeys.h146
-rw-r--r--distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzVideo.h229
-rw-r--r--distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzVideo.m1689
-rw-r--r--distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWM.h27
-rw-r--r--distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWM.m444
-rw-r--r--distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWindow.h51
-rw-r--r--distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWindow.m231
10 files changed, 4256 insertions, 0 deletions
diff --git a/distrib/sdl-1.2.15/src/video/quartz/CGS.h b/distrib/sdl-1.2.15/src/video/quartz/CGS.h
new file mode 100644
index 0000000..abe47f7
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/quartz/CGS.h
@@ -0,0 +1,84 @@
+/*
+ SDL - Simple DirectMedia Layer
+ 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
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+/*
+ 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 */
+#define kCGSWindowLevelTop 2147483632
+#define kCGSWindowLevelDockIconDrag 500
+#define kCGSWindowLevelDockMenu 101
+#define kCGSWindowLevelMenuIgnore 21
+#define kCGSWindowLevelMenu 20
+#define kCGSWindowLevelDockLabel 12
+#define kCGSWindowLevelDockIcon 11
+#define kCGSWindowLevelDock 10
+#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
+*/
+
+typedef CGError CGSError;
+typedef long CGSWindowCount;
+typedef void * CGSConnectionID;
+typedef int CGSWindowID;
+typedef CGSWindowID* CGSWindowIDList;
+typedef CGWindowLevel CGSWindowLevel;
+typedef NSRect CGSRect;
+
+extern CGSConnectionID _CGSDefaultConnection ();
+
+extern CGSError CGSGetOnScreenWindowList (CGSConnectionID cid,
+ CGSConnectionID owner,
+ CGSWindowCount listCapacity,
+ CGSWindowIDList list,
+ CGSWindowCount *listCount);
+
+extern CGSError CGSGetScreenRectForWindow (CGSConnectionID cid,
+ CGSWindowID wid,
+ CGSRect *rect);
+
+extern CGWindowLevel CGSGetWindowLevel (CGSConnectionID cid,
+ CGSWindowID wid,
+ CGSWindowLevel *level);
+
+extern CGSError CGSDisplayHWFill (CGDirectDisplayID id, unsigned int x, unsigned int y,
+ unsigned int w, unsigned int h, unsigned int color);
+
+extern CGSError CGSDisplayCanHWFill (CGDirectDisplayID id);
+
+extern CGSError CGSGetMouseEnabledFlags (CGSConnectionID cid, CGSWindowID wid, int *flags);
+
+int CGSDisplayHWSync (CGDirectDisplayID id);
+
diff --git a/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzEvents.m b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzEvents.m
new file mode 100644
index 0000000..773eb01
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzEvents.m
@@ -0,0 +1,1063 @@
+/*
+ SDL - Simple DirectMedia Layer
+ 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
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#include "SDL_QuartzVideo.h"
+#include "SDL_QuartzWM.h"
+
+#include <IOKit/IOMessage.h> /* For wake from sleep detection */
+#include <IOKit/pwr_mgt/IOPMLib.h> /* For wake from sleep detection */
+#include "SDL_QuartzKeys.h"
+
+/*
+ * On Leopard, this is missing from the 64-bit headers
+ */
+#if defined(__LP64__) && !defined(__POWER__)
+/*
+ * Workaround for a bug in the 10.5 SDK: By accident, OSService.h does
+ * not include Power.h at all when compiling in 64bit mode. This has
+ * been fixed in 10.6, but for 10.5, we manually define UsrActivity
+ * to ensure compilation works.
+ */
+#define UsrActivity 1
+#endif
+
+/*
+ * In Panther, this header defines device dependent masks for
+ * right side keys. These definitions only exist in Panther, but
+ * the header seems to exist at least in Jaguar and probably earlier
+ * versions of the OS, so this should't break anything.
+ */
+#include <IOKit/hidsystem/IOLLEvent.h>
+/*
+ * These are not defined before Panther. To keep the code compiling
+ * on systems without these, I will define if they don't exist.
+ */
+#ifndef NX_DEVICERCTLKEYMASK
+ #define NX_DEVICELCTLKEYMASK 0x00000001
+#endif
+#ifndef NX_DEVICELSHIFTKEYMASK
+ #define NX_DEVICELSHIFTKEYMASK 0x00000002
+#endif
+#ifndef NX_DEVICERSHIFTKEYMASK
+ #define NX_DEVICERSHIFTKEYMASK 0x00000004
+#endif
+#ifndef NX_DEVICELCMDKEYMASK
+ #define NX_DEVICELCMDKEYMASK 0x00000008
+#endif
+#ifndef NX_DEVICERCMDKEYMASK
+ #define NX_DEVICERCMDKEYMASK 0x00000010
+#endif
+#ifndef NX_DEVICELALTKEYMASK
+ #define NX_DEVICELALTKEYMASK 0x00000020
+#endif
+#ifndef NX_DEVICERALTKEYMASK
+ #define NX_DEVICERALTKEYMASK 0x00000040
+#endif
+#ifndef NX_DEVICERCTLKEYMASK
+ #define NX_DEVICERCTLKEYMASK 0x00002000
+#endif
+
+void QZ_InitOSKeymap (_THIS) {
+ BOOL saw_layout = NO;
+ UInt32 state;
+ UInt32 value;
+ Uint16 i;
+ int world = SDLK_WORLD_0;
+
+ for ( i=0; i<SDL_TABLESIZE(keymap); ++i )
+ keymap[i] = SDLK_UNKNOWN;
+
+ /* This keymap is almost exactly the same as the OS 9 one */
+ keymap[QZ_ESCAPE] = SDLK_ESCAPE;
+ keymap[QZ_F1] = SDLK_F1;
+ keymap[QZ_F2] = SDLK_F2;
+ keymap[QZ_F3] = SDLK_F3;
+ keymap[QZ_F4] = SDLK_F4;
+ keymap[QZ_F5] = SDLK_F5;
+ keymap[QZ_F6] = SDLK_F6;
+ keymap[QZ_F7] = SDLK_F7;
+ keymap[QZ_F8] = SDLK_F8;
+ keymap[QZ_F9] = SDLK_F9;
+ keymap[QZ_F10] = SDLK_F10;
+ keymap[QZ_F11] = SDLK_F11;
+ keymap[QZ_F12] = SDLK_F12;
+ keymap[QZ_F13] = SDLK_F13;
+ keymap[QZ_F14] = SDLK_F14;
+ keymap[QZ_F15] = SDLK_F15;
+/*
+ keymap[QZ_PRINT] = SDLK_PRINT;
+ keymap[QZ_SCROLLOCK] = SDLK_SCROLLOCK;
+ keymap[QZ_PAUSE] = SDLK_PAUSE;
+*/
+ keymap[QZ_POWER] = SDLK_POWER;
+ keymap[QZ_BACKQUOTE] = SDLK_BACKQUOTE;
+ keymap[QZ_1] = SDLK_1;
+ keymap[QZ_2] = SDLK_2;
+ keymap[QZ_3] = SDLK_3;
+ keymap[QZ_4] = SDLK_4;
+ keymap[QZ_5] = SDLK_5;
+ keymap[QZ_6] = SDLK_6;
+ keymap[QZ_7] = SDLK_7;
+ keymap[QZ_8] = SDLK_8;
+ keymap[QZ_9] = SDLK_9;
+ keymap[QZ_0] = SDLK_0;
+ keymap[QZ_MINUS] = SDLK_MINUS;
+ keymap[QZ_EQUALS] = SDLK_EQUALS;
+ keymap[QZ_BACKSPACE] = SDLK_BACKSPACE;
+ keymap[QZ_INSERT] = SDLK_INSERT;
+ keymap[QZ_HOME] = SDLK_HOME;
+ keymap[QZ_PAGEUP] = SDLK_PAGEUP;
+ keymap[QZ_NUMLOCK] = SDLK_NUMLOCK;
+ keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS;
+ keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE;
+ keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
+ keymap[QZ_TAB] = SDLK_TAB;
+ keymap[QZ_q] = SDLK_q;
+ keymap[QZ_w] = SDLK_w;
+ keymap[QZ_e] = SDLK_e;
+ keymap[QZ_r] = SDLK_r;
+ keymap[QZ_t] = SDLK_t;
+ keymap[QZ_y] = SDLK_y;
+ keymap[QZ_u] = SDLK_u;
+ keymap[QZ_i] = SDLK_i;
+ keymap[QZ_o] = SDLK_o;
+ keymap[QZ_p] = SDLK_p;
+ keymap[QZ_LEFTBRACKET] = SDLK_LEFTBRACKET;
+ keymap[QZ_RIGHTBRACKET] = SDLK_RIGHTBRACKET;
+ keymap[QZ_BACKSLASH] = SDLK_BACKSLASH;
+ keymap[QZ_DELETE] = SDLK_DELETE;
+ keymap[QZ_END] = SDLK_END;
+ keymap[QZ_PAGEDOWN] = SDLK_PAGEDOWN;
+ keymap[QZ_KP7] = SDLK_KP7;
+ keymap[QZ_KP8] = SDLK_KP8;
+ keymap[QZ_KP9] = SDLK_KP9;
+ keymap[QZ_KP_MINUS] = SDLK_KP_MINUS;
+ keymap[QZ_CAPSLOCK] = SDLK_CAPSLOCK;
+ keymap[QZ_a] = SDLK_a;
+ keymap[QZ_s] = SDLK_s;
+ keymap[QZ_d] = SDLK_d;
+ keymap[QZ_f] = SDLK_f;
+ keymap[QZ_g] = SDLK_g;
+ keymap[QZ_h] = SDLK_h;
+ keymap[QZ_j] = SDLK_j;
+ keymap[QZ_k] = SDLK_k;
+ keymap[QZ_l] = SDLK_l;
+ keymap[QZ_SEMICOLON] = SDLK_SEMICOLON;
+ keymap[QZ_QUOTE] = SDLK_QUOTE;
+ keymap[QZ_RETURN] = SDLK_RETURN;
+ keymap[QZ_KP4] = SDLK_KP4;
+ keymap[QZ_KP5] = SDLK_KP5;
+ keymap[QZ_KP6] = SDLK_KP6;
+ keymap[QZ_KP_PLUS] = SDLK_KP_PLUS;
+ keymap[QZ_LSHIFT] = SDLK_LSHIFT;
+ keymap[QZ_RSHIFT] = SDLK_RSHIFT;
+ keymap[QZ_z] = SDLK_z;
+ keymap[QZ_x] = SDLK_x;
+ keymap[QZ_c] = SDLK_c;
+ keymap[QZ_v] = SDLK_v;
+ keymap[QZ_b] = SDLK_b;
+ keymap[QZ_n] = SDLK_n;
+ keymap[QZ_m] = SDLK_m;
+ keymap[QZ_COMMA] = SDLK_COMMA;
+ keymap[QZ_PERIOD] = SDLK_PERIOD;
+ keymap[QZ_SLASH] = SDLK_SLASH;
+ keymap[QZ_UP] = SDLK_UP;
+ keymap[QZ_KP1] = SDLK_KP1;
+ keymap[QZ_KP2] = SDLK_KP2;
+ keymap[QZ_KP3] = SDLK_KP3;
+ keymap[QZ_KP_ENTER] = SDLK_KP_ENTER;
+ keymap[QZ_LCTRL] = SDLK_LCTRL;
+ keymap[QZ_LALT] = SDLK_LALT;
+ keymap[QZ_LMETA] = SDLK_LMETA;
+ keymap[QZ_RCTRL] = SDLK_RCTRL;
+ keymap[QZ_RALT] = SDLK_RALT;
+ keymap[QZ_RMETA] = SDLK_RMETA;
+ keymap[QZ_SPACE] = SDLK_SPACE;
+ keymap[QZ_LEFT] = SDLK_LEFT;
+ keymap[QZ_DOWN] = SDLK_DOWN;
+ keymap[QZ_RIGHT] = SDLK_RIGHT;
+ keymap[QZ_KP0] = SDLK_KP0;
+ keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD;
+ keymap[QZ_IBOOK_ENTER] = SDLK_KP_ENTER;
+ keymap[QZ_IBOOK_RIGHT] = SDLK_RIGHT;
+ keymap[QZ_IBOOK_DOWN] = SDLK_DOWN;
+ keymap[QZ_IBOOK_UP] = SDLK_UP;
+ keymap[QZ_IBOOK_LEFT] = SDLK_LEFT;
+
+ /*
+ Up there we setup a static scancode->keysym map. However, it will not
+ work very well on international keyboard. Hence we now query MacOS
+ for its own keymap to adjust our own mapping table. However, this is
+ basically only useful for ascii char keys. This is also the reason
+ why we keep the static table, too.
+ */
+
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 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;
+ }
+ }
+
+ if (count != 1) {
+ continue; /* no multi-char. Use SDL 1.3 instead. :) */
+ }
+
+ 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;
+
+ /* 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
+ distinguish between a key on the keypad and a regular key. We maybe
+ could get around this problem in another fashion: NSEvent's flags
+ include a "NSNumericPadKeyMask" bit; we could check that and modify
+ the symbol we return on the fly. However, this flag seems to exhibit
+ some weird behaviour related to the num lock key
+ */
+ keymap[QZ_KP0] = SDLK_KP0;
+ keymap[QZ_KP1] = SDLK_KP1;
+ keymap[QZ_KP2] = SDLK_KP2;
+ keymap[QZ_KP3] = SDLK_KP3;
+ keymap[QZ_KP4] = SDLK_KP4;
+ keymap[QZ_KP5] = SDLK_KP5;
+ keymap[QZ_KP6] = SDLK_KP6;
+ keymap[QZ_KP7] = SDLK_KP7;
+ keymap[QZ_KP8] = SDLK_KP8;
+ keymap[QZ_KP9] = SDLK_KP9;
+ keymap[QZ_KP_MINUS] = SDLK_KP_MINUS;
+ keymap[QZ_KP_PLUS] = SDLK_KP_PLUS;
+ keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD;
+ keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS;
+ keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE;
+ keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
+ keymap[QZ_KP_ENTER] = SDLK_KP_ENTER;
+}
+
+static void QZ_DoKey (_THIS, int state, NSEvent *event) {
+
+ NSString *chars = NULL;
+ unsigned int i, numChars;
+ SDL_keysym key;
+
+ /*
+ A key event can contain multiple characters,
+ or no characters at all. In most cases, it
+ will contain a single character. If it contains
+ 0 characters, we'll use 0 as the unicode. If it
+ contains multiple characters, we'll use 0 as
+ the scancode/keysym.
+ */
+ if (SDL_TranslateUNICODE && state == SDL_PRESSED) {
+ [field_edit interpretKeyEvents:[NSArray arrayWithObject:event]];
+ chars = [ event characters ];
+ numChars = [ chars length ];
+ if (numChars > 0)
+ [field_edit setString:@""];
+ } else {
+ numChars = 0;
+ }
+
+ if (numChars == 0) {
+
+ key.scancode = [ event keyCode ];
+ key.sym = keymap [ key.scancode ];
+ key.unicode = 0;
+ key.mod = KMOD_NONE;
+
+ SDL_PrivateKeyboard (state, &key);
+ }
+ else if (numChars >= 1) {
+
+ key.scancode = [ event keyCode ];
+ key.sym = keymap [ key.scancode ];
+ key.unicode = [ chars characterAtIndex:0 ];
+ key.mod = KMOD_NONE;
+
+ SDL_PrivateKeyboard (state, &key);
+
+ for (i = 1; i < numChars; i++) {
+
+ key.scancode = 0;
+ key.sym = 0;
+ key.unicode = [ chars characterAtIndex:i];
+ key.mod = KMOD_NONE;
+
+ SDL_PrivateKeyboard (state, &key);
+ }
+ }
+
+ if (SDL_getenv ("SDL_ENABLEAPPEVENTS"))
+ [ NSApp sendEvent:event ];
+}
+
+/* This is the original behavior, before support was added for
+ * differentiating between left and right versions of the keys.
+ */
+static void QZ_DoUnsidedModifiers (_THIS, unsigned int newMods) {
+
+ const int mapping[] = { SDLK_CAPSLOCK, SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA };
+
+ int i;
+ int bit;
+ SDL_keysym key;
+
+ key.scancode = 0;
+ key.sym = SDLK_UNKNOWN;
+ key.unicode = 0;
+ key.mod = KMOD_NONE;
+
+ /* Iterate through the bits, testing each against the current modifiers */
+ for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
+
+ unsigned int currentMask, newMask;
+
+ currentMask = current_mods & bit;
+ newMask = newMods & bit;
+
+ if ( currentMask &&
+ currentMask != newMask ) { /* modifier up event */
+
+ key.sym = mapping[i];
+ /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
+ if (bit == NSAlphaShiftKeyMask)
+ SDL_PrivateKeyboard (SDL_PRESSED, &key);
+ SDL_PrivateKeyboard (SDL_RELEASED, &key);
+ }
+ else if ( newMask &&
+ currentMask != newMask ) { /* modifier down event */
+
+ key.sym = mapping[i];
+ SDL_PrivateKeyboard (SDL_PRESSED, &key);
+ /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
+ if (bit == NSAlphaShiftKeyMask)
+ SDL_PrivateKeyboard (SDL_RELEASED, &key);
+ }
+ }
+}
+
+/* This is a helper function for QZ_HandleModifierSide. This
+ * function reverts back to behavior before the distinction between
+ * sides was made.
+ */
+static void QZ_HandleNonDeviceModifier ( _THIS, unsigned int device_independent_mask, unsigned int newMods, unsigned int key_sym) {
+ unsigned int currentMask, newMask;
+ SDL_keysym key;
+
+ key.scancode = 0;
+ key.sym = key_sym;
+ key.unicode = 0;
+ key.mod = KMOD_NONE;
+
+ /* Isolate just the bits we care about in the depedent bits so we can
+ * figure out what changed
+ */
+ currentMask = current_mods & device_independent_mask;
+ newMask = newMods & device_independent_mask;
+
+ if ( currentMask &&
+ currentMask != newMask ) { /* modifier up event */
+ SDL_PrivateKeyboard (SDL_RELEASED, &key);
+ }
+ else if ( newMask &&
+ currentMask != newMask ) { /* modifier down event */
+ SDL_PrivateKeyboard (SDL_PRESSED, &key);
+ }
+}
+
+/* This is a helper function for QZ_HandleModifierSide.
+ * This function sets the actual SDL_PrivateKeyboard event.
+ */
+static void QZ_HandleModifierOneSide ( _THIS, unsigned int newMods,
+ unsigned int key_sym,
+ unsigned int sided_device_dependent_mask ) {
+
+ SDL_keysym key;
+ unsigned int current_dep_mask, new_dep_mask;
+
+ key.scancode = 0;
+ key.sym = key_sym;
+ key.unicode = 0;
+ key.mod = KMOD_NONE;
+
+ /* Isolate just the bits we care about in the depedent bits so we can
+ * figure out what changed
+ */
+ current_dep_mask = current_mods & sided_device_dependent_mask;
+ new_dep_mask = newMods & sided_device_dependent_mask;
+
+ /* We now know that this side bit flipped. But we don't know if
+ * it went pressed to released or released to pressed, so we must
+ * find out which it is.
+ */
+ if( new_dep_mask &&
+ current_dep_mask != new_dep_mask ) {
+ /* Modifier down event */
+ SDL_PrivateKeyboard (SDL_PRESSED, &key);
+ }
+ else /* Modifier up event */ {
+ SDL_PrivateKeyboard (SDL_RELEASED, &key);
+ }
+}
+
+/* This is a helper function for QZ_DoSidedModifiers.
+ * This function will figure out if the modifier key is the left or right side,
+ * e.g. left-shift vs right-shift.
+ */
+static void QZ_HandleModifierSide ( _THIS, int device_independent_mask,
+ unsigned int newMods,
+ unsigned int left_key_sym,
+ unsigned int right_key_sym,
+ unsigned int left_device_dependent_mask,
+ unsigned int right_device_dependent_mask ) {
+ unsigned int device_dependent_mask = 0;
+ unsigned int diff_mod = 0;
+
+ device_dependent_mask = left_device_dependent_mask | right_device_dependent_mask;
+ /* On the basis that the device independent mask is set, but there are
+ * no device dependent flags set, we'll assume that we can't detect this
+ * keyboard and revert to the unsided behavior.
+ */
+ if ( (device_dependent_mask & newMods) == 0 ) {
+ /* Revert to the old behavior */
+ QZ_HandleNonDeviceModifier ( this, device_independent_mask, newMods, left_key_sym );
+ return;
+ }
+
+ /* XOR the previous state against the new state to see if there's a change */
+ diff_mod = (device_dependent_mask & current_mods)
+ ^ (device_dependent_mask & newMods);
+
+ if ( diff_mod ) {
+ /* A change in state was found. Isolate the left and right bits
+ * to handle them separately just in case the values can simulataneously
+ * change or if the bits don't both exist.
+ */
+ if ( left_device_dependent_mask & diff_mod ) {
+ QZ_HandleModifierOneSide ( this, newMods, left_key_sym, left_device_dependent_mask );
+ }
+ if ( right_device_dependent_mask & diff_mod ) {
+ QZ_HandleModifierOneSide ( this, newMods, right_key_sym, right_device_dependent_mask );
+ }
+ }
+}
+
+/* This is a helper function for QZ_DoSidedModifiers.
+ * This function will release a key press in the case that
+ * it is clear that the modifier has been released (i.e. one side
+ * can't still be down).
+ */
+static void QZ_ReleaseModifierSide ( _THIS,
+ unsigned int device_independent_mask,
+ unsigned int newMods,
+ unsigned int left_key_sym,
+ unsigned int right_key_sym,
+ unsigned int left_device_dependent_mask,
+ unsigned int right_device_dependent_mask ) {
+ unsigned int device_dependent_mask = 0;
+ SDL_keysym key;
+
+ key.scancode = 0;
+ key.sym = SDLK_UNKNOWN;
+ key.unicode = 0;
+ key.mod = KMOD_NONE;
+
+ device_dependent_mask = left_device_dependent_mask | right_device_dependent_mask;
+ /* On the basis that the device independent mask is set, but there are
+ * no device dependent flags set, we'll assume that we can't detect this
+ * keyboard and revert to the unsided behavior.
+ */
+ if ( (device_dependent_mask & current_mods) == 0 ) {
+ /* In this case, we can't detect the keyboard, so use the left side
+ * to represent both, and release it.
+ */
+ key.sym = left_key_sym;
+ SDL_PrivateKeyboard (SDL_RELEASED, &key);
+
+ return;
+ }
+
+
+ /*
+ * This could have been done in an if-else case because at this point,
+ * we know that all keys have been released when calling this function.
+ * But I'm being paranoid so I want to handle each separately,
+ * so I hope this doesn't cause other problems.
+ */
+ if ( left_device_dependent_mask & current_mods ) {
+ key.sym = left_key_sym;
+ SDL_PrivateKeyboard (SDL_RELEASED, &key);
+ }
+ if ( right_device_dependent_mask & current_mods ) {
+ key.sym = right_key_sym;
+ SDL_PrivateKeyboard (SDL_RELEASED, &key);
+ }
+}
+
+/* This is a helper function for QZ_DoSidedModifiers.
+ * This function handles the CapsLock case.
+ */
+static void QZ_HandleCapsLock (_THIS, unsigned int newMods) {
+ unsigned int currentMask, newMask;
+ SDL_keysym key;
+
+ key.scancode = 0;
+ key.sym = SDLK_CAPSLOCK;
+ key.unicode = 0;
+ key.mod = KMOD_NONE;
+
+ currentMask = current_mods & NSAlphaShiftKeyMask;
+ newMask = newMods & NSAlphaShiftKeyMask;
+
+ if ( currentMask &&
+ currentMask != newMask ) { /* modifier up event */
+ /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
+ SDL_PrivateKeyboard (SDL_PRESSED, &key);
+ SDL_PrivateKeyboard (SDL_RELEASED, &key);
+ }
+ else if ( newMask &&
+ currentMask != newMask ) { /* modifier down event */
+ /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
+ SDL_PrivateKeyboard (SDL_PRESSED, &key);
+ SDL_PrivateKeyboard (SDL_RELEASED, &key);
+ }
+}
+
+/* This function will handle the modifier keys and also determine the
+ * correct side of the key.
+ */
+static void QZ_DoSidedModifiers (_THIS, unsigned int newMods) {
+ /* Set up arrays for the key syms for the left and right side. */
+ const unsigned int left_mapping[] = { SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA };
+ const unsigned int right_mapping[] = { SDLK_RSHIFT, SDLK_RCTRL, SDLK_RALT, SDLK_RMETA };
+ /* Set up arrays for the device dependent masks with indices that
+ * correspond to the _mapping arrays
+ */
+ const unsigned int left_device_mapping[] = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK };
+ const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK };
+
+ unsigned int i;
+ unsigned int bit;
+
+ /* Handle CAPSLOCK separately because it doesn't have a left/right side */
+ QZ_HandleCapsLock ( this, newMods );
+
+ /* Iterate through the bits, testing each against the current modifiers */
+ for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
+
+ unsigned int currentMask, newMask;
+
+ currentMask = current_mods & bit;
+ newMask = newMods & bit;
+
+ /* If the bit is set, we must always examine it because the left
+ * and right side keys may alternate or both may be pressed.
+ */
+ if ( newMask ) {
+ QZ_HandleModifierSide ( this, bit, newMods,
+ left_mapping[i],
+ right_mapping[i],
+ left_device_mapping[i],
+ right_device_mapping[i] );
+ }
+ /* If the state changed from pressed to unpressed, we must examine
+ * the device dependent bits to release the correct keys.
+ */
+ else if ( currentMask &&
+ currentMask != newMask ) { /* modifier up event */
+ QZ_ReleaseModifierSide ( this, bit, newMods,
+ left_mapping[i],
+ right_mapping[i],
+ left_device_mapping[i],
+ right_device_mapping[i] );
+ }
+ }
+}
+
+/* This function is called to handle the modifiers.
+ * It will try to distinguish between the left side and right side
+ * of the keyboard for those modifiers that qualify if the
+ * operating system version supports it. Otherwise, the code
+ * will not try to make the distinction.
+ */
+static void QZ_DoModifiers (_THIS, unsigned int newMods) {
+
+ if (current_mods == newMods)
+ return;
+
+ /*
+ * Starting with Panther (10.3.0), the ability to distinguish between
+ * left side and right side modifiers is available.
+ */
+ if( system_version >= 0x1030 ) {
+ QZ_DoSidedModifiers (this, newMods);
+ }
+ else {
+ QZ_DoUnsidedModifiers (this, newMods);
+ }
+
+ current_mods = newMods;
+}
+
+static void QZ_GetMouseLocation (_THIS, NSPoint *p) {
+ *p = [ NSEvent mouseLocation ]; /* global coordinates */
+ if (qz_window)
+ QZ_PrivateGlobalToLocal (this, p);
+ QZ_PrivateCocoaToSDL (this, p);
+}
+
+void QZ_DoActivate (_THIS) {
+
+ SDL_PrivateAppActive (1, SDL_APPINPUTFOCUS | (QZ_IsMouseInWindow (this) ? SDL_APPMOUSEFOCUS : 0));
+
+ QZ_UpdateCursor(this);
+
+ /* Regrab input, only if it was previously grabbed */
+ if ( current_grab_mode == SDL_GRAB_ON ) {
+
+ /* Restore cursor location if input was grabbed */
+ QZ_PrivateWarpCursor (this, cursor_loc.x, cursor_loc.y);
+ QZ_ChangeGrabState (this, QZ_ENABLE_GRAB);
+ }
+ else {
+ /* Update SDL's mouse location */
+ NSPoint p;
+ QZ_GetMouseLocation (this, &p);
+ SDL_PrivateMouseMotion (0, 0, p.x, p.y);
+ }
+
+ QZ_UpdateCursor(this);
+}
+
+void QZ_DoDeactivate (_THIS) {
+
+ SDL_PrivateAppActive (0, SDL_APPINPUTFOCUS | SDL_APPMOUSEFOCUS);
+
+ /* Get the current cursor location, for restore on activate */
+ QZ_GetMouseLocation (this, &cursor_loc);
+
+ /* Reassociate mouse and cursor */
+ CGAssociateMouseAndMouseCursorPosition (1);
+
+ QZ_UpdateCursor(this);
+}
+
+void QZ_SleepNotificationHandler (void * refcon,
+ io_service_t service,
+ natural_t messageType,
+ void * messageArgument )
+{
+ SDL_VideoDevice *this = (SDL_VideoDevice*)refcon;
+
+ switch(messageType)
+ {
+ case kIOMessageSystemWillSleep:
+ IOAllowPowerChange(power_connection, (long) messageArgument);
+ break;
+ case kIOMessageCanSystemSleep:
+ IOAllowPowerChange(power_connection, (long) messageArgument);
+ break;
+ case kIOMessageSystemHasPoweredOn:
+ /* awake */
+ SDL_PrivateExpose();
+ break;
+ }
+}
+
+void QZ_RegisterForSleepNotifications (_THIS)
+{
+ CFRunLoopSourceRef rls;
+ IONotificationPortRef thePortRef;
+ io_object_t notifier;
+
+ power_connection = IORegisterForSystemPower (this, &thePortRef, QZ_SleepNotificationHandler, &notifier);
+
+ if (power_connection == 0)
+ NSLog(@"SDL: QZ_SleepNotificationHandler() IORegisterForSystemPower failed.");
+
+ rls = IONotificationPortGetRunLoopSource (thePortRef);
+ CFRunLoopAddSource (CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
+ CFRelease (rls);
+}
+
+
+/* Try to map Quartz mouse buttons to SDL's lingo... */
+static int QZ_OtherMouseButtonToSDL(int button)
+{
+ switch (button)
+ {
+ case 0:
+ return(SDL_BUTTON_LEFT); /* 1 */
+ case 1:
+ return(SDL_BUTTON_RIGHT); /* 3 */
+ case 2:
+ return(SDL_BUTTON_MIDDLE); /* 2 */
+ }
+
+ /* >= 3: skip 4 & 5, since those are the SDL mousewheel buttons. */
+ return(button + 3);
+}
+
+
+void QZ_PumpEvents (_THIS)
+{
+ int32_t dx, dy;
+
+ NSDate *distantPast;
+ NSEvent *event;
+ NSRect winRect;
+ NSAutoreleasePool *pool;
+
+ if (!SDL_VideoSurface)
+ return; /* don't do anything if there's no screen surface. */
+
+ /* Update activity every five seconds to prevent screensaver. --ryan. */
+ if (!allow_screensaver) {
+ static Uint32 screensaverTicks;
+ Uint32 nowTicks = SDL_GetTicks();
+ if ((nowTicks - screensaverTicks) > 5000)
+ {
+ UpdateSystemActivity(UsrActivity);
+ screensaverTicks = nowTicks;
+ }
+ }
+
+ pool = [ [ NSAutoreleasePool alloc ] init ];
+ distantPast = [ NSDate distantPast ];
+
+ winRect = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
+
+ /* while grabbed, accumulate all mouse moved events into one SDL mouse event */
+ dx = 0;
+ dy = 0;
+
+ do {
+
+ /* Poll for an event. This will not block */
+ event = [ NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:distantPast
+ inMode: NSDefaultRunLoopMode dequeue:YES ];
+ if (event != nil) {
+
+ int button;
+ unsigned int type;
+ BOOL isInGameWin;
+
+ #define DO_MOUSE_DOWN(button) do { \
+ if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { \
+ SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0); \
+ expect_mouse_up |= 1<<button; \
+ } \
+ [ NSApp sendEvent:event ]; \
+ } while(0)
+
+ #define DO_MOUSE_UP(button) do { \
+ if ( expect_mouse_up & (1<<button) ) { \
+ SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0); \
+ expect_mouse_up &= ~(1<<button); \
+ } \
+ [ NSApp sendEvent:event ]; \
+ } while(0)
+
+ type = [ event type ];
+ isInGameWin = QZ_IsMouseInWindow (this);
+
+ QZ_DoModifiers(this, [ event modifierFlags ] );
+
+ switch (type) {
+ case NSLeftMouseDown:
+ if ( SDL_getenv("SDL_HAS3BUTTONMOUSE") ) {
+ DO_MOUSE_DOWN (SDL_BUTTON_LEFT);
+ } else {
+ if ( NSCommandKeyMask & current_mods ) {
+ last_virtual_button = SDL_BUTTON_RIGHT;
+ DO_MOUSE_DOWN (SDL_BUTTON_RIGHT);
+ }
+ else if ( NSAlternateKeyMask & current_mods ) {
+ last_virtual_button = SDL_BUTTON_MIDDLE;
+ DO_MOUSE_DOWN (SDL_BUTTON_MIDDLE);
+ }
+ else {
+ DO_MOUSE_DOWN (SDL_BUTTON_LEFT);
+ }
+ }
+ break;
+
+ case NSLeftMouseUp:
+ if ( last_virtual_button != 0 ) {
+ DO_MOUSE_UP (last_virtual_button);
+ last_virtual_button = 0;
+ }
+ else {
+ DO_MOUSE_UP (SDL_BUTTON_LEFT);
+ }
+ break;
+
+ case NSOtherMouseDown:
+ case NSRightMouseDown:
+ button = QZ_OtherMouseButtonToSDL([ event buttonNumber ]);
+ DO_MOUSE_DOWN (button);
+ break;
+
+ case NSOtherMouseUp:
+ case NSRightMouseUp:
+ button = QZ_OtherMouseButtonToSDL([ event buttonNumber ]);
+ DO_MOUSE_UP (button);
+ break;
+
+ case NSSystemDefined:
+ /*
+ Future: up to 32 "mouse" buttons can be handled.
+ if ([event subtype] == 7) {
+ unsigned int buttons;
+ buttons = [ event data2 ];
+ */
+ break;
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSOtherMouseDragged: /* usually middle mouse dragged */
+ case NSMouseMoved:
+ if ( grab_state == QZ_INVISIBLE_GRAB ) {
+
+ /*
+ If input is grabbed+hidden, the cursor doesn't move,
+ so we have to call the lowlevel window server
+ function. This is less accurate but works OK.
+ */
+ int32_t dx1, dy1;
+ CGGetLastMouseDelta (&dx1, &dy1);
+ dx += dx1;
+ dy += dy1;
+ }
+ else {
+
+ /*
+ Get the absolute mouse location. This is not the
+ mouse location after the currently processed event,
+ but the *current* mouse location, i.e. after all
+ pending events. This means that if there are
+ multiple mouse moved events in the queue, we make
+ multiple identical calls to SDL_PrivateMouseMotion(),
+ but that's no problem since the latter only
+ generates SDL events for nonzero movements. In my
+ experience on PBG4/10.4.8, this rarely happens anyway.
+ */
+ NSPoint p;
+ QZ_GetMouseLocation (this, &p);
+ SDL_PrivateMouseMotion (0, 0, p.x, p.y);
+ }
+
+ /*
+ Handle grab input+cursor visible by warping the cursor back
+ into the game window. This still generates a mouse moved event,
+ but not as a result of the warp (so it's in the right direction).
+ */
+ if ( grab_state == QZ_VISIBLE_GRAB && !isInGameWin ) {
+
+ NSPoint p;
+ QZ_GetMouseLocation (this, &p);
+
+ if ( p.x < 0.0 )
+ p.x = 0.0;
+
+ if ( p.y < 0.0 )
+ p.y = 0.0;
+
+ if ( p.x >= winRect.size.width )
+ p.x = winRect.size.width-1;
+
+ if ( p.y >= winRect.size.height )
+ p.y = winRect.size.height-1;
+
+ QZ_PrivateWarpCursor (this, p.x, p.y);
+ }
+ else
+ if ( !isInGameWin && (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) {
+
+ SDL_PrivateAppActive (0, SDL_APPMOUSEFOCUS);
+
+ if (grab_state == QZ_INVISIBLE_GRAB)
+ /*The cursor has left the window even though it is
+ disassociated from the mouse (and therefore
+ shouldn't move): this can happen with Wacom
+ tablets, and it effectively breaks the grab, since
+ mouse down events now go to background
+ applications. The only possibility to avoid this
+ seems to be talking to the tablet driver
+ (AppleEvents) to constrain its mapped area to the
+ window, which may not be worth the effort. For
+ now, handle the condition more gracefully than
+ before by reassociating cursor and mouse until the
+ cursor enters the window again, making it obvious
+ to the user that the grab is broken.*/
+ CGAssociateMouseAndMouseCursorPosition (1);
+
+ QZ_UpdateCursor(this);
+ }
+ else
+ if ( isInGameWin && (SDL_GetAppState() & (SDL_APPMOUSEFOCUS | SDL_APPINPUTFOCUS)) == SDL_APPINPUTFOCUS ) {
+
+ SDL_PrivateAppActive (1, SDL_APPMOUSEFOCUS);
+
+ QZ_UpdateCursor(this);
+
+ if (grab_state == QZ_INVISIBLE_GRAB) { /*see comment above*/
+ QZ_PrivateWarpCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2);
+ CGAssociateMouseAndMouseCursorPosition (0);
+ }
+ }
+ break;
+ case NSScrollWheel:
+ if ( isInGameWin ) {
+ float dy, dx;
+ Uint8 button;
+ dy = [ event deltaY ];
+ dx = [ event deltaX ];
+ if ( dy > 0.0 ) /* Scroll up */
+ button = SDL_BUTTON_WHEELUP;
+ else if ( dy < 0.0 ) /* Scroll down */
+ button = SDL_BUTTON_WHEELDOWN;
+ else
+ break; /* Horizontal scroll */
+ /* For now, wheel is sent as a quick down+up */
+ SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0);
+ SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0);
+ }
+ break;
+ case NSKeyUp:
+ QZ_DoKey (this, SDL_RELEASED, event);
+ break;
+ case NSKeyDown:
+ QZ_DoKey (this, SDL_PRESSED, event);
+ break;
+ case NSFlagsChanged:
+ break;
+ case NSAppKitDefined:
+ [ NSApp sendEvent:event ];
+ if ([ event subtype ] == NSApplicationActivatedEventType && (mode_flags & SDL_FULLSCREEN)) {
+ /* the default handling of this event seems to reset any cursor set by [NSCursor set] (used by SDL_SetCursor() in fullscreen mode) to the default system arrow cursor */
+ SDL_Cursor *sdlc = SDL_GetCursor();
+ if (sdlc != NULL && sdlc->wm_cursor != NULL) {
+ [ sdlc->wm_cursor->nscursor set ];
+ }
+ }
+ break;
+ /* case NSApplicationDefined: break; */
+ /* case NSPeriodic: break; */
+ /* case NSCursorUpdate: break; */
+ default:
+ [ NSApp sendEvent:event ];
+ }
+ }
+ } while (event != nil);
+
+ /* handle accumulated mouse moved events */
+ if (dx != 0 || dy != 0)
+ SDL_PrivateMouseMotion (0, 1, dx, dy);
+
+ [ pool release ];
+}
+
+void QZ_UpdateMouse (_THIS)
+{
+ NSPoint p;
+ QZ_GetMouseLocation (this, &p);
+ SDL_PrivateAppActive (QZ_IsMouseInWindow (this), SDL_APPMOUSEFOCUS);
+ SDL_PrivateMouseMotion (0, 0, p.x, p.y);
+}
diff --git a/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzGL.m b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzGL.m
new file mode 100644
index 0000000..d38dceb
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzGL.m
@@ -0,0 +1,292 @@
+/*
+ SDL - Simple DirectMedia Layer
+ 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
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#include "SDL_QuartzVideo.h"
+
+/*
+ * GL_ARB_Multisample is supposed to be available in 10.1, according to Apple:
+ *
+ * http://developer.apple.com/graphicsimaging/opengl/extensions.html#GL_ARB_multisample
+ *
+ * ...but it isn't in the system headers, according to Sam:
+ *
+ * http://lists.libsdl.org/pipermail/sdl-libsdl.org/2003-December/039794.html
+ *
+ * These are normally enums and not #defines in the system headers.
+ *
+ * --ryan.
+ */
+#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1020)
+#define NSOpenGLPFASampleBuffers ((NSOpenGLPixelFormatAttribute) 55)
+#define NSOpenGLPFASamples ((NSOpenGLPixelFormatAttribute) 56)
+#endif
+
+#ifdef __powerpc__ /* we lost this in 10.6, which has no PPC support. */
+@implementation NSOpenGLContext (CGLContextAccess)
+- (CGLContextObj) cglContext;
+{
+ return _contextAuxiliary;
+}
+@end
+CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx)
+{
+ return [nsctx cglContext];
+}
+#else
+CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx)
+{
+ return (CGLContextObj) [nsctx CGLContextObj];
+}
+#endif
+
+
+/* OpenGL helper functions (used internally) */
+
+int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
+
+ NSOpenGLPixelFormatAttribute attr[32];
+ NSOpenGLPixelFormat *fmt;
+ int i = 0;
+ int colorBits = bpp;
+
+ /* if a GL library hasn't been loaded at this point, load the default. */
+ if (!this->gl_config.driver_loaded) {
+ if (QZ_GL_LoadLibrary(this, NULL) == -1)
+ return 0;
+ }
+
+ if ( flags & SDL_FULLSCREEN ) {
+
+ attr[i++] = NSOpenGLPFAFullScreen;
+ }
+ /* In windowed mode, the OpenGL pixel depth must match device pixel depth */
+ else if ( colorBits != device_bpp ) {
+
+ colorBits = device_bpp;
+ }
+
+ attr[i++] = NSOpenGLPFAColorSize;
+ attr[i++] = colorBits;
+
+ attr[i++] = NSOpenGLPFADepthSize;
+ attr[i++] = this->gl_config.depth_size;
+
+ if ( this->gl_config.double_buffer ) {
+ attr[i++] = NSOpenGLPFADoubleBuffer;
+ }
+
+ if ( this->gl_config.stereo ) {
+ attr[i++] = NSOpenGLPFAStereo;
+ }
+
+ if ( this->gl_config.stencil_size != 0 ) {
+ attr[i++] = NSOpenGLPFAStencilSize;
+ attr[i++] = this->gl_config.stencil_size;
+ }
+
+ if ( (this->gl_config.accum_red_size +
+ this->gl_config.accum_green_size +
+ this->gl_config.accum_blue_size +
+ this->gl_config.accum_alpha_size) > 0 ) {
+ attr[i++] = NSOpenGLPFAAccumSize;
+ attr[i++] = this->gl_config.accum_red_size + this->gl_config.accum_green_size + this->gl_config.accum_blue_size + this->gl_config.accum_alpha_size;
+ }
+
+ if ( this->gl_config.multisamplebuffers != 0 ) {
+ attr[i++] = NSOpenGLPFASampleBuffers;
+ attr[i++] = this->gl_config.multisamplebuffers;
+ }
+
+ if ( this->gl_config.multisamplesamples != 0 ) {
+ attr[i++] = NSOpenGLPFASamples;
+ attr[i++] = this->gl_config.multisamplesamples;
+ attr[i++] = NSOpenGLPFANoRecovery;
+ }
+
+ if ( this->gl_config.accelerated > 0 ) {
+ attr[i++] = NSOpenGLPFAAccelerated;
+ }
+
+ attr[i++] = NSOpenGLPFAScreenMask;
+ attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
+ attr[i] = 0;
+
+ fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
+ if (fmt == nil) {
+ SDL_SetError ("Failed creating OpenGL pixel format");
+ return 0;
+ }
+
+ gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
+ shareContext:nil];
+
+ [ fmt release ];
+
+ if (gl_context == nil) {
+ SDL_SetError ("Failed creating OpenGL context");
+ return 0;
+ }
+
+ /* Synchronize QZ_GL_SwapBuffers() to vertical retrace.
+ * (Apple's documentation is not completely clear about what this setting
+ * exactly does, IMHO - for a detailed explanation see
+ * http://lists.apple.com/archives/mac-opengl/2006/Jan/msg00080.html )
+ */
+ if ( this->gl_config.swap_control >= 0 ) {
+ GLint value;
+ value = this->gl_config.swap_control;
+ [ gl_context setValues: &value forParameter: NSOpenGLCPSwapInterval ];
+ }
+
+ /*
+ * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
+ * "You are blowing a couple of the internal OpenGL function caches. This
+ * appears to be happening in the VAO case. You can tell OpenGL to up
+ * the cache size by issuing the following calls right after you create
+ * the OpenGL context. The default cache size is 16." --ryan.
+ */
+
+ #ifndef GLI_ARRAY_FUNC_CACHE_MAX
+ #define GLI_ARRAY_FUNC_CACHE_MAX 284
+ #endif
+
+ #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
+ #define GLI_SUBMIT_FUNC_CACHE_MAX 280
+ #endif
+
+ {
+ 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);
+ }
+
+ /* End Wisdom from Apple Engineer section. --ryan. */
+
+ return 1;
+}
+
+void QZ_TearDownOpenGL (_THIS) {
+
+ [ NSOpenGLContext clearCurrentContext ];
+ [ gl_context clearDrawable ];
+ [ gl_context release ];
+}
+
+
+/* SDL OpenGL functions */
+static const char *DEFAULT_OPENGL_LIB_NAME =
+ "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib";
+
+int QZ_GL_LoadLibrary (_THIS, const char *location) {
+ if ( gl_context != NULL ) {
+ SDL_SetError("OpenGL context already created");
+ return -1;
+ }
+
+ if (opengl_library != NULL)
+ SDL_UnloadObject(opengl_library);
+
+ if (location == NULL)
+ location = DEFAULT_OPENGL_LIB_NAME;
+
+ opengl_library = SDL_LoadObject(location);
+ if (opengl_library != NULL) {
+ this->gl_config.driver_loaded = 1;
+ return 0;
+ }
+
+ this->gl_config.driver_loaded = 0;
+ return -1;
+}
+
+void* QZ_GL_GetProcAddress (_THIS, const char *proc) {
+ return SDL_LoadFunction(opengl_library, proc);
+}
+
+int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value) {
+
+ GLenum attr = 0;
+
+ QZ_GL_MakeCurrent (this);
+
+ switch (attrib) {
+ case SDL_GL_RED_SIZE: attr = GL_RED_BITS; break;
+ case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS; break;
+ case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break;
+ case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break;
+ case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break;
+ case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS; break;
+ case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break;
+ case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break;
+ case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break;
+ case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break;
+ case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break;
+ case SDL_GL_STEREO: attr = GL_STEREO; break;
+ case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break;
+ case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break;
+ case SDL_GL_BUFFER_SIZE:
+ {
+ GLint bits = 0;
+ GLint component;
+
+ /* there doesn't seem to be a single flag in OpenGL for this! */
+ glGetIntegerv (GL_RED_BITS, &component); bits += component;
+ glGetIntegerv (GL_GREEN_BITS,&component); bits += component;
+ glGetIntegerv (GL_BLUE_BITS, &component); bits += component;
+ glGetIntegerv (GL_ALPHA_BITS, &component); bits += component;
+
+ *value = bits;
+ return 0;
+ }
+ case SDL_GL_ACCELERATED_VISUAL:
+ {
+ GLint val;
+ /* FIXME: How do we get this information here?
+ [fmt getValues: &val forAttribute: NSOpenGLPFAAccelerated attr forVirtualScreen: 0];
+ */
+ val = (this->gl_config.accelerated != 0);;
+ *value = val;
+ return 0;
+ }
+ case SDL_GL_SWAP_CONTROL:
+ {
+ GLint val;
+ [ gl_context getValues: &val forParameter: NSOpenGLCPSwapInterval ];
+ *value = val;
+ return 0;
+ }
+ }
+
+ glGetIntegerv (attr, (GLint *)value);
+ return 0;
+}
+
+int QZ_GL_MakeCurrent (_THIS) {
+ [ gl_context makeCurrentContext ];
+ return 0;
+}
+
+void QZ_GL_SwapBuffers (_THIS) {
+ [ gl_context flushBuffer ];
+}
diff --git a/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzKeys.h b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzKeys.h
new file mode 100644
index 0000000..82b7859
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzKeys.h
@@ -0,0 +1,146 @@
+/*
+ SDL - Simple DirectMedia Layer
+ 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
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+/* These are the Macintosh key scancode constants -- from Inside Macintosh */
+
+#define QZ_ESCAPE 0x35
+#define QZ_F1 0x7A
+#define QZ_F2 0x78
+#define QZ_F3 0x63
+#define QZ_F4 0x76
+#define QZ_F5 0x60
+#define QZ_F6 0x61
+#define QZ_F7 0x62
+#define QZ_F8 0x64
+#define QZ_F9 0x65
+#define QZ_F10 0x6D
+#define QZ_F11 0x67
+#define QZ_F12 0x6F
+#define QZ_F13 0x69
+#define QZ_F14 0x6B
+#define QZ_F15 0x71
+/*
+#define QZ_PRINT 0x69
+#define QZ_SCROLLOCK 0x6B
+#define QZ_PAUSE 0x71
+*/
+#define QZ_POWER 0x7F
+#define QZ_BACKQUOTE 0x32
+#define QZ_1 0x12
+#define QZ_2 0x13
+#define QZ_3 0x14
+#define QZ_4 0x15
+#define QZ_5 0x17
+#define QZ_6 0x16
+#define QZ_7 0x1A
+#define QZ_8 0x1C
+#define QZ_9 0x19
+#define QZ_0 0x1D
+#define QZ_MINUS 0x1B
+#define QZ_EQUALS 0x18
+#define QZ_BACKSPACE 0x33
+#define QZ_INSERT 0x72
+#define QZ_HOME 0x73
+#define QZ_PAGEUP 0x74
+#define QZ_NUMLOCK 0x47
+#define QZ_KP_EQUALS 0x51
+#define QZ_KP_DIVIDE 0x4B
+#define QZ_KP_MULTIPLY 0x43
+#define QZ_TAB 0x30
+#define QZ_q 0x0C
+#define QZ_w 0x0D
+#define QZ_e 0x0E
+#define QZ_r 0x0F
+#define QZ_t 0x11
+#define QZ_y 0x10
+#define QZ_u 0x20
+#define QZ_i 0x22
+#define QZ_o 0x1F
+#define QZ_p 0x23
+#define QZ_LEFTBRACKET 0x21
+#define QZ_RIGHTBRACKET 0x1E
+#define QZ_BACKSLASH 0x2A
+#define QZ_DELETE 0x75
+#define QZ_END 0x77
+#define QZ_PAGEDOWN 0x79
+#define QZ_KP7 0x59
+#define QZ_KP8 0x5B
+#define QZ_KP9 0x5C
+#define QZ_KP_MINUS 0x4E
+#define QZ_CAPSLOCK 0x39
+#define QZ_a 0x00
+#define QZ_s 0x01
+#define QZ_d 0x02
+#define QZ_f 0x03
+#define QZ_g 0x05
+#define QZ_h 0x04
+#define QZ_j 0x26
+#define QZ_k 0x28
+#define QZ_l 0x25
+#define QZ_SEMICOLON 0x29
+#define QZ_QUOTE 0x27
+#define QZ_RETURN 0x24
+#define QZ_KP4 0x56
+#define QZ_KP5 0x57
+#define QZ_KP6 0x58
+#define QZ_KP_PLUS 0x45
+#define QZ_LSHIFT 0x38
+#define QZ_z 0x06
+#define QZ_x 0x07
+#define QZ_c 0x08
+#define QZ_v 0x09
+#define QZ_b 0x0B
+#define QZ_n 0x2D
+#define QZ_m 0x2E
+#define QZ_COMMA 0x2B
+#define QZ_PERIOD 0x2F
+#define QZ_SLASH 0x2C
+#if 1 /* Panther now defines right side keys */
+#define QZ_RSHIFT 0x3C
+#endif
+#define QZ_UP 0x7E
+#define QZ_KP1 0x53
+#define QZ_KP2 0x54
+#define QZ_KP3 0x55
+#define QZ_KP_ENTER 0x4C
+#define QZ_LCTRL 0x3B
+#define QZ_LALT 0x3A
+#define QZ_LMETA 0x37
+#define QZ_SPACE 0x31
+#if 1 /* Panther now defines right side keys */
+#define QZ_RMETA 0x36
+#define QZ_RALT 0x3D
+#define QZ_RCTRL 0x3E
+#endif
+#define QZ_LEFT 0x7B
+#define QZ_DOWN 0x7D
+#define QZ_RIGHT 0x7C
+#define QZ_KP0 0x52
+#define QZ_KP_PERIOD 0x41
+
+/* Wierd, these keys are on my iBook under Mac OS X */
+#define QZ_IBOOK_ENTER 0x34
+#define QZ_IBOOK_LEFT 0x3B
+#define QZ_IBOOK_RIGHT 0x3C
+#define QZ_IBOOK_DOWN 0x3D
+#define QZ_IBOOK_UP 0x3E
diff --git a/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzVideo.h b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzVideo.h
new file mode 100644
index 0000000..7506e0c
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzVideo.h
@@ -0,0 +1,229 @@
+/*
+ SDL - Simple DirectMedia Layer
+ 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
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+/*
+ @file SDL_QuartzVideo.h
+ @author Darrell Walisser, Max Horn, et al.
+
+ @abstract SDL video driver for Mac OS X.
+
+ @discussion
+
+ TODO
+ - Hardware Cursor support with NSCursor instead of Carbon
+ - Keyboard repeat/mouse speed adjust (if needed)
+ - Multiple monitor support (currently only main display)
+ - Accelerated blitting support
+ - 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
+ - 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) (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
+*/
+
+/* Needs to be first, so QuickTime.h doesn't include glext.h (10.4) */
+#include "SDL_opengl.h"
+
+#include <Cocoa/Cocoa.h>
+#include <Carbon/Carbon.h>
+#include <OpenGL/OpenGL.h> /* For CGL functions and types */
+#include <IOKit/IOKitLib.h> /* For powersave handling */
+#include <pthread.h>
+
+#include "SDL_thread.h"
+#include "SDL_video.h"
+#include "SDL_error.h"
+#include "SDL_timer.h"
+#include "SDL_loadso.h"
+#include "SDL_syswm.h"
+#include "../SDL_sysvideo.h"
+#include "../SDL_pixels_c.h"
+#include "../../events/SDL_events_c.h"
+
+
+#ifdef __powerpc__
+/*
+ This is a workaround to directly access NSOpenGLContext's CGL context
+ We need this to check for errors NSOpenGLContext doesn't support
+ Please note this is only used on PowerPC (Intel Macs are guaranteed to
+ have a better API for this, since it showed up in Mac OS X 10.3).
+*/
+@interface NSOpenGLContext (CGLContextAccess)
+- (CGLContextObj) cglContext;
+@end
+#endif
+
+/* use this to get the CGLContext; it handles Cocoa interface changes. */
+CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx);
+
+
+/* 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) */
+ 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 */
+ 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 */
+ NSView *view; /* the window's view; draw 2D and OpenGL into this view */
+ CGContextRef cg_context; /* CoreGraphics rendering context */
+ 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 */
+ 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 */
+ NSText *field_edit; /* a field editor for keyboard composition processing */
+ Uint32 last_virtual_button;/* last virtual mouse button pressed */
+ io_connect_t power_connection; /* used with IOKit to detect wake from sleep */
+ Uint8 expect_mouse_up; /* used to determine when to send mouse up events */
+ Uint8 grab_state; /* used to manage grab behavior */
+ NSPoint cursor_loc; /* saved cursor coords, for activate/deactivate when grabbed */
+ BOOL cursor_should_be_visible; /* tells if cursor is supposed to be visible (SDL_ShowCursor) */
+ BOOL cursor_visible; /* tells if cursor is *actually* visible or not */
+ Uint8* sw_buffers[2]; /* pointers to the two software buffers for double-buffer emulation */
+ SDL_Thread *thread; /* thread for async updates to the screen */
+ SDL_sem *sem1, *sem2; /* synchronization for async screen updates */
+ Uint8 *current_buffer; /* the buffer being copied to the screen */
+ BOOL quit_thread; /* used to quit the async blitting thread */
+ SInt32 system_version; /* used to dis-/enable workarounds depending on the system version */
+
+ void *opengl_library; /* dynamically loaded OpenGL library. */
+} SDL_PrivateVideoData;
+
+#define _THIS SDL_VideoDevice *this
+#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 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)
+#define mode_flags (this->hidden->flags)
+#define qz_window (this->hidden->window)
+#define window_view (this->hidden->view)
+#define cg_context (this->hidden->cg_context)
+#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 client_mode_list (this->hidden->client_mode_list)
+#define keymap (this->hidden->keymap)
+#define current_mods (this->hidden->current_mods)
+#define field_edit (this->hidden->field_edit)
+#define last_virtual_button (this->hidden->last_virtual_button)
+#define power_connection (this->hidden->power_connection)
+#define expect_mouse_up (this->hidden->expect_mouse_up)
+#define grab_state (this->hidden->grab_state)
+#define cursor_loc (this->hidden->cursor_loc)
+#define cursor_should_be_visible (this->hidden->cursor_should_be_visible)
+#define cursor_visible (this->hidden->cursor_visible)
+#define sw_buffers (this->hidden->sw_buffers)
+#define sw_contexts (this->hidden->sw_contexts)
+#define thread (this->hidden->thread)
+#define sem1 (this->hidden->sem1)
+#define sem2 (this->hidden->sem2)
+#define current_buffer (this->hidden->current_buffer)
+#define quit_thread (this->hidden->quit_thread)
+#define system_version (this->hidden->system_version)
+#define opengl_library (this->hidden->opengl_library)
+
+/* grab states - the input is in one of these states */
+enum {
+ QZ_UNGRABBED = 0,
+ QZ_VISIBLE_GRAB,
+ QZ_INVISIBLE_GRAB
+};
+
+/* grab actions - these can change the grabbed state */
+enum {
+ QZ_ENABLE_GRAB = 0,
+ QZ_DISABLE_GRAB,
+ QZ_HIDECURSOR,
+ QZ_SHOWCURSOR
+};
+
+/* Gamma Functions */
+int QZ_SetGamma (_THIS, float red, float green, float blue);
+int QZ_GetGamma (_THIS, float *red, float *green, float *blue);
+int QZ_SetGammaRamp (_THIS, Uint16 *ramp);
+int QZ_GetGammaRamp (_THIS, Uint16 *ramp);
+
+/* OpenGL functions */
+int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags);
+void QZ_TearDownOpenGL (_THIS);
+void* QZ_GL_GetProcAddress (_THIS, const char *proc);
+int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value);
+int QZ_GL_MakeCurrent (_THIS);
+void QZ_GL_SwapBuffers (_THIS);
+int QZ_GL_LoadLibrary (_THIS, const char *location);
+
+/* Cursor and Mouse functions */
+void QZ_FreeWMCursor (_THIS, WMcursor *cursor);
+WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask,
+ int w, int h, int hot_x, int hot_y);
+int QZ_ShowWMCursor (_THIS, WMcursor *cursor);
+void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y);
+void QZ_MoveWMCursor (_THIS, int x, int y);
+void QZ_CheckMouseMode (_THIS);
+void QZ_UpdateMouse (_THIS);
+
+/* Event functions */
+void QZ_InitOSKeymap (_THIS);
+void QZ_PumpEvents (_THIS);
+
+/* Window Manager functions */
+void QZ_SetCaption (_THIS, const char *title, const char *icon);
+void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask);
+int QZ_IconifyWindow (_THIS);
+SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode);
+/*int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info);*/
+
+/* Private functions (used internally) */
+void QZ_PrivateWarpCursor (_THIS, int x, int y);
+void QZ_ChangeGrabState (_THIS, int action);
+void QZ_RegisterForSleepNotifications (_THIS);
+void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p);
+void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p);
+BOOL QZ_IsMouseInWindow (_THIS);
+void QZ_DoActivate (_THIS);
+void QZ_DoDeactivate (_THIS);
diff --git a/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzVideo.m b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzVideo.m
new file mode 100644
index 0000000..fa04e9d
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzVideo.m
@@ -0,0 +1,1689 @@
+/*
+ SDL - Simple DirectMedia Layer
+ 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
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#include "SDL_QuartzVideo.h"
+#include "SDL_QuartzWindow.h"
+
+/* 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
+ that does not update this variable when switching
+ to fullscreen, we'll set it manually (but only for the
+ main screen).
+*/
+@interface NSScreen (NSScreenAccess)
+- (void) setFrame:(NSRect)frame;
+@end
+
+@implementation NSScreen (NSScreenAccess)
+- (void) setFrame:(NSRect)frame;
+{
+ _frame = frame;
+}
+@end
+static inline void QZ_SetFrame(_THIS, NSScreen *nsscreen, NSRect frame)
+{
+ if (!IS_SNOW_LEOPARD_OR_LATER(this)) {
+ [nsscreen setFrame:frame];
+ }
+}
+#else
+static inline void QZ_SetFrame(_THIS, NSScreen *nsscreen, NSRect frame)
+{
+}
+#endif
+
+@interface SDLTranslatorResponder : NSTextView
+{
+}
+- (void) doCommandBySelector:(SEL)myselector;
+@end
+
+@implementation SDLTranslatorResponder
+- (void) doCommandBySelector:(SEL) myselector {}
+@end
+
+/* absent in 10.3.9. */
+CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef);
+
+/* Bootstrap functions */
+static int QZ_Available ();
+static SDL_VideoDevice* QZ_CreateDevice (int device_index);
+static void QZ_DeleteDevice (SDL_VideoDevice *device);
+
+/* Initialization, Query, Setup, and Redrawing functions */
+static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format);
+
+static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format,
+ Uint32 flags);
+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,
+ Uint32 flags);
+static int QZ_ToggleFullScreen (_THIS, int on);
+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);
+
+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);
+
+/* 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 ()
+{
+ return 1;
+}
+
+static SDL_VideoDevice* QZ_CreateDevice (int device_index)
+{
+#pragma unused (device_index)
+
+ SDL_VideoDevice *device;
+ SDL_PrivateVideoData *hidden;
+
+ device = (SDL_VideoDevice*) SDL_malloc (sizeof (*device) );
+ hidden = (SDL_PrivateVideoData*) SDL_malloc (sizeof (*hidden) );
+
+ if (device == NULL || hidden == NULL)
+ SDL_OutOfMemory ();
+
+ SDL_memset (device, 0, sizeof (*device) );
+ SDL_memset (hidden, 0, sizeof (*hidden) );
+
+ device->hidden = hidden;
+
+ device->VideoInit = QZ_VideoInit;
+ device->ListModes = QZ_ListModes;
+ device->SetVideoMode = QZ_SetVideoMode;
+ device->ToggleFullScreen = QZ_ToggleFullScreen;
+ device->UpdateMouse = QZ_UpdateMouse;
+ device->SetColors = QZ_SetColors;
+ /* device->UpdateRects = QZ_UpdateRects; this is determined by SetVideoMode() */
+ device->VideoQuit = QZ_VideoQuit;
+
+ device->LockHWSurface = QZ_LockHWSurface;
+ device->UnlockHWSurface = QZ_UnlockHWSurface;
+ device->AllocHWSurface = QZ_AllocHWSurface;
+ device->FreeHWSurface = QZ_FreeHWSurface;
+
+ device->SetGamma = QZ_SetGamma;
+ device->GetGamma = QZ_GetGamma;
+ device->SetGammaRamp = QZ_SetGammaRamp;
+ device->GetGammaRamp = QZ_GetGammaRamp;
+
+ device->GL_GetProcAddress = QZ_GL_GetProcAddress;
+ device->GL_GetAttribute = QZ_GL_GetAttribute;
+ device->GL_MakeCurrent = QZ_GL_MakeCurrent;
+ device->GL_SwapBuffers = QZ_GL_SwapBuffers;
+ device->GL_LoadLibrary = QZ_GL_LoadLibrary;
+
+ device->FreeWMCursor = QZ_FreeWMCursor;
+ device->CreateWMCursor = QZ_CreateWMCursor;
+ device->ShowWMCursor = QZ_ShowWMCursor;
+ device->WarpWMCursor = QZ_WarpWMCursor;
+ device->MoveWMCursor = QZ_MoveWMCursor;
+ device->CheckMouseMode = QZ_CheckMouseMode;
+ device->InitOSKeymap = QZ_InitOSKeymap;
+ device->PumpEvents = QZ_PumpEvents;
+
+ device->SetCaption = QZ_SetCaption;
+ device->SetIcon = QZ_SetIcon;
+ device->IconifyWindow = QZ_IconifyWindow;
+ /*device->GetWMInfo = QZ_GetWMInfo;*/
+ device->GrabInput = QZ_GrabInput;
+
+ /*
+ * This is a big hassle, needing QuickDraw and QuickTime on older
+ * systems, and god knows what on 10.6, so we immediately fail here,
+ * which causes SDL to make an RGB surface and manage the YUV overlay
+ * in software. Sorry. Use SDL 1.3 if you want YUV rendering in a pixel
+ * shader. :)
+ */
+ /*device->CreateYUVOverlay = QZ_CreateYUVOverlay;*/
+
+ device->free = QZ_DeleteDevice;
+
+ return device;
+}
+
+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;
+
+#if 0 /* The mouse event code needs to take this into account... */
+ env = getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
+ if ( env ) {
+ int monitor = SDL_atoi(env);
+ CGDirectDisplayID activeDspys [3];
+ CGDisplayCount dspyCnt;
+ CGGetActiveDisplayList (3, activeDspys, &dspyCnt);
+ if ( monitor >= 0 && monitor < dspyCnt ) {
+ display_id = activeDspys[monitor];
+ }
+ }
+#endif
+
+#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");
+ if ( env ) {
+ allow_screensaver = SDL_atoi(env);
+ } else {
+#ifdef SDL_VIDEO_DISABLE_SCREENSAVER
+ allow_screensaver = 0;
+#else
+ allow_screensaver = 1;
+#endif
+ }
+
+ /* Gather some information that is useful to know about the display */
+ 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;
+ this->info.current_h = device_height;
+
+ /* Determine the default screen depth */
+ video_format->BitsPerPixel = device_bpp;
+
+ /* Set misc globals */
+ current_grab_mode = SDL_GRAB_OFF;
+ cursor_should_be_visible = YES;
+ cursor_visible = YES;
+ current_mods = 0;
+ field_edit = [[SDLTranslatorResponder alloc] initWithFrame:r];
+
+ /* register for sleep notifications so wake from sleep generates SDL_VIDEOEXPOSE */
+ QZ_RegisterForSleepNotifications (this);
+
+ /* Fill in some window manager capabilities */
+ this->info.wm_available = 1;
+
+ return 0;
+}
+
+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;
+
+ int list_size = 0;
+
+ /* Any windowed mode is acceptable */
+ if ( (flags & SDL_FULLSCREEN) == 0 )
+ return (SDL_Rect**)-1;
+
+ /* Free memory from previous call, if any */
+ if ( client_mode_list != NULL ) {
+ int i;
+
+ for (i = 0; client_mode_list[i] != NULL; i++)
+ SDL_free (client_mode_list[i]);
+
+ SDL_free (client_mode_list);
+ 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);
+
+ 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 */
+ 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++;
+
+ if (client_mode_list == NULL)
+ client_mode_list = (SDL_Rect**)
+ SDL_malloc (sizeof(*client_mode_list) * (list_size+1) );
+ 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;
+ }
+
+ rect->x = rect->y = 0;
+ rect->w = width;
+ rect->h = height;
+
+ client_mode_list[list_size-1] = rect;
+ client_mode_list[list_size] = NULL;
+ }
+ }
+ }
+
+ QZ_ReleaseDisplayModeList(this, mode_list);
+
+ /* Sort list largest to smallest (by area) */
+ {
+ int i, j;
+ for (i = 0; i < list_size; i++) {
+ for (j = 0; j < list_size-1; j++) {
+
+ int area1, area2;
+ area1 = client_mode_list[j]->w * client_mode_list[j]->h;
+ area2 = client_mode_list[j+1]->w * client_mode_list[j+1]->h;
+
+ if (area1 < area2) {
+ SDL_Rect *tmp = client_mode_list[j];
+ client_mode_list[j] = client_mode_list[j+1];
+ client_mode_list[j+1] = tmp;
+ }
+ }
+ }
+ }
+
+ return client_mode_list;
+}
+
+static SDL_bool QZ_WindowPosition(_THIS, int *x, int *y)
+{
+ const char *window = getenv("SDL_VIDEO_WINDOW_POS");
+ if ( window ) {
+ if ( sscanf(window, "%d,%d", x, y) == 2 ) {
+ return SDL_TRUE;
+ }
+ }
+ return SDL_FALSE;
+}
+
+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;
+ this->FillHWRect = NULL;
+ this->UpdateRects = NULL;
+ this->LockHWSurface = NULL;
+ this->UnlockHWSurface = NULL;
+
+ if (cg_context) {
+ CGContextFlush (cg_context);
+ CGContextRelease (cg_context);
+ cg_context = nil;
+ }
+
+ /* Release fullscreen resources */
+ if ( mode_flags & SDL_FULLSCREEN ) {
+
+ NSRect screen_rect;
+
+ /* Release double buffer stuff */
+#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);
+ SDL_DestroySemaphore (sem1);
+ 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 */
+ [ qz_window close ]; /* includes release because [qz_window isReleasedWhenClosed] */
+ qz_window = nil;
+ window_view = nil;
+ }
+ /*
+ Release the OpenGL context
+ Do this first to avoid trash on the display before fade
+ */
+ if ( mode_flags & SDL_OPENGL ) {
+ if (!save_gl) {
+ QZ_TearDownOpenGL (this);
+ }
+
+ #ifdef __powerpc__ /* we only use this for pre-10.3 compatibility. */
+ CGLSetFullScreen (NULL);
+ #endif
+ }
+ if (to_desktop) {
+ /* !!! 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 */
+ 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(this, [ NSScreen mainScreen ], screen_rect);
+ }
+ }
+ /* Release window mode resources */
+ else {
+ id delegate = [ qz_window delegate ];
+ [ qz_window close ]; /* includes release because [qz_window isReleasedWhenClosed] */
+ if (delegate != nil) [ delegate release ];
+ qz_window = nil;
+ window_view = nil;
+
+ /* Release the OpenGL context */
+ 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,
+ const BOOL save_gl)
+{
+ 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 ) {
+ CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
+ }
+
+ /* Destroy any previous mode */
+ if (video_set == SDL_TRUE)
+ QZ_UnsetVideoMode (this, FALSE, save_gl);
+
+ /* Sorry, QuickDraw was ripped out. */
+ if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) {
+ SDL_SetError ("Embedded QuickDraw windows are no longer supported");
+ goto ERR_NO_MATCH;
+ }
+
+ QZ_ReleaseDisplayMode(this, mode); /* NULL is okay. */
+
+ /* See if requested mode exists */
+ mode = QZ_BestMode(this, bpp, width, height);
+
+ /* Require an exact match to the requested mode */
+ if ( mode == NULL ) {
+ SDL_SetError ("Failed to find display resolution: %dx%dx%d", width, height, bpp);
+ goto ERR_NO_MATCH;
+ }
+
+ /* Put up the blanking window (a window above all other windows) */
+ if (getenv ("SDL_SINGLEDISPLAY"))
+ error = CGDisplayCapture (display_id);
+ else
+ error = CGCaptureAllDisplays ();
+
+ if ( CGDisplayNoErr != error ) {
+ SDL_SetError ("Failed capturing display");
+ goto ERR_NO_CAPTURE;
+ }
+
+ /* Do the physical switch */
+ if ( CGDisplayNoErr != QZ_SetDisplayMode(this, mode) ) {
+ SDL_SetError ("Failed switching display resolution");
+ goto ERR_NO_SWITCH;
+ }
+
+#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); */
+
+ this->UpdateRects = QZ_DirectUpdate;
+ this->LockHWSurface = QZ_LockHWSurface;
+ this->UnlockHWSurface = QZ_UnlockHWSurface;
+
+ /* 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;
+ }
+
+ 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);
+ }
+
+ 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:(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 */
+ else {
+ [ qz_window setContentSize:contentRect.size ];
+ current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags;
+ [ window_view setFrameSize:contentRect.size ];
+ }
+
+ /* Setup OpenGL for a fullscreen context */
+ if (flags & SDL_OPENGL) {
+
+ 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 ];
+
+ if ( isLion ) {
+ [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
+ }
+
+ [ [ qz_window contentView ] addSubview:window_view ];
+
+ /* 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);
+
+ [ 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 (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 ) {
+ CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
+ CGReleaseDisplayFadeReservation(fade_token);
+ }
+
+ /*
+ There is a bug in Cocoa where NSScreen doesn't synchronize
+ with CGDirectDisplay, so the main screen's frame is wrong.
+ As a result, coordinate translation produces incorrect results.
+ We can hack around this bug by setting the screen rect
+ ourselves. This hack should be removed if/when the bug is fixed.
+ */
+ screen_rect = NSMakeRect(0,0,width,height);
+ QZ_SetFrame(this, [ NSScreen mainScreen ], screen_rect);
+
+ /* Save the flags to ensure correct tear-down */
+ mode_flags = current->flags;
+
+ /* Set app state, hide cursor if necessary, ... */
+ QZ_DoActivate(this);
+
+ return current;
+
+ /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
+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 ) {
+ CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
+ CGReleaseDisplayFadeReservation (fade_token);
+ }
+ return NULL;
+}
+
+static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
+ int height, int *bpp, Uint32 flags,
+ const BOOL save_gl)
+{
+ unsigned int style;
+ NSRect contentRect;
+ int center_window = 1;
+ int origin_x, origin_y;
+ CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
+
+ current->flags = 0;
+ current->w = width;
+ current->h = height;
+
+ contentRect = NSMakeRect (0, 0, width, height);
+
+ /*
+ Check if we should completely destroy the previous mode
+ - If it is fullscreen
+ - If it has different noframe or resizable attribute
+ - If it is OpenGL (since gl attributes could be different)
+ - If new mode is OpenGL, but previous mode wasn't
+ */
+ if (video_set == SDL_TRUE) {
+ if (mode_flags & SDL_FULLSCREEN) {
+ /* 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) {
+ CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, 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, save_gl);
+ }
+ }
+
+ /* Sorry, QuickDraw was ripped out. */
+ if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) {
+ SDL_SetError ("Embedded QuickDraw windows are no longer supported");
+ if (fade_token != kCGDisplayFadeReservationInvalidToken) {
+ CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
+ CGReleaseDisplayFadeReservation (fade_token);
+ }
+ return NULL;
+ }
+
+ /* Check if we should recreate the window */
+ if (qz_window == nil) {
+
+ /* Set the window style based on input flags */
+ if ( flags & SDL_NOFRAME ) {
+ style = NSBorderlessWindowMask;
+ current->flags |= SDL_NOFRAME;
+ } else {
+ style = NSTitledWindowMask;
+ style |= (NSMiniaturizableWindowMask | NSClosableWindowMask);
+ if ( flags & SDL_RESIZABLE ) {
+ style |= NSResizableWindowMask;
+ current->flags |= SDL_RESIZABLE;
+ }
+ }
+
+ /* Manually create a window, avoids having a nib file resource */
+ qz_window = [ [ SDL_QuartzWindow alloc ]
+ initWithContentRect:contentRect
+ styleMask:style
+ backing:NSBackingStoreBuffered
+ defer:NO ];
+
+ if (qz_window == nil) {
+ SDL_SetError ("Could not create the Cocoa window");
+ if (fade_token != kCGDisplayFadeReservationInvalidToken) {
+ CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
+ CGReleaseDisplayFadeReservation (fade_token);
+ }
+ return NULL;
+ }
+
+ /*[ qz_window setReleasedWhenClosed:YES ];*/ /* no need to set this as it's the default for NSWindows */
+ QZ_SetCaption(this, this->wm_title, this->wm_icon);
+ [ qz_window setAcceptsMouseMovedEvents:YES ];
+ [ qz_window setViewsNeedDisplay:NO ];
+
+ if ( QZ_WindowPosition(this, &origin_x, &origin_y) ) {
+ /* have to flip the Y value (NSPoint is lower left corner origin) */
+ [ qz_window setFrameTopLeftPoint:NSMakePoint((float) origin_x, (float) (this->info.current_h - origin_y))];
+ center_window = 0;
+ } else if ( center_window ) {
+ [ qz_window center ];
+ }
+
+ [ qz_window setDelegate:
+ [ [ SDL_QuartzWindowDelegate alloc ] init ] ];
+ [ qz_window setContentView: [ [ [ SDL_QuartzView alloc ] init ] autorelease ] ];
+ }
+ /* We already have a window, just change its size */
+ else {
+ [ qz_window setContentSize:contentRect.size ];
+ current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags;
+ [ window_view setFrameSize:contentRect.size ];
+ }
+
+ /* For OpenGL, we bind the context to a subview */
+ if ( flags & SDL_OPENGL ) {
+
+ 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;
+ }
+ }
+
+ window_view = [ [ NSView alloc ] initWithFrame:contentRect ];
+ [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
+ [ [ qz_window contentView ] addSubview:window_view ];
+ [ gl_context setView: window_view ];
+ [ window_view release ];
+ [ gl_context makeCurrentContext];
+ [ qz_window makeKeyAndOrderFront:nil ];
+ current->flags |= SDL_OPENGL;
+ }
+ /* For 2D, we build a CGBitmapContext */
+ else {
+ 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 ];
+ [ qz_window makeKeyAndOrderFront:nil ];
+ }
+
+ 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;
+
+ this->UpdateRects = QZ_UpdateRects;
+ this->LockHWSurface = QZ_LockHWSurface;
+ this->UnlockHWSurface = QZ_UnlockHWSurface;
+ }
+
+ /* Save flags to ensure correct teardown */
+ mode_flags = current->flags;
+
+ /* Fade in again (asynchronously) if we came from a fullscreen mode and faded to black */
+ if (fade_token != kCGDisplayFadeReservationInvalidToken) {
+ CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
+ CGReleaseDisplayFadeReservation (fade_token);
+ }
+
+ return current;
+}
+
+
+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 ) {
+ if ( isLion ) {
+ bpp = 32;
+ }
+ current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags, save_gl );
+ if (current == NULL)
+ return NULL;
+ }
+ /* Setup windowed video */
+ else {
+ /* Force bpp to 32 */
+ bpp = 32;
+ 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,
+ rmask = 0,
+ gmask = 0,
+ bmask = 0;
+
+ switch (bpp) {
+ case 16: /* (1)-5-5-5 RGB */
+ amask = 0;
+ rmask = 0x7C00;
+ gmask = 0x03E0;
+ bmask = 0x001F;
+ break;
+ case 24:
+ SDL_SetError ("24bpp is not available");
+ return NULL;
+ case 32: /* (8)-8-8-8 ARGB */
+ amask = 0x00000000;
+ if ( (!isLion) && (flags & SDL_FULLSCREEN) ) {
+ rmask = 0x00FF0000;
+ gmask = 0x0000FF00;
+ bmask = 0x000000FF;
+ } else {
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+ rmask = 0x0000FF00;
+ gmask = 0x00FF0000;
+ bmask = 0xFF000000;
+#else
+ rmask = 0x00FF0000;
+ gmask = 0x0000FF00;
+ bmask = 0x000000FF;
+#endif
+ break;
+ }
+ }
+
+ if ( ! SDL_ReallocFormat (current, bpp,
+ rmask, gmask, bmask, amask ) ) {
+ SDL_SetError ("Couldn't reallocate pixel format");
+ return NULL;
+ }
+ }
+
+ /* Signal successful completion (used internally) */
+ video_set = SDL_TRUE;
+
+ 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;
+}
+
+static int QZ_SetColors (_THIS, int first_color, int num_colors,
+ SDL_Color *colors)
+{
+#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++) {
+
+ /* 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++;
+
+ CGPaletteSetColorAtIndex (palette, color, index);
+ }
+
+ return ( CGDisplayNoErr == CGDisplaySetPalette (display_id, palette) );
+ }
+#endif
+
+ return 0;
+}
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
+static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface)
+{
+ return 1;
+}
+
+static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface)
+{
+}
+
+/* The VBL delay is based on code by Ian R Ollmann's RezLib <iano@cco.caltech.edu> */
+static AbsoluteTime QZ_SecondsToAbsolute ( double seconds )
+{
+ union
+ {
+ UInt64 i;
+ Nanoseconds ns;
+ } temp;
+
+ temp.i = seconds * 1000000000.0;
+
+ return NanosecondsToAbsolute ( temp.ns );
+}
+
+static int QZ_ThreadFlip (_THIS)
+{
+ Uint8 *src, *dst;
+ int skip, len, h;
+
+ /*
+ Give this thread the highest scheduling priority possible,
+ in the hopes that it will immediately run after the VBL delay
+ */
+ {
+ pthread_t current_thread;
+ int policy;
+ struct sched_param param;
+
+ current_thread = pthread_self ();
+ pthread_getschedparam (current_thread, &policy, &param);
+ policy = SCHED_RR;
+ param.sched_priority = sched_get_priority_max (policy);
+ pthread_setschedparam (current_thread, policy, &param);
+ }
+
+ while (1) {
+
+ SDL_SemWait (sem1);
+ if (quit_thread)
+ return 0;
+
+ /*
+ * We have to add SDL_VideoSurface->offset here, since we might be a
+ * smaller surface in the center of the framebuffer (you asked for
+ * a fullscreen resolution smaller than the hardware could supply
+ * so SDL is centering it in a bigger resolution)...
+ */
+ 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;
+ skip = SDL_VideoSurface->pitch;
+
+ /* Wait for the VBL to occur (estimated since we don't have a hardware interrupt) */
+ {
+
+ /* The VBL delay is based on Ian Ollmann's RezLib <iano@cco.caltech.edu> */
+ double refreshRate;
+ double linesPerSecond;
+ double target;
+ double position;
+ double adjustment;
+ AbsoluteTime nextTime;
+ CFNumberRef refreshRateCFNumber;
+
+ refreshRateCFNumber = CFDictionaryGetValue (mode, kCGDisplayRefreshRate);
+ if ( NULL == refreshRateCFNumber ) {
+ SDL_SetError ("Mode has no refresh rate");
+ goto ERROR;
+ }
+
+ if ( 0 == CFNumberGetValue (refreshRateCFNumber, kCFNumberDoubleType, &refreshRate) ) {
+ SDL_SetError ("Error getting refresh rate");
+ goto ERROR;
+ }
+
+ if ( 0 == refreshRate ) {
+
+ SDL_SetError ("Display has no refresh rate, using 60hz");
+
+ /* ok, for LCD's we'll emulate a 60hz refresh, which may or may not look right */
+ refreshRate = 60.0;
+ }
+
+ linesPerSecond = refreshRate * h;
+ target = h;
+
+ /* Figure out the first delay so we start off about right */
+ position = CGDisplayBeamPosition (display_id);
+ if (position > target)
+ position = 0;
+
+ adjustment = (target - position) / linesPerSecond;
+
+ nextTime = AddAbsoluteToAbsolute (UpTime (), QZ_SecondsToAbsolute (adjustment));
+
+ MPDelayUntil (&nextTime);
+ }
+
+
+ /* On error, skip VBL delay */
+ ERROR:
+
+ /* TODO: use CGContextDrawImage here too! Create two CGContextRefs the same way we
+ create two buffers, replace current_buffer with current_context and set it
+ appropriately in QZ_FlipDoubleBuffer. */
+ while ( h-- ) {
+
+ SDL_memcpy (dst, src, len);
+ src += skip;
+ dst += skip;
+ }
+
+ /* signal flip completion */
+ SDL_SemPost (sem2);
+ }
+
+ return 0;
+}
+
+static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface)
+{
+ /* wait for previous flip to complete */
+ SDL_SemWait (sem2);
+
+ current_buffer = surface->pixels;
+
+ if (surface->pixels == sw_buffers[0])
+ surface->pixels = sw_buffers[1];
+ else
+ surface->pixels = sw_buffers[0];
+
+ /* signal worker thread to do the flip */
+ SDL_SemPost (sem1);
+
+ return 0;
+}
+
+static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects)
+{
+ /* perform a flip if someone calls updaterects on a doublebuferred surface */
+ this->FlipHWSurface (this, SDL_VideoSurface);
+}
+
+static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects)
+{
+#pragma unused(this,num_rects,rects)
+}
+#endif
+
+/* Resize icon, BMP format */
+static const 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)
+{
+ /* Check if we should draw the resize icon */
+ if (SDL_VideoSurface->flags & SDL_RESIZABLE) {
+
+ SDL_Rect icon_rect;
+
+ /* Create the icon image */
+ if (resize_icon == NULL) {
+
+ SDL_RWops *rw;
+ SDL_Surface *tmp;
+
+ rw = SDL_RWFromConstMem (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);
+ }
+}
+
+static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects)
+{
+ if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) {
+ QZ_GL_SwapBuffers (this);
+ }
+ else if ( [ qz_window isMiniaturized ] ) {
+
+ /* Do nothing if miniaturized */
+ }
+
+ else {
+ 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);
+ CGRect rectangle = CGRectMake (0,0,[window_view frame].size.width,[window_view frame].size.height);
+
+ CGContextDrawImage (cgc, rectangle, image);
+ CGImageRelease(image);
+ CGContextFlush (cgc);
+ }
+}
+
+static void QZ_VideoQuit (_THIS)
+{
+ CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
+
+ /* Restore gamma settings */
+ CGDisplayRestoreColorSyncSettings ();
+
+ /* Ensure the cursor will be visible and working when we quit */
+ CGDisplayShowCursor (display_id);
+ CGAssociateMouseAndMouseCursorPosition (1);
+
+ if (mode_flags & SDL_FULLSCREEN) {
+ /* 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) {
+ CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, 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, 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);
+ opengl_library = NULL;
+ }
+ this->gl_config.driver_loaded = 0;
+
+ if (field_edit) {
+ [field_edit release];
+ field_edit = NULL;
+ }
+}
+
+static int QZ_LockHWSurface(_THIS, SDL_Surface *surface)
+{
+ return 1;
+}
+
+static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface)
+{
+}
+
+static int QZ_AllocHWSurface(_THIS, SDL_Surface *surface)
+{
+ return(-1); /* unallowed (no HWSURFACE support here). */
+}
+
+static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface)
+{
+}
+
+/* Gamma functions */
+int QZ_SetGamma (_THIS, float red, float green, float blue)
+{
+ const CGGammaValue min = 0.0, max = 1.0;
+
+ if (red == 0.0)
+ red = FLT_MAX;
+ else
+ red = 1.0 / red;
+
+ if (green == 0.0)
+ green = FLT_MAX;
+ else
+ green = 1.0 / green;
+
+ if (blue == 0.0)
+ blue = FLT_MAX;
+ else
+ blue = 1.0 / blue;
+
+ if ( CGDisplayNoErr == CGSetDisplayTransferByFormula
+ (display_id, min, max, red, min, max, green, min, max, blue) ) {
+
+ return 0;
+ }
+ else {
+
+ return -1;
+ }
+}
+
+int QZ_GetGamma (_THIS, float *red, float *green, float *blue)
+{
+ CGGammaValue dummy;
+ if ( CGDisplayNoErr == CGGetDisplayTransferByFormula
+ (display_id, &dummy, &dummy, red,
+ &dummy, &dummy, green, &dummy, &dummy, blue) )
+
+ return 0;
+ else
+ return -1;
+}
+
+int QZ_SetGammaRamp (_THIS, Uint16 *ramp)
+{
+ const uint32_t tableSize = 255;
+ CGGammaValue redTable[tableSize];
+ CGGammaValue greenTable[tableSize];
+ CGGammaValue blueTable[tableSize];
+
+ int i;
+
+ /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */
+ for (i = 0; i < 256; i++)
+ redTable[i % 256] = ramp[i] / 65535.0;
+
+ for (i=256; i < 512; i++)
+ greenTable[i % 256] = ramp[i] / 65535.0;
+
+ for (i=512; i < 768; i++)
+ blueTable[i % 256] = ramp[i] / 65535.0;
+
+ if ( CGDisplayNoErr == CGSetDisplayTransferByTable
+ (display_id, tableSize, redTable, greenTable, blueTable) )
+ return 0;
+ else
+ return -1;
+}
+
+int QZ_GetGammaRamp (_THIS, Uint16 *ramp)
+{
+ const uint32_t tableSize = 255;
+ CGGammaValue redTable[tableSize];
+ CGGammaValue greenTable[tableSize];
+ CGGammaValue blueTable[tableSize];
+ uint32_t actual;
+ int i;
+
+ if ( CGDisplayNoErr != CGGetDisplayTransferByTable
+ (display_id, tableSize, redTable, greenTable, blueTable, &actual) ||
+ actual != tableSize)
+
+ return -1;
+
+ /* Pack tables into one array, with values from 0 to 65535 */
+ for (i = 0; i < 256; i++)
+ ramp[i] = redTable[i % 256] * 65535.0;
+
+ for (i=256; i < 512; i++)
+ ramp[i] = greenTable[i % 256] * 65535.0;
+
+ for (i=512; i < 768; i++)
+ ramp[i] = blueTable[i % 256] * 65535.0;
+
+ return 0;
+}
+
diff --git a/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWM.h b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWM.h
new file mode 100644
index 0000000..0b0767e
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWM.h
@@ -0,0 +1,27 @@
+/*
+ SDL - Simple DirectMedia Layer
+ 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
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+struct WMcursor {
+ NSCursor *nscursor;
+};
+
+void QZ_UpdateCursor(_THIS);
diff --git a/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWM.m b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWM.m
new file mode 100644
index 0000000..d526424
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWM.m
@@ -0,0 +1,444 @@
+/*
+ SDL - Simple DirectMedia Layer
+ 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
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#include "SDL_QuartzVideo.h"
+#include "SDL_QuartzWM.h"
+
+
+void QZ_FreeWMCursor (_THIS, WMcursor *cursor) {
+
+ if ( cursor != NULL ) {
+ [ cursor->nscursor release ];
+ free (cursor);
+ }
+}
+
+WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask,
+ int w, int h, int hot_x, int hot_y) {
+ WMcursor *cursor;
+ NSBitmapImageRep *imgrep;
+ NSImage *img;
+ unsigned char *planes[5];
+ int i;
+ NSAutoreleasePool *pool;
+
+ pool = [ [ NSAutoreleasePool alloc ] init ];
+
+ /* 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: 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] ^ 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;
+ [ img addRepresentation: imgrep ];
+ if (system_version < 0x1030) { /* on 10.2, cursors must be 16*16 */
+ if (w > 16 || h > 16) { /* too big: scale it down */
+ [ img setScalesWhenResized: YES ];
+ hot_x = hot_x*16/w;
+ hot_y = hot_y*16/h;
+ }
+ else { /* too small (or just right): extend it (from the bottom left corner, so hot_y must be adjusted) */
+ hot_y += 16 - h;
+ }
+ [ img setSize: NSMakeSize(16, 16) ];
+ }
+ cursor->nscursor = [ [ NSCursor alloc ] initWithImage: img hotSpot: NSMakePoint(hot_x, hot_y) ];
+ if (cursor->nscursor == nil) goto outOfMemory;
+
+ [ pool release ];
+ return(cursor);
+
+outOfMemory:
+ [ pool release ];
+ if (cursor != NULL) SDL_free(cursor);
+ SDL_OutOfMemory();
+ return(NULL);
+}
+
+void QZ_UpdateCursor (_THIS) {
+ BOOL state;
+
+ if (cursor_should_be_visible || !(SDL_GetAppState() & SDL_APPMOUSEFOCUS)) {
+ state = YES;
+ } else {
+ state = NO;
+ }
+ if (state != cursor_visible) {
+ if (state) {
+ [ NSCursor unhide ];
+ } else {
+ [ NSCursor hide ];
+ }
+ cursor_visible = state;
+ }
+}
+
+BOOL QZ_IsMouseInWindow (_THIS) {
+ if (qz_window == nil || (mode_flags & SDL_FULLSCREEN)) return YES; /*fullscreen*/
+ else {
+ NSPoint p = [ qz_window mouseLocationOutsideOfEventStream ];
+ p.y -= 1.0f; /* Apparently y goes from 1 to h, not from 0 to h-1 (i.e. the "location of the mouse" seems to be defined as "the location of the top left corner of the mouse pointer's hot pixel" */
+ return NSPointInRect(p, [ window_view frame ]);
+ }
+}
+
+int QZ_ShowWMCursor (_THIS, WMcursor *cursor) {
+
+ if ( cursor == NULL) {
+ if ( cursor_should_be_visible ) {
+ cursor_should_be_visible = NO;
+ QZ_ChangeGrabState (this, QZ_HIDECURSOR);
+ }
+ QZ_UpdateCursor(this);
+ }
+ 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);
+ }
+
+ 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.
+*/
+
+/* Convert Cocoa screen coordinate to Cocoa window coordinate */
+void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p) {
+
+ if ( ! CGDisplayIsCaptured (display_id) )
+ *p = [ qz_window convertScreenToBase:*p ];
+}
+
+
+/* Convert Cocoa window coordinate to Cocoa screen coordinate */
+void QZ_PrivateLocalToGlobal (_THIS, NSPoint *p) {
+
+ if ( ! CGDisplayIsCaptured (display_id) )
+ *p = [ qz_window convertBaseToScreen:*p ];
+}
+
+/* Convert SDL coordinate to Cocoa coordinate */
+void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) {
+
+ if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */
+
+ p->y = CGDisplayPixelsHigh (display_id) - p->y;
+ }
+ else {
+
+ *p = [ window_view convertPoint:*p toView: nil ];
+ p->y = [window_view frame].size.height - p->y;
+ }
+}
+
+/* Convert Cocoa coordinate to SDL coordinate */
+void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) {
+
+ if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */
+
+ p->y = CGDisplayPixelsHigh (display_id) - p->y;
+ }
+ else {
+
+ *p = [ window_view convertPoint:*p fromView: nil ];
+ p->y = [window_view frame].size.height - p->y;
+ }
+}
+
+/* Convert SDL coordinate to window server (CoreGraphics) coordinate */
+CGPoint QZ_PrivateSDLToCG (_THIS, NSPoint *p) {
+
+ CGPoint cgp;
+
+ if ( ! CGDisplayIsCaptured (display_id) ) { /* not captured => not fullscreen => local coord */
+
+ int height;
+
+ QZ_PrivateSDLToCocoa (this, p);
+ QZ_PrivateLocalToGlobal (this, p);
+
+ height = CGDisplayPixelsHigh (display_id);
+ p->y = height - p->y;
+ }
+
+ cgp.x = p->x;
+ cgp.y = p->y;
+
+ return cgp;
+}
+
+#if 0 /* Dead code */
+/* Convert window server (CoreGraphics) coordinate to SDL coordinate */
+void QZ_PrivateCGToSDL (_THIS, NSPoint *p) {
+
+ if ( ! CGDisplayIsCaptured (display_id) ) { /* not captured => not fullscreen => local coord */
+
+ int height;
+
+ /* Convert CG Global to Cocoa Global */
+ height = CGDisplayPixelsHigh (display_id);
+ p->y = height - p->y;
+
+ QZ_PrivateGlobalToLocal (this, p);
+ QZ_PrivateCocoaToSDL (this, p);
+ }
+}
+#endif /* Dead code */
+
+void QZ_PrivateWarpCursor (_THIS, int x, int y) {
+ NSPoint p;
+ CGPoint cgp;
+
+ p = NSMakePoint (x, y);
+ cgp = QZ_PrivateSDLToCG (this, &p);
+
+ /* this is the magic call that fixes cursor "freezing" after warp */
+ 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) {
+
+ /* Only allow warping when in foreground */
+ if ( ! [ NSApp isActive ] )
+ return;
+
+ /* Do the actual warp */
+ if (grab_state != QZ_INVISIBLE_GRAB) QZ_PrivateWarpCursor (this, x, y);
+
+ /* Generate the mouse moved event */
+ SDL_PrivateMouseMotion (0, 0, x, y);
+}
+
+void QZ_MoveWMCursor (_THIS, int x, int y) { }
+void QZ_CheckMouseMode (_THIS) { }
+
+void QZ_SetCaption (_THIS, const char *title, const char *icon) {
+
+ if ( qz_window != nil ) {
+ NSString *string;
+ if ( title != NULL ) {
+ string = [ [ NSString alloc ] initWithUTF8String:title ];
+ [ qz_window setTitle:string ];
+ [ string release ];
+ }
+ if ( icon != NULL ) {
+ string = [ [ NSString alloc ] initWithUTF8String:icon ];
+ [ qz_window setMiniwindowTitle:string ];
+ [ string release ];
+ }
+ }
+}
+
+void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask)
+{
+ NSBitmapImageRep *imgrep;
+ NSImage *img;
+ SDL_Surface *mergedSurface;
+ NSAutoreleasePool *pool;
+ Uint8 *pixels;
+ SDL_bool iconSrcAlpha;
+ Uint8 iconAlphaValue;
+ int i, j, maskPitch, index;
+
+ pool = [ [ NSAutoreleasePool alloc ] init ];
+
+ imgrep = [ [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes: NULL pixelsWide: icon->w pixelsHigh: icon->h bitsPerSample: 8 samplesPerPixel: 4 hasAlpha: YES isPlanar: NO colorSpaceName: NSDeviceRGBColorSpace bytesPerRow: 4*icon->w bitsPerPixel: 32 ] autorelease ];
+ if (imgrep == nil) goto freePool;
+ pixels = [ imgrep bitmapData ];
+ SDL_memset(pixels, 0, 4*icon->w*icon->h); /* make the background, which will survive in colorkeyed areas, completely transparent */
+
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+#define BYTEORDER_DEPENDENT_RGBA_MASKS 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF
+#else
+#define BYTEORDER_DEPENDENT_RGBA_MASKS 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
+#endif
+ mergedSurface = SDL_CreateRGBSurfaceFrom(pixels, icon->w, icon->h, 32, 4*icon->w, BYTEORDER_DEPENDENT_RGBA_MASKS);
+ if (mergedSurface == NULL) goto freePool;
+
+ /* blit, with temporarily cleared SRCALPHA flag because we want to copy, not alpha-blend */
+ iconSrcAlpha = ((icon->flags & SDL_SRCALPHA) != 0);
+ iconAlphaValue = icon->format->alpha;
+ SDL_SetAlpha(icon, 0, 255);
+ SDL_BlitSurface(icon, NULL, mergedSurface, NULL);
+ if (iconSrcAlpha) SDL_SetAlpha(icon, SDL_SRCALPHA, iconAlphaValue);
+
+ SDL_FreeSurface(mergedSurface);
+
+ /* apply mask, source alpha, and premultiply color values by alpha */
+ maskPitch = (icon->w+7)/8;
+ for (i = 0; i < icon->h; i++) {
+ for (j = 0; j < icon->w; j++) {
+ index = i*4*icon->w + j*4;
+ if (!(mask[i*maskPitch + j/8] & (128 >> j%8))) {
+ pixels[index + 3] = 0;
+ }
+ else {
+ if (iconSrcAlpha) {
+ if (icon->format->Amask == 0) pixels[index + 3] = icon->format->alpha;
+ }
+ else {
+ pixels[index + 3] = 255;
+ }
+ }
+ if (pixels[index + 3] < 255) {
+ pixels[index + 0] = (Uint16)pixels[index + 0]*pixels[index + 3]/255;
+ pixels[index + 1] = (Uint16)pixels[index + 1]*pixels[index + 3]/255;
+ pixels[index + 2] = (Uint16)pixels[index + 2]*pixels[index + 3]/255;
+ }
+ }
+ }
+
+ img = [ [ [ NSImage alloc ] initWithSize: NSMakeSize(icon->w, icon->h) ] autorelease ];
+ if (img == nil) goto freePool;
+ [ img addRepresentation: imgrep ];
+ [ NSApp setApplicationIconImage:img ];
+
+freePool:
+ [ pool release ];
+}
+
+int QZ_IconifyWindow (_THIS) {
+
+ if ( ! [ qz_window isMiniaturized ] ) {
+ [ qz_window miniaturize:nil ];
+ if ( ! [ qz_window isMiniaturized ] ) {
+ SDL_SetError ("window iconification failed");
+ return 0;
+ }
+ return 1;
+ }
+ else {
+ SDL_SetError ("window already iconified");
+ return 0;
+ }
+}
+
+/*
+int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) {
+ info->nsWindowPtr = qz_window;
+ return 0;
+}*/
+
+void QZ_ChangeGrabState (_THIS, int action) {
+
+ /*
+ Figure out what the next state should be based on the action.
+ Ignore actions that can't change the current state.
+ */
+ if ( grab_state == QZ_UNGRABBED ) {
+ if ( action == QZ_ENABLE_GRAB ) {
+ if ( cursor_should_be_visible )
+ grab_state = QZ_VISIBLE_GRAB;
+ else
+ grab_state = QZ_INVISIBLE_GRAB;
+ }
+ }
+ else if ( grab_state == QZ_VISIBLE_GRAB ) {
+ if ( action == QZ_DISABLE_GRAB )
+ grab_state = QZ_UNGRABBED;
+ else if ( action == QZ_HIDECURSOR )
+ grab_state = QZ_INVISIBLE_GRAB;
+ }
+ else {
+ assert( grab_state == QZ_INVISIBLE_GRAB );
+
+ if ( action == QZ_DISABLE_GRAB )
+ grab_state = QZ_UNGRABBED;
+ else if ( action == QZ_SHOWCURSOR )
+ grab_state = QZ_VISIBLE_GRAB;
+ }
+
+ /* now apply the new state */
+ if (grab_state == QZ_UNGRABBED) {
+
+ CGAssociateMouseAndMouseCursorPosition (1);
+ }
+ else if (grab_state == QZ_VISIBLE_GRAB) {
+
+ CGAssociateMouseAndMouseCursorPosition (1);
+ }
+ else {
+ assert( grab_state == QZ_INVISIBLE_GRAB );
+
+ QZ_PrivateWarpCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2);
+ CGAssociateMouseAndMouseCursorPosition (0);
+ }
+}
+
+SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) {
+
+ int doGrab = grab_mode & SDL_GRAB_ON;
+ /*int fullscreen = grab_mode & SDL_GRAB_FULLSCREEN;*/
+
+ if ( this->screen == NULL ) {
+ SDL_SetError ("QZ_GrabInput: screen is NULL");
+ return SDL_GRAB_OFF;
+ }
+
+ if ( ! video_set ) {
+ /*SDL_SetError ("QZ_GrabInput: video is not set, grab will take effect on mode switch"); */
+ current_grab_mode = grab_mode;
+ return grab_mode; /* Will be set later on mode switch */
+ }
+
+ if ( grab_mode != SDL_GRAB_QUERY ) {
+ if ( doGrab )
+ QZ_ChangeGrabState (this, QZ_ENABLE_GRAB);
+ else
+ QZ_ChangeGrabState (this, QZ_DISABLE_GRAB);
+
+ current_grab_mode = doGrab ? SDL_GRAB_ON : SDL_GRAB_OFF;
+ QZ_UpdateCursor(this);
+ }
+
+ return current_grab_mode;
+}
diff --git a/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWindow.h b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWindow.h
new file mode 100644
index 0000000..d19375b
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWindow.h
@@ -0,0 +1,51 @@
+/*
+ SDL - Simple DirectMedia Layer
+ 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
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1050)
+typedef unsigned int NSUInteger;
+#endif
+
+/* Subclass of NSWindow to fix genie effect and support resize events */
+@interface SDL_QuartzWindow : NSWindow
+{
+ BOOL watchForMouseUp;
+}
+
+- (void)miniaturize:(id)sender;
+- (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:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag;
+@end
+
+/* Delegate for our NSWindow to send SDLQuit() on close */
+@interface SDL_QuartzWindowDelegate : NSObject
+- (BOOL)windowShouldClose:(id)sender;
+@end
+
+/* Subclass of NSView to set cursor rectangle */
+@interface SDL_QuartzView : NSView
+- (void)resetCursorRects;
+@end
diff --git a/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWindow.m b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWindow.m
new file mode 100644
index 0000000..375833f
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/quartz/SDL_QuartzWindow.m
@@ -0,0 +1,231 @@
+/*
+ SDL - Simple DirectMedia Layer
+ 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
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#include "SDL_QuartzVideo.h"
+#include "SDL_QuartzWM.h"
+#include "SDL_QuartzWindow.h"
+
+/*
+ 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 () {
+
+ SDL_Surface *surface = current_video->screen;
+ int bpp;
+
+ bpp = surface->format->BitsPerPixel;
+
+ if (bpp == 32) {
+
+ Uint32 *pixels = (Uint32*) surface->pixels;
+ Uint32 rowPixels = surface->pitch / 4;
+ Uint32 i, j;
+
+ for (i = 0; i < surface->h; i++)
+ for (j = 0; j < surface->w; j++) {
+
+ pixels[ (i * rowPixels) + j ] |= 0xFF000000;
+ }
+ }
+}
+
+@implementation SDL_QuartzWindow
+
+/* we override these methods to fix the miniaturize animation/dock icon bug */
+- (void)miniaturize:(id)sender
+{
+ if (SDL_VideoSurface->flags & SDL_OPENGL) {
+
+ /*
+ Future: Grab framebuffer and put into NSImage
+ [ qz_window setMiniwindowImage:image ];
+ */
+ }
+ else {
+
+ /* make the alpha channel opaque so anim won't have holes in it */
+ QZ_SetPortAlphaOpaque ();
+ }
+
+ /* window is hidden now */
+ SDL_PrivateAppActive (0, SDL_APPACTIVE);
+
+ [ super miniaturize:sender ];
+}
+
+- (void)display
+{
+ /*
+ 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.
+ */
+ 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);
+}
+
+- (void)setFrame:(NSRect)frameRect display:(BOOL)flag
+{
+
+ /*
+ If the video surface is NULL, this originated from QZ_SetVideoMode,
+ so don't send the resize event.
+ */
+ SDL_VideoDevice *this = (SDL_VideoDevice*)current_video;
+
+ if (this && SDL_VideoSurface == NULL) {
+
+ [ super setFrame:frameRect display:flag ];
+ }
+ else if (this && qz_window) {
+
+ NSRect newViewFrame;
+
+ [ super setFrame:frameRect display:flag ];
+
+ newViewFrame = [ window_view frame ];
+
+ SDL_PrivateResize (newViewFrame.size.width, newViewFrame.size.height);
+ }
+}
+
+/* QZ_DoActivate() calls a low-level CoreGraphics routine to adjust
+ the cursor position, if input is being grabbed. If app activation is
+ triggered by a mouse click in the title bar, then the window manager
+ gets confused and thinks we're dragging the window. The solution
+ below postpones the activate event to avoid this scenario. */
+- (void)becomeKeyWindow
+{
+ NSEvent *event = [self currentEvent];
+ if ([event type] == NSLeftMouseDown && [event window] == self)
+ watchForMouseUp = YES;
+ else
+ [super becomeKeyWindow];
+}
+
+- (void)sendEvent:(NSEvent *)event
+{
+ [super sendEvent:event];
+ if (watchForMouseUp && [event type] == NSLeftMouseUp)
+ {
+ watchForMouseUp = NO;
+ [super becomeKeyWindow];
+ }
+}
+
+- (void)appDidHide:(NSNotification*)note
+{
+ 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);
+}
+
+- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag
+{
+ /* Make our window subclass receive these application notifications */
+ [ [ NSNotificationCenter defaultCenter ] addObserver:self
+ selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ];
+
+ [ [ 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 ];
+}
+
+@end
+
+@implementation SDL_QuartzWindowDelegate
+- (BOOL)windowShouldClose:(id)sender
+{
+ SDL_PrivateQuit();
+ return NO;
+}
+
+- (void)windowDidBecomeKey:(NSNotification *)aNotification
+{
+ QZ_DoActivate (current_video);
+}
+
+- (void)windowDidResignKey:(NSNotification *)aNotification
+{
+ QZ_DoDeactivate (current_video);
+}
+
+@end
+
+@implementation SDL_QuartzView
+
+- (void)resetCursorRects
+{
+ SDL_Cursor *sdlc = SDL_GetCursor();
+ if (sdlc != NULL && sdlc->wm_cursor != NULL) {
+ [self addCursorRect: [self visibleRect] cursor: sdlc->wm_cursor->nscursor];
+ }
+}
+
+@end