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
- @interface WindowServerConnectionManager : NSObject
184
- {
185
- }
186
- + (WindowServerConnectionManager*)sharedManager ;
187
- - (void )launch : (NSNotification *)notification ;
188
- @end
189
-
190
45
@interface Window : NSWindow
191
46
{ PyObject* manager;
192
47
}
@@ -284,15 +139,6 @@ static void lazy_init(void) {
284
139
NSApp = [NSApplication sharedApplication ];
285
140
[NSApp setActivationPolicy: NSApplicationActivationPolicyRegular];
286
141
287
- PyOS_InputHook = wait_for_stdin;
288
-
289
- WindowServerConnectionManager* connectionManager = [WindowServerConnectionManager sharedManager ];
290
- NSWorkspace * workspace = [NSWorkspace sharedWorkspace ];
291
- NSNotificationCenter * notificationCenter = [workspace notificationCenter ];
292
- [notificationCenter addObserver: connectionManager
293
- selector: @selector (launch: )
294
- name: NSWorkspaceDidLaunchApplicationNotification
295
- object: nil ];
296
142
}
297
143
298
144
static PyObject*
@@ -545,40 +391,6 @@ int mpl_check_modifier(
545
391
return NULL ;
546
392
}
547
393
548
- int error;
549
- int interrupted = 0 ;
550
- int channel[2 ];
551
- CFSocketRef sigint_socket = NULL ;
552
- PyOS_sighandler_t py_sigint_handler = NULL ;
553
-
554
- CFRunLoopRef runloop = CFRunLoopGetCurrent ();
555
-
556
- error = pipe (channel);
557
- if (!error) {
558
- CFSocketContext context = {0 , NULL , NULL , NULL , NULL };
559
- fcntl (channel[1 ], F_SETFL, O_WRONLY | O_NONBLOCK);
560
-
561
- context.info = &interrupted;
562
- sigint_socket = CFSocketCreateWithNative (kCFAllocatorDefault ,
563
- channel[0 ],
564
- kCFSocketReadCallBack ,
565
- _sigint_callback,
566
- &context);
567
- if (sigint_socket) {
568
- CFRunLoopSourceRef source = CFSocketCreateRunLoopSource (
569
- kCFAllocatorDefault , sigint_socket, 0 );
570
- CFRelease (sigint_socket);
571
- if (source) {
572
- CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode );
573
- CFRelease (source);
574
- sigint_fd = channel[1 ];
575
- py_sigint_handler = PyOS_setsig (SIGINT, _sigint_handler);
576
- }
577
- }
578
- else
579
- close (channel[0 ]);
580
- }
581
-
582
394
NSDate * date =
583
395
(timeout > 0.0 ) ? [NSDate dateWithTimeIntervalSinceNow: timeout]
584
396
: [NSDate distantFuture ];
@@ -591,11 +403,6 @@ int mpl_check_modifier(
591
403
[NSApp sendEvent: event];
592
404
}
593
405
594
- if (py_sigint_handler) { PyOS_setsig (SIGINT, py_sigint_handler); }
595
- if (sigint_socket) { CFSocketInvalidate (sigint_socket); }
596
- if (!error) { close (channel[1 ]); }
597
- if (interrupted) { raise (SIGINT); }
598
-
599
406
Py_RETURN_NONE;
600
407
}
601
408
@@ -1169,76 +976,6 @@ -(void)save_figure:(id)sender { gil_call_method(toolbar, "save_figure"); }
1169
976
Py_RETURN_NONE;
1170
977
}
1171
978
1172
- @implementation WindowServerConnectionManager
1173
- static WindowServerConnectionManager *sharedWindowServerConnectionManager = nil ;
1174
-
1175
- + (WindowServerConnectionManager *)sharedManager
1176
- {
1177
- if (sharedWindowServerConnectionManager == nil ) {
1178
- sharedWindowServerConnectionManager = [[super allocWithZone: NULL ] init ];
1179
- }
1180
- return sharedWindowServerConnectionManager;
1181
- }
1182
-
1183
- + (id )allocWithZone : (NSZone *)zone
1184
- {
1185
- return [[self sharedManager ] retain ];
1186
- }
1187
-
1188
- + (id )copyWithZone : (NSZone *)zone
1189
- {
1190
- return self;
1191
- }
1192
-
1193
- + (id )retain
1194
- {
1195
- return self;
1196
- }
1197
-
1198
- - (NSUInteger )retainCount
1199
- {
1200
- return NSUIntegerMax; // denotes an object that cannot be released
1201
- }
1202
-
1203
- - (oneway void )release
1204
- {
1205
- // Don't release a singleton object
1206
- }
1207
-
1208
- - (id )autorelease
1209
- {
1210
- return self;
1211
- }
1212
-
1213
- - (void )launch : (NSNotification *)notification
1214
- {
1215
- CFRunLoopRef runloop;
1216
- CFMachPortRef port;
1217
- CFRunLoopSourceRef source;
1218
- NSDictionary * dictionary = [notification userInfo ];
1219
- if (![[dictionary valueForKey: @" NSApplicationName" ]
1220
- localizedCaseInsensitiveContainsString: @" python" ])
1221
- return ;
1222
- NSNumber * psnLow = [dictionary valueForKey: @" NSApplicationProcessSerialNumberLow" ];
1223
- NSNumber * psnHigh = [dictionary valueForKey: @" NSApplicationProcessSerialNumberHigh" ];
1224
- ProcessSerialNumber psn;
1225
- psn.highLongOfPSN = [psnHigh intValue ];
1226
- psn.lowLongOfPSN = [psnLow intValue ];
1227
- runloop = CFRunLoopGetCurrent ();
1228
- port = CGEventTapCreateForPSN (&psn,
1229
- kCGHeadInsertEventTap ,
1230
- kCGEventTapOptionListenOnly ,
1231
- kCGEventMaskForAllEvents ,
1232
- &_eventtap_callback,
1233
- runloop);
1234
- source = CFMachPortCreateRunLoopSource (kCFAllocatorDefault ,
1235
- port,
1236
- 0 );
1237
- CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode );
1238
- CFRelease (port);
1239
- }
1240
- @end
1241
-
1242
979
@implementation Window
1243
980
- (Window*)initWithContentRect : (NSRect )rect styleMask : (unsigned int )mask backing : (NSBackingStoreType )bufferingType defer : (BOOL )deferCreation withManager : (PyObject*)theManager
1244
981
{
0 commit comments