40
40
static bool keyChangeCapsLock = false ;
41
41
/* Keep track of the current mouse up/down state for open/closed cursor hand */
42
42
static bool leftMouseGrabbing = false ;
43
- /* Keep track of whether stdin has been received */
44
- static bool stdin_received = false ;
45
- static bool stdin_sigint = false ;
46
43
// Global variable to store the original SIGINT handler
47
44
static PyOS_sighandler_t originalSigintAction = NULL ;
48
45
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
+
49
62
// Signal handler for SIGINT, only sets a flag to exit the run loop
50
63
static void handleSigint (int signal) {
51
- stdin_sigint = true ;
64
+ stop_with_event () ;
52
65
}
53
66
54
67
static int wait_for_stdin () {
55
68
@autoreleasepool {
56
- stdin_received = false ;
57
- stdin_sigint = false ;
58
-
59
69
// Set up a SIGINT handler to interrupt the event loop if ctrl+c comes in too
60
70
originalSigintAction = PyOS_setsig (SIGINT, handleSigint);
61
71
@@ -66,33 +76,14 @@ static int wait_for_stdin() {
66
76
[[NSNotificationCenter defaultCenter ] addObserverForName: NSFileHandleDataAvailableNotification
67
77
object: stdinHandle
68
78
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 ();}
73
80
];
74
81
75
82
// Wait in the background for anything that happens to stdin
76
83
[stdinHandle waitForDataInBackgroundAndNotify ];
77
84
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
+
96
87
// Remove the input handler as an observer
97
88
[[NSNotificationCenter defaultCenter ] removeObserver: stdinHandle];
98
89
@@ -240,20 +231,7 @@ static void lazy_init(void) {
240
231
static PyObject*
241
232
stop (PyObject* self)
242
233
{
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 ();
257
235
Py_RETURN_NONE;
258
236
}
259
237
0 commit comments