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
48
42
/* Keep track of the current mouse up/down state for open/closed cursor hand */
49
43
static bool leftMouseGrabbing = false ;
50
44
51
- /* -------------------------- Helper function ---------------------------- */
52
-
53
- static void
54
- _stdin_callback (CFReadStreamRef stream, CFStreamEventType eventType, void * info)
55
- {
56
- CFRunLoopRef runloop = info;
57
- CFRunLoopStop (runloop);
58
- }
59
-
60
- static int sigint_fd = -1 ;
61
-
62
- static void _sigint_handler (int sig)
63
- {
64
- const char c = ' i' ;
65
- write (sigint_fd, &c, 1 );
66
- }
67
-
68
- static void _sigint_callback (CFSocketRef s,
69
- CFSocketCallBackType type,
70
- CFDataRef address,
71
- const void * data,
72
- void *info)
73
- {
74
- char c;
75
- int * interrupted = info;
76
- CFSocketNativeHandle handle = CFSocketGetNative (s);
77
- CFRunLoopRef runloop = CFRunLoopGetCurrent ();
78
- read (handle, &c, 1 );
79
- *interrupted = 1 ;
80
- CFRunLoopStop (runloop);
81
- }
82
-
83
- static CGEventRef _eventtap_callback (
84
- CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
85
- {
86
- CFRunLoopRef runloop = refcon;
87
- CFRunLoopStop (runloop);
88
- return event;
89
- }
90
-
91
- static int wait_for_stdin (void )
92
- {
93
- int interrupted = 0 ;
94
- const UInt8 buffer[] = " /dev/fd/0" ;
95
- const CFIndex n = (CFIndex )strlen ((char *)buffer);
96
- CFRunLoopRef runloop = CFRunLoopGetCurrent ();
97
- CFURLRef url = CFURLCreateFromFileSystemRepresentation (kCFAllocatorDefault ,
98
- buffer,
99
- n,
100
- false );
101
- CFReadStreamRef stream = CFReadStreamCreateWithFile (kCFAllocatorDefault ,
102
- url);
103
- CFRelease (url);
104
-
105
- CFReadStreamOpen (stream);
106
- #ifdef PYOSINPUTHOOK_REPETITIVE
107
- if (!CFReadStreamHasBytesAvailable (stream))
108
- /* This is possible because of how PyOS_InputHook is called from Python */
109
- #endif
110
- {
111
- int error;
112
- int channel[2 ];
113
- CFSocketRef sigint_socket = NULL ;
114
- PyOS_sighandler_t py_sigint_handler = NULL ;
115
- CFStreamClientContext clientContext = {0 , NULL , NULL , NULL , NULL };
116
- clientContext.info = runloop;
117
- CFReadStreamSetClient (stream,
118
- kCFStreamEventHasBytesAvailable ,
119
- _stdin_callback,
120
- &clientContext);
121
- CFReadStreamScheduleWithRunLoop (stream, runloop, kCFRunLoopDefaultMode );
122
- error = socketpair (AF_UNIX, SOCK_STREAM, 0 , channel);
123
- if (!error) {
124
- CFSocketContext context;
125
- context.version = 0 ;
126
- context.info = &interrupted;
127
- context.retain = NULL ;
128
- context.release = NULL ;
129
- context.copyDescription = NULL ;
130
- fcntl (channel[0 ], F_SETFL, O_WRONLY | O_NONBLOCK);
131
- sigint_socket = CFSocketCreateWithNative (
132
- kCFAllocatorDefault ,
133
- channel[1 ],
134
- kCFSocketReadCallBack ,
135
- _sigint_callback,
136
- &context);
137
- if (sigint_socket) {
138
- CFRunLoopSourceRef source = CFSocketCreateRunLoopSource (
139
- kCFAllocatorDefault , sigint_socket, 0 );
140
- CFRelease (sigint_socket);
141
- if (source) {
142
- CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode );
143
- CFRelease (source);
144
- sigint_fd = channel[0 ];
145
- py_sigint_handler = PyOS_setsig (SIGINT, _sigint_handler);
146
- }
147
- }
148
- }
149
-
150
- NSEvent * event;
151
- while (true ) {
152
- while (true ) {
153
- event = [NSApp nextEventMatchingMask: NSEventMaskAny
154
- untilDate: [NSDate distantPast ]
155
- inMode: NSDefaultRunLoopMode
156
- dequeue: YES ];
157
- if (!event) { break ; }
158
- [NSApp sendEvent: event];
159
- }
160
- CFRunLoopRun ();
161
- if (interrupted || CFReadStreamHasBytesAvailable (stream)) { break ; }
162
- }
163
-
164
- if (py_sigint_handler) { PyOS_setsig (SIGINT, py_sigint_handler); }
165
- CFReadStreamUnscheduleFromRunLoop (
166
- stream, runloop, kCFRunLoopCommonModes );
167
- if (sigint_socket) { CFSocketInvalidate (sigint_socket); }
168
- if (!error) {
169
- close (channel[0 ]);
170
- close (channel[1 ]);
171
- }
172
- }
173
- CFReadStreamClose (stream);
174
- CFRelease (stream);
175
- if (interrupted) {
176
- errno = EINTR;
177
- raise (SIGINT);
178
- return -1 ;
179
- }
180
- return 1 ;
181
- }
182
-
183
45
/* ---------------------------- Cocoa classes ---------------------------- */
184
46
185
- @interface WindowServerConnectionManager : NSObject
186
- {
187
- }
188
- + (WindowServerConnectionManager*)sharedManager ;
189
- - (void )launch : (NSNotification *)notification ;
190
- @end
191
-
192
47
@interface Window : NSWindow
193
48
{ PyObject* manager;
194
49
}
@@ -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*
@@ -551,40 +397,6 @@ int mpl_check_modifier(
551
397
return NULL ;
552
398
}
553
399
554
- int error;
555
- int interrupted = 0 ;
556
- int channel[2 ];
557
- CFSocketRef sigint_socket = NULL ;
558
- PyOS_sighandler_t py_sigint_handler = NULL ;
559
-
560
- CFRunLoopRef runloop = CFRunLoopGetCurrent ();
561
-
562
- error = pipe (channel);
563
- if (!error) {
564
- CFSocketContext context = {0 , NULL , NULL , NULL , NULL };
565
- fcntl (channel[1 ], F_SETFL, O_WRONLY | O_NONBLOCK);
566
-
567
- context.info = &interrupted;
568
- sigint_socket = CFSocketCreateWithNative (kCFAllocatorDefault ,
569
- channel[0 ],
570
- kCFSocketReadCallBack ,
571
- _sigint_callback,
572
- &context);
573
- if (sigint_socket) {
574
- CFRunLoopSourceRef source = CFSocketCreateRunLoopSource (
575
- kCFAllocatorDefault , sigint_socket, 0 );
576
- CFRelease (sigint_socket);
577
- if (source) {
578
- CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode );
579
- CFRelease (source);
580
- sigint_fd = channel[1 ];
581
- py_sigint_handler = PyOS_setsig (SIGINT, _sigint_handler);
582
- }
583
- }
584
- else
585
- close (channel[0 ]);
586
- }
587
-
588
400
NSDate * date =
589
401
(timeout > 0.0 ) ? [NSDate dateWithTimeIntervalSinceNow: timeout]
590
402
: [NSDate distantFuture ];
@@ -597,11 +409,6 @@ int mpl_check_modifier(
597
409
[NSApp sendEvent: event];
598
410
}
599
411
600
- if (py_sigint_handler) { PyOS_setsig (SIGINT, py_sigint_handler); }
601
- if (sigint_socket) { CFSocketInvalidate (sigint_socket); }
602
- if (!error) { close (channel[1 ]); }
603
- if (interrupted) { raise (SIGINT); }
604
-
605
412
Py_RETURN_NONE;
606
413
}
607
414
@@ -1198,76 +1005,6 @@ -(void)save_figure:(id)sender { gil_call_method(toolbar, "save_figure"); }
1198
1005
Py_RETURN_NONE;
1199
1006
}
1200
1007
1201
- @implementation WindowServerConnectionManager
1202
- static WindowServerConnectionManager *sharedWindowServerConnectionManager = nil ;
1203
-
1204
- + (WindowServerConnectionManager *)sharedManager
1205
- {
1206
- if (sharedWindowServerConnectionManager == nil ) {
1207
- sharedWindowServerConnectionManager = [[super allocWithZone: NULL ] init ];
1208
- }
1209
- return sharedWindowServerConnectionManager;
1210
- }
1211
-
1212
- + (id )allocWithZone : (NSZone *)zone
1213
- {
1214
- return [[self sharedManager ] retain ];
1215
- }
1216
-
1217
- + (id )copyWithZone : (NSZone *)zone
1218
- {
1219
- return self;
1220
- }
1221
-
1222
- + (id )retain
1223
- {
1224
- return self;
1225
- }
1226
-
1227
- - (NSUInteger )retainCount
1228
- {
1229
- return NSUIntegerMax; // denotes an object that cannot be released
1230
- }
1231
-
1232
- - (oneway void )release
1233
- {
1234
- // Don't release a singleton object
1235
- }
1236
-
1237
- - (id )autorelease
1238
- {
1239
- return self;
1240
- }
1241
-
1242
- - (void )launch : (NSNotification *)notification
1243
- {
1244
- CFRunLoopRef runloop;
1245
- CFMachPortRef port;
1246
- CFRunLoopSourceRef source;
1247
- NSDictionary * dictionary = [notification userInfo ];
1248
- if (![[dictionary valueForKey: @" NSApplicationName" ]
1249
- localizedCaseInsensitiveContainsString: @" python" ])
1250
- return ;
1251
- NSNumber * psnLow = [dictionary valueForKey: @" NSApplicationProcessSerialNumberLow" ];
1252
- NSNumber * psnHigh = [dictionary valueForKey: @" NSApplicationProcessSerialNumberHigh" ];
1253
- ProcessSerialNumber psn;
1254
- psn.highLongOfPSN = [psnHigh intValue ];
1255
- psn.lowLongOfPSN = [psnLow intValue ];
1256
- runloop = CFRunLoopGetCurrent ();
1257
- port = CGEventTapCreateForPSN (&psn,
1258
- kCGHeadInsertEventTap ,
1259
- kCGEventTapOptionListenOnly ,
1260
- kCGEventMaskForAllEvents ,
1261
- &_eventtap_callback,
1262
- runloop);
1263
- source = CFMachPortCreateRunLoopSource (kCFAllocatorDefault ,
1264
- port,
1265
- 0 );
1266
- CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode );
1267
- CFRelease (port);
1268
- }
1269
- @end
1270
-
1271
1008
@implementation Window
1272
1009
- (Window*)initWithContentRect : (NSRect )rect styleMask : (unsigned int )mask backing : (NSBackingStoreType )bufferingType defer : (BOOL )deferCreation withManager : (PyObject*)theManager
1273
1010
{
0 commit comments