Added initial support for Quartz video (thanks Darrell!)

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%4048
This commit is contained in:
Sam Lantinga 2001-06-07 14:28:11 +00:00
parent d9a2eb5ef1
commit 72f7279bf8
23 changed files with 2127 additions and 29 deletions

View file

@ -105,9 +105,8 @@ static void callBackProc (SndChannel *chan, SndCommand *cmd_passed ) {
UInt32 fill_me, play_me;
SndCommand cmd;
SDL_AudioDevice *audio = (SDL_AudioDevice *)chan->userInfo;
fill_me = cmd_passed->param2; /* buffer that has just finished playing,
so fill it */
fill_me = cmd_passed->param2; /* buffer that has just finished playing, so fill it */
play_me = ! fill_me; /* filled buffer to play _now_ */
if ( ! audio->enabled ) {
@ -119,15 +118,21 @@ so fill it */
cmd.cmd = bufferCmd;
cmd.param1 = 0;
cmd.param2 = (long)&header;
SndDoCommand (chan, &cmd, 0);
SndDoCommand (chan, &cmd, 0);
memset (buffer[fill_me], 0, audio->spec.size);
if ( ! audio->paused ) {
if ( audio->convert.needed ) {
audio->spec.callback(audio->spec.userdata,
(Uint8 *)audio->convert.buf,audio->convert.len);
#if MACOSX
SDL_mutexP(audio->mixer_lock);
#endif
audio->spec.callback(audio->spec.userdata,
(Uint8 *)audio->convert.buf,audio->convert.len);
#if MACOSX
SDL_mutexV(audio->mixer_lock);
#endif
SDL_ConvertAudio(&audio->convert);
#if 0
if ( audio->convert.len_cvt != audio->spec.size ) {
@ -137,11 +142,17 @@ so fill it */
memcpy(buffer[fill_me], audio->convert.buf,
audio->convert.len_cvt);
} else {
#if MACOSX
SDL_mutexP(audio->mixer_lock);
#endif
audio->spec.callback(audio->spec.userdata,
(Uint8 *)buffer[fill_me], audio->spec.size);
#if MACOSX
SDL_mutexV(audio->mixer_lock);
#endif
}
}
if ( running ) {
cmd.cmd = callBackCmd;
@ -150,6 +161,7 @@ so fill it */
SndDoCommand (chan, &cmd, 0);
}
}
static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) {

View file

@ -0,0 +1,8 @@
#import <Cocoa/Cocoa.h>
@interface SDLMain : NSObject
{
}
- (IBAction)quit:(id)sender;
- (IBAction)makeFullscreen:(id)sender;
@end

88
src/main/macosx/SDLMain.m Normal file
View file

@ -0,0 +1,88 @@
/* SDLMain.m - main entry point for our Cocoa-ized SDL app
Darrell Walisser - dwaliss1@purdue.edu
Feel free to customize this file to suit your needs
*/
#import "SDL.h"
#import "SDLMain.h"
#import <sys/param.h> /* for MAXPATHLEN */
#import <unistd.h>
static int gArgc;
static char **gArgv;
/* The main class of the application, the application's delegate */
@implementation SDLMain
/* Invoked from the Quit menu item */
- (void) quit:(id)sender
{
SDL_Event event;
event.type = SDL_QUIT;
SDL_PushEvent(&event);
}
/* Invoked from the "Make fulllscreen" menu item */
- (void) makeFullscreen:(id)sender
{
}
/* Set the working directory to the .app's parent directory */
- (void) setupWorkingDirectory
{
char parentdir[MAXPATHLEN];
char *c;
strncpy ( parentdir, gArgv[0], MAXPATHLEN );
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 */
}
/* Called when the internal event loop has just started running */
- (void) applicationDidFinishLaunching: (NSNotification *) note
{
/* Set the working directory to the .app's parent directory */
[ self setupWorkingDirectory ];
/* This is passed if we are launched by double-clicking */
if ( gArgc >= 2 && strncmp (gArgv[1], "-psn", 4) == 0 )
gArgc = 1;
/* Hand off to main application code */
SDL_main (gArgc, gArgv);
exit(0);
}
@end
#ifdef main
# undef main
#endif
/* Main entry point to executible - should *not* be SDL_main! */
int main (int argc, char **argv) {
/* Copy the arguments into a global variable */
int i;
gArgc = argc;
gArgv = (char**) malloc (sizeof(*gArgv) * gArgc);
assert (gArgv != NULL);
for (i = 0; i < gArgc; i++) {
gArgv[i] = strdup (argv[i]);
}
NSApplicationMain (argc, argv);
return 0;
}

View file

@ -0,0 +1,35 @@
EXPORTS = SDL.x
HEADERS = \
../../../../include/SDL.h \
../../../../include/SDL_active.h \
../../../../include/SDL_audio.h \
../../../../include/SDL_byteorder.h \
../../../../include/SDL_cdrom.h \
../../../../include/SDL_copying.h \
../../../../include/SDL_endian.h \
../../../../include/SDL_error.h \
../../../../include/SDL_events.h \
../../../../include/SDL_getenv.h \
../../../../include/SDL_joystick.h \
../../../../include/SDL_keyboard.h \
../../../../include/SDL_keysym.h \
../../../../include/SDL_mouse.h \
../../../../include/SDL_mutex.h \
../../../../include/SDL_quit.h \
../../../../include/SDL_rwops.h \
../../../../include/SDL_syswm.h \
../../../../include/SDL_thread.h \
../../../../include/SDL_timer.h \
../../../../include/SDL_types.h \
../../../../include/SDL_version.h \
../../../../include/SDL_video.h
all: $(EXPORTS)
$(EXPORTS): $(HEADERS)
perl gendef.pl $(HEADERS) >$@ || rm $@
clean:
rm -f $(EXPORTS)

View file

@ -0,0 +1,177 @@
_SDL_Init
_SDL_InitSubSystem
_SDL_QuitSubSystem
_SDL_WasInit
_SDL_Quit
_SDL_GetAppState
_SDL_AudioInit
_SDL_AudioQuit
_SDL_AudioDriverName
_SDL_OpenAudio
_SDL_GetAudioStatus
_SDL_PauseAudio
_SDL_LoadWAV_RW
_SDL_FreeWAV
_SDL_BuildAudioCVT
_SDL_ConvertAudio
_SDL_MixAudio
_SDL_LockAudio
_SDL_UnlockAudio
_SDL_CloseAudio
_SDL_CDNumDrives
_SDL_CDName
_SDL_CDOpen
_SDL_CDStatus
_SDL_CDPlayTracks
_SDL_CDPlay
_SDL_CDPause
_SDL_CDResume
_SDL_CDStop
_SDL_CDEject
_SDL_CDClose
_SDL_ReadLE16
_SDL_ReadBE16
_SDL_ReadLE32
_SDL_ReadBE32
_SDL_ReadLE64
_SDL_ReadBE64
_SDL_WriteLE16
_SDL_WriteBE16
_SDL_WriteLE32
_SDL_WriteBE32
_SDL_WriteLE64
_SDL_WriteBE64
_SDL_SetError
_SDL_GetError
_SDL_ClearError
_SDL_PumpEvents
_SDL_PeepEvents
_SDL_PollEvent
_SDL_WaitEvent
_SDL_PushEvent
_SDL_SetEventFilter
_SDL_GetEventFilter
_SDL_EventState
_SDL_putenv
_SDL_getenv
_SDL_NumJoysticks
_SDL_JoystickName
_SDL_JoystickOpen
_SDL_JoystickOpened
_SDL_JoystickIndex
_SDL_JoystickNumAxes
_SDL_JoystickNumBalls
_SDL_JoystickNumHats
_SDL_JoystickNumButtons
_SDL_JoystickUpdate
_SDL_JoystickEventState
_SDL_JoystickGetAxis
_SDL_JoystickGetHat
_SDL_JoystickGetBall
_SDL_JoystickGetButton
_SDL_JoystickClose
_SDL_EnableUNICODE
_SDL_EnableKeyRepeat
_SDL_GetKeyState
_SDL_GetModState
_SDL_SetModState
_SDL_GetKeyName
_SDL_GetMouseState
_SDL_GetRelativeMouseState
_SDL_WarpMouse
_SDL_CreateCursor
_SDL_SetCursor
_SDL_GetCursor
_SDL_FreeCursor
_SDL_ShowCursor
_SDL_CreateMutex
_SDL_mutexP
_SDL_mutexV
_SDL_DestroyMutex
_SDL_CreateSemaphore
_SDL_DestroySemaphore
_SDL_SemWait
_SDL_SemTryWait
_SDL_SemWaitTimeout
_SDL_SemPost
_SDL_SemValue
_SDL_CreateCond
_SDL_DestroyCond
_SDL_CondSignal
_SDL_CondBroadcast
_SDL_CondWait
_SDL_CondWaitTimeout
_SDL_RWFromFile
_SDL_RWFromFP
_SDL_RWFromMem
_SDL_AllocRW
_SDL_FreeRW
_SDL_GetWMInfo
_SDL_CreateThread
_SDL_ThreadID
_SDL_GetThreadID
_SDL_WaitThread
_SDL_KillThread
_SDL_GetTicks
_SDL_Delay
_SDL_SetTimer
_SDL_AddTimer
_SDL_RemoveTimer
_SDL_Linked_Version
_SDL_VideoInit
_SDL_VideoQuit
_SDL_VideoDriverName
_SDL_GetVideoSurface
_SDL_GetVideoInfo
_SDL_VideoModeOK
_SDL_ListModes
_SDL_SetVideoMode
_SDL_UpdateRects
_SDL_UpdateRect
_SDL_Flip
_SDL_SetGamma
_SDL_SetGammaRamp
_SDL_GetGammaRamp
_SDL_SetColors
_SDL_SetPalette
_SDL_MapRGB
_SDL_MapRGBA
_SDL_GetRGB
_SDL_GetRGBA
_SDL_CreateRGBSurface
_SDL_CreateRGBSurfaceFrom
_SDL_FreeSurface
_SDL_LockSurface
_SDL_UnlockSurface
_SDL_LoadBMP_RW
_SDL_SaveBMP_RW
_SDL_SetColorKey
_SDL_SetAlpha
_SDL_SetClipRect
_SDL_GetClipRect
_SDL_ConvertSurface
_SDL_UpperBlit
_SDL_LowerBlit
_SDL_FillRect
_SDL_DisplayFormat
_SDL_DisplayFormatAlpha
_SDL_CreateYUVOverlay
_SDL_LockYUVOverlay
_SDL_UnlockYUVOverlay
_SDL_DisplayYUVOverlay
_SDL_FreeYUVOverlay
_SDL_GL_LoadLibrary
_SDL_GL_GetProcAddress
_SDL_GL_SetAttribute
_SDL_GL_GetAttribute
_SDL_GL_SwapBuffers
_SDL_GL_UpdateRects
_SDL_GL_Lock
_SDL_GL_Unlock
_SDL_WM_SetCaption
_SDL_WM_GetCaption
_SDL_WM_SetIcon
_SDL_WM_IconifyWindow
_SDL_WM_ToggleFullScreen
_SDL_WM_GrabInput
_SDL_SoftStretch

View file

@ -0,0 +1,20 @@
#!/usr/bin/perl
#
# Program to take a set of header files and generate DLL export definitions
while ( ($file = shift(@ARGV)) ) {
if ( ! defined(open(FILE, $file)) ) {
warn "Couldn't open $file: $!\n";
next;
}
$printed_header = 0;
$file =~ s,.*/,,;
while (<FILE>) {
if ( /DECLSPEC.*\s\**([^\s\(]+)\(/ ) {
print "\t_$1\n";
} elsif ( /DECLSPEC.*\s\**([^\s\(]+)$/ ) {
print "\t_$1\n";
}
}
close(FILE);
}

View file

@ -63,7 +63,7 @@ typedef struct SDL_VideoDevice SDL_VideoDevice;
#endif
struct SDL_VideoDevice {
/* * * */
/* The name of this audio driver */
/* The name of this video driver */
const char *name;
/* * * */
@ -377,10 +377,12 @@ extern VideoBootStrap TOOLBOX_bootstrap;
#ifdef ENABLE_DRAWSPROCKET
extern VideoBootStrap DSp_bootstrap;
#endif
#ifdef ENABLE_QUARTZ
extern VideoBootStrap QZ_bootstrap;
#endif
#ifdef ENABLE_CYBERGRAPHICS
extern VideoBootStrap CGX_bootstrap;
#endif
/* This is the current video device */
extern SDL_VideoDevice *current_video;

View file

@ -84,6 +84,9 @@ static VideoBootStrap *bootstrap[] = {
#ifdef ENABLE_DRAWSPROCKET
&DSp_bootstrap,
#endif
#ifdef ENABLE_QUARTZ
&QZ_bootstrap,
#endif
#ifdef ENABLE_CYBERGRAPHICS
&CGX_bootstrap,
#endif

View file

@ -34,7 +34,7 @@ static char rcsid =
is still at the back on MacOS X, which is where this code is needed.
*/
#if USE_QUICKTIME
#include <Movies.h>
#include <QuickTime/Movies.h>
#endif
#else
#include <LowMem.h>

View file

@ -0,0 +1,14 @@
## Makefile.am for SDL using the MacOS X Quartz video driver
noinst_LTLIBRARIES = libvideo_quartz.la
libvideo_quartz_la_SOURCES = $(QUARTZ_SRCS)
# The SDL MacOS X Quartz video driver sources
QUARTZ_SRCS = \
SDL_QuartzEvents.m \
SDL_QuartzKeys.h \
SDL_QuartzVideo.h \
SDL_QuartzVideo.m \
SDL_QuartzWM.m \
SDL_QuartzWindow.m

View file

@ -0,0 +1,368 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@devolution.com
*/
#include "SDL_QuartzKeys.h"
static void QZ_InitOSKeymap (_THIS) {
int i;
for ( i=0; i<SDL_TABLESIZE(keymap); ++i )
keymap[i] = SDLK_UNKNOWN;
// This keymap is almost exactly the same as the OS 9 one
keymap[QZ_ESCAPE] = SDLK_ESCAPE;
keymap[QZ_F1] = SDLK_F1;
keymap[QZ_F2] = SDLK_F2;
keymap[QZ_F3] = SDLK_F3;
keymap[QZ_F4] = SDLK_F4;
keymap[QZ_F5] = SDLK_F5;
keymap[QZ_F6] = SDLK_F6;
keymap[QZ_F7] = SDLK_F7;
keymap[QZ_F8] = SDLK_F8;
keymap[QZ_F9] = SDLK_F9;
keymap[QZ_F10] = SDLK_F10;
keymap[QZ_F11] = SDLK_F11;
keymap[QZ_F12] = SDLK_F12;
keymap[QZ_PRINT] = SDLK_PRINT;
keymap[QZ_SCROLLOCK] = SDLK_SCROLLOCK;
keymap[QZ_PAUSE] = SDLK_PAUSE;
keymap[QZ_POWER] = SDLK_POWER;
keymap[QZ_BACKQUOTE] = SDLK_BACKQUOTE;
keymap[QZ_1] = SDLK_1;
keymap[QZ_2] = SDLK_2;
keymap[QZ_3] = SDLK_3;
keymap[QZ_4] = SDLK_4;
keymap[QZ_5] = SDLK_5;
keymap[QZ_6] = SDLK_6;
keymap[QZ_7] = SDLK_7;
keymap[QZ_8] = SDLK_8;
keymap[QZ_9] = SDLK_9;
keymap[QZ_0] = SDLK_0;
keymap[QZ_MINUS] = SDLK_MINUS;
keymap[QZ_EQUALS] = SDLK_EQUALS;
keymap[QZ_BACKSPACE] = SDLK_BACKSPACE;
keymap[QZ_INSERT] = SDLK_INSERT;
keymap[QZ_HOME] = SDLK_HOME;
keymap[QZ_PAGEUP] = SDLK_PAGEUP;
keymap[QZ_NUMLOCK] = SDLK_NUMLOCK;
keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS;
keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE;
keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
keymap[QZ_TAB] = SDLK_TAB;
keymap[QZ_q] = SDLK_q;
keymap[QZ_w] = SDLK_w;
keymap[QZ_e] = SDLK_e;
keymap[QZ_r] = SDLK_r;
keymap[QZ_t] = SDLK_t;
keymap[QZ_y] = SDLK_y;
keymap[QZ_u] = SDLK_u;
keymap[QZ_i] = SDLK_i;
keymap[QZ_o] = SDLK_o;
keymap[QZ_p] = SDLK_p;
keymap[QZ_LEFTBRACKET] = SDLK_LEFTBRACKET;
keymap[QZ_RIGHTBRACKET] = SDLK_RIGHTBRACKET;
keymap[QZ_BACKSLASH] = SDLK_BACKSLASH;
keymap[QZ_DELETE] = SDLK_DELETE;
keymap[QZ_END] = SDLK_END;
keymap[QZ_PAGEDOWN] = SDLK_PAGEDOWN;
keymap[QZ_KP7] = SDLK_KP7;
keymap[QZ_KP8] = SDLK_KP8;
keymap[QZ_KP9] = SDLK_KP9;
keymap[QZ_KP_MINUS] = SDLK_KP_MINUS;
keymap[QZ_CAPSLOCK] = SDLK_CAPSLOCK;
keymap[QZ_a] = SDLK_a;
keymap[QZ_s] = SDLK_s;
keymap[QZ_d] = SDLK_d;
keymap[QZ_f] = SDLK_f;
keymap[QZ_g] = SDLK_g;
keymap[QZ_h] = SDLK_h;
keymap[QZ_j] = SDLK_j;
keymap[QZ_k] = SDLK_k;
keymap[QZ_l] = SDLK_l;
keymap[QZ_SEMICOLON] = SDLK_SEMICOLON;
keymap[QZ_QUOTE] = SDLK_QUOTE;
keymap[QZ_RETURN] = SDLK_RETURN;
keymap[QZ_KP4] = SDLK_KP4;
keymap[QZ_KP5] = SDLK_KP5;
keymap[QZ_KP6] = SDLK_KP6;
keymap[QZ_KP_PLUS] = SDLK_KP_PLUS;
keymap[QZ_LSHIFT] = SDLK_LSHIFT;
keymap[QZ_z] = SDLK_z;
keymap[QZ_x] = SDLK_x;
keymap[QZ_c] = SDLK_c;
keymap[QZ_v] = SDLK_v;
keymap[QZ_b] = SDLK_b;
keymap[QZ_n] = SDLK_n;
keymap[QZ_m] = SDLK_m;
keymap[QZ_COMMA] = SDLK_COMMA;
keymap[QZ_PERIOD] = SDLK_PERIOD;
keymap[QZ_SLASH] = SDLK_SLASH;
keymap[QZ_UP] = SDLK_UP;
keymap[QZ_KP1] = SDLK_KP1;
keymap[QZ_KP2] = SDLK_KP2;
keymap[QZ_KP3] = SDLK_KP3;
keymap[QZ_KP_ENTER] = SDLK_KP_ENTER;
keymap[QZ_LCTRL] = SDLK_LCTRL;
keymap[QZ_LALT] = SDLK_LALT;
keymap[QZ_LMETA] = SDLK_LMETA;
keymap[QZ_SPACE] = SDLK_SPACE;
keymap[QZ_LEFT] = SDLK_LEFT;
keymap[QZ_DOWN] = SDLK_DOWN;
keymap[QZ_RIGHT] = SDLK_RIGHT;
keymap[QZ_KP0] = SDLK_KP0;
keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD;
keymap[QZ_IBOOK_ENTER] = SDLK_KP_ENTER;
keymap[QZ_IBOOK_RIGHT] = SDLK_RIGHT;
keymap[QZ_IBOOK_DOWN] = SDLK_DOWN;
keymap[QZ_IBOOK_UP] = SDLK_UP;
keymap[QZ_IBOOK_LEFT] = SDLK_LEFT;
}
static void QZ_DoKey (int state, NSEvent *event) {
NSString *chars;
int i;
SDL_keysym key;
/* An event can contain multiple characters */
/* I'll ignore this fact for now, since there is only one virtual key code per event */
chars = [ event characters ];
for (i =0; i < 1 /*[ chars length ] */; i++) {
key.scancode = [ event keyCode ];
key.sym = keymap [ key.scancode ];
key.unicode = [ chars characterAtIndex:i];
key.mod = KMOD_NONE;
SDL_PrivateKeyboard (state, &key);
}
}
static void QZ_DoModifiers (unsigned int newMods) {
const int offset = 18;
const int mapping[] = { SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, 0, SDLK_LMETA } ;
int bit;
SDL_keysym key;
key.scancode = 0;
key.sym = SDLK_UNKNOWN;
key.unicode = 0;
key.mod = KMOD_NONE;
/* Iterate through the bits, testing each against the current modifiers */
for (bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1) {
unsigned int currentMask, newMask;
currentMask = currentMods & bit;
newMask = newMods & bit;
if ( currentMask &&
currentMask != newMask ) { /* modifier up event */
key.sym = mapping[ currentMask >> offset ];
SDL_PrivateKeyboard (SDL_RELEASED, &key);
}
else
if ( newMask &&
currentMask != newMask ) { /* modifier down event */
key.sym = mapping [ newMask >> offset ];
SDL_PrivateKeyboard (SDL_PRESSED, &key);
}
}
currentMods = newMods;
}
static void QZ_DoActivate (_THIS, NSPoint p) {
inForeground = YES;
/* Regrab the mouse */
if (currentGrabMode == SDL_GRAB_ON) {
QZ_WarpWMCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2);
CGAssociateMouseAndMouseCursorPosition (0);
}
SDL_PrivateAppActive (1, SDL_APPINPUTFOCUS);
}
static void QZ_DoDeactivate (_THIS) {
inForeground = NO;
/* Ungrab mouse if it is grabbed */
if (currentGrabMode == SDL_GRAB_ON) {
CGAssociateMouseAndMouseCursorPosition (1);
}
SDL_PrivateAppActive (0, SDL_APPINPUTFOCUS);
}
static void QZ_PumpEvents (_THIS) {
NSDate *distantPast = [ NSDate distantPast ];
//NSAutoreleasePool *pool;
//pool = [ [ NSAutoreleasePool alloc ] init ];
NSEvent *event;
NSRect winRect;
NSRect titleBarRect;
winRect = NSMakeRect (0, 0, SDL_VideoSurface->w + 1, SDL_VideoSurface->h + 1);
titleBarRect = NSMakeRect ( 0, SDL_VideoSurface->h, SDL_VideoSurface->w,
SDL_VideoSurface->h + 22 );
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;
NSPoint p;
type = [ event type ];
p = [ event locationInWindow ];
#define DO_MOUSE_DOWN(button, sendToWindow) \
if ( inForeground ) { \
if ( NSPointInRect(p,winRect)) \
SDL_PrivateMouseButton (SDL_PRESSED, button, p.x, SDL_VideoSurface->h - p.y); \
else if (sendToWindow) \
[ window sendEvent:event ]; \
} \
else { \
QZ_DoActivate (this, p); \
}
#define DO_MOUSE_UP(button, sendToWindow) \
if ( ! NSPointInRect (p, titleBarRect) ) \
SDL_PrivateMouseButton (SDL_RELEASED, button, p.x, SDL_VideoSurface->h - p.y); \
if (sendToWindow) \
[ window sendEvent:event ]
switch ( type) {
case NSLeftMouseDown:
if ( NSCommandKeyMask & currentMods ) {
DO_MOUSE_DOWN (3, 0);
}
else if ( NSAlternateKeyMask & currentMods ) {
DO_MOUSE_DOWN (2, 0);
}
else {
DO_MOUSE_DOWN (1, 1);
}
break;
case 25: DO_MOUSE_DOWN (2, 0); break;
case NSRightMouseDown: DO_MOUSE_DOWN (3, 0); break;
case NSLeftMouseUp:
if ( NSCommandKeyMask & currentMods ) {
DO_MOUSE_UP (3, 0);
}
else if ( NSAlternateKeyMask & currentMods ) {
DO_MOUSE_UP (2, 0);
}
else
DO_MOUSE_UP (1, 1);
break;
case 26: 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:
SDL_PrivateMouseMotion (SDL_PRESSED, 0, p.x, SDL_VideoSurface->h - p.y);
break;
case NSMouseMoved:
{
static int moves = 0;
if ( (moves % 10) == 0 ) {
SDL_PrivateMouseMotion (SDL_RELEASED, 0, p.x, SDL_VideoSurface->h - p.y);
moves = 0;
}
else {
CGMouseDelta dx, dy;
CGGetLastMouseDelta (&dx, &dy);
SDL_PrivateMouseMotion (SDL_RELEASED, 1, dx, dy);
moves++;
}
}
break;
case NSScrollWheel:
{
if (NSPointInRect(p, winRect)) {
float dy;
dy = [ event deltaY ];
if ( dy > 0.0 ) /* Scroll up */
SDL_PrivateMouseButton (SDL_PRESSED, 4, p.x, SDL_VideoSurface->h - p.y);
else /* Scroll down */
SDL_PrivateMouseButton (SDL_PRESSED, 5, p.x, SDL_VideoSurface->h - p.y);
}
}
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 NSMouseEntered: break;
case NSMouseExited: break;
case NSAppKitDefined:
switch ( [ event subtype ] ) {
case NSApplicationActivatedEventType:
QZ_DoActivate (this, p);
break;
case NSApplicationDeactivatedEventType:
QZ_DoDeactivate (this);
break;
case NSWindowMovedEventType:
[ window sendEvent:event ];
break;
}
break;
case NSApplicationDefined: break;
case NSPeriodic: break;
case NSCursorUpdate: break;
}
}
// [ pool release ];
} while (event != nil);
}

View file

@ -0,0 +1,140 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@devolution.com
*/
/* These are the Macintosh key scancode constants -- from Inside Macintosh */
#define QZ_ESCAPE 0x35
#define QZ_F1 0x7A
#define QZ_F2 0x78
#define QZ_F3 0x63
#define QZ_F4 0x76
#define QZ_F5 0x60
#define QZ_F6 0x61
#define QZ_F7 0x62
#define QZ_F8 0x64
#define QZ_F9 0x65
#define QZ_F10 0x6D
#define QZ_F11 0x67
#define QZ_F12 0x6F
#define QZ_PRINT 0x69
#define QZ_SCROLLOCK 0x6B
#define QZ_PAUSE 0x71
#define QZ_POWER 0x7F
#define QZ_BACKQUOTE 0x32
#define QZ_1 0x12
#define QZ_2 0x13
#define QZ_3 0x14
#define QZ_4 0x15
#define QZ_5 0x17
#define QZ_6 0x16
#define QZ_7 0x1A
#define QZ_8 0x1C
#define QZ_9 0x19
#define QZ_0 0x1D
#define QZ_MINUS 0x1B
#define QZ_EQUALS 0x18
#define QZ_BACKSPACE 0x33
#define QZ_INSERT 0x72
#define QZ_HOME 0x73
#define QZ_PAGEUP 0x74
#define QZ_NUMLOCK 0x47
#define QZ_KP_EQUALS 0x51
#define QZ_KP_DIVIDE 0x4B
#define QZ_KP_MULTIPLY 0x43
#define QZ_TAB 0x30
#define QZ_q 0x0C
#define QZ_w 0x0D
#define QZ_e 0x0E
#define QZ_r 0x0F
#define QZ_t 0x11
#define QZ_y 0x10
#define QZ_u 0x20
#define QZ_i 0x22
#define QZ_o 0x1F
#define QZ_p 0x23
#define QZ_LEFTBRACKET 0x21
#define QZ_RIGHTBRACKET 0x1E
#define QZ_BACKSLASH 0x2A
#define QZ_DELETE 0x75
#define QZ_END 0x77
#define QZ_PAGEDOWN 0x79
#define QZ_KP7 0x59
#define QZ_KP8 0x5B
#define QZ_KP9 0x5C
#define QZ_KP_MINUS 0x4E
#define QZ_CAPSLOCK 0x39
#define QZ_a 0x00
#define QZ_s 0x01
#define QZ_d 0x02
#define QZ_f 0x03
#define QZ_g 0x05
#define QZ_h 0x04
#define QZ_j 0x26
#define QZ_k 0x28
#define QZ_l 0x25
#define QZ_SEMICOLON 0x29
#define QZ_QUOTE 0x27
#define QZ_RETURN 0x24
#define QZ_KP4 0x56
#define QZ_KP5 0x57
#define QZ_KP6 0x58
#define QZ_KP_PLUS 0x45
#define QZ_LSHIFT 0x38
#define QZ_z 0x06
#define QZ_x 0x07
#define QZ_c 0x08
#define QZ_v 0x09
#define QZ_b 0x0B
#define QZ_n 0x2D
#define QZ_m 0x2E
#define QZ_COMMA 0x2B
#define QZ_PERIOD 0x2F
#define QZ_SLASH 0x2C
#if 0 /* These are the same as the left versions - use left by default */
#define QZ_RSHIFT 0x38
#endif
#define QZ_UP 0x7E
#define QZ_KP1 0x53
#define QZ_KP2 0x54
#define QZ_KP3 0x55
#define QZ_KP_ENTER 0x4C
#define QZ_LCTRL 0x3B
#define QZ_LALT 0x3A
#define QZ_LMETA 0x37
#define QZ_SPACE 0x31
#if 0 /* These are the same as the left versions - use left by default */
#define QZ_RMETA 0x37
#define QZ_RALT 0x3A
#define QZ_RCTRL 0x3B
#endif
#define QZ_LEFT 0x7B
#define QZ_DOWN 0x7D
#define QZ_RIGHT 0x7C
#define QZ_KP0 0x52
#define QZ_KP_PERIOD 0x41
/* Wierd, these keys are on my iBook under MacOS X */
#define QZ_IBOOK_ENTER 0x34
#define QZ_IBOOK_LEFT 0x3B
#define QZ_IBOOK_RIGHT 0x3C
#define QZ_IBOOK_DOWN 0x3D
#define QZ_IBOOK_UP 0x3E

View file

@ -0,0 +1,183 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@devolution.com
*/
/*
@file SDL_QuartzVideo.h
@author Darrell Walisser
@abstract SDL video driver for MacOS X.
@discussion
TODO
- Hardware Cursor support with NSCursor instead of Carbon
- Keyboard repeat/mouse speed adjust (if needed)
- Multiple monitor support (currently only main display)
- Accelerated blitting support
- Set the window icon (dock icon when API is available)
- Avoid erasing window on minimize, or disable minimize
Problems:
- OGL not working in full screen with software renderer
- SetColors sets palette correctly but clears framebuffer
- Crash in CG after several mode switches
- Retained windows don't draw their title bar quite right (OS Bug)
- Should I do depth switching for windowed modes?
- Launch times are slow, maybe prebinding will help
- Direct framebuffer access has some artifacts, maybe a driver issue
- Cursor in 8 bit modes is screwy
- Modifier + mouse-down maps alternate mouse button, but if modifier is released
before mouse button, corresponding mouse-up event is not generated.
- Clicking in content activates app, but doesn't generate the activate event,
and subsequent switches generate no activate/deactivate events! (OS Bug I hope)
*/
#include <ApplicationServices/ApplicationServices.h>
#include <OpenGL/OpenGL.h>
#include <Cocoa/Cocoa.h>
#include <Carbon/Carbon.h>
#include "SDL_video.h"
#include "SDL_error.h"
#include "SDL_syswm.h"
#include "SDL_sysvideo.h"
#include "SDL_pixels_c.h"
#include "SDL_events_c.h"
/* This is a workaround to directly access NSOpenGLContext's CGL context */
/* We need to do this in order to check for errors */
@interface NSOpenGLContext (CGLContextAccess)
- (CGLContextObj) cglContext;
@end
@implementation NSOpenGLContext (CGLContextAccess)
- (CGLContextObj) cglContext;
{
return _contextAuxiliary;
}
@end
typedef struct SDL_PrivateVideoData {
CGDirectDisplayID display; /* 0 == main display */
CFDictionaryRef mode;
CFDictionaryRef save_mode;
CFArrayRef mode_list;
CGDirectPaletteRef palette;
NSOpenGLContext *gl_context;
int width, height, bpp;
Uint32 flags;
/* Window-only fields */
NSWindow *window;
NSQuickDrawView *view;
NSString *title;
} SDL_PrivateVideoData ;
#define _THIS SDL_VideoDevice *this
#define display_id (this->hidden->display)
#define mode (this->hidden->mode)
#define save_mode (this->hidden->save_mode)
#define mode_list (this->hidden->mode_list)
#define palette (this->hidden->palette)
#define glcontext (this->hidden->glcontext)
#define objc_video (this->hidden->objc_video)
#define gl_context (this->hidden->gl_context)
#define device_width (this->hidden->width)
#define device_height (this->hidden->height)
#define device_bpp (this->hidden->bpp)
#define mode_flags (this->hidden->flags)
#define window (this->hidden->window)
#define windowView (this->hidden->view)
#define windowTitle (this->hidden->title)
/* Interface for hardware fill not (yet) in the public API */
int CGSDisplayHWFill (CGDirectDisplayID id, unsigned int x, unsigned int y,
unsigned int w, unsigned int h, unsigned int color);
int CGSDisplayCanHWFill (CGDirectDisplayID id);
/* Bootstrap functions */
static int QZ_Available ();
static SDL_VideoDevice* QZ_CreateDevice (int device_index);
static void QZ_DeleteDevice (SDL_VideoDevice *device);
/* Initialization, Query, Setup, and Redrawing functions */
static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format);
static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format,
Uint32 flags);
static void QZ_UnsetVideoMode (_THIS);
static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current,
int width, int height, int bpp,
Uint32 flags);
static int QZ_ToggleFullScreen (_THIS, int on);
static int QZ_SetColors (_THIS, int first_color,
int num_colors, SDL_Color *colors);
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_VideoQuit (_THIS);
/* Hardware surface functions (for fullscreen mode only) */
static int QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color);
static int QZ_LockHWSurface(_THIS, SDL_Surface *surface);
static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface);
static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface);
/* static int QZ_FlipHWSurface (_THIS, SDL_Surface *surface); */
/* Gamma Functions */
static int QZ_SetGamma (_THIS, float red, float green, float blue);
static int QZ_GetGamma (_THIS, float *red, float *green, float *blue);
static int QZ_SetGammaRamp (_THIS, Uint16 *ramp);
static int QZ_GetGammaRamp (_THIS, Uint16 *ramp);
/* OpenGL functions */
static int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags);
static void QZ_TearDownOpenGL (_THIS);
static void* QZ_GL_GetProcAddress (_THIS, const char *proc);
static int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value);
static int QZ_GL_MakeCurrent (_THIS);
static void QZ_GL_SwapBuffers (_THIS);
static int QZ_GL_LoadLibrary (_THIS, const char *location);
/* Private function to warp the cursor (used internally) */
static void QZ_PrivateWarpCursor (_THIS, int fullscreen, int h, int x, int y);
/* Cursor and Mouse functions */
static void QZ_FreeWMCursor (_THIS, WMcursor *cursor);
static WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask,
int w, int h, int hot_x, int hot_y);
static int QZ_ShowWMCursor (_THIS, WMcursor *cursor);
static void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y);
static void QZ_MoveWMCursor (_THIS, int x, int y);
static void QZ_CheckMouseMode (_THIS);
/* Event functions */
static void QZ_InitOSKeymap (_THIS);
static void QZ_PumpEvents (_THIS);
/* Window Manager functions */
static void QZ_SetCaption (_THIS, const char *title, const char *icon);
static void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask);
static int QZ_IconifyWindow (_THIS);
static SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode);
/*static int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info);*/

View file

@ -0,0 +1,756 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@devolution.com
*/
#include "SDL_QuartzVideo.h"
/* Some variables to share among files, put in device structure eventually */
static SDL_GrabMode currentGrabMode = SDL_GRAB_OFF;
static BOOL inForeground = YES;
static SDLKey keymap[256];
static unsigned int currentMods = 0; /* Current keyboard modifiers, to track modifier state */
/* Include files into one compile unit...break apart eventually */
#include "SDL_QuartzWM.m"
#include "SDL_QuartzEvents.m"
#include "SDL_QuartzWindow.m"
char QZ_Error[255]; /* Global error buffer to temporarily store more informative error messages */
/* Bootstrap binding, enables entry point into the driver */
VideoBootStrap QZ_bootstrap = {
"Quartz", "MacOS X CoreGraphics", QZ_Available, QZ_CreateDevice
};
/* Bootstrap functions */
static int QZ_Available () {
return 1;
}
static SDL_VideoDevice* QZ_CreateDevice (int device_index) {
#pragma unused (device_index)
SDL_VideoDevice *device;
SDL_PrivateVideoData *hidden;
device = (SDL_VideoDevice*) malloc (sizeof (*device) );
hidden = (SDL_PrivateVideoData*) malloc (sizeof (*hidden) );
if (device == NULL || hidden == NULL)
SDL_OutOfMemory ();
memset (device, 0, sizeof (*device) );
memset (hidden, 0, sizeof (*hidden) );
device->hidden = hidden;
device->VideoInit = QZ_VideoInit;
device->ListModes = QZ_ListModes;
device->SetVideoMode = QZ_SetVideoMode;
device->ToggleFullScreen = QZ_ToggleFullScreen;
device->SetColors = QZ_SetColors;
/* device->UpdateRects = QZ_UpdateRects; this is determined by SetVideoMode() */
device->VideoQuit = QZ_VideoQuit;
device->LockHWSurface = QZ_LockHWSurface;
device->UnlockHWSurface = QZ_UnlockHWSurface;
device->FreeHWSurface = QZ_FreeHWSurface;
/* device->FlipHWSurface = QZ_FlipHWSurface */;
device->SetGamma = QZ_SetGamma;
device->GetGamma = QZ_GetGamma;
device->SetGammaRamp = QZ_SetGammaRamp;
device->GetGammaRamp = QZ_GetGammaRamp;
device->GL_GetProcAddress = QZ_GL_GetProcAddress;
device->GL_GetAttribute = QZ_GL_GetAttribute;
device->GL_MakeCurrent = QZ_GL_MakeCurrent;
device->GL_SwapBuffers = QZ_GL_SwapBuffers;
device->GL_LoadLibrary = QZ_GL_LoadLibrary;
device->FreeWMCursor = QZ_FreeWMCursor;
device->CreateWMCursor = QZ_CreateWMCursor;
device->ShowWMCursor = QZ_ShowWMCursor;
device->WarpWMCursor = QZ_WarpWMCursor;
device->MoveWMCursor = QZ_MoveWMCursor;
device->CheckMouseMode = QZ_CheckMouseMode;
device->InitOSKeymap = QZ_InitOSKeymap;
device->PumpEvents = QZ_PumpEvents;
device->SetCaption = QZ_SetCaption;
device->SetIcon = QZ_SetIcon;
device->IconifyWindow = QZ_IconifyWindow;
/*device->GetWMInfo = QZ_GetWMInfo;*/
device->GrabInput = QZ_GrabInput;
device->free = QZ_DeleteDevice;
return device;
}
static void QZ_DeleteDevice (SDL_VideoDevice *device) {
free (device->hidden);
free (device);
}
static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) {
/* Initialize the video settings; this data persists between mode switches */
display_id = kCGDirectMainDisplay;
save_mode = CGDisplayCurrentMode (display_id);
mode_list = CGDisplayAvailableModes (display_id);
palette = CGPaletteCreateDefaultColorPalette ();
/* Gather some information that is useful to know about the display */
CFNumberGetValue (CFDictionaryGetValue (save_mode, kCGDisplayBitsPerPixel),
kCFNumberSInt32Type, &device_bpp);
CFNumberGetValue (CFDictionaryGetValue (save_mode, kCGDisplayWidth),
kCFNumberSInt32Type, &device_width);
CFNumberGetValue (CFDictionaryGetValue (save_mode, kCGDisplayHeight),
kCFNumberSInt32Type, &device_height);
video_format->BitsPerPixel = device_bpp;
windowTitle = @"";
return 0;
}
static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) {
CFIndex num_modes = CFArrayGetCount (mode_list);
CFIndex i;
static SDL_Rect **list = NULL;
int list_size = 0;
/* Any windowed mode is acceptable */
if ( (flags & SDL_FULLSCREEN) == 0 )
return (SDL_Rect**)-1;
/* Free memory from previous call, if any */
if ( list != NULL ) {
int i = 0;
for (i = 0; list[i] != NULL; i++)
free (list[i]);
free (list);
list = NULL;
}
/* Build list of modes with the requested bpp */
for (i = num_modes-1; i >= 0; i--) {
CFDictionaryRef onemode = CFArrayGetValueAtIndex (mode_list, i);
CFNumberRef number;
int bpp;
number = CFDictionaryGetValue (onemode, kCGDisplayBitsPerPixel);
CFNumberGetValue (number, kCFNumberSInt32Type, &bpp);
if (bpp == format->BitsPerPixel) {
int intvalue;
SDL_Rect *rect;
int lastwidth = 0, lastheight = 0, width, height;
number = CFDictionaryGetValue (onemode, kCGDisplayWidth);
CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue);
width = (Uint16) intvalue;
number = CFDictionaryGetValue (onemode, kCGDisplayHeight);
CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue);
height = (Uint16) intvalue;
/* We'll get a lot of modes with the same size, so ignore them */
if ( width != lastwidth && height != lastheight ) {
lastwidth = width;
lastheight = height;
list_size++;
if ( list == NULL)
list = (SDL_Rect**) malloc (sizeof(*list) * list_size+1);
else
list = (SDL_Rect**) realloc (list, sizeof(*list) * list_size+1);
rect = (SDL_Rect*) malloc (sizeof(**list));
if (list == NULL || rect == NULL)
SDL_OutOfMemory ();
rect->w = width;
rect->h = height;
list[list_size-1] = rect;
list[list_size] = NULL;
}
}
}
return list;
}
static void QZ_UnsetVideoMode (_THIS) {
if ( mode_flags & SDL_OPENGL )
QZ_TearDownOpenGL (this);
/* Reset values that may change between switches */
this->info.blit_fill = 0;
this->FillHWRect = NULL;
this->UpdateRects = NULL;
/* Restore gamma settings */
CGDisplayRestoreColorSyncSettings ();
/* Restore original screen resolution */
if ( mode_flags & SDL_FULLSCREEN ) {
CGDisplaySwitchToMode (display_id, save_mode);
CGDisplayRelease (display_id);
}
/* Release window mode data structures */
else {
if ( (mode_flags & SDL_OPENGL) == 0 ) {
UnlockPortBits ( [ windowView qdPort ] );
[ windowView release ];
}
[ window setContentView:nil ];
[ window close ];
[ window release ];
}
/* Ensure the cursor will be visible and working when we quit */
CGDisplayShowCursor (display_id);
CGAssociateMouseAndMouseCursorPosition (1);
}
static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width,
int height, int bpp, Uint32 flags) {
int exact_match;
/* See if requested mode exists */
mode = CGDisplayBestModeForParameters (display_id, bpp, width,
height, &exact_match);
/* Require an exact match to the requested mode */
if ( ! exact_match ) {
sprintf (QZ_Error, "Failed to find display resolution: %dx%dx%d", width, height, bpp);
SDL_SetError (QZ_Error);
goto ERR_NO_MATCH;
}
/* Put up the blanking window (a window above all other windows) */
if ( CGDisplayNoErr != CGDisplayCapture (display_id) ) {
SDL_SetError ("Failed capturing display");
goto ERR_NO_CAPTURE;
}
/* Do the physical switch */
if ( CGDisplayNoErr != CGDisplaySwitchToMode (display_id, mode) ) {
SDL_SetError ("Failed switching display resolution");
goto ERR_NO_SWITCH;
}
/* None of these methods seem to fix the fullscreen artifacts bug(s) */
#if USE_GDHANDLE
SetGDevice(GetMainDevice());
current->pitch = (**(** GetMainDevice() ).gdPMap).rowBytes & 0x3FFF;
current->pixels = (**(** GetMainDevice() ).gdPMap).baseAddr;
#elif USE_CREATEPORT
device_port = CreateNewPortForCGDisplayID((Uint32*)display_id);
SetPort (device_port);
LockPortBits ( device_port );
current->pixels = GetPixBaseAddr ( GetPortPixMap ( device_port ) );
current->pitch = GetPixRowBytes ( GetPortPixMap ( device_port ) );
UnlockPortBits ( device_port );
#else
current->pixels = (Uint32*) CGDisplayBaseAddress (display_id);
current->pitch = CGDisplayBytesPerRow (display_id);
#endif
current->w = width;
current->h = height;
current->flags |= SDL_FULLSCREEN;
current->flags |= SDL_HWSURFACE;
this->UpdateRects = QZ_DirectUpdate;
/* Setup some mode-dependant info */
if ( CGSDisplayCanHWFill (display_id) ) {
this->info.blit_fill = 1;
this->FillHWRect = QZ_FillHWRect;
}
if ( CGDisplayCanSetPalette (display_id) )
current->flags |= SDL_HWPALETTE;
/* Setup OpenGL for a fullscreen context */
if (flags & SDL_OPENGL) {
CGLError err;
CGLContextObj ctx;
if ( ! QZ_SetupOpenGL (this, bpp, flags) ) {
return NULL;
}
ctx = [ gl_context cglContext ];
err = CGLSetFullScreen (ctx);
if (err) {
sprintf (QZ_Error, "Error setting OpenGL fullscreen: %s", CGLErrorString(err));
SDL_SetError (QZ_Error);
goto ERR_NO_GL;
}
[ gl_context makeCurrentContext];
current->flags |= SDL_OPENGL;
}
/* If we don't hide menu bar, it will get events and interrupt the program */
HideMenuBar ();
/* Save the flags to ensure correct tear-down */
mode_flags = current->flags;
return current;
/* Since the blanking window covers *all* windows (even force quit) correct recovery is crutial */
ERR_NO_GL: CGDisplaySwitchToMode (display_id, save_mode);
ERR_NO_SWITCH: CGDisplayRelease (display_id);
ERR_NO_CAPTURE:
ERR_NO_MATCH: return NULL;
}
static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
int height, int bpp, Uint32 flags) {
NSRect rect;
rect = NSMakeRect (0, 0, width, height);
/* Manually create a window, avoids having a nib file resource */
window = [ [ SDL_QuartzWindow alloc ] initWithContentRect:rect
styleMask:(NSTitledWindowMask | NSMiniaturizableWindowMask)
backing: //NSBackingStoreBuffered
NSBackingStoreRetained
defer:NO ];
if (window == nil) {
SDL_SetError ("Could not create the Cocoa window");
return NULL;
}
current->w = width;
current->h = height;
[ window setTitle:windowTitle ];
[ window setAcceptsMouseMovedEvents:YES ];
[ window center ];
/* For OpenGL, we set the content view to a NSOpenGLView */
if ( flags & SDL_OPENGL ) {
if ( ! QZ_SetupOpenGL (this, bpp, flags) ) {
return NULL;
}
[ gl_context setView: [ window contentView ] ];
[ gl_context makeCurrentContext];
[ window orderFront:nil ];
current->flags |= SDL_OPENGL;
}
/* For 2D, we set the content view to a NSQuickDrawView */
else {
windowView = [ [ NSQuickDrawView alloc ] init ];
[ window setContentView:windowView ];
[ window orderFront:nil ];
LockPortBits ( [ windowView qdPort ] );
current->pixels = GetPixBaseAddr ( GetPortPixMap ( [ windowView qdPort ] ) );
current->pitch = GetPixRowBytes ( GetPortPixMap ( [ windowView qdPort ] ) );
/* Offset 22 pixels down to fill the full content region */
current->pixels += 22 * current->pitch;
current->flags |= SDL_SWSURFACE;
current->flags |= SDL_PREALLOC;
this->UpdateRects = QZ_UpdateRects;
}
return current;
}
static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width,
int height, int bpp, Uint32 flags) {
if (SDL_VideoSurface != NULL)
QZ_UnsetVideoMode (this);
current->flags = 0;
/* Setup full screen video */
if ( flags & SDL_FULLSCREEN ) {
current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags );
if (current == NULL)
return NULL;
}
/* Setup windowed video */
else {
/* Force bpp to the device's bpp */
bpp = current->format->BitsPerPixel;
current = QZ_SetVideoWindowed (this, current, width, height, bpp, flags);
if (current == NULL)
return NULL;
}
/* Setup the new pixel format */
{
int amask = 0,
rmask = 0,
gmask = 0,
bmask = 0;
switch (bpp) {
case 16: /* (1)-5-5-5 RGB */
amask = 0;
rmask = 0x7c00;
gmask = 0x3e0;
bmask = 0x1f;
break;
case 24:
SDL_SetError ("24bpp is not available");
return NULL;
case 32: /* (8)-8-8-8 ARGB */
amask = 0xFF000000;
rmask = 0x00FF0000;
gmask = 0x0000FF00;
bmask = 0x000000FF;
break;
}
if ( ! SDL_ReallocFormat (current, bpp,
rmask, gmask, bmask, amask ) ) {
SDL_SetError ("Couldn't reallocate pixel format");
return NULL;
}
}
/* Warp mouse to origin in order to get passive mouse motion events started correctly */
QZ_PrivateWarpCursor (this, current->flags & SDL_FULLSCREEN, height, 0, 0);
return current;
}
static int QZ_ToggleFullScreen (_THIS, int on) {
return -1;
}
static int QZ_SetColors (_THIS, int first_color, int num_colors,
SDL_Color *colors) {
CGTableCount index;
CGDeviceColor color;
for (index = first_color; index < first_color+num_colors; index++) {
/* Clamp colors between 0.0 and 1.0 */
color.red = colors->r / 255.0;
color.blue = colors->b / 255.0;
color.green = colors->g / 255.0;
colors++;
CGPaletteSetColorAtIndex (palette, color, index);
}
if ( CGDisplayNoErr != CGDisplaySetPalette (display_id, palette) )
return 0;
return 1;
}
static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) {
#pragma unused(this,num_rects,rects)
}
static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) {
if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) {
QZ_GL_SwapBuffers (this);
}
else {
int i;
RgnHandle dirty = NewRgn ();
RgnHandle temp = NewRgn ();
SetEmptyRgn (dirty);
/* Build the region of dirty rectangles */
for (i = 0; i < numRects; i++) {
MacSetRectRgn (temp, rects[i].x, rects[i].y,
rects[i].x + rects[i].w, rects[i].y + rects[i].h);
MacUnionRgn (dirty, temp, dirty);
}
/* Flush the dirty region */
QDFlushPortBuffer ( [ windowView qdPort ], dirty );
DisposeRgn (dirty);
DisposeRgn (temp);
}
}
static void QZ_VideoQuit (_THIS) {
QZ_UnsetVideoMode (this);
CGPaletteRelease (palette);
}
static int QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) {
CGSDisplayHWFill (display_id, rect->x, rect->y, rect->w, rect->h, color);
return 0;
}
static int QZ_LockHWSurface(_THIS, SDL_Surface *surface) {
return 1;
}
static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface) {
}
static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface) {
}
/*
int QZ_FlipHWSurface (_THIS, SDL_Surface *surface) {
return 0;
}
*/
/* Gamma functions */
static int QZ_SetGamma (_THIS, float red, float green, float blue) {
const CGGammaValue min = 0.0, max = 1.0;
if ( CGDisplayNoErr != CGSetDisplayTransferByFormula
(display_id, min, max, red, min, max, green, min, max, blue) )
return -1;
return 0;
}
static int QZ_GetGamma (_THIS, float *red, float *green, float *blue) {
CGGammaValue dummy;
if ( CGDisplayNoErr != CGGetDisplayTransferByFormula
(display_id, &dummy, &dummy, red,
&dummy, &dummy, green, &dummy, &dummy, blue) )
return -1;
return 0;
}
static int QZ_SetGammaRamp (_THIS, Uint16 *ramp) {
const CGTableCount tableSize = 255;
CGGammaValue redTable[tableSize];
CGGammaValue greenTable[tableSize];
CGGammaValue blueTable[tableSize];
int i;
/* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */
for (i = 0; i < 256; i++)
redTable[i % 256] = ramp[i] / 65535.0;
for (i=256; i < 512; i++)
greenTable[i % 256] = ramp[i] / 65535.0;
for (i=512; i < 768; i++)
blueTable[i % 256] = ramp[i] / 65535.0;
if ( CGDisplayNoErr != CGSetDisplayTransferByTable
(display_id, tableSize, redTable, greenTable, blueTable) )
return -1;
return 0;
}
static int QZ_GetGammaRamp (_THIS, Uint16 *ramp) {
const CGTableCount tableSize = 255;
CGGammaValue redTable[tableSize];
CGGammaValue greenTable[tableSize];
CGGammaValue blueTable[tableSize];
CGTableCount actual;
int i;
if ( CGDisplayNoErr != CGGetDisplayTransferByTable
(display_id, tableSize, redTable, greenTable, blueTable, &actual) ||
actual != tableSize)
return -1;
/* Pack tables into one array, with values from 0 to 65535 */
for (i = 0; i < 256; i++)
ramp[i] = redTable[i % 256] * 65535.0;
for (i=256; i < 512; i++)
ramp[i] = greenTable[i % 256] * 65535.0;
for (i=512; i < 768; i++)
ramp[i] = blueTable[i % 256] * 65535.0;
return 0;
}
/* OpenGL helper functions */
static int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
NSOpenGLPixelFormatAttribute attr[32];
NSOpenGLPixelFormat *fmt;
int i = 0;
int colorBits = bpp;
if ( flags & SDL_FULLSCREEN ) {
attr[i++] = NSOpenGLPFAFullScreen;
}
/* In windowed mode, the OpenGL pixel depth must match device pixel depth */
else if ( colorBits != device_bpp ) {
colorBits = device_bpp;
}
attr[i++] = NSOpenGLPFAColorSize;
attr[i++] = colorBits;
attr[i++] = NSOpenGLPFADepthSize;
attr[i++] = this->gl_config.depth_size;
if ( this->gl_config.double_buffer ) {
attr[i++] = NSOpenGLPFADoubleBuffer;
}
if ( this->gl_config.stencil_size != 0 ) {
attr[i++] = NSOpenGLPFAStencilSize;
attr[i++] = this->gl_config.stencil_size;
}
attr[i++] = NSOpenGLPFAScreenMask;
attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
attr[i] = 0;
fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
if (fmt == nil) {
SDL_SetError ("Failed creating OpenGL pixel format");
return 0;
}
gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
shareContext:nil];
if (gl_context == nil) {
SDL_SetError ("Failed creating OpenGL context");
return 0;
}
/* Convince SDL that the GL "driver" is loaded */
this->gl_config.driver_loaded = 1;
[ fmt release ];
return 1;
}
static void QZ_TearDownOpenGL (_THIS) {
[ NSOpenGLContext clearCurrentContext ];
[ gl_context clearDrawable ];
[ gl_context release ];
}
/* SDL OpenGL functions */
static int QZ_GL_LoadLibrary (_THIS, const char *location) {
return 1;
}
static void* QZ_GL_GetProcAddress (_THIS, const char *proc) {
/* We may want to cache the bundleRef at some point */
CFBundleRef bundle;
CFURLRef bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault,
CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true);
CFStringRef functionName = CFStringCreateWithCString
(kCFAllocatorDefault, proc, kCFStringEncodingASCII);
void *function;
bundle = CFBundleCreate (kCFAllocatorDefault, bundleURL);
assert (bundle != NULL);
function = CFBundleGetFunctionPointerForName (bundle, functionName);
CFRelease ( bundleURL );
CFRelease ( functionName );
CFRelease ( bundle );
return function;
}
static int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value) {
/*
CGLContextRef ctx = [ gl_context cglContext ];
CGLContextParameter param;
switch (attrib) {
case SDL_GL_RED_SIZE: param = CGLContextParameter break;
}
CGLGetParameter (ctx, param, (long*)value);
*/
*value = -1;
return -1;
}
static int QZ_GL_MakeCurrent (_THIS) {
[ gl_context makeCurrentContext ];
return 0;
}
static void QZ_GL_SwapBuffers (_THIS) {
[ gl_context flushBuffer ];
}

View file

@ -0,0 +1,175 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@devolution.com
*/
struct WMcursor {
Cursor curs;
};
static void QZ_FreeWMCursor (_THIS, WMcursor *cursor) {
if ( cursor != NULL )
free (cursor);
}
/* Use the Carbon cursor routines for now */
static WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask,
int w, int h, int hot_x, int hot_y) {
WMcursor *cursor;
int row, bytes;
cursor = (WMcursor *)malloc(sizeof(WMcursor));
if ( cursor == NULL ) {
SDL_OutOfMemory();
return(NULL);
}
memset(cursor, 0, sizeof(*cursor));
bytes = (w/8);
if ( bytes > 2 ) {
bytes = 2;
}
for ( row=0; row<h && (row < 16); ++row ) {
memcpy(&cursor->curs.data[row], data, bytes);
data += w/8;
}
for ( row=0; row<h && (row < 16); ++row ) {
memcpy(&cursor->curs.mask[row], mask, bytes);
mask += w/8;
}
cursor->curs.hotSpot.h = hot_x;
cursor->curs.hotSpot.v = hot_y;
return(cursor);
}
static int QZ_ShowWMCursor (_THIS, WMcursor *cursor) {
static int visible = 1;
if ( cursor == NULL) {
if ( visible ) {
HideCursor ();
visible = 0;
}
}
else {
SetCursor(&cursor->curs);
if ( ! visible ) {
ShowCursor ();
visible = 1;
}
}
return 1;
}
static void QZ_PrivateWarpCursor (_THIS, int fullscreen, int h, int x, int y) {
CGPoint p;
/* We require absolute screen coordiates for our warp */
p.x = x;
p.y = h - y;
if ( fullscreen )
/* Already absolute coordinates */
CGDisplayMoveCursorToPoint(display_id, p);
else {
/* Convert to absolute screen coordinates */
NSPoint base, screen;
base = NSMakePoint (p.x, p.y);
screen = [ window convertBaseToScreen:base ];
p.x = screen.x;
p.y = device_height - screen.y;
CGDisplayMoveCursorToPoint (display_id, p);
}
}
static void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y) {
/* Only allow warping when in foreground */
if ( ! inForeground )
return;
/* Do the actual warp */
QZ_PrivateWarpCursor (this, SDL_VideoSurface->flags & SDL_FULLSCREEN,
SDL_VideoSurface->h, x, y);
/* Generate mouse moved event */
SDL_PrivateMouseMotion (SDL_RELEASED, 0, x, y);
}
static void QZ_MoveWMCursor (_THIS, int x, int y) { }
static void QZ_CheckMouseMode (_THIS) { }
static void QZ_SetCaption (_THIS, const char *title, const char *icon) {
NSString *str = [ [ NSString alloc ] initWithCString:title ];
if (window != nil)
[ window setTitle:str ];
[ windowTitle release ];
windowTitle = str;
}
static void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask) {
/* Convert icon/mask to NSImage, assign with NSWindow's setMiniwindowImage method */
}
static int QZ_IconifyWindow (_THIS) {
/* Bug! minimize erases the framebuffer */
if ( ! [ window isMiniaturized ] ) {
[ window miniaturize:nil ];
return 1;
}
else {
SDL_SetError ("window already iconified");
return 0;
}
}
/*
static int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) {
info->nsWindowPtr = window;
return 0;
}*/
static SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) {
switch (grab_mode) {
case SDL_GRAB_QUERY:
break;
case SDL_GRAB_OFF:
CGAssociateMouseAndMouseCursorPosition (1);
currentGrabMode = SDL_GRAB_OFF;
break;
case SDL_GRAB_ON:
QZ_WarpWMCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2);
CGAssociateMouseAndMouseCursorPosition (0);
currentGrabMode = SDL_GRAB_ON;
break;
case SDL_GRAB_FULLSCREEN:
break;
}
return currentGrabMode;
}

View file

@ -0,0 +1,25 @@
/* Subclass of NSWindow to allow customization if we need it */
@interface SDL_QuartzWindow : NSWindow
{}
- (void)miniaturize:(id)sender;
- (void)deminiaturize:(id)sender;
@end
@implementation SDL_QuartzWindow
/* These methods should be rewritten to fix the miniaturize bug */
- (void)miniaturize:(id)sender
{
[ super miniaturize:sender ];
}
- (void)deminiaturize:(id)sender
{
/* Let the app know they have to redraw everything */
SDL_PrivateExpose ();
[ super deminiaturize:sender ];
}
@end