##// END OF EJS Templates
Wake the main loop with an event
Min RK -
Show More
@@ -1,104 +1,121 b''
1 1
2 2 # obj-c boilerplate from appnope, used under BSD 2-clause
3 3
4 4 import ctypes
5 5 import ctypes.util
6 6
7 7 objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('objc'))
8 8 CoreFoundation = ctypes.cdll.LoadLibrary(ctypes.util.find_library('CoreFoundation'))
9 # Cocoa = ctypes.cdll.LoadLibrary(ctypes.util.find_library('Cocoa'))
10 9
11 10 void_p = ctypes.c_void_p
12 11
13 12 objc.objc_getClass.restype = void_p
14 13 objc.sel_registerName.restype = void_p
15 14 objc.objc_msgSend.restype = void_p
16 15 objc.objc_msgSend.argtypes = [void_p, void_p]
17 16
18 17 msg = objc.objc_msgSend
19 18
20 19 def _utf8(s):
21 20 """ensure utf8 bytes"""
22 21 if not isinstance(s, bytes):
23 22 s = s.encode('utf8')
24 23 return s
25 24
26 25 def n(name):
27 """create a selector name (for methods)"""
26 """create a selector name (for ObjC methods)"""
28 27 return objc.sel_registerName(_utf8(name))
29 28
30 29 def C(classname):
31 30 """get an ObjC Class by name"""
32 31 return objc.objc_getClass(_utf8(classname))
33 32
34 33 # CoreFoundation calls we will use:
35 34 CFFileDescriptorCreate = CoreFoundation.CFFileDescriptorCreate
36 35 CFFileDescriptorCreate.restype = void_p
37 36 CFFileDescriptorCreate.argtypes = [void_p, ctypes.c_int, ctypes.c_bool, void_p]
38 37
39 38 CFFileDescriptorGetNativeDescriptor = CoreFoundation.CFFileDescriptorGetNativeDescriptor
40 39 CFFileDescriptorGetNativeDescriptor.restype = ctypes.c_int
41 40 CFFileDescriptorGetNativeDescriptor.argtypes = [void_p]
42 41
43 42 CFFileDescriptorEnableCallBacks = CoreFoundation.CFFileDescriptorEnableCallBacks
44 43 CFFileDescriptorEnableCallBacks.restype = None
45 44 CFFileDescriptorEnableCallBacks.argtypes = [void_p, ctypes.c_ulong]
46 45
47 46 CFFileDescriptorCreateRunLoopSource = CoreFoundation.CFFileDescriptorCreateRunLoopSource
48 47 CFFileDescriptorCreateRunLoopSource.restype = void_p
49 48 CFFileDescriptorCreateRunLoopSource.argtypes = [void_p, void_p, void_p]
50 49
51 50 CFRunLoopGetCurrent = CoreFoundation.CFRunLoopGetCurrent
52 51 CFRunLoopGetCurrent.restype = void_p
53 52
54 53 CFRunLoopAddSource = CoreFoundation.CFRunLoopAddSource
55 54 CFRunLoopAddSource.restype = None
56 55 CFRunLoopAddSource.argtypes = [void_p, void_p, void_p]
57 56
58 57 CFRelease = CoreFoundation.CFRelease
59 58 CFRelease.restype = None
60 59 CFRelease.argtypes = [void_p]
61 60
62 61 CFFileDescriptorInvalidate = CoreFoundation.CFFileDescriptorInvalidate
63 62 CFFileDescriptorInvalidate.restype = None
64 63 CFFileDescriptorInvalidate.argtypes = [void_p]
65 64
66
67 65 # From CFFileDescriptor.h
68 66 kCFFileDescriptorReadCallBack = 1
69 67 kCFRunLoopCommonModes = void_p.in_dll(CoreFoundation, 'kCFRunLoopCommonModes')
70 68
71 69 def _NSApp():
72 70 """Return the global NSApplication instance (NSApp)"""
73 71 return msg(C('NSApplication'), n('sharedApplication'))
74 72
73 def _wake(NSApp):
74 """Wake the Application"""
75 event = msg(C('NSEvent'),
76 n('otherEventWithType:location:modifierFlags:'
77 'timestamp:windowNumber:context:subtype:data1:data2:'),
78 15, # Type
79 0, # location
80 0, # flags
81 0, # timestamp
82 0, # window
83 None, # context
84 0, # subtype
85 0, # data1
86 0, # data2
87 )
88 msg(NSApp, n('postEvent:atStart:'), void_p(event), True)
89
75 90 def _input_callback(fdref, flags, info):
76 91 """Callback to fire when there's input to be read"""
77 92 CFFileDescriptorInvalidate(fdref)
78 93 CFRelease(fdref)
79 94 NSApp = _NSApp()
80 95 msg(NSApp, n('stop:'), NSApp)
96 _wake(NSApp)
81 97
82 98 _c_callback_func_type = ctypes.CFUNCTYPE(None, void_p, void_p, void_p)
83 _c_callback = _c_callback_func_type(_input_callback)
99 _c_input_callback = _c_callback_func_type(_input_callback)
84 100
85 101 def _stop_on_read(fd):
86 102 """Register callback to stop eventloop when there's data on fd"""
87 fdref = CFFileDescriptorCreate(None, fd, False, _c_callback, None)
103 fdref = CFFileDescriptorCreate(None, fd, False, _c_input_callback, None)
88 104 CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack)
89 105 source = CFFileDescriptorCreateRunLoopSource(None, fdref, 0)
90 106 loop = CFRunLoopGetCurrent()
91 107 CFRunLoopAddSource(loop, source, kCFRunLoopCommonModes)
92 108 CFRelease(source)
93 109
94 110 def inputhook(context):
95 111 """Inputhook for Cocoa (NSApp)"""
96 112 NSApp = _NSApp()
97 113 window_count = msg(
98 114 msg(NSApp, n('windows')),
99 115 n('count')
100 116 )
101 117 if not window_count:
102 118 return
103 119 _stop_on_read(context.fileno())
104 120 msg(NSApp, n('run'))
121
General Comments 0
You need to be logged in to leave comments. Login now