Commit aba4b443 authored by Sam Lantinga's avatar Sam Lantinga

Date: Sat, 1 Jun 2002 17:56:45 -0500

From: Darrell Walisser <dwaliss1@purdue.edu>
Subject: mac patch

In this patch:

- yuv code
- links to QuickTime
- tabs -> 4 spaces
- mouse events fix
- SDLMain path parsing fix
- BUGS updates
- some miscellaneous docs/comments/code cleanup

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40391
parent 455d014f
...@@ -72,26 +72,20 @@ MacOS X: ...@@ -72,26 +72,20 @@ MacOS X:
Joystick code is not extensively tested yet. Joystick code is not extensively tested yet.
Window may not close when unsetting video mode and resetting.
Resizeable windows aren't implemented yet. Resizeable windows aren't implemented yet.
Depth switching for windowed mode isn't implemented yet. Depth switching for windowed mode isn't implemented yet.
Palette handling isn't implemented in windowed mode yet. Palette handling isn't implemented in windowed mode yet.
Command-line arguments Dialog is not implemented yet. Command-line arguments dialog is not implemented yet.
Fullscreen drawing has some artifacts. Fullscreen drawing has some artifacts.
Fullscreen window covers *all* other windows - even force quit.
Fullscreen OpenGL for the software renderer is broken. Fullscreen OpenGL for the software renderer is broken.
Some OpenGL parameters are not accounted for, for example color bits customization. Some OpenGL parameters are not accounted for, for example color bits customization.
Getting OpenGL context parameters is not implemented.
Continuous mouse motion perhaps is not as smooth as it should be. Continuous mouse motion perhaps is not as smooth as it should be.
SDL_WM_GrabInput() is implemented, but it "freezes" the hardware SDL_WM_GrabInput() is implemented, but it "freezes" the hardware
......
...@@ -51,24 +51,25 @@ static BOOL gFinderLaunch; ...@@ -51,24 +51,25 @@ static BOOL gFinderLaunch;
/* Set the working directory to the .app's parent directory */ /* Set the working directory to the .app's parent directory */
- (void) setupWorkingDirectory:(BOOL)shouldChdir - (void) setupWorkingDirectory:(BOOL)shouldChdir
{ {
char parentdir[MAXPATHLEN];
char *c;
strncpy ( parentdir, gArgv[0], sizeof(parentdir) );
c = (char*) parentdir;
while (*c != '\0') /* go to end */
c++;
while (*c != '/') /* back up to parent */
c--;
*c++ = '\0'; /* cut off last part (binary name) */
if (shouldChdir) if (shouldChdir)
{ {
assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ char parentdir[MAXPATHLEN];
assert ( chdir ("../../../") == 0 ); /* chdir to the .app's parent */ char *c;
strncpy ( parentdir, gArgv[0], sizeof(parentdir) );
c = (char*) parentdir;
while (*c != '\0') /* go to end */
c++;
while (*c != '/') /* back up to parent */
c--;
*c++ = '\0'; /* cut off last part (binary name) */
assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */
assert ( chdir ("../../../") == 0 ); /* chdir to the .app's parent */
} }
} }
......
/* /*
SDL - Simple DirectMedia Layer SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version. version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details. Library General Public License for more details.
You should have received a copy of the GNU Library General Public You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
*/ */
#include <sys/time.h> #include <sys/time.h>
...@@ -27,479 +27,473 @@ static SDLKey keymap[256]; ...@@ -27,479 +27,473 @@ static SDLKey keymap[256];
static unsigned int currentMods = 0; /* Current keyboard modifiers, to track modifier state */ static unsigned int currentMods = 0; /* Current keyboard modifiers, to track modifier state */
static int last_virtual_button = 0; /* Last virtual mouse button pressed */ static int last_virtual_button = 0; /* Last virtual mouse button pressed */
static void QZ_InitOSKeymap (_THIS) { static void QZ_InitOSKeymap (_THIS) {
const void *KCHRPtr; const void *KCHRPtr;
UInt32 state; UInt32 state;
UInt32 value; UInt32 value;
int i; int i;
int world = SDLK_WORLD_0; int world = SDLK_WORLD_0;
for ( i=0; i<SDL_TABLESIZE(keymap); ++i ) for ( i=0; i<SDL_TABLESIZE(keymap); ++i )
keymap[i] = SDLK_UNKNOWN; keymap[i] = SDLK_UNKNOWN;
/* This keymap is almost exactly the same as the OS 9 one */ /* This keymap is almost exactly the same as the OS 9 one */
keymap[QZ_ESCAPE] = SDLK_ESCAPE; keymap[QZ_ESCAPE] = SDLK_ESCAPE;
keymap[QZ_F1] = SDLK_F1; keymap[QZ_F1] = SDLK_F1;
keymap[QZ_F2] = SDLK_F2; keymap[QZ_F2] = SDLK_F2;
keymap[QZ_F3] = SDLK_F3; keymap[QZ_F3] = SDLK_F3;
keymap[QZ_F4] = SDLK_F4; keymap[QZ_F4] = SDLK_F4;
keymap[QZ_F5] = SDLK_F5; keymap[QZ_F5] = SDLK_F5;
keymap[QZ_F6] = SDLK_F6; keymap[QZ_F6] = SDLK_F6;
keymap[QZ_F7] = SDLK_F7; keymap[QZ_F7] = SDLK_F7;
keymap[QZ_F8] = SDLK_F8; keymap[QZ_F8] = SDLK_F8;
keymap[QZ_F9] = SDLK_F9; keymap[QZ_F9] = SDLK_F9;
keymap[QZ_F10] = SDLK_F10; keymap[QZ_F10] = SDLK_F10;
keymap[QZ_F11] = SDLK_F11; keymap[QZ_F11] = SDLK_F11;
keymap[QZ_F12] = SDLK_F12; keymap[QZ_F12] = SDLK_F12;
keymap[QZ_PRINT] = SDLK_PRINT; keymap[QZ_PRINT] = SDLK_PRINT;
keymap[QZ_SCROLLOCK] = SDLK_SCROLLOCK; keymap[QZ_SCROLLOCK] = SDLK_SCROLLOCK;
keymap[QZ_PAUSE] = SDLK_PAUSE; keymap[QZ_PAUSE] = SDLK_PAUSE;
keymap[QZ_POWER] = SDLK_POWER; keymap[QZ_POWER] = SDLK_POWER;
keymap[QZ_BACKQUOTE] = SDLK_BACKQUOTE; keymap[QZ_BACKQUOTE] = SDLK_BACKQUOTE;
keymap[QZ_1] = SDLK_1; keymap[QZ_1] = SDLK_1;
keymap[QZ_2] = SDLK_2; keymap[QZ_2] = SDLK_2;
keymap[QZ_3] = SDLK_3; keymap[QZ_3] = SDLK_3;
keymap[QZ_4] = SDLK_4; keymap[QZ_4] = SDLK_4;
keymap[QZ_5] = SDLK_5; keymap[QZ_5] = SDLK_5;
keymap[QZ_6] = SDLK_6; keymap[QZ_6] = SDLK_6;
keymap[QZ_7] = SDLK_7; keymap[QZ_7] = SDLK_7;
keymap[QZ_8] = SDLK_8; keymap[QZ_8] = SDLK_8;
keymap[QZ_9] = SDLK_9; keymap[QZ_9] = SDLK_9;
keymap[QZ_0] = SDLK_0; keymap[QZ_0] = SDLK_0;
keymap[QZ_MINUS] = SDLK_MINUS; keymap[QZ_MINUS] = SDLK_MINUS;
keymap[QZ_EQUALS] = SDLK_EQUALS; keymap[QZ_EQUALS] = SDLK_EQUALS;
keymap[QZ_BACKSPACE] = SDLK_BACKSPACE; keymap[QZ_BACKSPACE] = SDLK_BACKSPACE;
keymap[QZ_INSERT] = SDLK_INSERT; keymap[QZ_INSERT] = SDLK_INSERT;
keymap[QZ_HOME] = SDLK_HOME; keymap[QZ_HOME] = SDLK_HOME;
keymap[QZ_PAGEUP] = SDLK_PAGEUP; keymap[QZ_PAGEUP] = SDLK_PAGEUP;
keymap[QZ_NUMLOCK] = SDLK_NUMLOCK; keymap[QZ_NUMLOCK] = SDLK_NUMLOCK;
keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS; keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS;
keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE; keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE;
keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY; keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
keymap[QZ_TAB] = SDLK_TAB; keymap[QZ_TAB] = SDLK_TAB;
keymap[QZ_q] = SDLK_q; keymap[QZ_q] = SDLK_q;
keymap[QZ_w] = SDLK_w; keymap[QZ_w] = SDLK_w;
keymap[QZ_e] = SDLK_e; keymap[QZ_e] = SDLK_e;
keymap[QZ_r] = SDLK_r; keymap[QZ_r] = SDLK_r;
keymap[QZ_t] = SDLK_t; keymap[QZ_t] = SDLK_t;
keymap[QZ_y] = SDLK_y; keymap[QZ_y] = SDLK_y;
keymap[QZ_u] = SDLK_u; keymap[QZ_u] = SDLK_u;
keymap[QZ_i] = SDLK_i; keymap[QZ_i] = SDLK_i;
keymap[QZ_o] = SDLK_o; keymap[QZ_o] = SDLK_o;
keymap[QZ_p] = SDLK_p; keymap[QZ_p] = SDLK_p;
keymap[QZ_LEFTBRACKET] = SDLK_LEFTBRACKET; keymap[QZ_LEFTBRACKET] = SDLK_LEFTBRACKET;
keymap[QZ_RIGHTBRACKET] = SDLK_RIGHTBRACKET; keymap[QZ_RIGHTBRACKET] = SDLK_RIGHTBRACKET;
keymap[QZ_BACKSLASH] = SDLK_BACKSLASH; keymap[QZ_BACKSLASH] = SDLK_BACKSLASH;
keymap[QZ_DELETE] = SDLK_DELETE; keymap[QZ_DELETE] = SDLK_DELETE;
keymap[QZ_END] = SDLK_END; keymap[QZ_END] = SDLK_END;
keymap[QZ_PAGEDOWN] = SDLK_PAGEDOWN; keymap[QZ_PAGEDOWN] = SDLK_PAGEDOWN;
keymap[QZ_KP7] = SDLK_KP7; keymap[QZ_KP7] = SDLK_KP7;
keymap[QZ_KP8] = SDLK_KP8; keymap[QZ_KP8] = SDLK_KP8;
keymap[QZ_KP9] = SDLK_KP9; keymap[QZ_KP9] = SDLK_KP9;
keymap[QZ_KP_MINUS] = SDLK_KP_MINUS; keymap[QZ_KP_MINUS] = SDLK_KP_MINUS;
keymap[QZ_CAPSLOCK] = SDLK_CAPSLOCK; keymap[QZ_CAPSLOCK] = SDLK_CAPSLOCK;
keymap[QZ_a] = SDLK_a; keymap[QZ_a] = SDLK_a;
keymap[QZ_s] = SDLK_s; keymap[QZ_s] = SDLK_s;
keymap[QZ_d] = SDLK_d; keymap[QZ_d] = SDLK_d;
keymap[QZ_f] = SDLK_f; keymap[QZ_f] = SDLK_f;
keymap[QZ_g] = SDLK_g; keymap[QZ_g] = SDLK_g;
keymap[QZ_h] = SDLK_h; keymap[QZ_h] = SDLK_h;
keymap[QZ_j] = SDLK_j; keymap[QZ_j] = SDLK_j;
keymap[QZ_k] = SDLK_k; keymap[QZ_k] = SDLK_k;
keymap[QZ_l] = SDLK_l; keymap[QZ_l] = SDLK_l;
keymap[QZ_SEMICOLON] = SDLK_SEMICOLON; keymap[QZ_SEMICOLON] = SDLK_SEMICOLON;
keymap[QZ_QUOTE] = SDLK_QUOTE; keymap[QZ_QUOTE] = SDLK_QUOTE;
keymap[QZ_RETURN] = SDLK_RETURN; keymap[QZ_RETURN] = SDLK_RETURN;
keymap[QZ_KP4] = SDLK_KP4; keymap[QZ_KP4] = SDLK_KP4;
keymap[QZ_KP5] = SDLK_KP5; keymap[QZ_KP5] = SDLK_KP5;
keymap[QZ_KP6] = SDLK_KP6; keymap[QZ_KP6] = SDLK_KP6;
keymap[QZ_KP_PLUS] = SDLK_KP_PLUS; keymap[QZ_KP_PLUS] = SDLK_KP_PLUS;
keymap[QZ_LSHIFT] = SDLK_LSHIFT; keymap[QZ_LSHIFT] = SDLK_LSHIFT;
keymap[QZ_z] = SDLK_z; keymap[QZ_z] = SDLK_z;
keymap[QZ_x] = SDLK_x; keymap[QZ_x] = SDLK_x;
keymap[QZ_c] = SDLK_c; keymap[QZ_c] = SDLK_c;
keymap[QZ_v] = SDLK_v; keymap[QZ_v] = SDLK_v;
keymap[QZ_b] = SDLK_b; keymap[QZ_b] = SDLK_b;
keymap[QZ_n] = SDLK_n; keymap[QZ_n] = SDLK_n;
keymap[QZ_m] = SDLK_m; keymap[QZ_m] = SDLK_m;
keymap[QZ_COMMA] = SDLK_COMMA; keymap[QZ_COMMA] = SDLK_COMMA;
keymap[QZ_PERIOD] = SDLK_PERIOD; keymap[QZ_PERIOD] = SDLK_PERIOD;
keymap[QZ_SLASH] = SDLK_SLASH; keymap[QZ_SLASH] = SDLK_SLASH;
keymap[QZ_UP] = SDLK_UP; keymap[QZ_UP] = SDLK_UP;
keymap[QZ_KP1] = SDLK_KP1; keymap[QZ_KP1] = SDLK_KP1;
keymap[QZ_KP2] = SDLK_KP2; keymap[QZ_KP2] = SDLK_KP2;
keymap[QZ_KP3] = SDLK_KP3; keymap[QZ_KP3] = SDLK_KP3;
keymap[QZ_KP_ENTER] = SDLK_KP_ENTER; keymap[QZ_KP_ENTER] = SDLK_KP_ENTER;
keymap[QZ_LCTRL] = SDLK_LCTRL; keymap[QZ_LCTRL] = SDLK_LCTRL;
keymap[QZ_LALT] = SDLK_LALT; keymap[QZ_LALT] = SDLK_LALT;
keymap[QZ_LMETA] = SDLK_LMETA; keymap[QZ_LMETA] = SDLK_LMETA;
keymap[QZ_SPACE] = SDLK_SPACE; keymap[QZ_SPACE] = SDLK_SPACE;
keymap[QZ_LEFT] = SDLK_LEFT; keymap[QZ_LEFT] = SDLK_LEFT;
keymap[QZ_DOWN] = SDLK_DOWN; keymap[QZ_DOWN] = SDLK_DOWN;
keymap[QZ_RIGHT] = SDLK_RIGHT; keymap[QZ_RIGHT] = SDLK_RIGHT;
keymap[QZ_KP0] = SDLK_KP0; keymap[QZ_KP0] = SDLK_KP0;
keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD; keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD;
keymap[QZ_IBOOK_ENTER] = SDLK_KP_ENTER; keymap[QZ_IBOOK_ENTER] = SDLK_KP_ENTER;
keymap[QZ_IBOOK_RIGHT] = SDLK_RIGHT; keymap[QZ_IBOOK_RIGHT] = SDLK_RIGHT;
keymap[QZ_IBOOK_DOWN] = SDLK_DOWN; keymap[QZ_IBOOK_DOWN] = SDLK_DOWN;
keymap[QZ_IBOOK_UP] = SDLK_UP; keymap[QZ_IBOOK_UP] = SDLK_UP;
keymap[QZ_IBOOK_LEFT] = SDLK_LEFT; keymap[QZ_IBOOK_LEFT] = SDLK_LEFT;
/* Up there we setup a static scancode->keysym map. However, it will not /* Up there we setup a static scancode->keysym map. However, it will not
* work very well on international keyboard. Hence we now query MacOS * work very well on international keyboard. Hence we now query MacOS
* for its own keymap to adjust our own mapping table. However, this is * for its own keymap to adjust our own mapping table. However, this is
* bascially only useful for ascii char keys. This is also the reason * bascially only useful for ascii char keys. This is also the reason
* why we keep the static table, too. * why we keep the static table, too.
*/ */
/* Get a pointer to the systems cached KCHR */ /* Get a pointer to the systems cached KCHR */
KCHRPtr = (void *)GetScriptManagerVariable(smKCHRCache); KCHRPtr = (void *)GetScriptManagerVariable(smKCHRCache);
if (KCHRPtr) if (KCHRPtr)
{ {
/* Loop over all 127 possible scan codes */ /* Loop over all 127 possible scan codes */
for (i = 0; i < 0x7F; i++) for (i = 0; i < 0x7F; i++)
{ {
/* We pretend a clean start to begin with (i.e. no dead keys active */ /* We pretend a clean start to begin with (i.e. no dead keys active */
state = 0; state = 0;
/* Now translate the key code to a key value */ /* Now translate the key code to a key value */
value = KeyTranslate(KCHRPtr, i, &state) & 0xff; value = KeyTranslate(KCHRPtr, i, &state) & 0xff;
/* If the state become 0, it was a dead key. We need to translate again, /* 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 */ passing in the new state, to get the actual key value */
if (state != 0) if (state != 0)
value = KeyTranslate(KCHRPtr, i, &state) & 0xff; 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 */ /* 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 (value >= 128) /* Some non-ASCII char, map it to SDLK_WORLD_* */
keymap[i] = world++; keymap[i] = world++;
else if (value >= 32) /* non-control ASCII char */ else if (value >= 32) /* non-control ASCII char */
keymap[i] = value; keymap[i] = value;
} }
} }
/* The keypad codes are re-setup here, because the loop above cannot /* 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 * distinguish between a key on the keypad and a regular key. We maybe
* could get around this problem in another fashion: NSEvent's flags * could get around this problem in another fashion: NSEvent's flags
* include a "NSNumericPadKeyMask" bit; we could check that and modify * include a "NSNumericPadKeyMask" bit; we could check that and modify
* the symbol we return on the fly. However, this flag seems to exhibit * the symbol we return on the fly. However, this flag seems to exhibit
* some weird behaviour related to the num lock key * some weird behaviour related to the num lock key
*/ */
keymap[QZ_KP0] = SDLK_KP0; keymap[QZ_KP0] = SDLK_KP0;
keymap[QZ_KP1] = SDLK_KP1; keymap[QZ_KP1] = SDLK_KP1;
keymap[QZ_KP2] = SDLK_KP2; keymap[QZ_KP2] = SDLK_KP2;
keymap[QZ_KP3] = SDLK_KP3; keymap[QZ_KP3] = SDLK_KP3;
keymap[QZ_KP4] = SDLK_KP4; keymap[QZ_KP4] = SDLK_KP4;
keymap[QZ_KP5] = SDLK_KP5; keymap[QZ_KP5] = SDLK_KP5;
keymap[QZ_KP6] = SDLK_KP6; keymap[QZ_KP6] = SDLK_KP6;
keymap[QZ_KP7] = SDLK_KP7; keymap[QZ_KP7] = SDLK_KP7;
keymap[QZ_KP8] = SDLK_KP8; keymap[QZ_KP8] = SDLK_KP8;
keymap[QZ_KP9] = SDLK_KP9; keymap[QZ_KP9] = SDLK_KP9;
keymap[QZ_KP_MINUS] = SDLK_KP_MINUS; keymap[QZ_KP_MINUS] = SDLK_KP_MINUS;
keymap[QZ_KP_PLUS] = SDLK_KP_PLUS; keymap[QZ_KP_PLUS] = SDLK_KP_PLUS;
keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD; keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD;
keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS; keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS;
keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE; keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE;
keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY; keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
keymap[QZ_KP_ENTER] = SDLK_KP_ENTER; keymap[QZ_KP_ENTER] = SDLK_KP_ENTER;
} }
static void QZ_DoKey (int state, NSEvent *event) { static void QZ_DoKey (int state, NSEvent *event) {
NSString *chars; NSString *chars;
int i; int i;
SDL_keysym key; SDL_keysym key;
/* An event can contain multiple characters */ /* An event can contain multiple characters */
/* I'll ignore this fact for now, since there is only one virtual key code per event */ /* I'll ignore this fact for now, since there is only one virtual key code per event */
chars = [ event characters ]; chars = [ event characters ];
for (i =0; i < 1 /*[ chars length ] */; i++) { for (i =0; i < 1 /*[ chars length ] */; i++) {
key.scancode = [ event keyCode ]; key.scancode = [ event keyCode ];
key.sym = keymap [ key.scancode ]; key.sym = keymap [ key.scancode ];
key.unicode = [ chars characterAtIndex:i]; key.unicode = [ chars characterAtIndex:i];
key.mod = KMOD_NONE; key.mod = KMOD_NONE;
SDL_PrivateKeyboard (state, &key); SDL_PrivateKeyboard (state, &key);
} }
} }
static void QZ_DoModifiers (unsigned int newMods) { static void QZ_DoModifiers (unsigned int newMods) {
const int mapping[] = { SDLK_CAPSLOCK, SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA } ; const int mapping[] = { SDLK_CAPSLOCK, SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA } ;
int i; int i;
int bit; int bit;
SDL_keysym key; SDL_keysym key;
key.scancode = 0; key.scancode = 0;
key.sym = SDLK_UNKNOWN; key.sym = SDLK_UNKNOWN;
key.unicode = 0; key.unicode = 0;
key.mod = KMOD_NONE; key.mod = KMOD_NONE;
/* Iterate through the bits, testing each against the current modifiers */ /* Iterate through the bits, testing each against the current modifiers */
for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) { for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
unsigned int currentMask, newMask; unsigned int currentMask, newMask;
currentMask = currentMods & bit; currentMask = currentMods & bit;
newMask = newMods & bit; newMask = newMods & bit;
if ( currentMask && if ( currentMask &&
currentMask != newMask ) { /* modifier up event */ currentMask != newMask ) { /* modifier up event */
key.sym = mapping[i]; key.sym = mapping[i];
/* If this was Caps Lock, we need some additional voodoo to make SDL happy */ /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
if (bit == NSAlphaShiftKeyMask) if (bit == NSAlphaShiftKeyMask)
SDL_PrivateKeyboard (SDL_PRESSED, &key); SDL_PrivateKeyboard (SDL_PRESSED, &key);
SDL_PrivateKeyboard (SDL_RELEASED, &key); SDL_PrivateKeyboard (SDL_RELEASED, &key);
} }
else else if ( newMask &&
if ( newMask && currentMask != newMask ) { /* modifier down event */
currentMask != newMask ) { /* modifier down event */
key.sym = mapping[i];
key.sym = mapping[i]; SDL_PrivateKeyboard (SDL_PRESSED, &key);
SDL_PrivateKeyboard (SDL_PRESSED, &key); /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
/* If this was Caps Lock, we need some additional voodoo to make SDL happy */ if (bit == NSAlphaShiftKeyMask)
if (bit == NSAlphaShiftKeyMask) SDL_PrivateKeyboard (SDL_RELEASED, &key);
SDL_PrivateKeyboard (SDL_RELEASED, &key); }
} }
}
currentMods = newMods;
currentMods = newMods;
} }
static void QZ_DoActivate (_THIS) static void QZ_DoActivate (_THIS)
{ {
inForeground = YES; inForeground = YES;
/* Regrab the mouse */ /* Regrab the mouse */
if (currentGrabMode == SDL_GRAB_ON) { if (currentGrabMode == SDL_GRAB_ON) {
QZ_WarpWMCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2); QZ_WarpWMCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2);
CGAssociateMouseAndMouseCursorPosition (0); CGAssociateMouseAndMouseCursorPosition (0);
} }
/* Hide the mouse cursor if inside the app window */ /* Hide the mouse cursor if inside the app window */
if (!QZ_cursor_visible) { if (!QZ_cursor_visible) {
HideCursor (); HideCursor ();
} }
SDL_PrivateAppActive (1, SDL_APPINPUTFOCUS); SDL_PrivateAppActive (1, SDL_APPINPUTFOCUS);
} }
static void QZ_DoDeactivate (_THIS) { static void QZ_DoDeactivate (_THIS) {
inForeground = NO; inForeground = NO;
/* Ungrab mouse if it is grabbed */ /* Ungrab mouse if it is grabbed */
if (currentGrabMode == SDL_GRAB_ON) { if (currentGrabMode == SDL_GRAB_ON) {
CGAssociateMouseAndMouseCursorPosition (1); CGAssociateMouseAndMouseCursorPosition (1);
} }
/* Show the mouse cursor */ /* Show the mouse cursor */
if (!QZ_cursor_visible) { if (!QZ_cursor_visible) {
ShowCursor (); ShowCursor ();
} }
SDL_PrivateAppActive (0, SDL_APPINPUTFOCUS); SDL_PrivateAppActive (0, SDL_APPINPUTFOCUS);
} }
static void QZ_PumpEvents (_THIS) static void QZ_PumpEvents (_THIS)
{ {
static NSPoint lastMouse;
static NSPoint lastMouse; NSPoint mouse, saveMouse;
NSPoint mouse, saveMouse; Point qdMouse;
Point qdMouse; CGMouseDelta dx, dy;
CGMouseDelta dx, dy;
NSDate *distantPast;
NSDate *distantPast; NSEvent *event;
NSEvent *event; NSRect winRect;
NSRect winRect; NSRect titleBarRect;
NSRect titleBarRect; NSAutoreleasePool *pool;
NSAutoreleasePool *pool;
pool = [ [ NSAutoreleasePool alloc ] init ];
pool = [ [ NSAutoreleasePool alloc ] init ]; distantPast = [ NSDate distantPast ];
distantPast = [ NSDate distantPast ];
winRect = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
winRect = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h); titleBarRect = NSMakeRect ( 0, SDL_VideoSurface->h, SDL_VideoSurface->w,
titleBarRect = NSMakeRect ( 0, SDL_VideoSurface->h, SDL_VideoSurface->w, SDL_VideoSurface->h + 22 );
SDL_VideoSurface->h + 22 );
if (currentGrabMode != SDL_GRAB_ON) { /* if grabbed, the cursor can't move! (see fallback below) */
if (currentGrabMode != SDL_GRAB_ON) { /* if grabbed, the cursor can't move! (see fallback below) */
/* 1/2 second after a warp, the mouse cannot move (don't ask me why) */
/* 1/2 second after a warp, the mouse cannot move (don't ask me why) */ /* So, approximate motion with CGGetLastMouseDelta, which still works, somehow */
/* So, approximate motion with CGGetLastMouseDelta, which still works, somehow */ if (! warp_flag) {
if (! warp_flag) {
GetGlobalMouse (&qdMouse); /* use Carbon since [ NSEvent mouseLocation ] is broken */
mouse = NSMakePoint (qdMouse.h, qdMouse.v);
saveMouse = mouse;
if (mouse.x != lastMouse.x || mouse.y != lastMouse.y) {
QZ_PrivateCGToSDL (this, &mouse);
/* -note- we now generate mouse motion events if the mouse isn't over the window */
if (inForeground /* && NSPointInRect (mouse, winRect)*/) {
//printf ("Mouse Loc: (%f, %f)\n", mouse.x, mouse.y);
SDL_PrivateMouseMotion (0, 0, mouse.x, mouse.y);
}
}
lastMouse = saveMouse;
}
}
/* accumulate any mouse 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) {
unsigned int type;
BOOL isForGameWin;
#define DO_MOUSE_DOWN(button, sendToWindow) do { \
if ( inForeground ) { \
if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) || \
NSPointInRect([event locationInWindow], winRect) ) \
SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0); \
} \
else { \
QZ_DoActivate (this); \
} \
[ NSApp sendEvent:event ]; \
} while(0)
#define DO_MOUSE_UP(button, sendToWindow) do { \
if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) || \
!NSPointInRect([event locationInWindow], titleBarRect) ) \
SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0); \
[ NSApp sendEvent:event ]; \
} while(0)
GetGlobalMouse (&qdMouse); /* use Carbon since [ NSEvent mouseLocation ] is broken */ type = [ event type ];
mouse = NSMakePoint (qdMouse.h, qdMouse.v); isForGameWin = (qz_window == [ event window ]);
saveMouse = mouse; switch (type) {
case NSLeftMouseDown:
if ( NSCommandKeyMask & currentMods ) {
last_virtual_button = 3;
DO_MOUSE_DOWN (3, 0);
}
else if ( NSAlternateKeyMask & currentMods ) {
last_virtual_button = 2;
DO_MOUSE_DOWN (2, 0);
}
else {
DO_MOUSE_DOWN (1, 1);
}
break;
case NSOtherMouseDown: DO_MOUSE_DOWN (2, 0); break;
case NSRightMouseDown: DO_MOUSE_DOWN (3, 0); break;
case NSLeftMouseUp:
if ( last_virtual_button != 0 ) {
DO_MOUSE_UP (last_virtual_button, 0);
last_virtual_button = 0;
}
else {
DO_MOUSE_UP (1, 1);
}
break;
case NSOtherMouseUp: DO_MOUSE_UP (2, 0); break;
case NSRightMouseUp: DO_MOUSE_UP (3, 0); break;
case NSSystemDefined:
//if ([event subtype] == 7) {
// unsigned int buttons; // up to 32 mouse button states!
// buttons = [ event data2 ];
//}
break;
case NSLeftMouseDragged:
case NSRightMouseDragged:
case 27:
case NSMouseMoved:
if (currentGrabMode == SDL_GRAB_ON) {
/**
* If input is grabbed, we'll wing it and try to send some mouse
* moved events with CGGetLastMouseDelta(). Not optimal, but better
* than nothing.
**/
CGMouseDelta dx1, dy1;
CGGetLastMouseDelta (&dx1, &dy1);
dx += dx1;
dy += dy1;
}
else if (warp_flag) {
Uint32 ticks;
ticks = SDL_GetTicks();
if (ticks - warp_ticks < 150) {
if (mouse.x != lastMouse.x || mouse.y != lastMouse.y) { CGMouseDelta dx1, dy1;
CGGetLastMouseDelta (&dx1, &dy1);
dx += dx1;
dy += dy1;
}
else {
QZ_PrivateCGToSDL (this, &mouse); warp_flag = 0;
if (inForeground && NSPointInRect (mouse, winRect)) { }
//printf ("Mouse Loc: (%f, %f)\n", mouse.x, mouse.y);
SDL_PrivateMouseMotion (0, 0, mouse.x, mouse.y);
} }
} break;
lastMouse = saveMouse; case NSScrollWheel:
if (NSPointInRect([ event locationInWindow ], winRect)) {
float dy;
dy = [ event deltaY ];
if ( dy > 0.0 ) /* Scroll up */
SDL_PrivateMouseButton (SDL_PRESSED, 4, 0, 0);
else /* Scroll down */
SDL_PrivateMouseButton (SDL_PRESSED, 5, 0, 0);
}
break;
case NSKeyUp:
QZ_DoKey (SDL_RELEASED, event);
break;
case NSKeyDown:
QZ_DoKey (SDL_PRESSED, event);
break;
case NSFlagsChanged:
QZ_DoModifiers( [ event modifierFlags ] );
break;
case NSAppKitDefined:
switch ( [ event subtype ] ) {
case NSApplicationActivatedEventType:
QZ_DoActivate (this);
break;
case NSApplicationDeactivatedEventType:
QZ_DoDeactivate (this);
break;
}
[ NSApp sendEvent:event ];
break;
/* case NSApplicationDefined: break; */
/* case NSPeriodic: break; */
/* case NSCursorUpdate: break; */
default:
[ NSApp sendEvent:event ];
} }
} }
} while (event != nil);
/* accumulate any mouse events into one SDL mouse event */
dx = 0; /* check for accumulated mouse events */
dy = 0; if (dx != 0 || dy != 0)
SDL_PrivateMouseMotion (0, 1, dx, dy);
do {
[ pool release ];
/* Poll for an event. This will not block */
event = [ NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:distantPast
inMode: NSDefaultRunLoopMode dequeue:YES ];
if (event != nil) {
unsigned int type;
BOOL isForGameWin;
#define DO_MOUSE_DOWN(button, sendToWindow) do { \
if ( inForeground ) { \
if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) || \
NSPointInRect([event locationInWindow], winRect) ) \
SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0); \
} \
else { \
QZ_DoActivate (this); \
} \
[ NSApp sendEvent:event ]; \
} while(0)
#define DO_MOUSE_UP(button, sendToWindow) do { \
if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) || \
!NSPointInRect([event locationInWindow], titleBarRect) ) \
SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0); \
[ NSApp sendEvent:event ]; \
} while(0)
type = [ event type ];
isForGameWin = (qz_window == [ event window ]);
switch (type) {
case NSLeftMouseDown:
if ( NSCommandKeyMask & currentMods ) {
last_virtual_button = 3;
DO_MOUSE_DOWN (3, 0);
}
else if ( NSAlternateKeyMask & currentMods ) {
last_virtual_button = 2;
DO_MOUSE_DOWN (2, 0);
}
else {
DO_MOUSE_DOWN (1, 1);
}
break;
case NSOtherMouseDown: DO_MOUSE_DOWN (2, 0); break;
case NSRightMouseDown: DO_MOUSE_DOWN (3, 0); break;
case NSLeftMouseUp:
if ( last_virtual_button != 0 ) {
DO_MOUSE_UP (last_virtual_button, 0);
last_virtual_button = 0;
}
else {
DO_MOUSE_UP (1, 1);
}
break;
case NSOtherMouseUp: DO_MOUSE_UP (2, 0); break;
case NSRightMouseUp: DO_MOUSE_UP (3, 0); break;
case NSSystemDefined:
//if ([event subtype] == 7) {
// unsigned int buttons; // up to 32 mouse button states!
// buttons = [ event data2 ];
//}
break;
case NSLeftMouseDragged:
case NSRightMouseDragged:
case 27:
case NSMouseMoved:
if (currentGrabMode == SDL_GRAB_ON) {
/**
* If input is grabbed, we'll wing it and try to send some mouse
* moved events with CGGetLastMouseDelta(). Not optimal, but better
* than nothing.
**/
CGMouseDelta dx1, dy1;
CGGetLastMouseDelta (&dx1, &dy1);
dx += dx1;
dy += dy1;
}
else if (warp_flag) {
Uint32 ticks;
ticks = SDL_GetTicks();
if (ticks - warp_ticks < 150) {
CGMouseDelta dx1, dy1;
CGGetLastMouseDelta (&dx1, &dy1);
dx += dx1;
dy += dy1;
}
else {
warp_flag = 0;
}
}
break;
case NSScrollWheel:
{
if (NSPointInRect([ event locationInWindow ], winRect)) {
float dy;
dy = [ event deltaY ];
if ( dy > 0.0 ) /* Scroll up */
SDL_PrivateMouseButton (SDL_PRESSED, 4, 0, 0);
else /* Scroll down */
SDL_PrivateMouseButton (SDL_PRESSED, 5, 0, 0);
}
}
break;
case NSKeyUp:
QZ_DoKey (SDL_RELEASED, event);
break;
case NSKeyDown:
QZ_DoKey (SDL_PRESSED, event);
break;
case NSFlagsChanged:
QZ_DoModifiers( [ event modifierFlags ] );
break;
case NSAppKitDefined:
switch ( [ event subtype ] ) {
case NSApplicationActivatedEventType:
QZ_DoActivate (this);
break;
case NSApplicationDeactivatedEventType:
QZ_DoDeactivate (this);
break;
}
[ NSApp sendEvent:event ];
break;
/* case NSApplicationDefined: break; */
/* case NSPeriodic: break; */
/* case NSCursorUpdate: break; */
default:
[ NSApp sendEvent:event ];
}
}
} while (event != nil);
/* check for accumulated mouse events */
if (dx != 0 || dy != 0)
SDL_PrivateMouseMotion (0, 1, dx, dy);
[ pool release ];
} }
/* /*
SDL - Simple DirectMedia Layer SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version. version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details. Library General Public License for more details.
You should have received a copy of the GNU Library General Public You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
*/ */
/* These are the Macintosh key scancode constants -- from Inside Macintosh */ /* These are the Macintosh key scancode constants -- from Inside Macintosh */
...@@ -36,10 +36,10 @@ ...@@ -36,10 +36,10 @@
#define QZ_F11 0x67 #define QZ_F11 0x67
#define QZ_F12 0x6F #define QZ_F12 0x6F
#define QZ_PRINT 0x69 #define QZ_PRINT 0x69
#define QZ_SCROLLOCK 0x6B #define QZ_SCROLLOCK 0x6B
#define QZ_PAUSE 0x71 #define QZ_PAUSE 0x71
#define QZ_POWER 0x7F #define QZ_POWER 0x7F
#define QZ_BACKQUOTE 0x32 #define QZ_BACKQUOTE 0x32
#define QZ_1 0x12 #define QZ_1 0x12
#define QZ_2 0x13 #define QZ_2 0x13
#define QZ_3 0x14 #define QZ_3 0x14
...@@ -52,14 +52,14 @@ ...@@ -52,14 +52,14 @@
#define QZ_0 0x1D #define QZ_0 0x1D
#define QZ_MINUS 0x1B #define QZ_MINUS 0x1B
#define QZ_EQUALS 0x18 #define QZ_EQUALS 0x18
#define QZ_BACKSPACE 0x33 #define QZ_BACKSPACE 0x33
#define QZ_INSERT 0x72 #define QZ_INSERT 0x72
#define QZ_HOME 0x73 #define QZ_HOME 0x73
#define QZ_PAGEUP 0x74 #define QZ_PAGEUP 0x74
#define QZ_NUMLOCK 0x47 #define QZ_NUMLOCK 0x47
#define QZ_KP_EQUALS 0x51 #define QZ_KP_EQUALS 0x51
#define QZ_KP_DIVIDE 0x4B #define QZ_KP_DIVIDE 0x4B
#define QZ_KP_MULTIPLY 0x43 #define QZ_KP_MULTIPLY 0x43
#define QZ_TAB 0x30 #define QZ_TAB 0x30
#define QZ_q 0x0C #define QZ_q 0x0C
#define QZ_w 0x0D #define QZ_w 0x0D
...@@ -71,9 +71,9 @@ ...@@ -71,9 +71,9 @@
#define QZ_i 0x22 #define QZ_i 0x22
#define QZ_o 0x1F #define QZ_o 0x1F
#define QZ_p 0x23 #define QZ_p 0x23
#define QZ_LEFTBRACKET 0x21 #define QZ_LEFTBRACKET 0x21
#define QZ_RIGHTBRACKET 0x1E #define QZ_RIGHTBRACKET 0x1E
#define QZ_BACKSLASH 0x2A #define QZ_BACKSLASH 0x2A
#define QZ_DELETE 0x75 #define QZ_DELETE 0x75
#define QZ_END 0x77 #define QZ_END 0x77
#define QZ_PAGEDOWN 0x79 #define QZ_PAGEDOWN 0x79
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
#define QZ_j 0x26 #define QZ_j 0x26
#define QZ_k 0x28 #define QZ_k 0x28
#define QZ_l 0x25 #define QZ_l 0x25
#define QZ_SEMICOLON 0x29 #define QZ_SEMICOLON 0x29
#define QZ_QUOTE 0x27 #define QZ_QUOTE 0x27
#define QZ_RETURN 0x24 #define QZ_RETURN 0x24
#define QZ_KP4 0x56 #define QZ_KP4 0x56
...@@ -130,11 +130,11 @@ ...@@ -130,11 +130,11 @@
#define QZ_DOWN 0x7D #define QZ_DOWN 0x7D
#define QZ_RIGHT 0x7C #define QZ_RIGHT 0x7C
#define QZ_KP0 0x52 #define QZ_KP0 0x52
#define QZ_KP_PERIOD 0x41 #define QZ_KP_PERIOD 0x41
/* Wierd, these keys are on my iBook under MacOS X */ /* Wierd, these keys are on my iBook under MacOS X */
#define QZ_IBOOK_ENTER 0x34 #define QZ_IBOOK_ENTER 0x34
#define QZ_IBOOK_LEFT 0x3B #define QZ_IBOOK_LEFT 0x3B
#define QZ_IBOOK_RIGHT 0x3C #define QZ_IBOOK_RIGHT 0x3C
#define QZ_IBOOK_DOWN 0x3D #define QZ_IBOOK_DOWN 0x3D
#define QZ_IBOOK_UP 0x3E #define QZ_IBOOK_UP 0x3E
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
slouken@libsdl.org slouken@libsdl.org
*/ */
/* /*
@file SDL_QuartzVideo.h @file SDL_QuartzVideo.h
@author Darrell Walisser @author Darrell Walisser
...@@ -33,16 +33,15 @@ ...@@ -33,16 +33,15 @@
- Keyboard repeat/mouse speed adjust (if needed) - Keyboard repeat/mouse speed adjust (if needed)
- Multiple monitor support (currently only main display) - Multiple monitor support (currently only main display)
- Accelerated blitting support - Accelerated blitting support
- Set the window icon (dock icon when API is available) - Fix white OpenGL window on minimize (fixed)
- Fix white OpenGL window on minimize
- Find out what events should be sent/ignored if window is mimimized - Find out what events should be sent/ignored if window is mimimized
- Find a better way to deal with resolution/depth switch while app is running - Find a way to deal with external resolution/depth switch while app is running
- Resizeable windows - Resizeable windows
- Check accuracy of QZ_SetGamma() - Check accuracy of QZ_SetGamma()
Problems: Problems:
- OGL not working in full screen with software renderer - OGL not working in full screen with software renderer
- SetColors sets palette correctly but clears framebuffer - SetColors sets palette correctly but clears framebuffer
- Crash in CG after several mode switches - 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) - Retained windows don't draw their title bar quite right (OS Bug) (not using retained windows)
- Cursor in 8 bit modes is screwy (might just be Radeon PCI bug) - Cursor in 8 bit modes is screwy (might just be Radeon PCI bug)
- Warping cursor delays mouse events for a fraction of a second, - Warping cursor delays mouse events for a fraction of a second,
...@@ -52,6 +51,7 @@ ...@@ -52,6 +51,7 @@
#include <Cocoa/Cocoa.h> #include <Cocoa/Cocoa.h>
#include <OpenGL/OpenGL.h> #include <OpenGL/OpenGL.h>
#include <Carbon/Carbon.h> #include <Carbon/Carbon.h>
#include <QuickTime/QuickTime.h>
#include "SDL_video.h" #include "SDL_video.h"
#include "SDL_error.h" #include "SDL_error.h"
...@@ -102,10 +102,17 @@ typedef struct SDL_PrivateVideoData { ...@@ -102,10 +102,17 @@ typedef struct SDL_PrivateVideoData {
Uint32 warp_ticks; /* timestamp when the warp occured */ Uint32 warp_ticks; /* timestamp when the warp occured */
NSWindow *window; /* Cocoa window to implement the SDL window */ NSWindow *window; /* Cocoa window to implement the SDL window */
NSQuickDrawView *view; /* the window's view; draw 2D into this view */ NSQuickDrawView *view; /* the window's view; draw 2D into this view */
ImageDescriptionHandle yuv_idh;
MatrixRecordPtr yuv_matrix;
DecompressorComponent yuv_codec;
ImageSequence yuv_seq;
PlanarPixmapInfoYUV420 *yuv_pixmap;
Sint16 yuv_width, yuv_height;
CGrafPtr yuv_port;
} SDL_PrivateVideoData ; } SDL_PrivateVideoData ;
#define _THIS SDL_VideoDevice *this #define _THIS SDL_VideoDevice *this
#define display_id (this->hidden->display) #define display_id (this->hidden->display)
#define mode (this->hidden->mode) #define mode (this->hidden->mode)
#define save_mode (this->hidden->save_mode) #define save_mode (this->hidden->save_mode)
...@@ -121,6 +128,15 @@ typedef struct SDL_PrivateVideoData { ...@@ -121,6 +128,15 @@ typedef struct SDL_PrivateVideoData {
#define video_set (this->hidden->video_set) #define video_set (this->hidden->video_set)
#define warp_ticks (this->hidden->warp_ticks) #define warp_ticks (this->hidden->warp_ticks)
#define warp_flag (this->hidden->warp_flag) #define warp_flag (this->hidden->warp_flag)
#define yuv_idh (this->hidden->yuv_idh)
#define yuv_matrix (this->hidden->yuv_matrix)
#define yuv_codec (this->hidden->yuv_codec)
#define yuv_seq (this->hidden->yuv_seq)
#define yuv_pixmap (this->hidden->yuv_pixmap)
#define yuv_data (this->hidden->yuv_data)
#define yuv_width (this->hidden->yuv_width)
#define yuv_height (this->hidden->yuv_height)
#define yuv_port (this->hidden->yuv_port)
/* Obscuring code: maximum number of windows above ours (inclusive) */ /* Obscuring code: maximum number of windows above ours (inclusive) */
#define kMaxWindows 256 #define kMaxWindows 256
...@@ -144,16 +160,16 @@ typedef struct SDL_PrivateVideoData { ...@@ -144,16 +160,16 @@ typedef struct SDL_PrivateVideoData {
*/ */
typedef CGError CGSError; typedef CGError CGSError;
typedef long CGSWindowCount; typedef long CGSWindowCount;
typedef void * CGSConnectionID; typedef void * CGSConnectionID;
typedef int CGSWindowID; typedef int CGSWindowID;
typedef CGSWindowID* CGSWindowIDList; typedef CGSWindowID* CGSWindowIDList;
typedef CGWindowLevel CGSWindowLevel; typedef CGWindowLevel CGSWindowLevel;
typedef NSRect CGSRect; typedef NSRect CGSRect;
extern CGSConnectionID _CGSDefaultConnection (); extern CGSConnectionID _CGSDefaultConnection ();
extern CGSError CGSGetOnScreenWindowList (CGSConnectionID cid, extern CGSError CGSGetOnScreenWindowList (CGSConnectionID cid,
CGSConnectionID owner, CGSConnectionID owner,
CGSWindowCount listCapacity, CGSWindowCount listCapacity,
CGSWindowIDList list, CGSWindowIDList list,
...@@ -166,9 +182,9 @@ extern CGSError CGSGetScreenRectForWindow (CGSConnectionID cid, ...@@ -166,9 +182,9 @@ extern CGSError CGSGetScreenRectForWindow (CGSConnectionID cid,
extern CGWindowLevel CGSGetWindowLevel (CGSConnectionID cid, extern CGWindowLevel CGSGetWindowLevel (CGSConnectionID cid,
CGSWindowID wid, CGSWindowID wid,
CGSWindowLevel *level); CGSWindowLevel *level);
extern CGSError CGSDisplayHWFill (CGDirectDisplayID id, unsigned int x, unsigned int y, extern CGSError CGSDisplayHWFill (CGDirectDisplayID id, unsigned int x, unsigned int y,
unsigned int w, unsigned int h, unsigned int color); unsigned int w, unsigned int h, unsigned int color);
extern CGSError CGSDisplayCanHWFill (CGDirectDisplayID id); extern CGSError CGSDisplayCanHWFill (CGDirectDisplayID id);
...@@ -182,16 +198,16 @@ static void QZ_DeleteDevice (SDL_VideoDevice *device); ...@@ -182,16 +198,16 @@ static void QZ_DeleteDevice (SDL_VideoDevice *device);
/* Initialization, Query, Setup, and Redrawing functions */ /* Initialization, Query, Setup, and Redrawing functions */
static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format); static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format);
static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format,
Uint32 flags); Uint32 flags);
static void QZ_UnsetVideoMode (_THIS); static void QZ_UnsetVideoMode (_THIS);
static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current,
int width, int height, int bpp, int width, int height, int bpp,
Uint32 flags); Uint32 flags);
static int QZ_ToggleFullScreen (_THIS, int on); static int QZ_ToggleFullScreen (_THIS, int on);
static int QZ_SetColors (_THIS, int first_color, static int QZ_SetColors (_THIS, int first_color,
int num_colors, SDL_Color *colors); int num_colors, SDL_Color *colors);
static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects); static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects);
static void QZ_UpdateRects (_THIS, int num_rects, SDL_Rect *rects); static void QZ_UpdateRects (_THIS, int num_rects, SDL_Rect *rects);
static void QZ_VideoQuit (_THIS); static void QZ_VideoQuit (_THIS);
...@@ -223,8 +239,8 @@ static void QZ_PrivateWarpCursor (_THIS, int x, int y); ...@@ -223,8 +239,8 @@ static void QZ_PrivateWarpCursor (_THIS, int x, int y);
/* Cursor and Mouse functions */ /* Cursor and Mouse functions */
static void QZ_FreeWMCursor (_THIS, WMcursor *cursor); static void QZ_FreeWMCursor (_THIS, WMcursor *cursor);
static WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, static WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask,
int w, int h, int hot_x, int hot_y); int w, int h, int hot_x, int hot_y);
static int QZ_ShowWMCursor (_THIS, WMcursor *cursor); static int QZ_ShowWMCursor (_THIS, WMcursor *cursor);
static void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y); static void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y);
static void QZ_MoveWMCursor (_THIS, int x, int y); static void QZ_MoveWMCursor (_THIS, int x, int y);
...@@ -241,3 +257,7 @@ static int QZ_IconifyWindow (_THIS); ...@@ -241,3 +257,7 @@ static int QZ_IconifyWindow (_THIS);
static SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode); static SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode);
/*static int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info);*/ /*static int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info);*/
/* YUV functions */
static SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height,
Uint32 format, SDL_Surface *display);
...@@ -32,7 +32,6 @@ static char QZ_Error[255]; /* Global error buffer to temporarily store more info ...@@ -32,7 +32,6 @@ static char QZ_Error[255]; /* Global error buffer to temporarily store more info
#include "SDL_QuartzEvents.m" #include "SDL_QuartzEvents.m"
#include "SDL_QuartzWindow.m" #include "SDL_QuartzWindow.m"
/* Bootstrap binding, enables entry point into the driver */ /* Bootstrap binding, enables entry point into the driver */
VideoBootStrap QZ_bootstrap = { VideoBootStrap QZ_bootstrap = {
"Quartz", "Mac OS X CoreGraphics", QZ_Available, QZ_CreateDevice "Quartz", "Mac OS X CoreGraphics", QZ_Available, QZ_CreateDevice
...@@ -100,7 +99,9 @@ static SDL_VideoDevice* QZ_CreateDevice (int device_index) { ...@@ -100,7 +99,9 @@ static SDL_VideoDevice* QZ_CreateDevice (int device_index) {
/*device->GetWMInfo = QZ_GetWMInfo;*/ /*device->GetWMInfo = QZ_GetWMInfo;*/
device->GrabInput = QZ_GrabInput; device->GrabInput = QZ_GrabInput;
device->free = QZ_DeleteDevice; device->CreateYUVOverlay = QZ_CreateYUVOverlay;
device->free = QZ_DeleteDevice;
return device; return device;
} }
...@@ -135,106 +136,106 @@ static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) { ...@@ -135,106 +136,106 @@ static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) {
} }
static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) { static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) {
CFIndex num_modes; CFIndex num_modes;
CFIndex i; CFIndex i;
static SDL_Rect **list = NULL; static SDL_Rect **list = NULL;
int list_size = 0; int list_size = 0;
/* Any windowed mode is acceptable */ /* Any windowed mode is acceptable */
if ( (flags & SDL_FULLSCREEN) == 0 ) if ( (flags & SDL_FULLSCREEN) == 0 )
return (SDL_Rect**)-1; return (SDL_Rect**)-1;
/* Free memory from previous call, if any */ /* Free memory from previous call, if any */
if ( list != NULL ) { if ( list != NULL ) {
int i; int i;
for (i = 0; list[i] != NULL; i++) for (i = 0; list[i] != NULL; i++)
free (list[i]); free (list[i]);
free (list); free (list);
list = NULL; list = NULL;
} }
num_modes = CFArrayGetCount (mode_list); num_modes = CFArrayGetCount (mode_list);
/* Build list of modes with the requested bpp */ /* Build list of modes with the requested bpp */
for (i = 0; i < num_modes; i++) { for (i = 0; i < num_modes; i++) {
CFDictionaryRef onemode; CFDictionaryRef onemode;
CFNumberRef number; CFNumberRef number;
int bpp; int bpp;
onemode = CFArrayGetValueAtIndex (mode_list, i); onemode = CFArrayGetValueAtIndex (mode_list, i);
number = CFDictionaryGetValue (onemode, kCGDisplayBitsPerPixel); number = CFDictionaryGetValue (onemode, kCGDisplayBitsPerPixel);
CFNumberGetValue (number, kCFNumberSInt32Type, &bpp); CFNumberGetValue (number, kCFNumberSInt32Type, &bpp);
if (bpp == format->BitsPerPixel) { if (bpp == format->BitsPerPixel) {
int intvalue; int intvalue;
int hasMode; int hasMode;
int width, height; int width, height;
number = CFDictionaryGetValue (onemode, kCGDisplayWidth); number = CFDictionaryGetValue (onemode, kCGDisplayWidth);
CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue); CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue);
width = (Uint16) intvalue; width = (Uint16) intvalue;
number = CFDictionaryGetValue (onemode, kCGDisplayHeight); number = CFDictionaryGetValue (onemode, kCGDisplayHeight);
CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue); CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue);
height = (Uint16) intvalue; height = (Uint16) intvalue;
/* Check if mode is already in the list */ /* Check if mode is already in the list */
{ {
int i; int i;
hasMode = SDL_FALSE; hasMode = SDL_FALSE;
for (i = 0; i < list_size; i++) { for (i = 0; i < list_size; i++) {
if (list[i]->w == width && list[i]->h == height) { if (list[i]->w == width && list[i]->h == height) {
hasMode = SDL_TRUE; hasMode = SDL_TRUE;
break; break;
}
} }
} }
}
/* Grow the list and add mode to the list */
/* Grow the list and add mode to the list */ if ( ! hasMode ) {
if ( ! hasMode ) {
SDL_Rect *rect;
SDL_Rect *rect;
list_size++;
list_size++;
if (list == NULL)
if (list == NULL) list = (SDL_Rect**) malloc (sizeof(*list) * (list_size+1) );
list = (SDL_Rect**) malloc (sizeof(*list) * (list_size+1) ); else
else list = (SDL_Rect**) realloc (list, sizeof(*list) * (list_size+1));
list = (SDL_Rect**) realloc (list, sizeof(*list) * (list_size+1));
rect = (SDL_Rect*) malloc (sizeof(**list));
rect = (SDL_Rect*) malloc (sizeof(**list));
if (list == NULL || rect == NULL) {
if (list == NULL || rect == NULL) { SDL_OutOfMemory ();
SDL_OutOfMemory (); return NULL;
return NULL; }
rect->w = width;
rect->h = height;
list[list_size-1] = rect;
list[list_size] = NULL;
} }
rect->w = width;
rect->h = height;
list[list_size-1] = rect;
list[list_size] = NULL;
} }
}
} }
/* Sort list largest to smallest (by area) */ /* Sort list largest to smallest (by area) */
{ {
int i, j; int i, j;
for (i = 0; i < list_size; i++) { for (i = 0; i < list_size; i++) {
for (j = 0; j < list_size-1; j++) { for (j = 0; j < list_size-1; j++) {
int area1, area2; int area1, area2;
area1 = list[j]->w * list[j]->h; area1 = list[j]->w * list[j]->h;
area2 = list[j+1]->w * list[j+1]->h; area2 = list[j+1]->w * list[j+1]->h;
if (area1 < area2) { if (area1 < area2) {
SDL_Rect *tmp = list[j]; SDL_Rect *tmp = list[j];
list[j] = list[j+1]; list[j] = list[j+1];
...@@ -299,8 +300,8 @@ static UInt32 QZ_FadeGammaOut (_THIS, SDL_QuartzGammaTable *table) { ...@@ -299,8 +300,8 @@ static UInt32 QZ_FadeGammaOut (_THIS, SDL_QuartzGammaTable *table) {
static UInt32 QZ_FadeGammaIn (_THIS, SDL_QuartzGammaTable *table) { static UInt32 QZ_FadeGammaIn (_THIS, SDL_QuartzGammaTable *table) {
CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE], CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE],
greenTable[QZ_GAMMA_TABLE_SIZE], greenTable[QZ_GAMMA_TABLE_SIZE],
blueTable[QZ_GAMMA_TABLE_SIZE]; blueTable[QZ_GAMMA_TABLE_SIZE];
float percent; float percent;
int j; int j;
...@@ -308,7 +309,7 @@ static UInt32 QZ_FadeGammaIn (_THIS, SDL_QuartzGammaTable *table) { ...@@ -308,7 +309,7 @@ static UInt32 QZ_FadeGammaIn (_THIS, SDL_QuartzGammaTable *table) {
memset (redTable, 0, sizeof(redTable)); memset (redTable, 0, sizeof(redTable));
memset (greenTable, 0, sizeof(greenTable)); memset (greenTable, 0, sizeof(greenTable));
memset (blueTable, 0, sizeof(greenTable)); memset (blueTable, 0, sizeof(greenTable));
for (percent = 0.0; percent <= 1.0; percent += 0.01) { for (percent = 0.0; percent <= 1.0; percent += 0.01) {
for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) { for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) {
...@@ -338,7 +339,7 @@ static void QZ_UnsetVideoMode (_THIS) { ...@@ -338,7 +339,7 @@ static void QZ_UnsetVideoMode (_THIS) {
this->info.blit_fill = 0; this->info.blit_fill = 0;
this->FillHWRect = NULL; this->FillHWRect = NULL;
this->UpdateRects = NULL; this->UpdateRects = NULL;
/* Release fullscreen resources */ /* Release fullscreen resources */
if ( mode_flags & SDL_FULLSCREEN ) { if ( mode_flags & SDL_FULLSCREEN ) {
...@@ -351,7 +352,7 @@ static void QZ_UnsetVideoMode (_THIS) { ...@@ -351,7 +352,7 @@ static void QZ_UnsetVideoMode (_THIS) {
/* Do this first to avoid trash on the display before fade */ /* Do this first to avoid trash on the display before fade */
if ( mode_flags & SDL_OPENGL ) if ( mode_flags & SDL_OPENGL )
QZ_TearDownOpenGL (this); QZ_TearDownOpenGL (this);
if (mode_flags & SDL_OPENGL) if (mode_flags & SDL_OPENGL)
CGLSetFullScreen(NULL); CGLSetFullScreen(NULL);
...@@ -359,12 +360,12 @@ static void QZ_UnsetVideoMode (_THIS) { ...@@ -359,12 +360,12 @@ static void QZ_UnsetVideoMode (_THIS) {
CGDisplaySwitchToMode (display_id, save_mode); CGDisplaySwitchToMode (display_id, save_mode);
CGDisplayRelease (display_id); CGDisplayRelease (display_id);
ShowMenuBar (); ShowMenuBar ();
if (! gamma_error) if (! gamma_error)
QZ_FadeGammaIn (this, &gamma_table); QZ_FadeGammaIn (this, &gamma_table);
} }
/* Release window mode resources */ /* Release window mode resources */
else { else {
if ( (mode_flags & SDL_OPENGL) == 0 ) { if ( (mode_flags & SDL_OPENGL) == 0 ) {
UnlockPortBits ( [ window_view qdPort ] ); UnlockPortBits ( [ window_view qdPort ] );
[ window_view release ]; [ window_view release ];
...@@ -373,7 +374,7 @@ static void QZ_UnsetVideoMode (_THIS) { ...@@ -373,7 +374,7 @@ static void QZ_UnsetVideoMode (_THIS) {
[ qz_window setDelegate:nil ]; [ qz_window setDelegate:nil ];
[ qz_window close ]; [ qz_window close ];
[ qz_window release ]; [ qz_window release ];
qz_window = nil; qz_window = nil;
/* Release the OpenGL context */ /* Release the OpenGL context */
if ( mode_flags & SDL_OPENGL ) if ( mode_flags & SDL_OPENGL )
...@@ -382,15 +383,15 @@ static void QZ_UnsetVideoMode (_THIS) { ...@@ -382,15 +383,15 @@ static void QZ_UnsetVideoMode (_THIS) {
/* Restore gamma settings */ /* Restore gamma settings */
CGDisplayRestoreColorSyncSettings (); CGDisplayRestoreColorSyncSettings ();
/* Set pixels to null (so other code doesn't try to free it) */ /* Set pixels to null (so other code doesn't try to free it) */
if (this->screen != NULL) if (this->screen != NULL)
this->screen->pixels = NULL; this->screen->pixels = NULL;
/* Ensure the cursor will be visible and working when we quit */ /* Ensure the cursor will be visible and working when we quit */
CGDisplayShowCursor (display_id); CGDisplayShowCursor (display_id);
CGAssociateMouseAndMouseCursorPosition (1); CGAssociateMouseAndMouseCursorPosition (1);
/* Signal successful teardown */ /* Signal successful teardown */
video_set = SDL_FALSE; video_set = SDL_FALSE;
} }
...@@ -400,11 +401,11 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt ...@@ -400,11 +401,11 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
int exact_match; int exact_match;
int gamma_error; int gamma_error;
SDL_QuartzGammaTable gamma_table; SDL_QuartzGammaTable gamma_table;
/* See if requested mode exists */ /* See if requested mode exists */
mode = CGDisplayBestModeForParameters (display_id, bpp, width, mode = CGDisplayBestModeForParameters (display_id, bpp, width,
height, &exact_match); height, &exact_match);
/* Require an exact match to the requested mode */ /* Require an exact match to the requested mode */
if ( ! exact_match ) { if ( ! exact_match ) {
sprintf (QZ_Error, "Failed to find display resolution: %dx%dx%d", width, height, bpp); sprintf (QZ_Error, "Failed to find display resolution: %dx%dx%d", width, height, bpp);
...@@ -421,7 +422,7 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt ...@@ -421,7 +422,7 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
goto ERR_NO_CAPTURE; goto ERR_NO_CAPTURE;
} }
/* Do the physical switch */ /* Do the physical switch */
if ( CGDisplayNoErr != CGDisplaySwitchToMode (display_id, mode) ) { if ( CGDisplayNoErr != CGDisplaySwitchToMode (display_id, mode) ) {
SDL_SetError ("Failed switching display resolution"); SDL_SetError ("Failed switching display resolution");
...@@ -434,45 +435,45 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt ...@@ -434,45 +435,45 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
current->flags = 0; current->flags = 0;
current->w = width; current->w = width;
current->h = height; current->h = height;
current->flags |= SDL_FULLSCREEN; current->flags |= SDL_FULLSCREEN;
current->flags |= SDL_HWSURFACE; current->flags |= SDL_HWSURFACE;
this->UpdateRects = QZ_DirectUpdate; this->UpdateRects = QZ_DirectUpdate;
/* Setup some mode-dependant info */ /* Setup some mode-dependant info */
if ( CGSDisplayCanHWFill (display_id) ) { if ( CGSDisplayCanHWFill (display_id) ) {
this->info.blit_fill = 1; this->info.blit_fill = 1;
this->FillHWRect = QZ_FillHWRect; this->FillHWRect = QZ_FillHWRect;
} }
if ( CGDisplayCanSetPalette (display_id) ) if ( CGDisplayCanSetPalette (display_id) )
current->flags |= SDL_HWPALETTE; current->flags |= SDL_HWPALETTE;
/* Setup OpenGL for a fullscreen context */ /* Setup OpenGL for a fullscreen context */
if (flags & SDL_OPENGL) { if (flags & SDL_OPENGL) {
CGLError err; CGLError err;
CGLContextObj ctx; CGLContextObj ctx;
if ( ! QZ_SetupOpenGL (this, bpp, flags) ) { if ( ! QZ_SetupOpenGL (this, bpp, flags) ) {
goto ERR_NO_GL; goto ERR_NO_GL;
} }
ctx = [ gl_context cglContext ]; ctx = [ gl_context cglContext ];
err = CGLSetFullScreen (ctx); err = CGLSetFullScreen (ctx);
if (err) { if (err) {
sprintf (QZ_Error, "Error setting OpenGL fullscreen: %s", CGLErrorString(err)); sprintf (QZ_Error, "Error setting OpenGL fullscreen: %s", CGLErrorString(err));
SDL_SetError (QZ_Error); SDL_SetError (QZ_Error);
goto ERR_NO_GL; goto ERR_NO_GL;
} }
[ gl_context makeCurrentContext]; [ gl_context makeCurrentContext];
glClear (GL_COLOR_BUFFER_BIT); glClear (GL_COLOR_BUFFER_BIT);
[ gl_context flushBuffer ]; [ gl_context flushBuffer ];
current->flags |= SDL_OPENGL; current->flags |= SDL_OPENGL;
} }
...@@ -482,23 +483,23 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt ...@@ -482,23 +483,23 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
/* Fade the display to original gamma */ /* Fade the display to original gamma */
if (! gamma_error ) if (! gamma_error )
QZ_FadeGammaIn (this, &gamma_table); QZ_FadeGammaIn (this, &gamma_table);
/* Save the flags to ensure correct tear-down */ /* Save the flags to ensure correct tear-down */
mode_flags = current->flags; mode_flags = current->flags;
return current; return current;
/* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */ /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
ERR_NO_GL: CGDisplaySwitchToMode (display_id, save_mode); ERR_NO_GL: CGDisplaySwitchToMode (display_id, save_mode);
ERR_NO_SWITCH: CGDisplayRelease (display_id); ERR_NO_SWITCH: CGDisplayRelease (display_id);
ERR_NO_CAPTURE: if (!gamma_error) { QZ_FadeGammaIn (this, &gamma_table); } ERR_NO_CAPTURE: if (!gamma_error) { QZ_FadeGammaIn (this, &gamma_table); }
ERR_NO_MATCH: return NULL; ERR_NO_MATCH: return NULL;
} }
static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
int height, int bpp, Uint32 flags) { int height, int bpp, Uint32 flags) {
unsigned int style; unsigned int style;
NSRect rect; NSRect rect;
rect = NSMakeRect (0, 0, width, height); rect = NSMakeRect (0, 0, width, height);
#if 1 // FIXME - the resize button doesn't show? Also need resize events... #if 1 // FIXME - the resize button doesn't show? Also need resize events...
...@@ -515,17 +516,17 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, ...@@ -515,17 +516,17 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
} }
/* Manually create a window, avoids having a nib file resource */ /* Manually create a window, avoids having a nib file resource */
qz_window = [ [ SDL_QuartzWindow alloc ] initWithContentRect:rect qz_window = [ [ SDL_QuartzWindow alloc ] initWithContentRect:rect
styleMask:style backing:NSBackingStoreBuffered defer:NO ]; styleMask:style backing:NSBackingStoreBuffered defer:NO ];
if (qz_window == nil) { if (qz_window == nil) {
SDL_SetError ("Could not create the Cocoa window"); SDL_SetError ("Could not create the Cocoa window");
return NULL; return NULL;
} }
current->flags = 0; current->flags = 0;
current->w = width; current->w = width;
current->h = height; current->h = height;
[ qz_window setReleasedWhenClosed:YES ]; [ qz_window setReleasedWhenClosed:YES ];
QZ_SetCaption(this, this->wm_title, this->wm_icon); QZ_SetCaption(this, this->wm_title, this->wm_icon);
[ qz_window setAcceptsMouseMovedEvents:YES ]; [ qz_window setAcceptsMouseMovedEvents:YES ];
...@@ -533,14 +534,14 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, ...@@ -533,14 +534,14 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
[ qz_window center ]; [ qz_window center ];
[ qz_window setDelegate: [ qz_window setDelegate:
[ [ [ SDL_QuartzWindowDelegate alloc ] init ] autorelease ] ]; [ [ [ SDL_QuartzWindowDelegate alloc ] init ] autorelease ] ];
/* For OpenGL, we set the content view to a NSOpenGLView */ /* For OpenGL, we set the content view to a NSOpenGLView */
if ( flags & SDL_OPENGL ) { if ( flags & SDL_OPENGL ) {
if ( ! QZ_SetupOpenGL (this, bpp, flags) ) { if ( ! QZ_SetupOpenGL (this, bpp, flags) ) {
return NULL; return NULL;
} }
[ gl_context setView: [ qz_window contentView ] ]; [ gl_context setView: [ qz_window contentView ] ];
[ gl_context makeCurrentContext]; [ gl_context makeCurrentContext];
[ qz_window makeKeyAndOrderFront:nil ]; [ qz_window makeKeyAndOrderFront:nil ];
...@@ -548,45 +549,45 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, ...@@ -548,45 +549,45 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
} }
/* For 2D, we set the content view to a NSQuickDrawView */ /* For 2D, we set the content view to a NSQuickDrawView */
else { else {
window_view = [ [ SDL_QuartzWindowView alloc ] init ]; window_view = [ [ SDL_QuartzWindowView alloc ] init ];
[ qz_window setContentView:window_view ]; [ qz_window setContentView:window_view ];
[ qz_window makeKeyAndOrderFront:nil ]; [ qz_window makeKeyAndOrderFront:nil ];
LockPortBits ( [ window_view qdPort ] ); LockPortBits ( [ window_view qdPort ] );
current->pixels = GetPixBaseAddr ( GetPortPixMap ( [ window_view qdPort ] ) ); current->pixels = GetPixBaseAddr ( GetPortPixMap ( [ window_view qdPort ] ) );
current->pitch = GetPixRowBytes ( GetPortPixMap ( [ window_view qdPort ] ) ); current->pitch = GetPixRowBytes ( GetPortPixMap ( [ window_view qdPort ] ) );
current->flags |= SDL_SWSURFACE; current->flags |= SDL_SWSURFACE;
current->flags |= SDL_PREALLOC; current->flags |= SDL_PREALLOC;
if ( flags & SDL_NOFRAME ) if ( flags & SDL_NOFRAME )
current->flags |= SDL_NOFRAME; current->flags |= SDL_NOFRAME;
if ( flags & SDL_RESIZABLE ) if ( flags & SDL_RESIZABLE )
current->flags |= SDL_RESIZABLE; current->flags |= SDL_RESIZABLE;
/* Offset 22 pixels down to fill the full content region */ /* Offset 22 pixels down to fill the full content region */
if ( ! (current->flags & SDL_NOFRAME) ) { if ( ! (current->flags & SDL_NOFRAME) ) {
current->pixels += 22 * current->pitch; current->pixels += 22 * current->pitch;
} }
this->UpdateRects = QZ_UpdateRects; this->UpdateRects = QZ_UpdateRects;
} }
/* Save flags to ensure correct teardown */ /* Save flags to ensure correct teardown */
mode_flags = current->flags; mode_flags = current->flags;
return current; return current;
} }
static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width,
int height, int bpp, Uint32 flags) { int height, int bpp, Uint32 flags) {
if (video_set == SDL_TRUE) if (video_set == SDL_TRUE)
QZ_UnsetVideoMode (this); QZ_UnsetVideoMode (this);
current->flags = 0; current->flags = 0;
/* Setup full screen video */ /* Setup full screen video */
if ( flags & SDL_FULLSCREEN ) { if ( flags & SDL_FULLSCREEN ) {
current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags ); current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags );
...@@ -601,17 +602,17 @@ static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, ...@@ -601,17 +602,17 @@ static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width,
if (current == NULL) if (current == NULL)
return NULL; return NULL;
} }
/* Setup the new pixel format */ /* Setup the new pixel format */
{ {
int amask = 0, int amask = 0,
rmask = 0, rmask = 0,
gmask = 0, gmask = 0,
bmask = 0; bmask = 0;
switch (bpp) { switch (bpp) {
case 16: /* (1)-5-5-5 RGB */ case 16: /* (1)-5-5-5 RGB */
amask = 0; amask = 0;
rmask = 0x7C00; rmask = 0x7C00;
gmask = 0x03E0; gmask = 0x03E0;
bmask = 0x001F; bmask = 0x001F;
...@@ -626,212 +627,212 @@ static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, ...@@ -626,212 +627,212 @@ static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width,
bmask = 0x000000FF; bmask = 0x000000FF;
break; break;
} }
if ( ! SDL_ReallocFormat (current, bpp, if ( ! SDL_ReallocFormat (current, bpp,
rmask, gmask, bmask, amask ) ) { rmask, gmask, bmask, amask ) ) {
SDL_SetError ("Couldn't reallocate pixel format"); SDL_SetError ("Couldn't reallocate pixel format");
return NULL; return NULL;
} }
} }
/* Signal successful completion (used internally) */ /* Signal successful completion (used internally) */
video_set = SDL_TRUE; video_set = SDL_TRUE;
return current; return current;
} }
static int QZ_ToggleFullScreen (_THIS, int on) { static int QZ_ToggleFullScreen (_THIS, int on) {
return -1; return -1;
} }
static int QZ_SetColors (_THIS, int first_color, int num_colors, static int QZ_SetColors (_THIS, int first_color, int num_colors,
SDL_Color *colors) { SDL_Color *colors) {
CGTableCount index; CGTableCount index;
CGDeviceColor color; CGDeviceColor color;
for (index = first_color; index < first_color+num_colors; index++) { for (index = first_color; index < first_color+num_colors; index++) {
/* Clamp colors between 0.0 and 1.0 */ /* Clamp colors between 0.0 and 1.0 */
color.red = colors->r / 255.0; color.red = colors->r / 255.0;
color.blue = colors->b / 255.0; color.blue = colors->b / 255.0;
color.green = colors->g / 255.0; color.green = colors->g / 255.0;
colors++; colors++;
CGPaletteSetColorAtIndex (palette, color, index); CGPaletteSetColorAtIndex (palette, color, index);
} }
if ( CGDisplayNoErr != CGDisplaySetPalette (display_id, palette) ) if ( CGDisplayNoErr != CGDisplaySetPalette (display_id, palette) )
return 0; return 0;
return 1; return 1;
} }
static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) { static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) {
#pragma unused(this,num_rects,rects) #pragma unused(this,num_rects,rects)
} }
/** /**
* The obscured code is based on work by Matt Slot fprefect@ambrosiasw.com, * The obscured code is based on work by Matt Slot fprefect@ambrosiasw.com,
* who supplied sample code for Carbon. * who supplied sample code for Carbon.
**/ **/
static int QZ_IsWindowObscured (NSWindow *window) { static int QZ_IsWindowObscured (NSWindow *window) {
//#define TEST_OBSCURED 1 //#define TEST_OBSCURED 1
#if TEST_OBSCURED #if TEST_OBSCURED
/* In order to determine if a direct copy to the screen is possible, /* In order to determine if a direct copy to the screen is possible,
we must figure out if there are any windows covering ours (including shadows). we must figure out if there are any windows covering ours (including shadows).
This can be done by querying the window server about the on screen This can be done by querying the window server about the on screen
windows for their screen rectangle and window level. windows for their screen rectangle and window level.
The procedure used below is puts accuracy before speed; however, it aims to call The procedure used below is puts accuracy before speed; however, it aims to call
the window server the fewest number of times possible to keep things reasonable. the window server the fewest number of times possible to keep things reasonable.
In my testing on a 300mhz G3, this routine typically takes < 2 ms. -DW In my testing on a 300mhz G3, this routine typically takes < 2 ms. -DW
Notes: Notes:
-Calls into the Window Server involve IPC which is slow. -Calls into the Window Server involve IPC which is slow.
-Getting a rectangle seems slower than getting the window level -Getting a rectangle seems slower than getting the window level
-The window list we get back is in sorted order, top to bottom -The window list we get back is in sorted order, top to bottom
-On average, I suspect, most windows above ours are dock icon windows (hence optimization) -On average, I suspect, most windows above ours are dock icon windows (hence optimization)
-Some windows above ours are always there, and cannot move or obscure us (menu bar) -Some windows above ours are always there, and cannot move or obscure us (menu bar)
Bugs:
-no way (yet) to deactivate direct drawing when a window is dragged,
or suddenly obscured, so drawing continues and can produce garbage
We need some kind of locking mechanism on window movement to prevent this
-deactivated normal windows use activated normal
window shadows (slight inaccuraccy)
*/
/* Cache the connection to the window server */ Bugs:
static CGSConnectionID cgsConnection = (CGSConnectionID) -1; -no way (yet) to deactivate direct drawing when a window is dragged,
or suddenly obscured, so drawing continues and can produce garbage
We need some kind of locking mechanism on window movement to prevent this
-deactivated normal windows use activated normal
window shadows (slight inaccuraccy)
*/
/* Cache the connection to the window server */
static CGSConnectionID cgsConnection = (CGSConnectionID) -1;
/* Cache the dock icon windows */ /* Cache the dock icon windows */
static CGSWindowID dockIcons[kMaxWindows]; static CGSWindowID dockIcons[kMaxWindows];
static int numCachedDockIcons = 0; static int numCachedDockIcons = 0;
CGSWindowID windows[kMaxWindows]; CGSWindowID windows[kMaxWindows];
CGSWindowCount i, count; CGSWindowCount i, count;
CGSWindowLevel winLevel; CGSWindowLevel winLevel;
CGSRect winRect; CGSRect winRect;
CGSRect contentRect; CGSRect contentRect;
int windowNumber; int windowNumber;
//int isMainWindow; //int isMainWindow;
int firstDockIcon; int firstDockIcon;
int dockIconCacheMiss; int dockIconCacheMiss;
int windowContentOffset; int windowContentOffset;
int obscured = SDL_TRUE; int obscured = SDL_TRUE;
if ( [ window isVisible ] ) { if ( [ window isVisible ] ) {
/* walk the window list looking for windows over top of /* walk the window list looking for windows over top of
(or casting a shadow on) ours */ (or casting a shadow on) ours */
/* Get a connection to the window server */ /* Get a connection to the window server */
/* Should probably be moved out into SetVideoMode() or InitVideo() */ /* Should probably be moved out into SetVideoMode() or InitVideo() */
if (cgsConnection == (CGSConnectionID) -1) { if (cgsConnection == (CGSConnectionID) -1) {
cgsConnection = (CGSConnectionID) 0; cgsConnection = (CGSConnectionID) 0;
cgsConnection = _CGSDefaultConnection (); cgsConnection = _CGSDefaultConnection ();
} }
if (cgsConnection) { if (cgsConnection) {
if ( ! [ window styleMask ] & NSBorderlessWindowMask ) if ( ! [ window styleMask ] & NSBorderlessWindowMask )
windowContentOffset = 22; windowContentOffset = 22;
else else
windowContentOffset = 0; windowContentOffset = 0;
windowNumber = [ window windowNumber ]; windowNumber = [ window windowNumber ];
//isMainWindow = [ window isMainWindow ]; //isMainWindow = [ window isMainWindow ];
/* The window list is sorted according to order on the screen */ /* The window list is sorted according to order on the screen */
count = 0; count = 0;
CGSGetOnScreenWindowList (cgsConnection, 0, kMaxWindows, windows, &count); CGSGetOnScreenWindowList (cgsConnection, 0, kMaxWindows, windows, &count);
CGSGetScreenRectForWindow (cgsConnection, windowNumber, &contentRect); CGSGetScreenRectForWindow (cgsConnection, windowNumber, &contentRect);
/* adjust rect for window title bar (if present) */ /* adjust rect for window title bar (if present) */
contentRect.origin.y += windowContentOffset; contentRect.origin.y += windowContentOffset;
contentRect.size.height -= windowContentOffset; contentRect.size.height -= windowContentOffset;
firstDockIcon = -1; firstDockIcon = -1;
dockIconCacheMiss = SDL_FALSE; dockIconCacheMiss = SDL_FALSE;
/* The first window is always an empty window with level kCGSWindowLevelTop /* The first window is always an empty window with level kCGSWindowLevelTop
so start at index 1 */ so start at index 1 */
for (i = 1; i < count; i++) { for (i = 1; i < count; i++) {
/* If we reach our window in the list, it cannot be obscured */ /* If we reach our window in the list, it cannot be obscured */
if (windows[i] == windowNumber) { if (windows[i] == windowNumber) {
obscured = SDL_FALSE; obscured = SDL_FALSE;
break; break;
} }
else { else {
float shadowSide; float shadowSide;
float shadowTop; float shadowTop;
float shadowBottom; float shadowBottom;
CGSGetWindowLevel (cgsConnection, windows[i], &winLevel); CGSGetWindowLevel (cgsConnection, windows[i], &winLevel);
if (winLevel == kCGSWindowLevelDockIcon) { if (winLevel == kCGSWindowLevelDockIcon) {
int j; int j;
if (firstDockIcon < 0) { if (firstDockIcon < 0) {
firstDockIcon = i; firstDockIcon = i;
if (numCachedDockIcons > 0) { if (numCachedDockIcons > 0) {
for (j = 0; j < numCachedDockIcons; j++) { for (j = 0; j < numCachedDockIcons; j++) {
if (windows[i] == dockIcons[j]) if (windows[i] == dockIcons[j])
i++; i++;
else else
break; break;
} }
if (j != 0) { if (j != 0) {
i--; i--;
if (j < numCachedDockIcons) { if (j < numCachedDockIcons) {
dockIconCacheMiss = SDL_TRUE; dockIconCacheMiss = SDL_TRUE;
} }
} }
} }
} }
continue; continue;
} }
else if (winLevel == kCGSWindowLevelMenuIgnore else if (winLevel == kCGSWindowLevelMenuIgnore
/* winLevel == kCGSWindowLevelTop */) { /* winLevel == kCGSWindowLevelTop */) {
continue; /* cannot obscure window */ continue; /* cannot obscure window */
} }
else if (winLevel == kCGSWindowLevelDockMenu || else if (winLevel == kCGSWindowLevelDockMenu ||
winLevel == kCGSWindowLevelMenu) { winLevel == kCGSWindowLevelMenu) {
shadowSide = 18; shadowSide = 18;
shadowTop = 4; shadowTop = 4;
shadowBottom = 22; shadowBottom = 22;
} }
else if (winLevel == kCGSWindowLevelUtility) { else if (winLevel == kCGSWindowLevelUtility) {
shadowSide = 8; shadowSide = 8;
shadowTop = 4; shadowTop = 4;
shadowBottom = 12; shadowBottom = 12;
} }
else if (winLevel == kCGSWindowLevelNormal) { else if (winLevel == kCGSWindowLevelNormal) {
/* These numbers are for foreground windows, /* These numbers are for foreground windows,
they are too big (but will work) for background windows */ they are too big (but will work) for background windows */
shadowSide = 20; shadowSide = 20;
...@@ -839,52 +840,52 @@ static int QZ_IsWindowObscured (NSWindow *window) { ...@@ -839,52 +840,52 @@ static int QZ_IsWindowObscured (NSWindow *window) {
shadowBottom = 24; shadowBottom = 24;
} }
else if (winLevel == kCGSWindowLevelDock) { else if (winLevel == kCGSWindowLevelDock) {
/* Create dock icon cache */ /* Create dock icon cache */
if (numCachedDockIcons != (i-firstDockIcon) || if (numCachedDockIcons != (i-firstDockIcon) ||
dockIconCacheMiss) { dockIconCacheMiss) {
numCachedDockIcons = i - firstDockIcon; numCachedDockIcons = i - firstDockIcon;
memcpy (dockIcons, &(windows[firstDockIcon]), memcpy (dockIcons, &(windows[firstDockIcon]),
numCachedDockIcons * sizeof(*windows)); numCachedDockIcons * sizeof(*windows));
} }
/* no shadow */ /* no shadow */
shadowSide = 0; shadowSide = 0;
shadowTop = 0; shadowTop = 0;
shadowBottom = 0; shadowBottom = 0;
} }
else { else {
/* kCGSWindowLevelDockLabel, /* kCGSWindowLevelDockLabel,
kCGSWindowLevelDock, kCGSWindowLevelDock,
kOther??? */ kOther??? */
/* no shadow */ /* no shadow */
shadowSide = 0; shadowSide = 0;
shadowTop = 0; shadowTop = 0;
shadowBottom = 0; shadowBottom = 0;
} }
CGSGetScreenRectForWindow (cgsConnection, windows[i], &winRect); CGSGetScreenRectForWindow (cgsConnection, windows[i], &winRect);
winRect.origin.x -= shadowSide; winRect.origin.x -= shadowSide;
winRect.origin.y -= shadowTop; winRect.origin.y -= shadowTop;
winRect.size.width += shadowSide; winRect.size.width += shadowSide;
winRect.size.height += shadowBottom; winRect.size.height += shadowBottom;
if (NSIntersectsRect (contentRect, winRect)) { if (NSIntersectsRect (contentRect, winRect)) {
obscured = SDL_TRUE; obscured = SDL_TRUE;
break; break;
} }
} /* window was not our window */ } /* window was not our window */
} /* iterate over windows */ } /* iterate over windows */
} /* get cgsConnection */ } /* get cgsConnection */
} /* window is visible */ } /* window is visible */
return obscured; return obscured;
...@@ -893,86 +894,86 @@ static int QZ_IsWindowObscured (NSWindow *window) { ...@@ -893,86 +894,86 @@ static int QZ_IsWindowObscured (NSWindow *window) {
#endif #endif
} }
static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) { static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) {
if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) { if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) {
QZ_GL_SwapBuffers (this); QZ_GL_SwapBuffers (this);
} }
else if ( [ qz_window isMiniaturized ] && else if ( [ qz_window isMiniaturized ] &&
! (SDL_VideoSurface->flags & SDL_OPENGL)) { ! (SDL_VideoSurface->flags & SDL_OPENGL)) {
/** /**
* Set port alpha opaque so deminiaturize looks right * Set port alpha opaque so deminiaturize looks right
* This isn't so nice, but there is no * This isn't so nice, but there is no
* initial deminatureize notification (before demini starts) * initial deminatureize notification (before demini starts)
**/ **/
QZ_SetPortAlphaOpaque ([ [ qz_window contentView ] qdPort], QZ_SetPortAlphaOpaque ([ [ qz_window contentView ] qdPort],
[ qz_window styleMask ] & NSBorderlessWindowMask); [ qz_window styleMask ] & NSBorderlessWindowMask);
} }
else if ( ! QZ_IsWindowObscured (qz_window) ) { else if ( ! QZ_IsWindowObscured (qz_window) ) {
/* Use direct copy to flush contents to the display */ /* Use direct copy to flush contents to the display */
CGrafPtr savePort; CGrafPtr savePort;
CGrafPtr dstPort, srcPort; CGrafPtr dstPort, srcPort;
const BitMap *dstBits, *srcBits; const BitMap *dstBits, *srcBits;
Rect dstRect, srcRect; Rect dstRect, srcRect;
Point offset; Point offset;
int i; int i;
GetPort (&savePort); GetPort (&savePort);
dstPort = CreateNewPortForCGDisplayID ((UInt32)display_id); dstPort = CreateNewPortForCGDisplayID ((UInt32)display_id);
srcPort = [ window_view qdPort ]; srcPort = [ window_view qdPort ];
offset.h = 0; offset.h = 0;
offset.v = 0; offset.v = 0;
SetPort (srcPort); SetPort (srcPort);
LocalToGlobal (&offset); LocalToGlobal (&offset);
SetPort (dstPort); SetPort (dstPort);
LockPortBits (dstPort); LockPortBits (dstPort);
LockPortBits (srcPort); LockPortBits (srcPort);
dstBits = GetPortBitMapForCopyBits (dstPort); dstBits = GetPortBitMapForCopyBits (dstPort);
srcBits = GetPortBitMapForCopyBits (srcPort); srcBits = GetPortBitMapForCopyBits (srcPort);
for (i = 0; i < numRects; i++) { for (i = 0; i < numRects; i++) {
SetRect (&srcRect, rects[i].x, rects[i].y, SetRect (&srcRect, rects[i].x, rects[i].y,
rects[i].x + rects[i].w, rects[i].x + rects[i].w,
rects[i].y + rects[i].h); rects[i].y + rects[i].h);
SetRect (&dstRect, SetRect (&dstRect,
rects[i].x + offset.h, rects[i].x + offset.h,
rects[i].y + offset.v, rects[i].y + offset.v,
rects[i].x + rects[i].w + offset.h, rects[i].x + rects[i].w + offset.h,
rects[i].y + rects[i].h + offset.v); rects[i].y + rects[i].h + offset.v);
CopyBits (srcBits, dstBits, CopyBits (srcBits, dstBits,
&srcRect, &dstRect, srcCopy, NULL); &srcRect, &dstRect, srcCopy, NULL);
} }
SetPort (savePort); SetPort (savePort);
} }
else { else {
/* Use QDFlushPortBuffer() to flush content to display */ /* Use QDFlushPortBuffer() to flush content to display */
int i; int i;
RgnHandle dirty = NewRgn (); RgnHandle dirty = NewRgn ();
RgnHandle temp = NewRgn (); RgnHandle temp = NewRgn ();
SetEmptyRgn (dirty); SetEmptyRgn (dirty);
/* Build the region of dirty rectangles */ /* Build the region of dirty rectangles */
for (i = 0; i < numRects; i++) { for (i = 0; i < numRects; i++) {
MacSetRectRgn (temp, rects[i].x, rects[i].y, MacSetRectRgn (temp, rects[i].x, rects[i].y,
rects[i].x + rects[i].w, rects[i].y + rects[i].h); rects[i].x + rects[i].w, rects[i].y + rects[i].h);
MacUnionRgn (dirty, temp, dirty); MacUnionRgn (dirty, temp, dirty);
} }
/* Flush the dirty region */ /* Flush the dirty region */
QDFlushPortBuffer ( [ window_view qdPort ], dirty ); QDFlushPortBuffer ( [ window_view qdPort ], dirty );
DisposeRgn (dirty); DisposeRgn (dirty);
...@@ -993,7 +994,7 @@ static int QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color ...@@ -993,7 +994,7 @@ static int QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color
return 0; return 0;
} }
static int QZ_LockHWSurface(_THIS, SDL_Surface *surface) { static int QZ_LockHWSurface(_THIS, SDL_Surface *surface) {
return 1; return 1;
} }
...@@ -1006,10 +1007,10 @@ static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface) { ...@@ -1006,10 +1007,10 @@ static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface) {
} }
/* /*
int QZ_FlipHWSurface (_THIS, SDL_Surface *surface) { int QZ_FlipHWSurface (_THIS, SDL_Surface *surface) {
return 0; return 0;
} }
*/ */
/* Gamma functions */ /* Gamma functions */
static int QZ_SetGamma (_THIS, float red, float green, float blue) { static int QZ_SetGamma (_THIS, float red, float green, float blue) {
...@@ -1030,14 +1031,14 @@ static int QZ_SetGamma (_THIS, float red, float green, float blue) { ...@@ -1030,14 +1031,14 @@ static int QZ_SetGamma (_THIS, float red, float green, float blue) {
blue = FLT_MAX; blue = FLT_MAX;
else else
blue = 1.0 / blue; blue = 1.0 / blue;
if ( CGDisplayNoErr == CGSetDisplayTransferByFormula if ( CGDisplayNoErr == CGSetDisplayTransferByFormula
(display_id, min, max, red, min, max, green, min, max, blue) ) { (display_id, min, max, red, min, max, green, min, max, blue) ) {
return 0; return 0;
} }
else { else {
return -1; return -1;
} }
} }
...@@ -1046,66 +1047,66 @@ static int QZ_GetGamma (_THIS, float *red, float *green, float *blue) { ...@@ -1046,66 +1047,66 @@ static int QZ_GetGamma (_THIS, float *red, float *green, float *blue) {
CGGammaValue dummy; CGGammaValue dummy;
if ( CGDisplayNoErr == CGGetDisplayTransferByFormula if ( CGDisplayNoErr == CGGetDisplayTransferByFormula
(display_id, &dummy, &dummy, red, (display_id, &dummy, &dummy, red,
&dummy, &dummy, green, &dummy, &dummy, blue) ) &dummy, &dummy, green, &dummy, &dummy, blue) )
return 0; return 0;
else else
return -1; return -1;
} }
static int QZ_SetGammaRamp (_THIS, Uint16 *ramp) { static int QZ_SetGammaRamp (_THIS, Uint16 *ramp) {
const CGTableCount tableSize = 255; const CGTableCount tableSize = 255;
CGGammaValue redTable[tableSize]; CGGammaValue redTable[tableSize];
CGGammaValue greenTable[tableSize]; CGGammaValue greenTable[tableSize];
CGGammaValue blueTable[tableSize]; CGGammaValue blueTable[tableSize];
int i; int i;
/* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */ /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
redTable[i % 256] = ramp[i] / 65535.0; redTable[i % 256] = ramp[i] / 65535.0;
for (i=256; i < 512; i++) for (i=256; i < 512; i++)
greenTable[i % 256] = ramp[i] / 65535.0; greenTable[i % 256] = ramp[i] / 65535.0;
for (i=512; i < 768; i++) for (i=512; i < 768; i++)
blueTable[i % 256] = ramp[i] / 65535.0; blueTable[i % 256] = ramp[i] / 65535.0;
if ( CGDisplayNoErr == CGSetDisplayTransferByTable if ( CGDisplayNoErr == CGSetDisplayTransferByTable
(display_id, tableSize, redTable, greenTable, blueTable) ) (display_id, tableSize, redTable, greenTable, blueTable) )
return 0; return 0;
else else
return -1; return -1;
} }
static int QZ_GetGammaRamp (_THIS, Uint16 *ramp) { static int QZ_GetGammaRamp (_THIS, Uint16 *ramp) {
const CGTableCount tableSize = 255; const CGTableCount tableSize = 255;
CGGammaValue redTable[tableSize]; CGGammaValue redTable[tableSize];
CGGammaValue greenTable[tableSize]; CGGammaValue greenTable[tableSize];
CGGammaValue blueTable[tableSize]; CGGammaValue blueTable[tableSize];
CGTableCount actual; CGTableCount actual;
int i; int i;
if ( CGDisplayNoErr != CGGetDisplayTransferByTable if ( CGDisplayNoErr != CGGetDisplayTransferByTable
(display_id, tableSize, redTable, greenTable, blueTable, &actual) || (display_id, tableSize, redTable, greenTable, blueTable, &actual) ||
actual != tableSize) actual != tableSize)
return -1; return -1;
/* Pack tables into one array, with values from 0 to 65535 */ /* Pack tables into one array, with values from 0 to 65535 */
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
ramp[i] = redTable[i % 256] * 65535.0; ramp[i] = redTable[i % 256] * 65535.0;
for (i=256; i < 512; i++) for (i=256; i < 512; i++)
ramp[i] = greenTable[i % 256] * 65535.0; ramp[i] = greenTable[i % 256] * 65535.0;
for (i=512; i < 768; i++) for (i=512; i < 768; i++)
ramp[i] = blueTable[i % 256] * 65535.0; ramp[i] = blueTable[i % 256] * 65535.0;
return 0; return 0;
} }
/* OpenGL helper functions (used internally) */ /* OpenGL helper functions (used internally) */
...@@ -1118,53 +1119,53 @@ static int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) { ...@@ -1118,53 +1119,53 @@ static int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
int colorBits = bpp; int colorBits = bpp;
if ( flags & SDL_FULLSCREEN ) { if ( flags & SDL_FULLSCREEN ) {
attr[i++] = NSOpenGLPFAFullScreen; attr[i++] = NSOpenGLPFAFullScreen;
} }
/* In windowed mode, the OpenGL pixel depth must match device pixel depth */ /* In windowed mode, the OpenGL pixel depth must match device pixel depth */
else if ( colorBits != device_bpp ) { else if ( colorBits != device_bpp ) {
colorBits = device_bpp; colorBits = device_bpp;
} }
attr[i++] = NSOpenGLPFAColorSize; attr[i++] = NSOpenGLPFAColorSize;
attr[i++] = colorBits; attr[i++] = colorBits;
attr[i++] = NSOpenGLPFADepthSize; attr[i++] = NSOpenGLPFADepthSize;
attr[i++] = this->gl_config.depth_size; attr[i++] = this->gl_config.depth_size;
if ( this->gl_config.double_buffer ) { if ( this->gl_config.double_buffer ) {
attr[i++] = NSOpenGLPFADoubleBuffer; attr[i++] = NSOpenGLPFADoubleBuffer;
} }
if ( this->gl_config.stencil_size != 0 ) { if ( this->gl_config.stencil_size != 0 ) {
attr[i++] = NSOpenGLPFAStencilSize; attr[i++] = NSOpenGLPFAStencilSize;
attr[i++] = this->gl_config.stencil_size; attr[i++] = this->gl_config.stencil_size;
} }
attr[i++] = NSOpenGLPFAScreenMask; attr[i++] = NSOpenGLPFAScreenMask;
attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id); attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
attr[i] = 0; attr[i] = 0;
fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ]; fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
if (fmt == nil) { if (fmt == nil) {
SDL_SetError ("Failed creating OpenGL pixel format"); SDL_SetError ("Failed creating OpenGL pixel format");
return 0; return 0;
} }
gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
shareContext:nil]; shareContext:nil];
if (gl_context == nil) { if (gl_context == nil) {
SDL_SetError ("Failed creating OpenGL context"); SDL_SetError ("Failed creating OpenGL context");
return 0; return 0;
} }
/* Convince SDL that the GL "driver" is loaded */ /* Convince SDL that the GL "driver" is loaded */
this->gl_config.driver_loaded = 1; this->gl_config.driver_loaded = 1;
[ fmt release ]; [ fmt release ];
return 1; return 1;
} }
...@@ -1187,23 +1188,23 @@ static void* QZ_GL_GetProcAddress (_THIS, const char *proc) { ...@@ -1187,23 +1188,23 @@ static void* QZ_GL_GetProcAddress (_THIS, const char *proc) {
/* We may want to cache the bundleRef at some point */ /* We may want to cache the bundleRef at some point */
CFBundleRef bundle; CFBundleRef bundle;
CFURLRef bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, CFURLRef bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault,
CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true); CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true);
CFStringRef functionName = CFStringCreateWithCString CFStringRef functionName = CFStringCreateWithCString
(kCFAllocatorDefault, proc, kCFStringEncodingASCII); (kCFAllocatorDefault, proc, kCFStringEncodingASCII);
void *function; void *function;
bundle = CFBundleCreate (kCFAllocatorDefault, bundleURL); bundle = CFBundleCreate (kCFAllocatorDefault, bundleURL);
assert (bundle != NULL); assert (bundle != NULL);
function = CFBundleGetFunctionPointerForName (bundle, functionName); function = CFBundleGetFunctionPointerForName (bundle, functionName);
CFRelease ( bundleURL ); CFRelease ( bundleURL );
CFRelease ( functionName ); CFRelease ( functionName );
CFRelease ( bundle ); CFRelease ( bundle );
return function; return function;
} }
...@@ -1214,18 +1215,18 @@ static int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value) { ...@@ -1214,18 +1215,18 @@ static int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value) {
QZ_GL_MakeCurrent (this); QZ_GL_MakeCurrent (this);
switch (attrib) { switch (attrib) {
case SDL_GL_RED_SIZE: attr = GL_RED_BITS; break; case SDL_GL_RED_SIZE: attr = GL_RED_BITS; break;
case SDL_GL_BLUE_SIZE: attr = GL_BLUE_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_GREEN_SIZE: attr = GL_GREEN_BITS; break;
case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break; case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break;
case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break; case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break;
case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS; break; case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS; break;
case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_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_RED_SIZE: attr = GL_ACCUM_RED_BITS; break;
case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_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_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break;
case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break; case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break;
case SDL_GL_BUFFER_SIZE: case SDL_GL_BUFFER_SIZE:
{ {
GLint bits = 0; GLint bits = 0;
GLint component; GLint component;
...@@ -1254,4 +1255,298 @@ static void QZ_GL_SwapBuffers (_THIS) { ...@@ -1254,4 +1255,298 @@ static void QZ_GL_SwapBuffers (_THIS) {
[ gl_context flushBuffer ]; [ gl_context flushBuffer ];
} }
static int QZ_LockYUV (_THIS, SDL_Overlay *overlay) {
return 0;
}
static void QZ_UnlockYUV (_THIS, SDL_Overlay *overlay) {
;
}
static int QZ_DisplayYUV (_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect) {
OSErr err;
CodecFlags flags;
if (dstrect->x != 0 || dstrect->y != 0) {
SDL_SetError ("Need a dstrect at (0,0)");
return -1;
}
if (dstrect->w != yuv_width || dstrect->h != yuv_height) {
Fixed scale_x, scale_y;
scale_x = FixDiv ( Long2Fix (dstrect->w), Long2Fix (overlay->w) );
scale_y = FixDiv ( Long2Fix (dstrect->h), Long2Fix (overlay->h) );
SetIdentityMatrix (yuv_matrix);
ScaleMatrix (yuv_matrix, scale_x, scale_y, Long2Fix (0), Long2Fix (0));
SetDSequenceMatrix (yuv_seq, yuv_matrix);
yuv_width = dstrect->w;
yuv_height = dstrect->h;
}
if( ( err = DecompressSequenceFrameS(
yuv_seq,
(void*)yuv_pixmap,
sizeof (PlanarPixmapInfoYUV420),
codecFlagUseImageBuffer, &flags, nil ) != noErr ) )
{
SDL_SetError ("DecompressSequenceFrameS failed");
}
return err == noErr;
}
static void QZ_FreeHWYUV (_THIS, SDL_Overlay *overlay) {
CDSequenceEnd (yuv_seq);
ExitMovies();
free (overlay->hwfuncs);
free (overlay->pitches);
free (overlay->pixels);
if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
[ qz_window close ];
qz_window = nil;
}
free (yuv_matrix);
DisposeHandle ((Handle)yuv_idh);
}
#include "SDL_yuvfuncs.h"
/**
* check for 16 byte alignment, bail otherwise
**/
#define CHECK_ALIGN(x) do { if ((Uint32)x & 15) { SDL_SetError("Alignment error"); return NULL; } } while(0)
/**
* align a byte offset, return how much to add to make it
* a multiple of 16
**/
#define ALIGN(x) ((16 - (x & 15)) & 15)
static SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height,
Uint32 format, SDL_Surface *display) {
Uint32 codec;
OSStatus err;
CGrafPtr port;
SDL_Overlay *overlay;
if (format == SDL_YV12_OVERLAY ||
format == SDL_IYUV_OVERLAY) {
codec = kYUV420CodecType;
}
else {
SDL_SetError ("Hardware: unsupported video format");
return NULL;
}
yuv_idh = (ImageDescriptionHandle) NewHandleClear (sizeof(ImageDescription));
if (yuv_idh == NULL) {
SDL_OutOfMemory();
return NULL;
}
yuv_matrix = (MatrixRecordPtr) malloc (sizeof(MatrixRecord));
if (yuv_matrix == NULL) {
SDL_OutOfMemory();
return NULL;
}
if ( EnterMovies() != noErr ) {
SDL_SetError ("Could not init QuickTime for YUV playback");
return NULL;
}
err = FindCodec (codec, bestSpeedCodec, nil, &yuv_codec);
if (err != noErr) {
SDL_SetError ("Could not find QuickTime codec for format");
return NULL;
}
if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
/**
* Good acceleration requires a window to be present.
* A CGrafPtr that points to the screen isn't good enough
**/
NSRect content = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
qz_window = [ [ SDL_QuartzWindow alloc ]
initWithContentRect:content
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered defer:NO ];
if (qz_window == nil) {
SDL_SetError ("Could not create the Cocoa window");
return NULL;
}
[ qz_window setContentView:[ [ SDL_QuartzWindowView alloc ] init ] ];
[ qz_window setReleasedWhenClosed:YES ];
[ qz_window center ];
[ qz_window setAcceptsMouseMovedEvents:YES ];
[ qz_window setLevel:CGShieldingWindowLevel() ];
[ qz_window makeKeyAndOrderFront:nil ];
port = [ [ qz_window contentView ] qdPort ];
SetPort (port);
// BUG: would like to remove white flash when window kicks in
//{
// Rect r;
// SetRect (&r, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
// PaintRect (&r);
// QDFlushPortBuffer (port, nil);
//}
}
else {
port = [ [ qz_window contentView ] qdPort ];
SetPort (port);
}
SetIdentityMatrix (yuv_matrix);
HLock ((Handle)yuv_idh);
(**yuv_idh).idSize = sizeof(ImageDescription);
(**yuv_idh).cType = codec;
(**yuv_idh).version = 1;
(**yuv_idh).revisionLevel = 0;
(**yuv_idh).width = width;
(**yuv_idh).height = height;
(**yuv_idh).hRes = Long2Fix(72);
(**yuv_idh).vRes = Long2Fix(72);
(**yuv_idh).spatialQuality = codecLosslessQuality;
(**yuv_idh).frameCount = 1;
(**yuv_idh).clutID = -1;
(**yuv_idh).dataSize = 0;
(**yuv_idh).depth = 12;
HUnlock ((Handle)yuv_idh);
err = DecompressSequenceBeginS (
&yuv_seq,
yuv_idh,
NULL,
0,
port,
NULL,
NULL,
yuv_matrix,
0,
NULL,
codecFlagUseImageBuffer,
codecLosslessQuality,
yuv_codec);
if (err != noErr) {
SDL_SetError ("Error trying to start YUV codec.");
return NULL;
}
overlay = (SDL_Overlay*) malloc (sizeof(*overlay));
if (overlay == NULL) {
SDL_OutOfMemory();
return NULL;
}
overlay->format = format;
overlay->w = width;
overlay->h = height;
overlay->planes = 3;
overlay->hw_overlay = 1;
{
int offset;
Uint8 **pixels;
Uint16 *pitches;
int plane2, plane3;
if (format == SDL_IYUV_OVERLAY) {
plane2 = 1; /* Native codec format */
plane3 = 2;
}
else if (format == SDL_YV12_OVERLAY) {
/* switch the U and V planes */
plane2 = 2; /* U plane maps to plane 3 */
plane3 = 1; /* V plane maps to plane 2 */
}
else {
SDL_SetError("Unsupported YUV format");
return NULL;
}
pixels = (Uint8**) malloc (sizeof(*pixels) * 3);
pitches = (Uint16*) malloc (sizeof(*pitches) * 3);
if (pixels == NULL || pitches == NULL) {
SDL_OutOfMemory();
return NULL;
}
yuv_pixmap = (PlanarPixmapInfoYUV420*)
malloc (sizeof(PlanarPixmapInfoYUV420) +
(width * height * 2));
if (yuv_pixmap == NULL) {
SDL_OutOfMemory ();
return NULL;
}
//CHECK_ALIGN(yuv_pixmap);
offset = sizeof(PlanarPixmapInfoYUV420);
//offset += ALIGN(offset);
//CHECK_ALIGN(offset);
pixels[0] = (Uint8*)yuv_pixmap + offset;
//CHECK_ALIGN(pixels[0]);
pitches[0] = width;
yuv_pixmap->componentInfoY.offset = offset;
yuv_pixmap->componentInfoY.rowBytes = width;
offset += width * height;
pixels[plane2] = (Uint8*)yuv_pixmap + offset;
pitches[plane2] = width / 2;
yuv_pixmap->componentInfoCb.offset = offset;
yuv_pixmap->componentInfoCb.rowBytes = width / 2;
offset += (width * height / 4);
pixels[plane3] = (Uint8*)yuv_pixmap + offset;
pitches[plane3] = width / 2;
yuv_pixmap->componentInfoCr.offset = offset;
yuv_pixmap->componentInfoCr.rowBytes = width / 2;
overlay->pixels = pixels;
overlay->pitches = pitches;
}
overlay->hwfuncs = malloc (sizeof(*overlay->hwfuncs));
if (overlay->hwfuncs == NULL) {
SDL_OutOfMemory();
return NULL;
}
overlay->hwfuncs->Lock = QZ_LockYUV;
overlay->hwfuncs->Unlock = QZ_UnlockYUV;
overlay->hwfuncs->Display = QZ_DisplayYUV;
overlay->hwfuncs->FreeHW = QZ_FreeHWYUV;
yuv_width = overlay->w;
yuv_height = overlay->h;
return overlay;
}
...@@ -32,17 +32,17 @@ static void QZ_FreeWMCursor (_THIS, WMcursor *cursor) { ...@@ -32,17 +32,17 @@ static void QZ_FreeWMCursor (_THIS, WMcursor *cursor) {
/* Use the Carbon cursor routines for now */ /* Use the Carbon cursor routines for now */
static WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, static WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask,
int w, int h, int hot_x, int hot_y) { int w, int h, int hot_x, int hot_y) {
WMcursor *cursor; WMcursor *cursor;
int row, bytes; int row, bytes;
/* Allocate the cursor memory */ /* Allocate the cursor memory */
cursor = (WMcursor *)malloc(sizeof(WMcursor)); cursor = (WMcursor *)malloc(sizeof(WMcursor));
if ( cursor == NULL ) { if ( cursor == NULL ) {
SDL_OutOfMemory(); SDL_OutOfMemory();
return(NULL); return(NULL);
} }
memset(cursor, 0, sizeof(*cursor)); memset(cursor, 0, sizeof(*cursor));
if (w > 16) if (w > 16)
w = 16; w = 16;
...@@ -50,19 +50,19 @@ static WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, ...@@ -50,19 +50,19 @@ static WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask,
if (h > 16) if (h > 16)
h = 16; h = 16;
bytes = (w+7)/8; bytes = (w+7)/8;
for ( row=0; row<h; ++row ) { for ( row=0; row<h; ++row ) {
memcpy(&cursor->curs.data[row], data, bytes); memcpy(&cursor->curs.data[row], data, bytes);
data += bytes; data += bytes;
} }
for ( row=0; row<h; ++row ) { for ( row=0; row<h; ++row ) {
memcpy(&cursor->curs.mask[row], mask, bytes); memcpy(&cursor->curs.mask[row], mask, bytes);
mask += bytes; mask += bytes;
} }
cursor->curs.hotSpot.h = hot_x; cursor->curs.hotSpot.h = hot_x;
cursor->curs.hotSpot.v = hot_y; cursor->curs.hotSpot.v = hot_y;
return(cursor); return(cursor);
} }
...@@ -246,18 +246,18 @@ static void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask) ...@@ -246,18 +246,18 @@ static void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask)
#define ALPHASHIFT 3 #define ALPHASHIFT 3
for (i=0;i<masksize;i+=8) for (i=0;i<masksize;i+=8)
for (j=0;j<8;j++) for (j=0;j<8;j++)
surfPtr[ALPHASHIFT+((i+j)<<2)]=(mask[i>>3]&(1<<(7-j)))?0xFF:0x00; surfPtr[ALPHASHIFT+((i+j)<<2)]=(mask[i>>3]&(1<<(7-j)))?0xFF:0x00;
} }
imgrep = [[NSBitmapImageRep alloc] imgrep = [ [ NSBitmapImageRep alloc]
initWithBitmapDataPlanes:(unsigned char **)&mergedSurface->pixels initWithBitmapDataPlanes:(unsigned char **)&mergedSurface->pixels
pixelsWide:icon->w pixelsHigh:icon->h bitsPerSample:8 samplesPerPixel:4 pixelsWide:icon->w pixelsHigh:icon->h bitsPerSample:8 samplesPerPixel:4
hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:icon->w<<2 bitsPerPixel:32]; bytesPerRow:icon->w<<2 bitsPerPixel:32 ];
img = [[NSImage alloc] initWithSize:imgSize]; img = [ [ NSImage alloc ] initWithSize:imgSize ];
[img addRepresentation: imgrep]; [ img addRepresentation: imgrep ];
[NSApp setApplicationIconImage:img]; [ NSApp setApplicationIconImage:img ];
[img release]; [ img release ];
[imgrep release]; [ imgrep release ];
SDL_FreeSurface(mergedSurface); SDL_FreeSurface(mergedSurface);
freePool: freePool:
[pool release]; [pool release];
...@@ -285,19 +285,18 @@ static int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) { ...@@ -285,19 +285,18 @@ static int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) {
static SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) { static SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) {
switch (grab_mode) { switch (grab_mode) {
case SDL_GRAB_QUERY: case SDL_GRAB_QUERY:
break; break;
case SDL_GRAB_OFF: case SDL_GRAB_OFF:
CGAssociateMouseAndMouseCursorPosition (1); CGAssociateMouseAndMouseCursorPosition (1);
currentGrabMode = SDL_GRAB_OFF; currentGrabMode = SDL_GRAB_OFF;
break; break;
case SDL_GRAB_ON: case SDL_GRAB_ON:
QZ_WarpWMCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2); QZ_WarpWMCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2);
CGAssociateMouseAndMouseCursorPosition (0); CGAssociateMouseAndMouseCursorPosition (0);
currentGrabMode = SDL_GRAB_ON; currentGrabMode = SDL_GRAB_ON;
break; break;
case SDL_GRAB_FULLSCREEN: case SDL_GRAB_FULLSCREEN:
break; break;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment