|
41 | 41 | staticbool keyChangeCapsLock =false; |
42 | 42 | /* Keep track of the current mouse up/down state for open/closed cursor hand*/ |
43 | 43 | staticbool leftMouseGrabbing =false; |
| 44 | +/* Keep track of whether stdin has been received*/ |
| 45 | +staticbool stdin_received =false; |
| 46 | +staticbool stdin_sigint =false; |
| 47 | +// Global variable to store the original SIGINT handler |
| 48 | +staticstruct sigaction originalSigintAction = {0}; |
| 49 | + |
| 50 | +// Signal handler for SIGINT, only sets a flag to exit the run loop |
| 51 | +staticvoidhandleSigint(int signal) { |
| 52 | + stdin_sigint =true; |
| 53 | +} |
| 54 | + |
| 55 | +staticintwait_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 = [NSFileHandlefileHandleWithStandardInput]; |
| 68 | + |
| 69 | +// Register for data available notifications on standard input |
| 70 | + [[NSNotificationCenterdefaultCenter]addObserverForName:NSFileHandleDataAvailableNotification |
| 71 | +object: stdinHandle |
| 72 | +queue: [NSOperationQueuemainQueue]// 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 | + [stdinHandlewaitForDataInBackgroundAndNotify]; |
| 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 = [NSAppnextEventMatchingMask: NSEventMaskAny |
| 86 | +untilDate: [NSDatedistantPast] |
| 87 | +inMode:NSDefaultRunLoopMode |
| 88 | +dequeue:YES]; |
| 89 | +if (!event) {break; } |
| 90 | + [NSAppsendEvent: 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 | + [[NSRunLoopcurrentRunLoop]runUntilDate: [NSDatedateWithTimeIntervalSinceNow:0.01]]; |
| 95 | + } |
| 96 | +// Remove the input handler as an observer |
| 97 | + [[NSNotificationCenterdefaultCenter]removeObserver: stdinHandle]; |
| 98 | + |
| 99 | +// Restore the original SIGINT handler upon exiting the function |
| 100 | +sigaction(SIGINT, &originalSigintAction,NULL); |
| 101 | +return1; |
| 102 | + } |
| 103 | +} |
44 | 104 |
|
45 | 105 | /* ---------------------------- Cocoa classes ----------------------------*/ |
46 | 106 |
|
@@ -139,6 +199,9 @@ static void lazy_init(void) { |
139 | 199 | NSApp = [NSApplicationsharedApplication]; |
140 | 200 | [NSAppsetActivationPolicy: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* |
|