4040static bool keyChangeCapsLock = false ;
4141/* Keep track of the current mouse up/down state for open/closed cursor hand */
4242static bool leftMouseGrabbing = false ;
43- /* Keep track of whether stdin has been received */
44- static bool stdin_received = false ;
45- static bool stdin_sigint = false ;
4643// Global variable to store the original SIGINT handler
4744static PyOS_sighandler_t originalSigintAction = NULL ;
4845
46+ // Stop the current app's run loop, sending an event to ensure it actually stops
47+ static void stop_with_event () {
48+ [NSApp stop: nil ];
49+ // Post an event to trigger the actual stopping.
50+ [NSApp postEvent: [NSEvent otherEventWithType: NSEventTypeApplicationDefined
51+ location: NSZeroPoint
52+ modifierFlags: 0
53+ timestamp: 0
54+ windowNumber: 0
55+ context: nil
56+ subtype: 0
57+ data1: 0
58+ data2: 0 ]
59+ atStart: YES ];
60+ }
61+
4962// Signal handler for SIGINT, only sets a flag to exit the run loop
5063static void handleSigint (int signal) {
51- stdin_sigint = true ;
64+ stop_with_event () ;
5265}
5366
5467static int wait_for_stdin () {
5568 @autoreleasepool {
56- stdin_received = false ;
57- stdin_sigint = false ;
58-
5969 // Set up a SIGINT handler to interrupt the event loop if ctrl+c comes in too
6070 originalSigintAction = PyOS_setsig (SIGINT, handleSigint);
6171
@@ -66,33 +76,14 @@ static int wait_for_stdin() {
6676 [[NSNotificationCenter defaultCenter ] addObserverForName: NSFileHandleDataAvailableNotification
6777 object: stdinHandle
6878 queue: [NSOperationQueue mainQueue ] // Use the main queue
69- usingBlock: ^(NSNotification *notification) {
70- // Mark that input has been received
71- stdin_received = true ;
72- }
79+ usingBlock: ^(NSNotification *notification) {stop_with_event ();}
7380 ];
7481
7582 // Wait in the background for anything that happens to stdin
7683 [stdinHandle waitForDataInBackgroundAndNotify ];
7784
78- // continuously run an event loop until the stdin_received flag is set to exit
79- while (!stdin_received && !stdin_sigint) {
80- // This loop is similar to the main event loop and flush_events which have
81- // Py_[BEGIN|END]_ALLOW_THREADS surrounding the loop.
82- // This should not be necessary here because PyOS_InputHook releases the GIL for us.
83- while (true ) {
84- NSEvent *event = [NSApp nextEventMatchingMask: NSEventMaskAny
85- untilDate: [NSDate distantPast ]
86- inMode: NSDefaultRunLoopMode
87- dequeue: YES ];
88- if (!event) { break ; }
89- [NSApp sendEvent: event];
90- }
91- // We need to run the run loop for a short time to allow the
92- // events to be processed and keep flushing them while we wait for stdin
93- // without this, the CPU usage will be very high constantly polling this loop
94- [[NSRunLoop currentRunLoop ] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01 ]];
95- }
85+ [NSApp run ];
86+
9687 // Remove the input handler as an observer
9788 [[NSNotificationCenter defaultCenter ] removeObserver: stdinHandle];
9889
@@ -240,20 +231,7 @@ static void lazy_init(void) {
240231static PyObject*
241232stop (PyObject* self)
242233{
243- // Remove our input hook and stop the event loop.
244- PyOS_InputHook = NULL ;
245- [NSApp stop: nil ];
246- // Post an event to trigger the actual stopping.
247- [NSApp postEvent: [NSEvent otherEventWithType: NSEventTypeApplicationDefined
248- location: NSZeroPoint
249- modifierFlags: 0
250- timestamp: 0
251- windowNumber: 0
252- context: nil
253- subtype: 0
254- data1: 0
255- data2: 0 ]
256- atStart: YES ];
234+ stop_with_event ();
257235 Py_RETURN_NONE;
258236}
259237
0 commit comments