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