diff --git a/BUGS b/BUGS
index 0636142f2..bded19035 100644
--- a/BUGS
+++ b/BUGS
@@ -70,22 +70,35 @@ MacOS:
Not all of the keys are properly recognized on the keyboard.
MacOS X:
- Fullscreen mode doesn't work - it requires the QuickTime framework
- and that the new SDL window gets raised to the top of the Z order.
+ Joystick and CD-ROM functions are not implemented yet.
+ Closing window from window's close widget not implemented yet.
+
+ Minimizing the window erases the framebuffer to the pinstripe pattern.
+
+ Window may not close when unsetting video mode and resetting.
+
+ Depth switching for windowed mode isn't implemented yet.
+
Palette handling isn't implemented in windowed mode yet.
+
+ Command-line arguments Dialog is not implemented yet.
- Native sound and video routines are not finished, though Carbon
- seems to work fairly well.
+ Fullscreen drawing has some artifacts.
+
+ Fullscreen window covers *all* other windows - even force quit.
+
+ Fullscreen OpenGL for the software renderer is broken.
- Joysticks and CD-ROM functions are not implemented yet.
+ 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.
- SDL_WM_GrabInput() is not implemented.
- Does anyone know how to do this? SDL_WM_GrabInput() is designed
- to prevent the user from switching input and mouse focus away from
- the SDL application.
-
- Continuous relative mouse motion is not implemented.
+ SDL_WM_GrabInput() is implemented, but it "freezes" the hardware
+ cursor in the center of the window/screen. Also, mouse moved events
+ are not generated, and the keyboard cannot be grabbed.
Not all of the keys are properly recognized on the keyboard.
diff --git a/README.MacOSX b/README.MacOSX
index 0295bb3a4..745103f93 100644
--- a/README.MacOSX
+++ b/README.MacOSX
@@ -34,11 +34,80 @@ and linking, respectively:
sdl-config knows about the linking path and -framework, so it's
recommended to use it to fill in your Makefile variables.
-[Add instructions for how to build using PB]
+==============================================================================
+Using the Simple DirectMedia Layer with Project Builder
+==============================================================================
-As of this writing (Sep 2000), OS X is in public beta. This means
-that while most of the APIs are frozen, things are still subject to
-change, and many of the known problems will be resolved before the
-final release comes out.
+These instructions are for using Apple's Project Builder IDE to build SDL applications.
+- Building the Framework
+
+The SDL Library is packaged as a framework bundle, an organized
+relocatable folder heirarchy of executible code, interface headers,
+and additional resources. For practical purposes, you can think of a
+framework as a more user and system-friendly shared library, whose library
+file behaves more or less like a standard UNIX shared library.
+
+To build the framework, simply open the framework project and build it.
+By default, the framework bundle "SDL.framework" is installed in
+~/Library/Frameworks. Therefore, the testers and project stationary expect
+it to be located there. However, it will function the same in any of the
+following locations:
+
+ ~/Library/Frameworks
+ /Local/Library/Frameworks
+ /System/Library/Frameworks
+
+- Build Options
+ There are two "Build Styles" (See the "Targets" tab) for SDL.
+ "Deployment" should be used if you aren't tweaking the SDL library.
+ "Development" should be used to debug SDL apps or the library itself.
+
+- Building the Testers
+ Open the SDLTest project and build away!
+
+- Using the Project Stationary
+ Copy the stationary to the indicated folders to access it from
+ the "New Project" and "Add target" menus. What could be easier?
+
+- Setting up a new project by hand
+ Some of you won't want to use the Stationary so I'll give some tips:
+ * Create a new "Cocoa Application"
+ * Add src/main/macosx/SDLMain.m , .h and .nib to your project
+ * Remove "main.c" from your project
+ * Remove "MainMenu.nib" from your project
+ * Add "$(HOME)/Library/Frameworks/SDL.framework/Headers" to include path
+ * Add "$(HOME)/Library/Frameworks" to the frameworks search path
+ * Add "-framework SDL" to the "OTHER_LDFLAGS" variable
+ * Set the "Main Nib File" under "Application Settings" to "SDLMain.nib"
+ * Add your files
+ * Clean and build
+
+- Building from command line
+ Use pbxbuild in the same directory as your .pbproj file
+
+- Running your app
+ You can send command line args to your app by either invoking it from
+ the command line (in *.app/Contents/MacOS) or by entering them in the
+ "Executibles" panel of the target settings.
+
+- Implementation Notes
+ Some things that may be of interest about how it all works...
+ * Working directory
+ As defined in the SDLMain.m file, the working directory of your SDL app
+ is by default set to its parent. You may wish to change this to better
+ suit your needs.
+ * You have a Cocoa App!
+ Your SDL app is essentially a Cocoa application. When your app
+ starts up and the libraries finish loading, a Cocoa procedure is called,
+ which sets up the working directory and calls your main() method.
+ You are free to modify your Cocoa app with generally no consequence
+ to SDL. You cannot, however, easily change the SDL window itself.
+ Functionality may be added in the future to help this.
+ * My development setup:
+ I am using version 1.0.1 (v63.0) of Project Builder on MacOS X 10.0.3,
+ from the Developer Tools CD for May 2001.
+ As of May 31 2001, Apple hasn't released this version of the tools to the public,
+ but I expect that things will still work on older versions.
+
Known bugs are listed in the file "BUGS"
diff --git a/configure.in b/configure.in
index d2ba61bf2..1b4d7ccb8 100644
--- a/configure.in
+++ b/configure.in
@@ -63,6 +63,10 @@ case "$target" in
*-*-linux*)
AC_PROG_CXX
;;
+ *-*-darwin*)
+ OBJC="???"
+ AC_SUBST(OBJC)
+ ;;
esac
AC_PROG_INSTALL
AC_FUNC_ALLOCA
@@ -1979,6 +1983,7 @@ src/video/ggi/Makefile
src/video/maccommon/Makefile
src/video/macdsp/Makefile
src/video/macrom/Makefile
+src/video/quartz/Makefile
src/video/svga/Makefile
src/video/aalib/Makefile
src/video/wincommon/Makefile
diff --git a/docs.html b/docs.html
index ea26c74e3..6d4f52684 100644
--- a/docs.html
+++ b/docs.html
@@ -16,6 +16,7 @@ be found at the main SDL page.
Major changes since SDL 1.0.0:
+ - 1.2.1: Added initial support for Quartz video (thanks Darrell!)
- 1.2.1: Added native OpenBSD audio driver (thanks vedge!)
- 1.2.1: Added detection of Open Sound System on Solaris x86
- 1.2.1: Added initial support for Nano-X (thanks Hsieh-Fu!)
diff --git a/include/SDL_main.h b/include/SDL_main.h
index 26d0d9c14..df291a615 100644
--- a/include/SDL_main.h
+++ b/include/SDL_main.h
@@ -31,7 +31,7 @@ static char rcsid =
/* Redefine main() on Win32 and MacOS so that it is called by winmain.c */
#if defined(WIN32) || (defined(__MWERKS__) && !defined(__BEOS__)) || \
- defined(macintosh)
+ defined(macintosh) || defined(__APPLE__)
#ifdef __cplusplus
#define C_LINKAGE "C"
diff --git a/include/SDL_video.h b/include/SDL_video.h
index 70cf4b6c1..ad2bc04b2 100644
--- a/include/SDL_video.h
+++ b/include/SDL_video.h
@@ -878,6 +878,10 @@ typedef enum {
*/
extern DECLSPEC SDL_GrabMode SDL_WM_GrabInput(SDL_GrabMode mode);
+/* Not in public API at the moment - do not use! */
+extern DECLSPEC int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect,
+ SDL_Surface *dst, SDL_Rect *dstrect);
+
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
diff --git a/src/audio/macrom/SDL_romaudio.c b/src/audio/macrom/SDL_romaudio.c
index 6ecaef93b..065a4894b 100644
--- a/src/audio/macrom/SDL_romaudio.c
+++ b/src/audio/macrom/SDL_romaudio.c
@@ -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) {
diff --git a/src/main/macosx/SDLMain.h b/src/main/macosx/SDLMain.h
new file mode 100644
index 000000000..a30735527
--- /dev/null
+++ b/src/main/macosx/SDLMain.h
@@ -0,0 +1,8 @@
+#import
+
+@interface SDLMain : NSObject
+{
+}
+- (IBAction)quit:(id)sender;
+- (IBAction)makeFullscreen:(id)sender;
+@end
diff --git a/src/main/macosx/SDLMain.m b/src/main/macosx/SDLMain.m
new file mode 100644
index 000000000..1c5f0dc21
--- /dev/null
+++ b/src/main/macosx/SDLMain.m
@@ -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 /* for MAXPATHLEN */
+#import
+
+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;
+}
\ No newline at end of file
diff --git a/src/main/macosx/exports/Makefile b/src/main/macosx/exports/Makefile
new file mode 100644
index 000000000..15f801f79
--- /dev/null
+++ b/src/main/macosx/exports/Makefile
@@ -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)
diff --git a/src/main/macosx/exports/SDL.x b/src/main/macosx/exports/SDL.x
new file mode 100644
index 000000000..40cefc157
--- /dev/null
+++ b/src/main/macosx/exports/SDL.x
@@ -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
diff --git a/src/main/macosx/exports/gendef.pl b/src/main/macosx/exports/gendef.pl
new file mode 100644
index 000000000..82c0710cc
--- /dev/null
+++ b/src/main/macosx/exports/gendef.pl
@@ -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 () {
+ if ( /DECLSPEC.*\s\**([^\s\(]+)\(/ ) {
+ print "\t_$1\n";
+ } elsif ( /DECLSPEC.*\s\**([^\s\(]+)$/ ) {
+ print "\t_$1\n";
+ }
+ }
+ close(FILE);
+}
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index ae079c396..783129768 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -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;
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index a9470b35a..fca9754e1 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -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
diff --git a/src/video/macrom/SDL_romvideo.c b/src/video/macrom/SDL_romvideo.c
index b73c17bea..5dcada350 100644
--- a/src/video/macrom/SDL_romvideo.c
+++ b/src/video/macrom/SDL_romvideo.c
@@ -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
+#include
#endif
#else
#include
diff --git a/src/video/quartz/Makefile.am b/src/video/quartz/Makefile.am
new file mode 100644
index 000000000..b846af896
--- /dev/null
+++ b/src/video/quartz/Makefile.am
@@ -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
diff --git a/src/video/quartz/SDL_QuartzEvents.m b/src/video/quartz/SDL_QuartzEvents.m
new file mode 100644
index 000000000..ac94d0585
--- /dev/null
+++ b/src/video/quartz/SDL_QuartzEvents.m
@@ -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> 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);
+}
+
diff --git a/src/video/quartz/SDL_QuartzKeys.h b/src/video/quartz/SDL_QuartzKeys.h
new file mode 100644
index 000000000..7c08f268a
--- /dev/null
+++ b/src/video/quartz/SDL_QuartzKeys.h
@@ -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
diff --git a/src/video/quartz/SDL_QuartzVideo.h b/src/video/quartz/SDL_QuartzVideo.h
new file mode 100644
index 000000000..05f4e3cfd
--- /dev/null
+++ b/src/video/quartz/SDL_QuartzVideo.h
@@ -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
+#include
+#include
+#include
+
+#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);*/
diff --git a/src/video/quartz/SDL_QuartzVideo.m b/src/video/quartz/SDL_QuartzVideo.m
new file mode 100644
index 000000000..c142a5503
--- /dev/null
+++ b/src/video/quartz/SDL_QuartzVideo.m
@@ -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 ];
+}
diff --git a/src/video/quartz/SDL_QuartzWM.m b/src/video/quartz/SDL_QuartzWM.m
new file mode 100644
index 000000000..c997d7045
--- /dev/null
+++ b/src/video/quartz/SDL_QuartzWM.m
@@ -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; rowcurs.data[row], data, bytes);
+ data += w/8;
+ }
+ for ( row=0; rowcurs.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;
+}
diff --git a/src/video/quartz/SDL_QuartzWindow.m b/src/video/quartz/SDL_QuartzWindow.m
new file mode 100644
index 000000000..dd0f4f035
--- /dev/null
+++ b/src/video/quartz/SDL_QuartzWindow.m
@@ -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
diff --git a/test/testtypes.c b/test/testtypes.c
index 0c34a71ce..3ed73f077 100644
--- a/test/testtypes.c
+++ b/test/testtypes.c
@@ -1,6 +1,6 @@
#include
-
+#include "SDL_main.h"
#include "SDL_types.h"
int main(int argc, char *argv[])