1
1
#define PY_SSIZE_T_CLEAN
2
2
#include < Cocoa/Cocoa.h>
3
3
#include < ApplicationServices/ApplicationServices.h>
4
- #include < sys/socket.h>
5
4
#include < Python.h>
6
5
#include " mplutils.h"
7
6
8
- #ifndef PYPY
9
- /* Remove this once Python is fixed: https://bugs.python.org/issue23237 */
10
- #define PYOSINPUTHOOK_REPETITIVE 1
11
- #endif
12
-
13
7
/* Proper way to check for the OS X version we are compiling for, from
14
8
* https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/cross_development/Using/using.html
15
9
46
40
static bool keyChangeOption = false ;
47
41
static bool keyChangeCapsLock = false ;
48
42
49
- /* -------------------------- Helper function ---------------------------- */
50
-
51
- static void
52
- _stdin_callback (CFReadStreamRef stream, CFStreamEventType eventType, void * info)
53
- {
54
- CFRunLoopRef runloop = info;
55
- CFRunLoopStop (runloop);
56
- }
57
-
58
- static int sigint_fd = -1 ;
59
-
60
- static void _sigint_handler (int sig)
61
- {
62
- const char c = ' i' ;
63
- write (sigint_fd, &c, 1 );
64
- }
65
-
66
- static void _sigint_callback (CFSocketRef s,
67
- CFSocketCallBackType type,
68
- CFDataRef address,
69
- const void * data,
70
- void *info)
71
- {
72
- char c;
73
- int * interrupted = info;
74
- CFSocketNativeHandle handle = CFSocketGetNative (s);
75
- CFRunLoopRef runloop = CFRunLoopGetCurrent ();
76
- read (handle, &c, 1 );
77
- *interrupted = 1 ;
78
- CFRunLoopStop (runloop);
79
- }
80
-
81
- static CGEventRef _eventtap_callback (
82
- CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
83
- {
84
- CFRunLoopRef runloop = refcon;
85
- CFRunLoopStop (runloop);
86
- return event;
87
- }
88
-
89
- static int wait_for_stdin (void )
90
- {
91
- int interrupted = 0 ;
92
- const UInt8 buffer[] = " /dev/fd/0" ;
93
- const CFIndex n = (CFIndex)strlen ((char *)buffer);
94
- CFRunLoopRef runloop = CFRunLoopGetCurrent ();
95
- CFURLRef url = CFURLCreateFromFileSystemRepresentation (kCFAllocatorDefault ,
96
- buffer,
97
- n,
98
- false );
99
- CFReadStreamRef stream = CFReadStreamCreateWithFile (kCFAllocatorDefault ,
100
- url);
101
- CFRelease (url);
102
-
103
- CFReadStreamOpen (stream);
104
- #ifdef PYOSINPUTHOOK_REPETITIVE
105
- if (!CFReadStreamHasBytesAvailable (stream))
106
- /* This is possible because of how PyOS_InputHook is called from Python */
107
- #endif
108
- {
109
- int error;
110
- int channel[2 ];
111
- CFSocketRef sigint_socket = NULL ;
112
- PyOS_sighandler_t py_sigint_handler = NULL ;
113
- CFStreamClientContext clientContext = {0 , NULL , NULL , NULL , NULL };
114
- clientContext.info = runloop;
115
- CFReadStreamSetClient (stream,
116
- kCFStreamEventHasBytesAvailable ,
117
- _stdin_callback,
118
- &clientContext);
119
- CFReadStreamScheduleWithRunLoop (stream, runloop, kCFRunLoopDefaultMode );
120
- error = socketpair (AF_UNIX, SOCK_STREAM, 0 , channel);
121
- if (!error) {
122
- CFSocketContext context;
123
- context.version = 0 ;
124
- context.info = &interrupted;
125
- context.retain = NULL ;
126
- context.release = NULL ;
127
- context.copyDescription = NULL ;
128
- fcntl (channel[0 ], F_SETFL, O_WRONLY | O_NONBLOCK);
129
- sigint_socket = CFSocketCreateWithNative (
130
- kCFAllocatorDefault ,
131
- channel[1 ],
132
- kCFSocketReadCallBack ,
133
- _sigint_callback,
134
- &context);
135
- if (sigint_socket) {
136
- CFRunLoopSourceRef source = CFSocketCreateRunLoopSource (
137
- kCFAllocatorDefault , sigint_socket, 0 );
138
- CFRelease (sigint_socket);
139
- if (source) {
140
- CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode );
141
- CFRelease (source);
142
- sigint_fd = channel[0 ];
143
- py_sigint_handler = PyOS_setsig (SIGINT, _sigint_handler);
144
- }
145
- }
146
- }
147
-
148
- NSEvent * event;
149
- while (true ) {
150
- while (true ) {
151
- event = [NSApp nextEventMatchingMask: NSEventMaskAny
152
- untilDate: [NSDate distantPast ]
153
- inMode: NSDefaultRunLoopMode
154
- dequeue: YES ];
155
- if (!event) { break ; }
156
- [NSApp sendEvent: event];
157
- }
158
- CFRunLoopRun ();
159
- if (interrupted || CFReadStreamHasBytesAvailable (stream)) { break ; }
160
- }
161
-
162
- if (py_sigint_handler) { PyOS_setsig (SIGINT, py_sigint_handler); }
163
- CFReadStreamUnscheduleFromRunLoop (
164
- stream, runloop, kCFRunLoopCommonModes );
165
- if (sigint_socket) { CFSocketInvalidate (sigint_socket); }
166
- if (!error) {
167
- close (channel[0 ]);
168
- close (channel[1 ]);
169
- }
170
- }
171
- CFReadStreamClose (stream);
172
- CFRelease (stream);
173
- if (interrupted) {
174
- errno = EINTR;
175
- raise (SIGINT);
176
- return -1 ;
177
- }
178
- return 1 ;
179
- }
180
-
181
43
/* ---------------------------- Cocoa classes ---------------------------- */
182
44
183
45
@interface WindowServerConnectionManager : NSObject
184
46
{
185
47
}
186
48
+ (WindowServerConnectionManager*)sharedManager ;
187
- - (void )launch : (NSNotification *)notification ;
188
49
- (void )receivedData : (NSNotification *)notification ;
189
50
@end
190
51
@@ -285,15 +146,6 @@ static void lazy_init(void) {
285
146
NSApp = [NSApplication sharedApplication ];
286
147
[NSApp setActivationPolicy: NSApplicationActivationPolicyRegular];
287
148
288
- PyOS_InputHook = wait_for_stdin;
289
-
290
- WindowServerConnectionManager* connectionManager = [WindowServerConnectionManager sharedManager ];
291
- NSWorkspace * workspace = [NSWorkspace sharedWorkspace ];
292
- NSNotificationCenter * notificationCenter = [workspace notificationCenter ];
293
- [notificationCenter addObserver: connectionManager
294
- selector: @selector (launch: )
295
- name: NSWorkspaceDidLaunchApplicationNotification
296
- object: nil ];
297
149
}
298
150
299
151
static PyObject*
@@ -327,7 +179,7 @@ static void lazy_init(void) {
327
179
[NSApp stop: nil ];
328
180
// Post an event to trigger the actual stopping.
329
181
[NSApp postEvent: [NSEvent otherEventWithType: NSEventTypeApplicationDefined
330
- location: NSMakePoint ( 0 , 0 )
182
+ location: NSZeroPoint
331
183
modifierFlags: 0
332
184
timestamp: 0
333
185
windowNumber: 0
@@ -542,40 +394,6 @@ int mpl_check_modifier(
542
394
return NULL ;
543
395
}
544
396
545
- int error;
546
- int interrupted = 0 ;
547
- int channel[2 ];
548
- CFSocketRef sigint_socket = NULL ;
549
- PyOS_sighandler_t py_sigint_handler = NULL ;
550
-
551
- CFRunLoopRef runloop = CFRunLoopGetCurrent ();
552
-
553
- error = pipe (channel);
554
- if (!error) {
555
- CFSocketContext context = {0 , NULL , NULL , NULL , NULL };
556
- fcntl (channel[1 ], F_SETFL, O_WRONLY | O_NONBLOCK);
557
-
558
- context.info = &interrupted;
559
- sigint_socket = CFSocketCreateWithNative (kCFAllocatorDefault ,
560
- channel[0 ],
561
- kCFSocketReadCallBack ,
562
- _sigint_callback,
563
- &context);
564
- if (sigint_socket) {
565
- CFRunLoopSourceRef source = CFSocketCreateRunLoopSource (
566
- kCFAllocatorDefault , sigint_socket, 0 );
567
- CFRelease (sigint_socket);
568
- if (source) {
569
- CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode );
570
- CFRelease (source);
571
- sigint_fd = channel[1 ];
572
- py_sigint_handler = PyOS_setsig (SIGINT, _sigint_handler);
573
- }
574
- }
575
- else
576
- close (channel[0 ]);
577
- }
578
-
579
397
NSDate * date =
580
398
(timeout > 0.0 ) ? [NSDate dateWithTimeIntervalSinceNow: timeout]
581
399
: [NSDate distantFuture ];
@@ -588,11 +406,6 @@ int mpl_check_modifier(
588
406
[NSApp sendEvent: event];
589
407
}
590
408
591
- if (py_sigint_handler) { PyOS_setsig (SIGINT, py_sigint_handler); }
592
- if (sigint_socket) { CFSocketInvalidate (sigint_socket); }
593
- if (!error) { close (channel[1 ]); }
594
- if (interrupted) { raise (SIGINT); }
595
-
596
409
Py_RETURN_NONE;
597
410
}
598
411
@@ -1207,34 +1020,6 @@ - (id)autorelease
1207
1020
return self;
1208
1021
}
1209
1022
1210
- - (void )launch : (NSNotification *)notification
1211
- {
1212
- CFRunLoopRef runloop;
1213
- CFMachPortRef port;
1214
- CFRunLoopSourceRef source;
1215
- NSDictionary * dictionary = [notification userInfo ];
1216
- if (![[dictionary valueForKey: @" NSApplicationName" ]
1217
- localizedCaseInsensitiveContainsString: @" python" ])
1218
- return ;
1219
- NSNumber * psnLow = [dictionary valueForKey: @" NSApplicationProcessSerialNumberLow" ];
1220
- NSNumber * psnHigh = [dictionary valueForKey: @" NSApplicationProcessSerialNumberHigh" ];
1221
- ProcessSerialNumber psn;
1222
- psn.highLongOfPSN = [psnHigh intValue ];
1223
- psn.lowLongOfPSN = [psnLow intValue ];
1224
- runloop = CFRunLoopGetCurrent ();
1225
- port = CGEventTapCreateForPSN (&psn,
1226
- kCGHeadInsertEventTap ,
1227
- kCGEventTapOptionListenOnly ,
1228
- kCGEventMaskForAllEvents ,
1229
- &_eventtap_callback,
1230
- runloop);
1231
- source = CFMachPortCreateRunLoopSource (kCFAllocatorDefault ,
1232
- port,
1233
- 0 );
1234
- CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode );
1235
- CFRelease (port);
1236
- }
1237
-
1238
1023
- (void )receivedData : (NSNotification *)notification
1239
1024
{
1240
1025
PyGILState_STATE gstate = PyGILState_Ensure ();
0 commit comments