Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3157f23

Browse files
authored
Merge pull request#29046 from meeseeksmachine/auto-backport-of-pr-28981-on-v3.9.x
Backport PR#28981 on branch v3.9.x (FIX: macos: Use standard NSApp run loop in our input hook)
2 parentsf4e9226 +985e8f4 commit3157f23

File tree

1 file changed

+56
-54
lines changed

1 file changed

+56
-54
lines changed

‎src/_macosx.m‎

Lines changed: 56 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -40,60 +40,84 @@
4040
staticbool keyChangeCapsLock =false;
4141
/* Keep track of the current mouse up/down state for open/closed cursor hand*/
4242
staticbool leftMouseGrabbing =false;
43-
/* Keep track of whether stdin has been received*/
44-
staticbool stdin_received =false;
45-
staticbool stdin_sigint =false;
4643
// Global variable to store the original SIGINT handler
4744
static PyOS_sighandler_t originalSigintAction =NULL;
4845

49-
// Signal handler for SIGINT, only sets a flag to exit the run loop
46+
// Stop the current app's run loop, sending an event to ensure it actually stops
47+
staticvoidstopWithEvent() {
48+
[NSAppstop:nil];
49+
// Post an event to trigger the actual stopping.
50+
[NSApppostEvent: [NSEventotherEventWithType: 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+
62+
// Signal handler for SIGINT, only argument matching for stopWithEvent
5063
staticvoidhandleSigint(int signal) {
51-
stdin_sigint =true;
64+
stopWithEvent();
65+
}
66+
67+
// Helper function to flush all events.
68+
// This is needed in some instances to ensure e.g. that windows are properly closed.
69+
// It is used in the input hook as well as wrapped in a version callable from Python.
70+
staticvoidflushEvents() {
71+
while (true) {
72+
NSEvent* event = [NSAppnextEventMatchingMask: NSEventMaskAny
73+
untilDate: [NSDatedistantPast]
74+
inMode:NSDefaultRunLoopMode
75+
dequeue:YES];
76+
if (!event) {
77+
break;
78+
}
79+
[NSAppsendEvent:event];
80+
}
5281
}
5382

5483
staticintwait_for_stdin() {
55-
@autoreleasepool {
56-
stdin_received =false;
57-
stdin_sigint =false;
84+
// Short circuit if no windows are active
85+
// Rely on Python's input handling to manage CPU usage
86+
// This queries the NSApp, rather than using our FigureWindowCount because that is decremented when events still
87+
// need to be processed to properly close the windows.
88+
if (![[NSAppwindows]count]) {
89+
flushEvents();
90+
return1;
91+
}
5892

93+
@autoreleasepool {
5994
// Set up a SIGINT handler to interrupt the event loop if ctrl+c comes in too
6095
originalSigintAction =PyOS_setsig(SIGINT, handleSigint);
6196

6297
// Create an NSFileHandle for standard input
6398
NSFileHandle *stdinHandle = [NSFileHandlefileHandleWithStandardInput];
6499

100+
65101
// Register for data available notifications on standard input
66-
[[NSNotificationCenterdefaultCenter]addObserverForName:NSFileHandleDataAvailableNotification
67-
object: stdinHandle
68-
queue: [NSOperationQueuemainQueue]// Use the main queue
69-
usingBlock: ^(NSNotification *notification) {
70-
// Mark that input has been received
71-
stdin_received =true;
72-
}
102+
id notificationID = [[NSNotificationCenterdefaultCenter]addObserverForName:NSFileHandleDataAvailableNotification
103+
object: stdinHandle
104+
queue: [NSOperationQueuemainQueue]// Use the main queue
105+
usingBlock: ^(NSNotification *notification) {stopWithEvent();}
73106
];
74107

75108
// Wait in the background for anything that happens to stdin
76109
[stdinHandlewaitForDataInBackgroundAndNotify];
77110

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 = [NSAppnextEventMatchingMask: NSEventMaskAny
85-
untilDate: [NSDatedistantPast]
86-
inMode:NSDefaultRunLoopMode
87-
dequeue:YES];
88-
if (!event) {break; }
89-
[NSAppsendEvent: event];
90-
}
91-
}
111+
// Run the application's event loop, which will be interrupted on stdin or SIGINT
112+
[NSApprun];
113+
92114
// Remove the input handler as an observer
93-
[[NSNotificationCenterdefaultCenter]removeObserver: stdinHandle];
115+
[[NSNotificationCenterdefaultCenter]removeObserver: notificationID];
116+
94117

95118
// Restore the original SIGINT handler upon exiting the function
96119
PyOS_setsig(SIGINT, originalSigintAction);
120+
97121
return1;
98122
}
99123
}
@@ -236,18 +260,7 @@ static void lazy_init(void) {
236260
static PyObject*
237261
stop(PyObject* self)
238262
{
239-
[NSAppstop:nil];
240-
// Post an event to trigger the actual stopping.
241-
[NSApppostEvent: [NSEventotherEventWithType: NSEventTypeApplicationDefined
242-
location:NSZeroPoint
243-
modifierFlags:0
244-
timestamp:0
245-
windowNumber:0
246-
context:nil
247-
subtype:0
248-
data1:0
249-
data2:0]
250-
atStart:YES];
263+
stopWithEvent();
251264
Py_RETURN_NONE;
252265
}
253266

@@ -382,20 +395,9 @@ static CGFloat _get_device_scale(CGContextRef cr)
382395
// We run the app, matching any events that are waiting in the queue
383396
// to process, breaking out of the loop when no events remain and
384397
// displaying the canvas if needed.
385-
NSEvent *event;
386-
387398
Py_BEGIN_ALLOW_THREADS
388399

389-
while (true) {
390-
event = [NSAppnextEventMatchingMask: NSEventMaskAny
391-
untilDate: [NSDatedistantPast]
392-
inMode:NSDefaultRunLoopMode
393-
dequeue:YES];
394-
if (!event) {
395-
break;
396-
}
397-
[NSAppsendEvent:event];
398-
}
400+
flushEvents();
399401

400402
Py_END_ALLOW_THREADS
401403

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp