1#!/usr/bin/pythonw
2"""
3This is an evil undocumented SPI hack that shows how to enable GUI operation
4from a console application.
5
6BUNDLES ARE RECOMMENDED, USE THIS AT YOUR OWN RISK!!
7"""
8import os
9import sys
10import objc
11from Foundation import *
12
13def S(*args):
14    return ''.join(args)
15
16OSErr = objc._C_SHT
17OUTPSN = 'o^{ProcessSerialNumber=LL}'
18INPSN = 'n^{ProcessSerialNumber=LL}'
19
20FUNCTIONS=[
21    # These two are public API
22    ( u'GetCurrentProcess', S(OSErr, OUTPSN) ),
23    ( u'SetFrontProcess', S(OSErr, INPSN) ),
24    # This is undocumented SPI
25    ( u'CPSSetProcessName', S(OSErr, INPSN, objc._C_CHARPTR) ),
26    ( u'CPSEnableForegroundOperation', S(OSErr, INPSN) ),
27]
28
29def WMEnable(name='Python'):
30    if isinstance(name, unicode):
31        name = name.encode('utf8')
32    mainBundle = NSBundle.mainBundle()
33    bPath = os.path.split(os.path.split(os.path.split(sys.executable)[0])[0])[0]
34    if mainBundle.bundlePath() == bPath:
35        return True
36    bndl = NSBundle.bundleWithPath_(objc.pathForFramework('/System/Library/Frameworks/ApplicationServices.framework'))
37    if bndl is None:
38        print >>sys.stderr, 'ApplicationServices missing'
39        return False
40    d = {}
41    objc.loadBundleFunctions(bndl, d, FUNCTIONS)
42    for (fn, sig) in FUNCTIONS:
43        if fn not in d:
44            print >>sys.stderr, 'Missing', fn
45            return False
46    err, psn = d['GetCurrentProcess']()
47    if err:
48        print >>sys.stderr, 'GetCurrentProcess', (err, psn)
49        return False
50    err = d['CPSSetProcessName'](psn, name)
51    if err:
52        print >>sys.stderr, 'CPSSetProcessName', (err, psn)
53        return False
54    err = d['CPSEnableForegroundOperation'](psn)
55    if err:
56        print >>sys.stderr, 'CPSEnableForegroundOperation', (err, psn)
57        return False
58    err = d['SetFrontProcess'](psn)
59    if err:
60        print >>sys.stderr, 'SetFrontProcess', (err, psn)
61        return False
62    return True
63
64class AppDelegate(NSObject):
65    def applicationDidFinishLaunching_(self, sender):
66        rval = AppKit.NSRunAlertPanel(u'WM Enabled', u'WM was enabled!', None, None, None)
67        AppKit.NSApp().terminate_(self)
68
69if __name__ == "__main__":
70    import sys
71    if WMEnable(os.path.basename(os.path.splitext(sys.argv[0])[0])):
72        import AppKit
73        app = AppKit.NSApplication.sharedApplication()
74        delegate = AppDelegate.alloc().init()
75        app.setDelegate_(delegate)
76        app.run()
77    else:
78        print 'WM was not enabled'
79