Commits

brian  committed 401c014

Removing PyObjC dependency

  • Participants
  • Parent commits bb0a859

Comments (0)

Files changed (8)

File Setup_Darwin.in

+#This file defines platform specific modules for mac os x
+sdlmain_osx src/sdlmain_osx.m $(SDL) $(DEBUG)
     else:
         dep.line = dep.name+' =' + inc + lid + ' ' + dep.cflags + libs
 
-def writesetupfile(deps, basepath):
+def writesetupfile(deps, basepath, additional_lines):
     "create a modified copy of Setup.in"
     origsetup = open('Setup.in', 'r')
     newsetup = open('Setup', 'w')
     for d in deps:
         newsetup.write(d.line + '\n')
 
-    while line:
-        line = origsetup.readline()
+    lines = origsetup.readlines()
+    lines.extend(additional_lines)
+    for line in lines:
         useit = 1
         if not line.startswith('COPYLIB'):
             for d in deps:
                     newsetup.write('#'+line)
                     break
         if useit:
-            newsetup.write(line)
+            newsetup.write(line)        
 
 def main():
+    additional_platform_setup = []
     if sys.platform == 'win32' and not is_msys_mingw():
         print_('Using WINDOWS configuration...\n')
         import config_win as CFG
     elif sys.platform == 'darwin':
         print_('Using Darwin configuration...\n')
         import config_darwin as CFG
+        additional_platform_setup = file("Setup_Darwin.in", "r").readlines()
     else:
         print_('Using UNIX configuration...\n')
         import config_unix as CFG
         basepath = None
         for d in deps:
             prepdep(d, basepath)
-        writesetupfile(deps, basepath)
+        writesetupfile(deps, basepath, additional_platform_setup)
         print_("""\nIf you get compiler errors during install, doublecheck
 the compiler flags in the "Setup" file.\n""")
     else:

File config_darwin.py

     for d in DEPS:
         d.configure(incdirs, libdirs)
     DEPS[0].cflags = '-Ddarwin '+ DEPS[0].cflags
-    try:
-        import objc
-    except ImportError:
-        raise SystemExit, "Pygame requires PyObjC version 1.1 or above."
     return DEPS
 
 

File lib/__init__.py

 """
 
 import sys, os, string
-def _check_darwin():
-    try:
-        from objc import loadBundleFunctions
-        import AppKit
-        import Foundation
-    except ImportError:
-        raise ImportError("PyObjC 1.2 or later is required to use pygame on Mac OS X. http://pygame.org/wiki/PyObjC")
-
-if sys.platform == 'darwin':
-    _check_darwin()
-
 
 # check if is old windows... if so use directx video driver by default.
 # if someone sets this respect their setting...

File lib/macosx.py

-from Foundation import *
-from AppKit import *
 import os, sys
-import objc
 import MacOS
 from pygame.pkgdata import getResource
-from pygame.base import get_sdl_version
 
-__all__ = ['init']
+from pygame import sdlmain_osx
 
-# Need to do this if not running with a nib
-def setupAppleMenu(app):
-    appleMenuController = NSAppleMenuController.alloc().init()
-    appleMenuController.retain()
-    appleMenu = NSMenu.alloc().initWithTitle_('')
-    appleMenuItem = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_('', None, '')
-    appleMenuItem.setSubmenu_(appleMenu)
-    app.mainMenu().addItem_(appleMenuItem)
-    appleMenuController.controlMenu_(appleMenu)
-    app.mainMenu().removeItem_(appleMenuItem)
-    
-# Need to do this if not running with a nib
-def setupWindowMenu(app):
-    windowMenu = NSMenu.alloc().initWithTitle_('Window')
-    windowMenu.retain()
-    menuItem = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_('Minimize', 'performMiniaturize:', 'm')
-    windowMenu.addItem_(menuItem)
-    windowMenuItem = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_('Window', None, '')
-    windowMenuItem.setSubmenu_(windowMenu)
-    app.mainMenu().addItem_(windowMenuItem)
-    app.setWindowsMenu_(windowMenu)
+__all__ = ['Video_AutoInit']
 
-# Used to cleanly terminate
-class PyGameAppDelegate(NSObject):
-    def applicationShouldTerminate_(self, app):
-        import pygame.event
-        pygame.event.post(pygame.event.Event(pygame.QUIT))
-        return NSTerminateLater
-
-    def windowUpdateNotification_(self, notification):
-        win = notification.object()
-        if get_sdl_version() < (1, 2, 8) and isinstance(win, objc.lookUpClass('SDL_QuartzWindow')):
-            # Seems to be a retain count bug in SDL.. workaround!
-            win.retain()
-        NSNotificationCenter.defaultCenter().removeObserver_name_object_(
-            self, NSWindowDidUpdateNotification, None)
-        self.release()
-
-def setIcon(app):
-    try:
-        defaultIcon = getResource('pygame_icon.tiff').read()
-    except IOError:
-        return
-    data = NSData.dataWithBytes_length_(defaultIcon, len(defaultIcon))
-    if data is None:
-        return
-    img = NSImage.alloc().initWithData_(data)
-    if img is None:
-        return
-    app.setApplicationIconImage_(img)
-
-def install():
-    app = NSApplication.sharedApplication()
-    setIcon(app)
-    appDelegate = PyGameAppDelegate.alloc().init()
-    app.setDelegate_(appDelegate)
-    appDelegate.retain()
-    NSNotificationCenter.defaultCenter().addObserver_selector_name_object_(
-        appDelegate,
-        'windowUpdateNotification:',
-        NSWindowDidUpdateNotification,
-        None)
-    if not app.mainMenu():
-        mainMenu = NSMenu.alloc().init()
-        app.setMainMenu_(mainMenu)
-        setupAppleMenu(app)
-        setupWindowMenu(app)
-    app.finishLaunching()
-    app.updateWindows()
-    app.activateIgnoringOtherApps_(True)
-
-def S(*args):
-    return ''.join(args)
-
-OSErr = objc._C_SHT
-OUTPSN = 'o^{ProcessSerialNumber=LL}'
-INPSN = 'n^{ProcessSerialNumber=LL}'
-
-FUNCTIONS=[
-    # These two are public API
-    ( u'GetCurrentProcess', S(OSErr, OUTPSN) ),
-    ( u'SetFrontProcess', S(OSErr, INPSN) ),
-    # This is undocumented SPI
-    ( u'CPSSetProcessName', S(OSErr, INPSN, objc._C_CHARPTR) ),
-    ( u'CPSEnableForegroundOperation', S(OSErr, INPSN) ),
-]
-
-def WMEnable(name=None):
-    if name is None:
-        name = os.path.splitext(os.path.basename(sys.argv[0]))[0]
-    if isinstance(name, unicode):
-        name = name.encode('utf-8')
-    if not hasattr(objc, 'loadBundleFunctions'):
-        return False
-    bndl = NSBundle.bundleWithPath_(objc.pathForFramework('/System/Library/Frameworks/ApplicationServices.framework'))
-    if bndl is None:
-        print >>sys.stderr, 'ApplicationServices missing'
-        return False
-    d = {}
-    app = NSApplication.sharedApplication()
-    objc.loadBundleFunctions(bndl, d, FUNCTIONS)
-    for (fn, sig) in FUNCTIONS:
-        if fn not in d:
-            print >>sys.stderr, 'Missing', fn
-            return False
-    err, psn = d['GetCurrentProcess']()
-    if err:
-        print >>sys.stderr, 'GetCurrentProcess', (err, psn)
-        return False
-    err = d['CPSSetProcessName'](psn, name)
-    if err:
-        print >>sys.stderr, 'CPSSetProcessName', (err, psn)
-        return False
-    err = d['CPSEnableForegroundOperation'](psn)
-    if err:
-        print >>sys.stderr, 'CPSEnableForegroundOperation', (err, psn)
-        return False
-    err = d['SetFrontProcess'](psn)
-    if err:
-        print >>sys.stderr, 'SetFrontProcess', (err, psn)
-        return False
-    return True
-
-def init():
-    if not (MacOS.WMAvailable() or WMEnable()):
-        raise ImportError, "Can not access the window manager.  Use py2app or execute with the pythonw script."
-    if not NSApp():
-        # running outside of a bundle
-        install()
-    # running inside a bundle, change dir
+def Video_AutoInit():
+    """This is a function that's called from the c extension code
+       just before the display module is initialized"""
+    if not MacOS.WMAvailable():
+        if not sdlmain_osx.WMEnable():
+            raise ImportError, "Can not access the window manager.  Use py2app or execute with the pythonw script."
+    if not sdlmain_osx.RunningFromBundleWithNSApplication():
+        try:
+            default_icon_data = getResource('pygame_icon.tiff').read()
+        except IOError:
+            default_icon_data = None
+        sdlmain_osx.InstallNSApplication(default_icon_data)
     if (os.getcwd() == '/') and len(sys.argv) > 1:
         os.chdir(os.path.dirname(sys.argv[0]))
     return True
     sys.argv.remove ("-setuptools")
 
 
-# NOTE: the pyobjc, and bdist_mpkg_support is for darwin.
+# NOTE: the bdist_mpkg_support is for darwin.
 try:
     import bdist_mpkg_support
     from setuptools import setup, Extension
 except:
     pass
 
-#get compile info for all extensions
-try: extensions = read_setup_file('Setup')
-except: raise SystemExit, """Error with the "Setup" file,
+# get compile info for all extensions
+try: 
+    extensions = read_setup_file('Setup')
+except: 
+    print """Error with the "Setup" file,
 perhaps make a clean copy from "Setup.in"."""
+    raise
 
 
 #extra files to install
         PyObject *rval;
         module = PyImport_ImportModule ("pygame.macosx");
         if (!module)
+        {
+        	printf("ERROR: pygame.macosx import FAILED\n");
             return -1;
+        }
 
-        rval = PyObject_CallMethod (module, "init", "");
+        rval = PyObject_CallMethod (module, "Video_AutoInit", "");
         Py_DECREF (module);
         if (!rval)
+        {
+        	printf("ERROR: pygame.macosx.Video_AutoInit() call FAILED\n");
             return -1;
+        }
 
         status = PyObject_IsTrue (rval);
         Py_DECREF (rval);

File src/sdlmain_osx.m

+/*
+    pygame - Python Game Library
+    Copyright (C) 2009 Brian Fisher
+
+    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
+*/
+
+/* Mac OS X functions to accommodate the fact SDLMain.m is not included */
+
+#include "pygame.h"
+#include <Carbon/Carbon.h>
+#include <Foundation/Foundation.h>
+#include <AppKit/NSApplication.h>
+#include <AppKit/NSMenuItem.h>
+#include <AppKit/NSMenu.h>
+#include <AppKit/NSEvent.h>
+#include <Foundation/NSData.h>
+#include <AppKit/NSImage.h>
+
+struct CPSProcessSerNum
+{
+	UInt32 lo;
+	UInt32 hi;
+};
+typedef struct CPSProcessSerNum CPSProcessSerNum;
+
+extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn);
+extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
+extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
+extern OSErr CPSSetProcessName ( CPSProcessSerNum *psn, const char *processname );
+
+static NSString *getApplicationName(void)
+{
+    const NSDictionary *dict;
+    NSString *appName = 0;
+
+    /* Determine the application name */
+    dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
+    if (dict)
+        appName = [dict objectForKey: @"CFBundleName"];
+    
+    if (![appName length])
+        appName = [[NSProcessInfo processInfo] processName];
+
+    return appName;
+}
+
+static PyObject*
+_WMEnable(PyObject* self)
+{
+	CPSProcessSerNum psn;
+    OSErr err;
+    const char* nameString;
+    NSString* nameNSString;
+    
+    err = CPSGetCurrentProcess(&psn);
+    if (err == 0)
+    {
+    	nameNSString = getApplicationName();
+    	nameString = [nameNSString UTF8String];
+    	CPSSetProcessName(&psn, nameString);
+
+        err = CPSEnableForegroundOperation(&psn,0x03,0x3C,0x2C,0x1103);
+        if (err == 0)
+        {
+        	err = CPSSetFrontProcess(&psn);
+        	if (err != 0)
+        	{
+            	return RAISE (PyExc_SDLError, "CPSSetFrontProcess failed");        		
+        	}
+        }
+        else
+        {
+        	return RAISE (PyExc_SDLError, "CPSEnableForegroundOperation failed");
+        }
+    }
+    else
+    {
+    	return RAISE (PyExc_SDLError, "CPSGetCurrentProcess failed");
+    }
+    
+    Py_RETURN_TRUE;
+}
+
+static PyObject*
+_RunningFromBundleWithNSApplication(PyObject* self)
+{
+	CFBundleRef MainBundle = CFBundleGetMainBundle();
+	if (MainBundle != NULL)
+	{
+		if (CFBundleGetDataPointerForName(MainBundle, CFSTR("NSApp")) != NULL)
+		{
+			Py_RETURN_TRUE;
+		}
+	}
+    Py_RETURN_FALSE;
+}
+
+//#############################################################################
+// Defining the NSApplication class we will use
+//#############################################################################
+@interface SDLApplication : NSApplication
+@end
+
+/* For some reaon, Apple removed setAppleMenu from the headers in 10.4,
+ but the method still is there and works. To avoid warnings, we declare
+ it ourselves here. */
+@interface NSApplication(SDL_Missing_Methods)
+- (void)setAppleMenu:(NSMenu *)menu;
+@end
+
+@implementation SDLApplication
+/* Invoked from the Quit menu item */
+- (void)terminate:(id)sender
+{
+    SDL_Event event;
+    event.type = SDL_QUIT;
+    SDL_PushEvent(&event);
+}
+@end
+
+static void setApplicationMenu(void)
+{
+    NSMenu *appleMenu;
+    NSMenuItem *menuItem;
+    NSString *title;
+    NSString *appName;
+    
+    appName = getApplicationName();
+    appleMenu = [[NSMenu alloc] initWithTitle:@""];
+    
+
+    title = [@"About " stringByAppendingString:appName];
+    [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
+
+    [appleMenu addItem:[NSMenuItem separatorItem]];
+
+    title = [@"Hide " stringByAppendingString:appName];
+    [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
+
+    menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
+    [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
+
+    [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
+
+    [appleMenu addItem:[NSMenuItem separatorItem]];
+
+    title = [@"Quit " stringByAppendingString:appName];
+    [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
+
+    
+    menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
+    [menuItem setSubmenu:appleMenu];
+    [[NSApp mainMenu] addItem:menuItem];
+
+    [NSApp setAppleMenu:appleMenu];
+
+    [appleMenu release];
+    [menuItem release];
+}
+
+static void setupWindowMenu(void)
+{
+    NSMenu      *windowMenu;
+    NSMenuItem  *windowMenuItem;
+    NSMenuItem  *menuItem;
+
+    windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+    
+    menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
+    [windowMenu addItem:menuItem];
+    [menuItem release];
+    
+    windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
+    [windowMenuItem setSubmenu:windowMenu];
+    [[NSApp mainMenu] addItem:windowMenuItem];
+    
+    [NSApp setWindowsMenu:windowMenu];
+
+    [windowMenu release];
+    [windowMenuItem release];
+}
+
+static PyObject*
+_InstallNSApplication(PyObject* self, PyObject* arg)
+{
+    char* icon_data = NULL;
+    int data_len = 0;
+
+    NSAutoreleasePool	*pool = [[NSAutoreleasePool alloc] init];
+
+    [SDLApplication sharedApplication];
+
+    if (PyArg_ParseTuple (arg, "|z#", &icon_data, &data_len))
+    {
+        NSData *image_data = [NSData dataWithBytes:icon_data length:data_len];
+	    NSImage *icon_img = [[NSImage alloc] initWithData:image_data];
+	    if (icon_img != NULL)
+	    {
+	    	[NSApp setApplicationIconImage:icon_img];
+	    }
+    }
+
+    [NSApp setMainMenu:[[NSMenu alloc] init]];
+    setApplicationMenu();
+    setupWindowMenu();
+
+    [NSApp finishLaunching];
+    [NSApp updateWindows];
+    [NSApp activateIgnoringOtherApps:true];
+
+	Py_RETURN_TRUE;
+}
+
+static PyMethodDef macosx_builtins[] =
+{
+    { "WMEnable", (PyCFunction) _WMEnable, METH_NOARGS, "Enables Foreground Operation when Window Manager is not available" },
+    { "RunningFromBundleWithNSApplication", (PyCFunction) _RunningFromBundleWithNSApplication, METH_NOARGS, "Returns true if we are running from an AppBundle with a variable named NSApp" },
+    { "InstallNSApplication", _InstallNSApplication, METH_VARARGS, "Creates an NSApplication with the right behaviors for SDL" },
+    { NULL, NULL, 0, NULL}
+};
+
+PYGAME_EXPORT
+void initsdlmain_osx (void)
+{
+    PyObject *mod;
+
+    /* create the module */
+    mod = Py_InitModule3 ("sdlmain_osx", macosx_builtins, NULL);
+
+    /*imported needed apis*/
+    import_pygame_base ();
+}