Skip to content

Commit 17e562e

Browse files
authored
Merge pull request #26970 from greglucas/macos-stdin
FIX: Add PyOS_InputHook back to macos backend
2 parents 8e1cb76 + 4a83974 commit 17e562e

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

src/_macosx.m

+63
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,66 @@
4141
static bool keyChangeCapsLock = false;
4242
/* Keep track of the current mouse up/down state for open/closed cursor hand */
4343
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+
}
44104

45105
/* ---------------------------- Cocoa classes ---------------------------- */
46106

@@ -139,6 +199,9 @@ static void lazy_init(void) {
139199
NSApp = [NSApplication sharedApplication];
140200
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
141201

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;
142205
}
143206

144207
static PyObject*

0 commit comments

Comments
 (0)