Date: Tue, 21 Aug 2001 03:50:01 +0200
authorSam Lantinga <slouken@libsdl.org>
Tue, 21 Aug 2001 07:19:59 +0000
changeset 158 4382c38dfbee
parent 157 de04f423389a
child 159 9841293e9e86
Date: Tue, 21 Aug 2001 03:50:01 +0200 From: Max Horn <max@quendi.de> Subject: New patch for OS X Attached a .patch file for SDL/OSX with some nice bug fixes / enhancments. * fixes the activation issues, which also caused the window to be always drawn like an inactive. The close/minimize widgets now are animated properly, too. * the menu items are automatically adjusted to use the app name instead of just "SDL App". I did this so that we really can use one central SDLMain.nib file, w/o requiring developers to make a copy of it and adjust it. * libSDLMain now contains the proper cocoa code, not as before the carbon code. This means apps no longer have to carry a copy of SDLMain.m/SDLMain.h * revamped configure.in to properly build a Cocoa/Quartz SDL lib, not a Carbon based SDL lib
configure.in
src/main/Makefile.am
src/main/macosx/SDLMain.h
src/main/macosx/SDLMain.m
src/video/quartz/SDL_QuartzEvents.m
src/video/quartz/SDL_QuartzVideo.h
src/video/quartz/SDL_QuartzVideo.m
src/video/quartz/SDL_QuartzWM.m
--- a/configure.in	Mon Aug 20 04:41:49 2001 +0000
+++ b/configure.in	Tue Aug 21 07:19:59 2001 +0000
@@ -63,10 +63,6 @@
     *-*-linux*)
         AC_PROG_CXX
         ;;
-    *-*-darwin*)
-        OBJC="???"
-        AC_SUBST(OBJC)
-        ;;
 esac
 AC_PROG_INSTALL
 AC_FUNC_ALLOCA
@@ -1192,6 +1188,21 @@
     VIDEO_DRIVERS="$VIDEO_DRIVERS macrom/libvideo_macrom.la"
 }
 
+dnl Set up the Mac toolbox video driver for Mac OS X
+CheckQUARTZ()
+{
+    # "MACOSX" is not an official definition, but it's commonly
+    # accepted as a way to differentiate between what runs on X
+    # and what runs on older Macs - while in theory "Carbon" defns
+    # are consistent between the two, in practice Carbon is still
+    # changing. -sts Aug 2000
+    CFLAGS="$CFLAGS -I/System/Library/Frameworks/Carbon.framework/Headers \
+      -I/System/Library/Frameworks/Cocoa.framework/Headers -fpascal-strings \
+      -DENABLE_QUARTZ -DMACOSX -DTARGET_API_MAC_CARBON=1 -I\$(top_srcdir)/src/video/quartz"
+    VIDEO_SUBDIRS="$VIDEO_SUBDIRS quartz"
+    VIDEO_DRIVERS="$VIDEO_DRIVERS quartz/libvideo_quartz.la"
+}
+
 dnl Set up the kernel statistics library for Solaris
 CheckKSTAT()
 {
@@ -1994,17 +2005,17 @@
         ;;
     *-*-darwin* )
         # Strictly speaking, we want "Mac OS X", not "Darwin", which is
-        # just the OS X kernel sans upper layers like Carbon.  But
-        # config.guess comes back with "darwin", so go with the flow.
-        ARCH=macos
+        # just the OS X kernel sans upper layers like Carbon and Cocoa.
+        # But config.guess comes back with "darwin", so go with the flow.
+        ARCH=macosx
         CheckDummyVideo
         CheckDiskAudio
-        CheckCARBON
+        CheckQUARTZ
         CheckMacGL
         CheckPTHREAD
         # Set up files for the main() stub
-        # COPY_ARCH_SRC(src/main, macos, SDL_main.c)
-        COPY_ARCH_SRC(src/main, linux, SDL_main.c)
+        COPY_ARCH_SRC(src/main, macosx, SDLmain.m)
+        COPY_ARCH_SRC(src/main, macosx, SDLmain.h)
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
             AUDIO_SUBDIRS="$AUDIO_SUBDIRS macrom"
@@ -2040,8 +2051,8 @@
             COPY_ARCH_SRC(src/timer, linux, SDL_systimer.c)
         fi
         # The MacOS X platform requires special setup
-        SDL_CFLAGS="$SDL_CFLAGS -F/System/Library/Frameworks/Carbon.framework"
-        SDL_LIBS="-lSDLmain $SDL_LIBS -framework Carbon"
+        SDL_CFLAGS="$SDL_CFLAGS -F/System/Library/Frameworks/Carbon.framework -F/System/Library/Frameworks/Cocoa.framework"
+        SDL_LIBS="-lSDLmain $SDL_LIBS -framework Carbon -framework Cocoa"
         ;;
     *)
         AC_MSG_ERROR(Unsupported target:  Please add to configure.in)
@@ -2061,6 +2072,7 @@
 AM_CONDITIONAL(TARGET_WIN32, test $ARCH = win32)
 AM_CONDITIONAL(TARGET_BEOS, test $ARCH = beos)
 AM_CONDITIONAL(TARGET_MACOS, test $ARCH = macos)
+AM_CONDITIONAL(TARGET_MACOSX, test $ARCH = macosx)
 
 # Set conditional variables for shared and static library selection.
 # These are not used in any Makefile.am but in sdl-config.in.
@@ -2122,6 +2134,18 @@
 CFLAGS="$CFLAGS -I\$(top_srcdir)/src/file"
 CXXFLAGS="$CFLAGS"
 
+
+# Check for darwin at the very end and set up the Objective C compiler
+# We do this here so that we get the full CFLAGS into OBJCFLAGS
+case "$target" in
+    *-*-darwin*)
+        OBJC="cc"
+        OBJCFLAGS="$CFLAGS"
+        AC_SUBST(OBJC)
+        AC_SUBST(OBJCFLAGS)
+        ;;
+esac
+
 # Finally create all the generated files
 dnl Important: Any directory that you want to be in the distcheck should
 dnl            have a file listed here, so that configure generates the
--- a/src/main/Makefile.am	Mon Aug 20 04:41:49 2001 +0000
+++ b/src/main/Makefile.am	Tue Aug 21 07:19:59 2001 +0000
@@ -10,7 +10,11 @@
 # Build a separate library containing the main() entry point.
 lib_LIBRARIES = libSDLmain.a
 
+if TARGET_MACOSX
+MAINLIB_ARCH_SRCS = SDLmain.m SDLmain.h
+else
 MAINLIB_ARCH_SRCS = SDL_main.c
+endif
 
 libSDLmain_a_SOURCES = $(MAINLIB_ARCH_SRCS)
 
--- a/src/main/macosx/SDLMain.h	Mon Aug 20 04:41:49 2001 +0000
+++ b/src/main/macosx/SDLMain.h	Tue Aug 21 07:19:59 2001 +0000
@@ -1,7 +1,14 @@
+/*   SDLMain.h - 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 <Cocoa/Cocoa.h>
 
 @interface SDLMain : NSObject
 {
 }
 - (IBAction)quit:(id)sender;
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
 @end
--- a/src/main/macosx/SDLMain.m	Mon Aug 20 04:41:49 2001 +0000
+++ b/src/main/macosx/SDLMain.m	Tue Aug 21 07:19:59 2001 +0000
@@ -11,6 +11,12 @@
 
 static int    gArgc;
 static char  **gArgv;
+static NSString *gAppName = 0;
+
+@interface NSString (ReplaceSubString)
+- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString;
+@end
+
 
 /* The main class of the application, the application's delegate */
 @implementation SDLMain
@@ -18,9 +24,9 @@
 /* Invoked from the Quit menu item */
 - (void) quit:(id)sender
 {
-    	SDL_Event event;
-	event.type = SDL_QUIT;
-	SDL_PushEvent(&event);
+    SDL_Event event;
+    event.type = SDL_QUIT;
+    SDL_PushEvent(&event);
 }
 
 /* Set the working directory to the .app's parent directory */
@@ -29,7 +35,7 @@
     char parentdir[MAXPATHLEN];
     char *c;
     
-    strncpy ( parentdir, gArgv[0], MAXPATHLEN );
+    strncpy ( parentdir, gArgv[0], sizeof(parentdir) );
     c = (char*) parentdir;
     
     while (*c != '\0')     /* go to end */
@@ -38,10 +44,35 @@
     while (*c != '/')      /* back up to parent */
         c--;
     
-    *c = '\0';             /* cut off last part (binary name) */
+    *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 */
+    
+    gAppName = [ NSString stringWithCString: c ];
+}
+
+/* Fix menu to contain the real app name instead of "SDL App" */
+- (void) fixMenu:(NSMenu *)aMenu
+{
+    NSRange aRange;
+    NSEnumerator *enumerator;
+    NSMenuItem *menuItem;
+
+    aRange = [[aMenu title] rangeOfString:@"SDL App"];
+    if (aRange.length != 0)
+        [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:gAppName]];
+
+    enumerator = [[aMenu itemArray] objectEnumerator];
+    while ((menuItem = [enumerator nextObject]))
+    {
+        aRange = [[menuItem title] rangeOfString:@"SDL App"];
+        if (aRange.length != 0)
+            [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:gAppName]];
+        if ([menuItem hasSubmenu])
+            [self fixMenu: [menuItem submenu]];
+    }
+    [ aMenu sizeToFit ];
 }
 
 /* Called when the internal event loop has just started running */
@@ -52,6 +83,9 @@
     /* Set the working directory to the .app's parent directory */
     [ self setupWorkingDirectory ];
 
+    /* Set the main menu to contain the real app name instead of "SDL App" */
+    [ self fixMenu: [ NSApp mainMenu ] ];
+
     /* Hand off to main application code */
     status = SDL_main (gArgc, gArgv);
 
@@ -60,6 +94,47 @@
 }
 @end
 
+
+@implementation NSString (ReplaceSubString)
+
+- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString
+{
+    unsigned int bufferSize;
+    unsigned int selfLen = [self length];
+    unsigned int aStringLen = [aString length];
+    unichar *buffer;
+    NSRange localRange;
+    NSString *result;
+
+    bufferSize = selfLen + aStringLen - aRange.length;
+    buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar));
+    
+    // Get first part into buffer
+    localRange.location = 0;
+    localRange.length = aRange.location;
+    [self getCharacters:buffer range:localRange];
+    
+    // Get middle part into buffer
+    localRange.location = 0;
+    localRange.length = aStringLen;
+    [aString getCharacters:(buffer+aRange.location) range:localRange];
+     
+    // Get last part into buffer
+    localRange.location = aRange.location + aRange.length;
+    localRange.length = selfLen - localRange.location;
+    [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
+    
+    // Build output string
+    result = [NSString stringWithCharacters:buffer length:bufferSize];
+    
+    NSDeallocateMemoryPages(buffer, bufferSize);
+    
+    return result;
+}
+
+@end
+
+
 #ifdef main
 #  undef main
 #endif
--- a/src/video/quartz/SDL_QuartzEvents.m	Mon Aug 20 04:41:49 2001 +0000
+++ b/src/video/quartz/SDL_QuartzEvents.m	Tue Aug 21 07:19:59 2001 +0000
@@ -223,7 +223,7 @@
 }
 
 static void QZ_PumpEvents (_THIS)
-{ 
+{
     NSDate *distantPast;
     NSEvent *event;
     NSRect winRect;
@@ -247,27 +247,29 @@
     
         if (event != nil) {
             unsigned int type;
+            BOOL isForGameWin;
 
-            #define DO_MOUSE_DOWN(button, sendToWindow)                      \
+            #define DO_MOUSE_DOWN(button, sendToWindow) do {                 \
                 if ( inForeground ) {                                        \
                     if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) ||       \
                          NSPointInRect([event locationInWindow], winRect) )  \
                         SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0);  \
-                    else if (sendToWindow)                                   \
-                            [ window sendEvent:event ];                      \
                 }                                                            \
                 else {                                                       \
                     QZ_DoActivate (this);                                    \
-                }       
-            
-            #define DO_MOUSE_UP(button, sendToWindow)                        \
+                }                                                            \
+                [ NSApp sendEvent:event ];                                   \
+                } while(0)
+                
+            #define DO_MOUSE_UP(button, sendToWindow) do {                   \
                 if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) ||           \
                      !NSPointInRect([event locationInWindow], titleBarRect) )\
                     SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0);     \
-                if (sendToWindow)                                            \
-                    [ window sendEvent:event ]
-                    
+                [ NSApp sendEvent:event ];                                   \
+                } while(0)
+
             type = [ event type ];
+            isForGameWin = (qz_window == [ event window ]);
             switch (type) {
             
             case NSLeftMouseDown:  
@@ -351,8 +353,8 @@
             case NSFlagsChanged:
                 QZ_DoModifiers( [ event modifierFlags ] );
                 break;
-            case NSMouseEntered: break;
-            case NSMouseExited: break;
+//            case NSMouseEntered: break;
+//            case NSMouseExited: break;
             case NSAppKitDefined:
                 switch ( [ event subtype ] ) {
                 case NSApplicationActivatedEventType:
@@ -361,14 +363,14 @@
                 case NSApplicationDeactivatedEventType:
                     QZ_DoDeactivate (this);
                     break;
-                case NSWindowMovedEventType:
-                    [ window sendEvent:event ];
-                    break;
                 }
+                [ NSApp sendEvent:event ];
                 break;
-            case NSApplicationDefined: break;
-            case NSPeriodic: break;
-            case NSCursorUpdate: break;
+//            case NSApplicationDefined: break;
+//            case NSPeriodic: break;
+//            case NSCursorUpdate: break;
+            default:
+                [ NSApp sendEvent:event ];
             }
         }
       } while (event != nil);
--- a/src/video/quartz/SDL_QuartzVideo.h	Mon Aug 20 04:41:49 2001 +0000
+++ b/src/video/quartz/SDL_QuartzVideo.h	Tue Aug 21 07:19:59 2001 +0000
@@ -44,10 +44,6 @@
         - 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>
@@ -107,7 +103,7 @@
 #define device_bpp (this->hidden->bpp)
 #define mode_flags (this->hidden->flags)
 #define video_set (this->hidden->video_is_set)
-#define window (this->hidden->window)
+#define qz_window (this->hidden->window)
 #define windowView (this->hidden->view)
 
 /* Interface for hardware fill not (yet) in the public API */
--- a/src/video/quartz/SDL_QuartzVideo.m	Mon Aug 20 04:41:49 2001 +0000
+++ b/src/video/quartz/SDL_QuartzVideo.m	Tue Aug 21 07:19:59 2001 +0000
@@ -267,9 +267,9 @@
             UnlockPortBits ( [ windowView qdPort ] );
             [ windowView release  ];
         }
-        [ window setContentView:nil ];
-        [ window setDelegate:nil ];
-        [ window close ];
+        [ qz_window setContentView:nil ];
+        [ qz_window setDelegate:nil ];
+        [ qz_window close ];
     }
     
     /* Set pixels to null (so other code doesn't try to free it) */
@@ -408,9 +408,9 @@
     }
 
     /* Manually create a window, avoids having a nib file resource */
-    window = [ [ SDL_QuartzWindow alloc ] initWithContentRect:rect 
+    qz_window = [ [ SDL_QuartzWindow alloc ] initWithContentRect:rect 
         styleMask:style backing:NSBackingStoreBuffered defer:NO ];
-    if (window == nil) {
+    if (qz_window == nil) {
         SDL_SetError ("Could not create the Cocoa window");
         return NULL;
     }
@@ -419,12 +419,12 @@
     current->w = width;
     current->h = height;
     
-    [ window setReleasedWhenClosed:YES ];
+    [ qz_window setReleasedWhenClosed:YES ];
     QZ_SetCaption(this, this->wm_title, this->wm_icon);
-    [ window setAcceptsMouseMovedEvents:YES ];
-    [ window setViewsNeedDisplay:NO ];
-    [ window center ];
-    [ window setDelegate:
+    [ qz_window setAcceptsMouseMovedEvents:YES ];
+    [ qz_window setViewsNeedDisplay:NO ];
+    [ qz_window center ];
+    [ qz_window setDelegate:
         [ [ [ SDL_QuartzWindowDelegate alloc ] init ] autorelease ] ];
     
     /* For OpenGL, we set the content view to a NSOpenGLView */
@@ -434,17 +434,17 @@
             return NULL;
         }
         
-        [ gl_context setView: [ window contentView ] ];
+        [ gl_context setView: [ qz_window contentView ] ];
         [ gl_context makeCurrentContext];
-        [ window orderFront:nil ];
+        [ qz_window makeKeyAndOrderFront: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 ];    
+        [ qz_window setContentView:windowView ];
+        [ qz_window makeKeyAndOrderFront:nil ];    
         
         LockPortBits ( [ windowView qdPort ] );
         current->pixels = GetPixBaseAddr ( GetPortPixMap ( [ windowView qdPort ] ) );
--- a/src/video/quartz/SDL_QuartzWM.m	Mon Aug 20 04:41:49 2001 +0000
+++ b/src/video/quartz/SDL_QuartzWM.m	Tue Aug 21 07:19:59 2001 +0000
@@ -96,7 +96,7 @@
         /* Convert to absolute screen coordinates */
         NSPoint base, screen;
         base = NSMakePoint (p.x, p.y);
-        screen = [ window convertBaseToScreen:base ];
+        screen = [ qz_window convertBaseToScreen:base ];
         p.x = screen.x;
         p.y = device_height - screen.y;
         CGDisplayMoveCursorToPoint (display_id, p);
@@ -122,16 +122,16 @@
 
 static void QZ_SetCaption    (_THIS, const char *title, const char *icon) {
 
-    if ( window != nil ) {
+    if ( qz_window != nil ) {
         NSString *string;
         if ( title != NULL ) {
             string = [ [ NSString alloc ] initWithCString:title ];
-            [ window setTitle:string ];
+            [ qz_window setTitle:string ];
             [ string release ];
         }
         if ( icon != NULL ) {
             string = [ [ NSString alloc ] initWithCString:icon ];
-            [ window setMiniwindowTitle:string ];
+            [ qz_window setMiniwindowTitle:string ];
             [ string release ];
         }
     }
@@ -144,19 +144,19 @@
 static int  QZ_IconifyWindow (_THIS) { 
 
     /* Bug! minimize erases the framebuffer */
-    if ( ! [ window isMiniaturized ] ) {
-        [ window miniaturize:nil ];
+    if ( ! [ qz_window isMiniaturized ] ) {
+        [ qz_window miniaturize:nil ];
         return 1;
     }
     else {
-        SDL_SetError ("window already iconified");
+        SDL_SetError ("qz_window already iconified");
         return 0;
     }
 }
 
 /*
 static int  QZ_GetWMInfo  (_THIS, SDL_SysWMinfo *info) { 
-    info->nsWindowPtr = window;
+    info->nsWindowPtr = qz_window;
     return 0; 
 }*/