##// END OF EJS Templates
attempt reformat
attempt reformat

File last commit:

r26485:288afbf3
r27004:31a08778
Show More
osx.py
157 lines | 4.7 KiB | text/x-python | PythonLexer
Min RK
tidy, docstrings
r22161 """Inputhook for OS X
Calls NSApp / CoreFoundation APIs via ctypes.
"""
Min RK
Add OS X input hook...
r22159
# obj-c boilerplate from appnope, used under BSD 2-clause
import ctypes
import ctypes.util
Min RK
run CFRunLoopRun if NSApp:run finishes on its own...
r22776 from threading import Event
Min RK
Add OS X input hook...
r22159
Matthias Bussonnier
update
r26485 objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("objc")) # type: ignore
Min RK
Add OS X input hook...
r22159
void_p = ctypes.c_void_p
objc.objc_getClass.restype = void_p
objc.sel_registerName.restype = void_p
objc.objc_msgSend.restype = void_p
objc.objc_msgSend.argtypes = [void_p, void_p]
msg = objc.objc_msgSend
def _utf8(s):
"""ensure utf8 bytes"""
if not isinstance(s, bytes):
s = s.encode('utf8')
return s
def n(name):
Min RK
Wake the main loop with an event
r22160 """create a selector name (for ObjC methods)"""
Min RK
Add OS X input hook...
r22159 return objc.sel_registerName(_utf8(name))
def C(classname):
"""get an ObjC Class by name"""
return objc.objc_getClass(_utf8(classname))
Min RK
tidy, docstrings
r22161 # end obj-c boilerplate from appnope
# CoreFoundation C-API calls we will use:
Matthias Bussonnier
update
r26485 CoreFoundation = ctypes.cdll.LoadLibrary(ctypes.util.find_library("CoreFoundation")) # type: ignore
Min RK
tidy, docstrings
r22161
Min RK
Add OS X input hook...
r22159 CFFileDescriptorCreate = CoreFoundation.CFFileDescriptorCreate
CFFileDescriptorCreate.restype = void_p
Eli Rykoff
Fix CFFileDescriptorCreate argtypes.
r26318 CFFileDescriptorCreate.argtypes = [void_p, ctypes.c_int, ctypes.c_bool, void_p, void_p]
Min RK
Add OS X input hook...
r22159
CFFileDescriptorGetNativeDescriptor = CoreFoundation.CFFileDescriptorGetNativeDescriptor
CFFileDescriptorGetNativeDescriptor.restype = ctypes.c_int
CFFileDescriptorGetNativeDescriptor.argtypes = [void_p]
CFFileDescriptorEnableCallBacks = CoreFoundation.CFFileDescriptorEnableCallBacks
CFFileDescriptorEnableCallBacks.restype = None
CFFileDescriptorEnableCallBacks.argtypes = [void_p, ctypes.c_ulong]
CFFileDescriptorCreateRunLoopSource = CoreFoundation.CFFileDescriptorCreateRunLoopSource
CFFileDescriptorCreateRunLoopSource.restype = void_p
CFFileDescriptorCreateRunLoopSource.argtypes = [void_p, void_p, void_p]
CFRunLoopGetCurrent = CoreFoundation.CFRunLoopGetCurrent
CFRunLoopGetCurrent.restype = void_p
CFRunLoopAddSource = CoreFoundation.CFRunLoopAddSource
CFRunLoopAddSource.restype = None
CFRunLoopAddSource.argtypes = [void_p, void_p, void_p]
CFRelease = CoreFoundation.CFRelease
CFRelease.restype = None
CFRelease.argtypes = [void_p]
CFFileDescriptorInvalidate = CoreFoundation.CFFileDescriptorInvalidate
CFFileDescriptorInvalidate.restype = None
CFFileDescriptorInvalidate.argtypes = [void_p]
# From CFFileDescriptor.h
kCFFileDescriptorReadCallBack = 1
kCFRunLoopCommonModes = void_p.in_dll(CoreFoundation, 'kCFRunLoopCommonModes')
Min RK
tidy, docstrings
r22161
Min RK
Add OS X input hook...
r22159 def _NSApp():
"""Return the global NSApplication instance (NSApp)"""
Eli Rykoff
Add explicit argtype counting, required for osx-arm64.
r26312 objc.objc_msgSend.argtypes = [void_p, void_p]
Min RK
Add OS X input hook...
r22159 return msg(C('NSApplication'), n('sharedApplication'))
Min RK
tidy, docstrings
r22161
Min RK
Wake the main loop with an event
r22160 def _wake(NSApp):
"""Wake the Application"""
Eli Rykoff
Fix formatting.
r26313 objc.objc_msgSend.argtypes = [
void_p,
void_p,
void_p,
void_p,
void_p,
void_p,
void_p,
void_p,
void_p,
void_p,
Eli Rykoff
Fix formatting.
r26314 void_p,
]
Eli Rykoff
Fix formatting.
r26313 event = msg(
C("NSEvent"),
n(
"otherEventWithType:location:modifierFlags:"
"timestamp:windowNumber:context:subtype:data1:data2:"
),
15, # Type
0, # location
0, # flags
0, # timestamp
0, # window
None, # context
0, # subtype
0, # data1
0, # data2
Min RK
Wake the main loop with an event
r22160 )
Eli Rykoff
Add explicit argtype counting, required for osx-arm64.
r26312 objc.objc_msgSend.argtypes = [void_p, void_p, void_p, void_p]
Min RK
Wake the main loop with an event
r22160 msg(NSApp, n('postEvent:atStart:'), void_p(event), True)
Min RK
tidy, docstrings
r22161
Min RK
run CFRunLoopRun if NSApp:run finishes on its own...
r22776 _triggered = Event()
Min RK
Add OS X input hook...
r22159 def _input_callback(fdref, flags, info):
"""Callback to fire when there's input to be read"""
Min RK
run CFRunLoopRun if NSApp:run finishes on its own...
r22776 _triggered.set()
Min RK
Add OS X input hook...
r22159 CFFileDescriptorInvalidate(fdref)
CFRelease(fdref)
NSApp = _NSApp()
Eli Rykoff
Add explicit argtype counting, required for osx-arm64.
r26312 objc.objc_msgSend.argtypes = [void_p, void_p, void_p]
Min RK
Add OS X input hook...
r22159 msg(NSApp, n('stop:'), NSApp)
Min RK
Wake the main loop with an event
r22160 _wake(NSApp)
Min RK
Add OS X input hook...
r22159
_c_callback_func_type = ctypes.CFUNCTYPE(None, void_p, void_p, void_p)
Min RK
Wake the main loop with an event
r22160 _c_input_callback = _c_callback_func_type(_input_callback)
Min RK
Add OS X input hook...
r22159
Min RK
tidy, docstrings
r22161
Min RK
Add OS X input hook...
r22159 def _stop_on_read(fd):
"""Register callback to stop eventloop when there's data on fd"""
Min RK
run CFRunLoopRun if NSApp:run finishes on its own...
r22776 _triggered.clear()
Min RK
Wake the main loop with an event
r22160 fdref = CFFileDescriptorCreate(None, fd, False, _c_input_callback, None)
Min RK
Add OS X input hook...
r22159 CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack)
source = CFFileDescriptorCreateRunLoopSource(None, fdref, 0)
loop = CFRunLoopGetCurrent()
CFRunLoopAddSource(loop, source, kCFRunLoopCommonModes)
CFRelease(source)
Min RK
tidy, docstrings
r22161
Min RK
Add OS X input hook...
r22159 def inputhook(context):
"""Inputhook for Cocoa (NSApp)"""
NSApp = _NSApp()
_stop_on_read(context.fileno())
Eli Rykoff
Add explicit argtype counting, required for osx-arm64.
r26312 objc.objc_msgSend.argtypes = [void_p, void_p]
Min RK
Add OS X input hook...
r22159 msg(NSApp, n('run'))
Min RK
run CFRunLoopRun if NSApp:run finishes on its own...
r22776 if not _triggered.is_set():
# app closed without firing callback,
# probably due to last window being closed.
# Run the loop manually in this case,
# since there may be events still to process (#9734)
CoreFoundation.CFRunLoopRun()