Skip to content

FIX: Add PyOS_InputHook back to macos backend #26970

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 26, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions src/_macosx.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,66 @@
static bool keyChangeCapsLock = false;
/* Keep track of the current mouse up/down state for open/closed cursor hand */
static bool leftMouseGrabbing = false;
/* Keep track of whether stdin has been received */
static bool stdin_received = false;
static bool stdin_sigint = false;
// Global variable to store the original SIGINT handler
static struct sigaction originalSigintAction = {0};

// Signal handler for SIGINT, only sets a flag to exit the run loop
static void handleSigint(int signal) {
stdin_sigint = true;
}

static int wait_for_stdin() {
@autoreleasepool {
stdin_received = false;
stdin_sigint = false;

// Set up a SIGINT handler to interrupt the event loop if ctrl+c comes in too
struct sigaction customAction = {0};
customAction.sa_handler = handleSigint;
// Set the new handler and store the old one
sigaction(SIGINT, &customAction, &originalSigintAction);

// Create an NSFileHandle for standard input
NSFileHandle *stdinHandle = [NSFileHandle fileHandleWithStandardInput];

// Register for data available notifications on standard input
[[NSNotificationCenter defaultCenter] addObserverForName: NSFileHandleDataAvailableNotification
object: stdinHandle
queue: [NSOperationQueue mainQueue] // Use the main queue
usingBlock: ^(NSNotification *notification) {
// Mark that input has been received
stdin_received = true;
}
];

// Wait in the background for anything that happens to stdin
[stdinHandle waitForDataInBackgroundAndNotify];

// continuously run an event loop until the stdin_received flag is set to exit
while (!stdin_received && !stdin_sigint) {
while (true) {
NSEvent *event = [NSApp nextEventMatchingMask: NSEventMaskAny
untilDate: [NSDate distantPast]
inMode: NSDefaultRunLoopMode
dequeue: YES];
if (!event) { break; }
[NSApp sendEvent: event];
}
// We need to run the run loop for a short time to allow the
// events to be processed and keep flushing them while we wait for stdin
[[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
}
// Remove the input handler as an observer
[[NSNotificationCenter defaultCenter] removeObserver: stdinHandle];

// Restore the original SIGINT handler upon exiting the function
sigaction(SIGINT, &originalSigintAction, NULL);
return 1;
}
}

/* ---------------------------- Cocoa classes ---------------------------- */

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

// Run our own event loop while waiting for stdin on the Python side
// this is needed to keep the application responsive while waiting for input
PyOS_InputHook = wait_for_stdin;
}

static PyObject*
Expand Down