Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/ipykernel/_eventloop_macos.py: 0%
60 statements
« prev ^ index » next coverage.py v7.3.3, created at 2023-12-15 06:13 +0000
« prev ^ index » next coverage.py v7.3.3, created at 2023-12-15 06:13 +0000
1"""Eventloop hook for OS X
3Calls NSApp / CoreFoundation APIs via ctypes.
4"""
6# cribbed heavily from IPython.terminal.pt_inputhooks.osx
7# obj-c boilerplate from appnope, used under BSD 2-clause
9import ctypes
10import ctypes.util
11from threading import Event
13objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("objc")) # type:ignore[arg-type]
15void_p = ctypes.c_void_p
17objc.objc_getClass.restype = void_p
18objc.sel_registerName.restype = void_p
19objc.objc_msgSend.restype = void_p
20objc.objc_msgSend.argtypes = [void_p, void_p]
22msg = objc.objc_msgSend
25def _utf8(s):
26 """ensure utf8 bytes"""
27 if not isinstance(s, bytes):
28 s = s.encode("utf8")
29 return s
32def n(name):
33 """create a selector name (for ObjC methods)"""
34 return objc.sel_registerName(_utf8(name))
37def C(classname):
38 """get an ObjC Class by name"""
39 return objc.objc_getClass(_utf8(classname))
42# end obj-c boilerplate from appnope
44# CoreFoundation C-API calls we will use:
45CoreFoundation = ctypes.cdll.LoadLibrary(
46 ctypes.util.find_library("CoreFoundation") # type:ignore[arg-type]
47)
49CFAbsoluteTimeGetCurrent = CoreFoundation.CFAbsoluteTimeGetCurrent
50CFAbsoluteTimeGetCurrent.restype = ctypes.c_double
52CFRunLoopGetCurrent = CoreFoundation.CFRunLoopGetCurrent
53CFRunLoopGetCurrent.restype = void_p
55CFRunLoopGetMain = CoreFoundation.CFRunLoopGetMain
56CFRunLoopGetMain.restype = void_p
58CFRunLoopStop = CoreFoundation.CFRunLoopStop
59CFRunLoopStop.restype = None
60CFRunLoopStop.argtypes = [void_p]
62CFRunLoopTimerCreate = CoreFoundation.CFRunLoopTimerCreate
63CFRunLoopTimerCreate.restype = void_p
64CFRunLoopTimerCreate.argtypes = [
65 void_p, # allocator (NULL)
66 ctypes.c_double, # fireDate
67 ctypes.c_double, # interval
68 ctypes.c_int, # flags (0)
69 ctypes.c_int, # order (0)
70 void_p, # callout
71 void_p, # context
72]
74CFRunLoopAddTimer = CoreFoundation.CFRunLoopAddTimer
75CFRunLoopAddTimer.restype = None
76CFRunLoopAddTimer.argtypes = [void_p, void_p, void_p]
78kCFRunLoopCommonModes = void_p.in_dll(CoreFoundation, "kCFRunLoopCommonModes")
81def _NSApp():
82 """Return the global NSApplication instance (NSApp)"""
83 return msg(C("NSApplication"), n("sharedApplication"))
86def _wake(NSApp):
87 """Wake the Application"""
88 event = msg(
89 C("NSEvent"),
90 n(
91 "otherEventWithType:location:modifierFlags:"
92 "timestamp:windowNumber:context:subtype:data1:data2:"
93 ),
94 15, # Type
95 0, # location
96 0, # flags
97 0, # timestamp
98 0, # window
99 None, # context
100 0, # subtype
101 0, # data1
102 0, # data2
103 )
104 msg(NSApp, n("postEvent:atStart:"), void_p(event), True)
107_triggered = Event()
110def stop(timer=None, loop=None):
111 """Callback to fire when there's input to be read"""
112 _triggered.set()
113 NSApp = _NSApp()
114 # if NSApp is not running, stop CFRunLoop directly,
115 # otherwise stop and wake NSApp
116 if msg(NSApp, n("isRunning")):
117 msg(NSApp, n("stop:"), NSApp)
118 _wake(NSApp)
119 else:
120 CFRunLoopStop(CFRunLoopGetCurrent())
123_c_callback_func_type = ctypes.CFUNCTYPE(None, void_p, void_p)
124_c_stop_callback = _c_callback_func_type(stop)
127def _stop_after(delay):
128 """Register callback to stop eventloop after a delay"""
129 timer = CFRunLoopTimerCreate(
130 None, # allocator
131 CFAbsoluteTimeGetCurrent() + delay, # fireDate
132 0, # interval
133 0, # flags
134 0, # order
135 _c_stop_callback,
136 None,
137 )
138 CFRunLoopAddTimer(
139 CFRunLoopGetMain(),
140 timer,
141 kCFRunLoopCommonModes,
142 )
145def mainloop(duration=1):
146 """run the Cocoa eventloop for the specified duration (seconds)"""
148 _triggered.clear()
149 NSApp = _NSApp()
150 _stop_after(duration)
151 msg(NSApp, n("run"))
152 if not _triggered.is_set():
153 # app closed without firing callback,
154 # probably due to last window being closed.
155 # Run the loop manually in this case,
156 # since there may be events still to process (ipython/ipython#9734)
157 CoreFoundation.CFRunLoopRun()