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