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']
# 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)
# 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
if (os.getcwd() == '/') and len(sys.argv) > 1:
os.chdir(os.path.dirname(sys.argv[0]))
return True
syntax highlighted by Code2HTML, v. 0.9.1