Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/ipykernel/_eventloop_macos.py: 0%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

65 statements  

1"""Eventloop hook for OS X 

2 

3Calls NSApp / CoreFoundation APIs via ctypes. 

4""" 

5 

6# cribbed heavily from IPython.terminal.pt_inputhooks.osx 

7# obj-c boilerplate from appnope, used under BSD 2-clause 

8 

9import ctypes 

10import ctypes.util 

11from threading import Event 

12 

13objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("objc")) # type:ignore[arg-type] 

14 

15void_p = ctypes.c_void_p 

16 

17objc.objc_getClass.restype = void_p 

18objc.sel_registerName.restype = void_p 

19objc.objc_msgSend.restype = void_p 

20 

21msg = objc.objc_msgSend 

22 

23 

24def _utf8(s): 

25 """ensure utf8 bytes""" 

26 if not isinstance(s, bytes): 

27 s = s.encode("utf8") 

28 return s 

29 

30 

31def n(name): 

32 """create a selector name (for ObjC methods)""" 

33 return objc.sel_registerName(_utf8(name)) 

34 

35 

36def C(classname): 

37 """get an ObjC Class by name""" 

38 return objc.objc_getClass(_utf8(classname)) 

39 

40 

41# end obj-c boilerplate from appnope 

42 

43# CoreFoundation C-API calls we will use: 

44CoreFoundation = ctypes.cdll.LoadLibrary( 

45 ctypes.util.find_library("CoreFoundation") # type:ignore[arg-type] 

46) 

47 

48CFAbsoluteTimeGetCurrent = CoreFoundation.CFAbsoluteTimeGetCurrent 

49CFAbsoluteTimeGetCurrent.restype = ctypes.c_double 

50 

51CFRunLoopGetCurrent = CoreFoundation.CFRunLoopGetCurrent 

52CFRunLoopGetCurrent.restype = void_p 

53 

54CFRunLoopGetMain = CoreFoundation.CFRunLoopGetMain 

55CFRunLoopGetMain.restype = void_p 

56 

57CFRunLoopStop = CoreFoundation.CFRunLoopStop 

58CFRunLoopStop.restype = None 

59CFRunLoopStop.argtypes = [void_p] 

60 

61CFRunLoopTimerCreate = CoreFoundation.CFRunLoopTimerCreate 

62CFRunLoopTimerCreate.restype = void_p 

63CFRunLoopTimerCreate.argtypes = [ 

64 void_p, # allocator (NULL) 

65 ctypes.c_double, # fireDate 

66 ctypes.c_double, # interval 

67 ctypes.c_int, # flags (0) 

68 ctypes.c_int, # order (0) 

69 void_p, # callout 

70 void_p, # context 

71] 

72 

73CFRunLoopAddTimer = CoreFoundation.CFRunLoopAddTimer 

74CFRunLoopAddTimer.restype = None 

75CFRunLoopAddTimer.argtypes = [void_p, void_p, void_p] 

76 

77kCFRunLoopCommonModes = void_p.in_dll(CoreFoundation, "kCFRunLoopCommonModes") 

78 

79 

80def _NSApp(): 

81 """Return the global NSApplication instance (NSApp)""" 

82 objc.objc_msgSend.argtypes = [void_p, void_p] 

83 return msg(C("NSApplication"), n("sharedApplication")) 

84 

85 

86def _wake(NSApp): 

87 """Wake the Application""" 

88 objc.objc_msgSend.argtypes = [ 

89 void_p, 

90 void_p, 

91 void_p, 

92 void_p, 

93 void_p, 

94 void_p, 

95 void_p, 

96 void_p, 

97 void_p, 

98 void_p, 

99 void_p, 

100 ] 

101 event = msg( 

102 C("NSEvent"), 

103 n( 

104 "otherEventWithType:location:modifierFlags:" 

105 "timestamp:windowNumber:context:subtype:data1:data2:" 

106 ), 

107 15, # Type 

108 0, # location 

109 0, # flags 

110 0, # timestamp 

111 0, # window 

112 None, # context 

113 0, # subtype 

114 0, # data1 

115 0, # data2 

116 ) 

117 objc.objc_msgSend.argtypes = [void_p, void_p, void_p, void_p] 

118 msg(NSApp, n("postEvent:atStart:"), void_p(event), True) 

119 

120 

121_triggered = Event() 

122 

123 

124def stop(timer=None, loop=None): 

125 """Callback to fire when there's input to be read""" 

126 _triggered.set() 

127 NSApp = _NSApp() 

128 # if NSApp is not running, stop CFRunLoop directly, 

129 # otherwise stop and wake NSApp 

130 objc.objc_msgSend.argtypes = [void_p, void_p] 

131 if msg(NSApp, n("isRunning")): 

132 objc.objc_msgSend.argtypes = [void_p, void_p, void_p] 

133 msg(NSApp, n("stop:"), NSApp) 

134 _wake(NSApp) 

135 else: 

136 CFRunLoopStop(CFRunLoopGetCurrent()) 

137 

138 

139_c_callback_func_type = ctypes.CFUNCTYPE(None, void_p, void_p) 

140_c_stop_callback = _c_callback_func_type(stop) 

141 

142 

143def _stop_after(delay): 

144 """Register callback to stop eventloop after a delay""" 

145 timer = CFRunLoopTimerCreate( 

146 None, # allocator 

147 CFAbsoluteTimeGetCurrent() + delay, # fireDate 

148 0, # interval 

149 0, # flags 

150 0, # order 

151 _c_stop_callback, 

152 None, 

153 ) 

154 CFRunLoopAddTimer( 

155 CFRunLoopGetMain(), 

156 timer, 

157 kCFRunLoopCommonModes, 

158 ) 

159 

160 

161def mainloop(duration=1): 

162 """run the Cocoa eventloop for the specified duration (seconds)""" 

163 

164 _triggered.clear() 

165 NSApp = _NSApp() 

166 _stop_after(duration) 

167 objc.objc_msgSend.argtypes = [void_p, void_p] 

168 msg(NSApp, n("run")) 

169 if not _triggered.is_set(): 

170 # app closed without firing callback, 

171 # probably due to last window being closed. 

172 # Run the loop manually in this case, 

173 # since there may be events still to process (ipython/ipython#9734) 

174 CoreFoundation.CFRunLoopRun()