|
41 | 41 | static bool keyChangeCapsLock = false;
|
42 | 42 | /* Keep track of the current mouse up/down state for open/closed cursor hand */
|
43 | 43 | static bool leftMouseGrabbing = false;
|
| 44 | +/* Keep track of whether stdin has been received */ |
| 45 | +static bool stdin_received = false; |
| 46 | +static bool stdin_sigint = false; |
| 47 | +// Global variable to store the original SIGINT handler |
| 48 | +static struct sigaction originalSigintAction = {0}; |
| 49 | + |
| 50 | +// Signal handler for SIGINT, only sets a flag to exit the run loop |
| 51 | +static void handleSigint(int signal) { |
| 52 | + stdin_sigint = true; |
| 53 | +} |
| 54 | + |
| 55 | +static int wait_for_stdin() { |
| 56 | + @autoreleasepool { |
| 57 | + stdin_received = false; |
| 58 | + stdin_sigint = false; |
| 59 | + |
| 60 | + // Set up a SIGINT handler to interrupt the event loop if ctrl+c comes in too |
| 61 | + struct sigaction customAction = {0}; |
| 62 | + customAction.sa_handler = handleSigint; |
| 63 | + // Set the new handler and store the old one |
| 64 | + sigaction(SIGINT, &customAction, &originalSigintAction); |
| 65 | + |
| 66 | + // Create an NSFileHandle for standard input |
| 67 | + NSFileHandle *stdinHandle = [NSFileHandle fileHandleWithStandardInput]; |
| 68 | + |
| 69 | + // Register for data available notifications on standard input |
| 70 | + [[NSNotificationCenter defaultCenter] addObserverForName: NSFileHandleDataAvailableNotification |
| 71 | + object: stdinHandle |
| 72 | + queue: [NSOperationQueue mainQueue] // Use the main queue |
| 73 | + usingBlock: ^(NSNotification *notification) { |
| 74 | + // Mark that input has been received |
| 75 | + stdin_received = true; |
| 76 | + } |
| 77 | + ]; |
| 78 | + |
| 79 | + // Wait in the background for anything that happens to stdin |
| 80 | + [stdinHandle waitForDataInBackgroundAndNotify]; |
| 81 | + |
| 82 | + // continuously run an event loop until the stdin_received flag is set to exit |
| 83 | + while (!stdin_received && !stdin_sigint) { |
| 84 | + while (true) { |
| 85 | + NSEvent *event = [NSApp nextEventMatchingMask: NSEventMaskAny |
| 86 | + untilDate: [NSDate distantPast] |
| 87 | + inMode: NSDefaultRunLoopMode |
| 88 | + dequeue: YES]; |
| 89 | + if (!event) { break; } |
| 90 | + [NSApp sendEvent: event]; |
| 91 | + } |
| 92 | + // We need to run the run loop for a short time to allow the |
| 93 | + // events to be processed and keep flushing them while we wait for stdin |
| 94 | + [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]; |
| 95 | + } |
| 96 | + // Remove the input handler as an observer |
| 97 | + [[NSNotificationCenter defaultCenter] removeObserver: stdinHandle]; |
| 98 | + |
| 99 | + // Restore the original SIGINT handler upon exiting the function |
| 100 | + sigaction(SIGINT, &originalSigintAction, NULL); |
| 101 | + return 1; |
| 102 | + } |
| 103 | +} |
44 | 104 |
|
45 | 105 | /* ---------------------------- Cocoa classes ---------------------------- */
|
46 | 106 |
|
@@ -139,6 +199,9 @@ static void lazy_init(void) {
|
139 | 199 | NSApp = [NSApplication sharedApplication];
|
140 | 200 | [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
141 | 201 |
|
| 202 | + // Run our own event loop while waiting for stdin on the Python side |
| 203 | + // this is needed to keep the application responsive while waiting for input |
| 204 | + PyOS_InputHook = wait_for_stdin; |
142 | 205 | }
|
143 | 206 |
|
144 | 207 | static PyObject*
|
|
0 commit comments