Blame


1 100ec44e 2010-01-04 rsc #define Point OSXPoint
2 100ec44e 2010-01-04 rsc #define Rect OSXRect
3 100ec44e 2010-01-04 rsc #define Cursor OSXCursor
4 100ec44e 2010-01-04 rsc #include <Carbon/Carbon.h>
5 813b3eea 2011-10-23 rsc #import <Foundation/Foundation.h>
6 5e83be0d 2011-06-20 rsc #ifdef MULTITOUCH
7 5e83be0d 2011-06-20 rsc #include <IOKit/IOKitLib.h>
8 5e83be0d 2011-06-20 rsc #include <IOKit/hidsystem/IOHIDShared.h>
9 5e83be0d 2011-06-20 rsc #endif
10 100ec44e 2010-01-04 rsc #undef Rect
11 100ec44e 2010-01-04 rsc #undef Point
12 100ec44e 2010-01-04 rsc #undef Cursor
13 100ec44e 2010-01-04 rsc #undef offsetof
14 100ec44e 2010-01-04 rsc #undef nil
15 100ec44e 2010-01-04 rsc
16 100ec44e 2010-01-04 rsc #include "u.h"
17 100ec44e 2010-01-04 rsc #include "libc.h"
18 100ec44e 2010-01-04 rsc #include <thread.h>
19 100ec44e 2010-01-04 rsc #include <draw.h>
20 100ec44e 2010-01-04 rsc #include <memdraw.h>
21 100ec44e 2010-01-04 rsc #include <keyboard.h>
22 100ec44e 2010-01-04 rsc #include "mouse.h"
23 100ec44e 2010-01-04 rsc #include <cursor.h>
24 100ec44e 2010-01-04 rsc #include "osx-screen.h"
25 100ec44e 2010-01-04 rsc #include "osx-keycodes.h"
26 100ec44e 2010-01-04 rsc #include "devdraw.h"
27 100ec44e 2010-01-04 rsc #include "glendapng.h"
28 100ec44e 2010-01-04 rsc
29 100ec44e 2010-01-04 rsc AUTOFRAMEWORK(Carbon)
30 100ec44e 2010-01-04 rsc AUTOFRAMEWORK(Cocoa)
31 100ec44e 2010-01-04 rsc
32 100ec44e 2010-01-04 rsc #ifdef MULTITOUCH
33 ecb01aca 2010-01-26 rsc AUTOFRAMEWORK(MultitouchSupport)
34 5e83be0d 2011-06-20 rsc AUTOFRAMEWORK(IOKit)
35 100ec44e 2010-01-04 rsc #endif
36 100ec44e 2010-01-04 rsc
37 100ec44e 2010-01-04 rsc #define panic sysfatal
38 100ec44e 2010-01-04 rsc
39 100ec44e 2010-01-04 rsc extern Rectangle mouserect;
40 100ec44e 2010-01-04 rsc
41 100ec44e 2010-01-04 rsc struct {
42 100ec44e 2010-01-04 rsc char *label;
43 100ec44e 2010-01-04 rsc char *winsize;
44 100ec44e 2010-01-04 rsc QLock labellock;
45 100ec44e 2010-01-04 rsc
46 100ec44e 2010-01-04 rsc Rectangle fullscreenr;
47 100ec44e 2010-01-04 rsc Rectangle screenr;
48 100ec44e 2010-01-04 rsc Memimage *screenimage;
49 100ec44e 2010-01-04 rsc int isfullscreen;
50 100ec44e 2010-01-04 rsc ulong fullscreentime;
51 100ec44e 2010-01-04 rsc
52 100ec44e 2010-01-04 rsc Point xy;
53 100ec44e 2010-01-04 rsc int buttons;
54 100ec44e 2010-01-04 rsc int kbuttons;
55 100ec44e 2010-01-04 rsc
56 100ec44e 2010-01-04 rsc CGDataProviderRef provider;
57 100ec44e 2010-01-04 rsc MenuRef wmenu;
58 100ec44e 2010-01-04 rsc MenuRef vmenu;
59 100ec44e 2010-01-04 rsc WindowRef window;
60 100ec44e 2010-01-04 rsc CGImageRef image;
61 100ec44e 2010-01-04 rsc CGContextRef windowctx;
62 100ec44e 2010-01-04 rsc PasteboardRef snarf;
63 100ec44e 2010-01-04 rsc int needflush;
64 100ec44e 2010-01-04 rsc QLock flushlock;
65 100ec44e 2010-01-04 rsc int active;
66 100ec44e 2010-01-04 rsc int infullscreen;
67 100ec44e 2010-01-04 rsc int kalting; // last keystroke was Kalt
68 100ec44e 2010-01-04 rsc int touched; // last mouse event was touchCallback
69 7d9c0f0f 2010-01-05 rsc int collapsed; // parked in dock
70 f50c3e95 2010-04-02 rsc int flushing; // flushproc has started
71 100ec44e 2010-01-04 rsc NSMutableArray* devicelist;
72 100ec44e 2010-01-04 rsc } osx;
73 100ec44e 2010-01-04 rsc
74 100ec44e 2010-01-04 rsc /*
75 100ec44e 2010-01-04 rsc These structs are required, in order to handle some parameters returned from the
76 100ec44e 2010-01-04 rsc Support.framework
77 100ec44e 2010-01-04 rsc */
78 100ec44e 2010-01-04 rsc typedef struct {
79 100ec44e 2010-01-04 rsc float x;
80 100ec44e 2010-01-04 rsc float y;
81 100ec44e 2010-01-04 rsc }mtPoint;
82 100ec44e 2010-01-04 rsc
83 100ec44e 2010-01-04 rsc typedef struct {
84 100ec44e 2010-01-04 rsc mtPoint position;
85 100ec44e 2010-01-04 rsc mtPoint velocity;
86 100ec44e 2010-01-04 rsc }mtReadout;
87 100ec44e 2010-01-04 rsc
88 100ec44e 2010-01-04 rsc /*
89 100ec44e 2010-01-04 rsc Some reversed engineered informations from MultiTouchSupport.framework
90 100ec44e 2010-01-04 rsc */
91 100ec44e 2010-01-04 rsc typedef struct
92 100ec44e 2010-01-04 rsc {
93 100ec44e 2010-01-04 rsc int frame; //the current frame
94 100ec44e 2010-01-04 rsc double timestamp; //event timestamp
95 100ec44e 2010-01-04 rsc int identifier; //identifier guaranteed unique for life of touch per device
96 100ec44e 2010-01-04 rsc int state; //the current state (not sure what the values mean)
97 100ec44e 2010-01-04 rsc int unknown1; //no idea what this does
98 100ec44e 2010-01-04 rsc int unknown2; //no idea what this does either
99 100ec44e 2010-01-04 rsc mtReadout normalized; //the normalized position and vector of the touch (0,0 to 1,1)
100 100ec44e 2010-01-04 rsc float size; //the size of the touch (the area of your finger being tracked)
101 100ec44e 2010-01-04 rsc int unknown3; //no idea what this does
102 100ec44e 2010-01-04 rsc float angle; //the angle of the touch -|
103 100ec44e 2010-01-04 rsc float majorAxis; //the major axis of the touch -|-- an ellipsoid. you can track the angle of each finger!
104 100ec44e 2010-01-04 rsc float minorAxis; //the minor axis of the touch -|
105 100ec44e 2010-01-04 rsc mtReadout unknown4; //not sure what this is for
106 100ec44e 2010-01-04 rsc int unknown5[2]; //no clue
107 100ec44e 2010-01-04 rsc float unknown6; //no clue
108 100ec44e 2010-01-04 rsc }Touch;
109 100ec44e 2010-01-04 rsc
110 100ec44e 2010-01-04 rsc //a reference pointer for the multitouch device
111 100ec44e 2010-01-04 rsc typedef void *MTDeviceRef;
112 100ec44e 2010-01-04 rsc
113 100ec44e 2010-01-04 rsc //the prototype for the callback function
114 100ec44e 2010-01-04 rsc typedef int (*MTContactCallbackFunction)(int,Touch*,int,double,int);
115 100ec44e 2010-01-04 rsc
116 100ec44e 2010-01-04 rsc //returns a pointer to the default device (the trackpad?)
117 100ec44e 2010-01-04 rsc MTDeviceRef MTDeviceCreateDefault(void);
118 100ec44e 2010-01-04 rsc
119 100ec44e 2010-01-04 rsc //returns a CFMutableArrayRef array of all multitouch devices
120 100ec44e 2010-01-04 rsc CFMutableArrayRef MTDeviceCreateList(void);
121 100ec44e 2010-01-04 rsc
122 100ec44e 2010-01-04 rsc //registers a device's frame callback to your callback function
123 100ec44e 2010-01-04 rsc void MTRegisterContactFrameCallback(MTDeviceRef, MTContactCallbackFunction);
124 5e83be0d 2011-06-20 rsc void MTUnregisterContactFrameCallback(MTDeviceRef, MTContactCallbackFunction);
125 100ec44e 2010-01-04 rsc
126 100ec44e 2010-01-04 rsc //start sending events
127 100ec44e 2010-01-04 rsc void MTDeviceStart(MTDeviceRef, int);
128 100ec44e 2010-01-04 rsc void MTDeviceStop(MTDeviceRef);
129 5e83be0d 2011-06-20 rsc
130 5e83be0d 2011-06-20 rsc MTDeviceRef MTDeviceCreateFromService(io_service_t);
131 5e83be0d 2011-06-20 rsc io_service_t MTDeviceGetService(MTDeviceRef);
132 100ec44e 2010-01-04 rsc
133 100ec44e 2010-01-04 rsc #define kNTracks 10
134 100ec44e 2010-01-04 rsc struct TouchTrack {
135 100ec44e 2010-01-04 rsc int id;
136 100ec44e 2010-01-04 rsc float firstThreshTime;
137 100ec44e 2010-01-04 rsc mtPoint pos;
138 100ec44e 2010-01-04 rsc } tracks[kNTracks];
139 100ec44e 2010-01-04 rsc
140 100ec44e 2010-01-04 rsc #define kSizeSensitivity 1.25f
141 100ec44e 2010-01-04 rsc #define kTimeSensitivity 0.03f /* seconds */
142 100ec44e 2010-01-04 rsc #define kButtonLimit 0.6f /* percentage from base of pad */
143 100ec44e 2010-01-04 rsc
144 100ec44e 2010-01-04 rsc int
145 100ec44e 2010-01-04 rsc findTrack(int id)
146 100ec44e 2010-01-04 rsc {
147 100ec44e 2010-01-04 rsc int i;
148 100ec44e 2010-01-04 rsc for(i = 0; i < kNTracks; ++i)
149 100ec44e 2010-01-04 rsc if(tracks[i].id == id)
150 100ec44e 2010-01-04 rsc return i;
151 100ec44e 2010-01-04 rsc return -1;
152 100ec44e 2010-01-04 rsc }
153 100ec44e 2010-01-04 rsc
154 100ec44e 2010-01-04 rsc #define kMoveSensitivity 0.05f
155 100ec44e 2010-01-04 rsc
156 100ec44e 2010-01-04 rsc int
157 100ec44e 2010-01-04 rsc moved(mtPoint a, mtPoint b)
158 100ec44e 2010-01-04 rsc {
159 100ec44e 2010-01-04 rsc if(fabs(a.x - b.x) > kMoveSensitivity)
160 100ec44e 2010-01-04 rsc return 1;
161 100ec44e 2010-01-04 rsc if(fabs(a.y - b.y) > kMoveSensitivity)
162 100ec44e 2010-01-04 rsc return 1;
163 100ec44e 2010-01-04 rsc return 0;
164 100ec44e 2010-01-04 rsc }
165 100ec44e 2010-01-04 rsc
166 100ec44e 2010-01-04 rsc int
167 100ec44e 2010-01-04 rsc classifyTouch(Touch *t)
168 100ec44e 2010-01-04 rsc {
169 100ec44e 2010-01-04 rsc mtPoint p;
170 100ec44e 2010-01-04 rsc int i;
171 100ec44e 2010-01-04 rsc
172 100ec44e 2010-01-04 rsc p = t->normalized.position;
173 100ec44e 2010-01-04 rsc
174 100ec44e 2010-01-04 rsc i = findTrack(t->identifier);
175 100ec44e 2010-01-04 rsc if(i == -1) {
176 100ec44e 2010-01-04 rsc i = findTrack(-1);
177 100ec44e 2010-01-04 rsc if(i == -1)
178 100ec44e 2010-01-04 rsc return 0; // No empty tracks.
179 100ec44e 2010-01-04 rsc tracks[i].id = t->identifier;
180 100ec44e 2010-01-04 rsc tracks[i].firstThreshTime = t->timestamp;
181 100ec44e 2010-01-04 rsc tracks[i].pos = p;
182 100ec44e 2010-01-04 rsc // we don't have a touch yet - we wait kTimeSensitivity before reporting it.
183 100ec44e 2010-01-04 rsc return 0;
184 100ec44e 2010-01-04 rsc }
185 100ec44e 2010-01-04 rsc
186 100ec44e 2010-01-04 rsc if(t->size == 0) { // lost touch
187 100ec44e 2010-01-04 rsc tracks[i].id = -1;
188 100ec44e 2010-01-04 rsc return 0;
189 100ec44e 2010-01-04 rsc }
190 100ec44e 2010-01-04 rsc if(t->size < kSizeSensitivity) {
191 100ec44e 2010-01-04 rsc tracks[i].firstThreshTime = t->timestamp;
192 100ec44e 2010-01-04 rsc }
193 100ec44e 2010-01-04 rsc if((t->timestamp - tracks[i].firstThreshTime) < kTimeSensitivity) {
194 100ec44e 2010-01-04 rsc return 0;
195 100ec44e 2010-01-04 rsc }
196 28afa898 2010-02-07 rsc if(p.y > kButtonLimit && t->size > kSizeSensitivity) {
197 100ec44e 2010-01-04 rsc if(p.x < 0.35)
198 100ec44e 2010-01-04 rsc return 1;
199 100ec44e 2010-01-04 rsc if(p.x > 0.65)
200 100ec44e 2010-01-04 rsc return 4;
201 100ec44e 2010-01-04 rsc if(p.x > 0.35 && p.x < 0.65)
202 100ec44e 2010-01-04 rsc return 2;
203 100ec44e 2010-01-04 rsc }
204 100ec44e 2010-01-04 rsc return 0;
205 100ec44e 2010-01-04 rsc }
206 100ec44e 2010-01-04 rsc
207 100ec44e 2010-01-04 rsc static ulong msec(void);
208 100ec44e 2010-01-04 rsc
209 100ec44e 2010-01-04 rsc int
210 100ec44e 2010-01-04 rsc touchCallback(int device, Touch *data, int nFingers, double timestamp, int frame)
211 100ec44e 2010-01-04 rsc {
212 100ec44e 2010-01-04 rsc #ifdef MULTITOUCH
213 100ec44e 2010-01-04 rsc int buttons, delta, i;
214 100ec44e 2010-01-04 rsc static int obuttons;
215 100ec44e 2010-01-04 rsc CGPoint p;
216 100ec44e 2010-01-04 rsc CGEventRef e;
217 100ec44e 2010-01-04 rsc
218 7d419a14 2010-01-15 rsc p.x = osx.xy.x+osx.screenr.min.x;
219 7d419a14 2010-01-15 rsc p.y = osx.xy.y+osx.screenr.min.y;
220 7d419a14 2010-01-15 rsc if(!ptinrect(Pt(p.x, p.y), osx.screenr))
221 7d419a14 2010-01-15 rsc return 0;
222 100ec44e 2010-01-04 rsc osx.touched = 1;
223 100ec44e 2010-01-04 rsc buttons = 0;
224 100ec44e 2010-01-04 rsc for(i = 0; i < nFingers; ++i)
225 100ec44e 2010-01-04 rsc buttons |= classifyTouch(data+i);
226 100ec44e 2010-01-04 rsc delta = buttons ^ obuttons;
227 100ec44e 2010-01-04 rsc obuttons = buttons;
228 100ec44e 2010-01-04 rsc if(delta & 1) {
229 100ec44e 2010-01-04 rsc e = CGEventCreateMouseEvent(NULL,
230 100ec44e 2010-01-04 rsc (buttons & 1) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp,
231 100ec44e 2010-01-04 rsc p,
232 100ec44e 2010-01-04 rsc 29);
233 100ec44e 2010-01-04 rsc CGEventPost(kCGSessionEventTap, e);
234 100ec44e 2010-01-04 rsc CFRelease(e);
235 100ec44e 2010-01-04 rsc }
236 100ec44e 2010-01-04 rsc if(delta & 2) {
237 100ec44e 2010-01-04 rsc e = CGEventCreateMouseEvent(NULL,
238 100ec44e 2010-01-04 rsc (buttons & 2) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp,
239 100ec44e 2010-01-04 rsc p,
240 100ec44e 2010-01-04 rsc 30);
241 100ec44e 2010-01-04 rsc CGEventPost(kCGSessionEventTap, e);
242 100ec44e 2010-01-04 rsc CFRelease(e);
243 100ec44e 2010-01-04 rsc }
244 100ec44e 2010-01-04 rsc if(delta & 4){
245 100ec44e 2010-01-04 rsc e = CGEventCreateMouseEvent(NULL,
246 100ec44e 2010-01-04 rsc (buttons & 4) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp,
247 100ec44e 2010-01-04 rsc p,
248 100ec44e 2010-01-04 rsc 31);
249 100ec44e 2010-01-04 rsc CGEventPost(kCGSessionEventTap, e);
250 100ec44e 2010-01-04 rsc CFRelease(e);
251 100ec44e 2010-01-04 rsc }
252 100ec44e 2010-01-04 rsc return delta != 0;
253 100ec44e 2010-01-04 rsc #else
254 100ec44e 2010-01-04 rsc return 0;
255 100ec44e 2010-01-04 rsc #endif
256 100ec44e 2010-01-04 rsc }
257 100ec44e 2010-01-04 rsc
258 100ec44e 2010-01-04 rsc extern int multitouch;
259 100ec44e 2010-01-04 rsc
260 100ec44e 2010-01-04 rsc enum
261 100ec44e 2010-01-04 rsc {
262 100ec44e 2010-01-04 rsc WindowAttrs =
263 100ec44e 2010-01-04 rsc kWindowCloseBoxAttribute |
264 100ec44e 2010-01-04 rsc kWindowCollapseBoxAttribute |
265 100ec44e 2010-01-04 rsc kWindowResizableAttribute |
266 100ec44e 2010-01-04 rsc kWindowStandardHandlerAttribute |
267 100ec44e 2010-01-04 rsc kWindowFullZoomAttribute
268 100ec44e 2010-01-04 rsc };
269 100ec44e 2010-01-04 rsc
270 100ec44e 2010-01-04 rsc enum
271 100ec44e 2010-01-04 rsc {
272 100ec44e 2010-01-04 rsc P9PEventLabelUpdate = 1
273 100ec44e 2010-01-04 rsc };
274 100ec44e 2010-01-04 rsc
275 100ec44e 2010-01-04 rsc static void screenproc(void*);
276 100ec44e 2010-01-04 rsc static void eresized(int);
277 100ec44e 2010-01-04 rsc static void fullscreen(int);
278 100ec44e 2010-01-04 rsc static void seticon(void);
279 100ec44e 2010-01-04 rsc static void activated(int);
280 100ec44e 2010-01-04 rsc
281 100ec44e 2010-01-04 rsc static OSStatus quithandler(EventHandlerCallRef, EventRef, void*);
282 100ec44e 2010-01-04 rsc static OSStatus eventhandler(EventHandlerCallRef, EventRef, void*);
283 100ec44e 2010-01-04 rsc static OSStatus cmdhandler(EventHandlerCallRef, EventRef, void*);
284 100ec44e 2010-01-04 rsc
285 100ec44e 2010-01-04 rsc enum
286 100ec44e 2010-01-04 rsc {
287 100ec44e 2010-01-04 rsc CmdFullScreen = 1,
288 100ec44e 2010-01-04 rsc };
289 100ec44e 2010-01-04 rsc
290 100ec44e 2010-01-04 rsc void screeninit(void);
291 100ec44e 2010-01-04 rsc void _flushmemscreen(Rectangle r);
292 100ec44e 2010-01-04 rsc
293 5e83be0d 2011-06-20 rsc #ifdef MULTITOUCH
294 100ec44e 2010-01-04 rsc static void
295 5e83be0d 2011-06-20 rsc RegisterMultitouch(void *ctx, io_iterator_t iter)
296 5e83be0d 2011-06-20 rsc {
297 5e83be0d 2011-06-20 rsc io_object_t io;
298 5e83be0d 2011-06-20 rsc MTDeviceRef dev;
299 5e83be0d 2011-06-20 rsc
300 5e83be0d 2011-06-20 rsc while((io = IOIteratorNext(iter)) != 0){
301 5e83be0d 2011-06-20 rsc dev = MTDeviceCreateFromService(io);
302 5e83be0d 2011-06-20 rsc if (dev != nil){
303 5e83be0d 2011-06-20 rsc MTRegisterContactFrameCallback(dev, touchCallback);
304 5e83be0d 2011-06-20 rsc [osx.devicelist addObject:dev];
305 5e83be0d 2011-06-20 rsc if(osx.active)
306 5e83be0d 2011-06-20 rsc MTDeviceStart(dev, 0);
307 5e83be0d 2011-06-20 rsc }
308 5e83be0d 2011-06-20 rsc
309 5e83be0d 2011-06-20 rsc IOObjectRelease(io);
310 5e83be0d 2011-06-20 rsc }
311 5e83be0d 2011-06-20 rsc }
312 5e83be0d 2011-06-20 rsc
313 5e83be0d 2011-06-20 rsc static void
314 5e83be0d 2011-06-20 rsc UnregisterMultitouch(void *ctx, io_iterator_t iter)
315 100ec44e 2010-01-04 rsc {
316 5e83be0d 2011-06-20 rsc io_object_t io;
317 5e83be0d 2011-06-20 rsc MTDeviceRef dev;
318 5e83be0d 2011-06-20 rsc int i;
319 5e83be0d 2011-06-20 rsc
320 5e83be0d 2011-06-20 rsc while((io = IOIteratorNext(iter)) != 0){
321 5e83be0d 2011-06-20 rsc for(i = 0; i < [osx.devicelist count]; i++){
322 5e83be0d 2011-06-20 rsc dev = [osx.devicelist objectAtIndex:i];
323 5e83be0d 2011-06-20 rsc if(IOObjectIsEqualTo(MTDeviceGetService(dev), io)){
324 5e83be0d 2011-06-20 rsc if(osx.active)
325 5e83be0d 2011-06-20 rsc MTDeviceStop(dev);
326 5e83be0d 2011-06-20 rsc MTUnregisterContactFrameCallback(dev, touchCallback);
327 5e83be0d 2011-06-20 rsc [osx.devicelist removeObjectAtIndex:i];
328 5e83be0d 2011-06-20 rsc break;
329 5e83be0d 2011-06-20 rsc }
330 5e83be0d 2011-06-20 rsc }
331 5e83be0d 2011-06-20 rsc
332 5e83be0d 2011-06-20 rsc IOObjectRelease(io);
333 5e83be0d 2011-06-20 rsc }
334 5e83be0d 2011-06-20 rsc }
335 5e83be0d 2011-06-20 rsc
336 5e83be0d 2011-06-20 rsc #endif /*MULTITOUCH*/
337 5e83be0d 2011-06-20 rsc
338 5e83be0d 2011-06-20 rsc static void
339 5e83be0d 2011-06-20 rsc InitMultiTouch()
340 5e83be0d 2011-06-20 rsc {
341 100ec44e 2010-01-04 rsc #ifdef MULTITOUCH
342 5e83be0d 2011-06-20 rsc IONotificationPortRef port;
343 5e83be0d 2011-06-20 rsc CFRunLoopSourceRef source;
344 5e83be0d 2011-06-20 rsc io_iterator_t iter;
345 5e83be0d 2011-06-20 rsc kern_return_t kr;
346 5e83be0d 2011-06-20 rsc io_object_t obj;
347 100ec44e 2010-01-04 rsc int i;
348 100ec44e 2010-01-04 rsc
349 100ec44e 2010-01-04 rsc if(!multitouch)
350 100ec44e 2010-01-04 rsc return;
351 100ec44e 2010-01-04 rsc
352 5e83be0d 2011-06-20 rsc osx.devicelist = [[NSMutableArray alloc] init];
353 5e83be0d 2011-06-20 rsc
354 5e83be0d 2011-06-20 rsc for(i = 0; i < kNTracks; ++i)
355 100ec44e 2010-01-04 rsc tracks[i].id = -1;
356 100ec44e 2010-01-04 rsc
357 5e83be0d 2011-06-20 rsc port = IONotificationPortCreate(kIOMasterPortDefault);
358 5e83be0d 2011-06-20 rsc if(port == nil){
359 5e83be0d 2011-06-20 rsc fprint(2, "failed to get an IO notification port\n");
360 5e83be0d 2011-06-20 rsc return;
361 100ec44e 2010-01-04 rsc }
362 5e83be0d 2011-06-20 rsc
363 5e83be0d 2011-06-20 rsc source = IONotificationPortGetRunLoopSource(port);
364 5e83be0d 2011-06-20 rsc if(source == nil){
365 5e83be0d 2011-06-20 rsc fprint(2, "failed to get loop source for port");
366 5e83be0d 2011-06-20 rsc return;
367 5e83be0d 2011-06-20 rsc }
368 5e83be0d 2011-06-20 rsc
369 5e83be0d 2011-06-20 rsc CFRunLoopAddSource(
370 5e83be0d 2011-06-20 rsc (CFRunLoopRef)GetCFRunLoopFromEventLoop(GetMainEventLoop()),
371 5e83be0d 2011-06-20 rsc source,
372 5e83be0d 2011-06-20 rsc kCFRunLoopDefaultMode);
373 5e83be0d 2011-06-20 rsc
374 5e83be0d 2011-06-20 rsc kr = IOServiceAddMatchingNotification(
375 5e83be0d 2011-06-20 rsc port, kIOTerminatedNotification,
376 5e83be0d 2011-06-20 rsc IOServiceMatching("AppleMultitouchDevice"),
377 5e83be0d 2011-06-20 rsc &UnregisterMultitouch,
378 5e83be0d 2011-06-20 rsc nil, &iter);
379 5e83be0d 2011-06-20 rsc
380 5e83be0d 2011-06-20 rsc if(kr != KERN_SUCCESS){
381 5e83be0d 2011-06-20 rsc fprint(2, "failed to add termination notification\n");
382 5e83be0d 2011-06-20 rsc return;
383 5e83be0d 2011-06-20 rsc }
384 5e83be0d 2011-06-20 rsc
385 5e83be0d 2011-06-20 rsc /* Arm the notification */
386 5e83be0d 2011-06-20 rsc while((obj = IOIteratorNext(iter)) != 0)
387 5e83be0d 2011-06-20 rsc IOObjectRelease(obj);
388 5e83be0d 2011-06-20 rsc
389 5e83be0d 2011-06-20 rsc kr = IOServiceAddMatchingNotification(
390 5e83be0d 2011-06-20 rsc port, kIOMatchedNotification,
391 5e83be0d 2011-06-20 rsc IOServiceMatching("AppleMultitouchDevice"),
392 5e83be0d 2011-06-20 rsc &RegisterMultitouch,
393 5e83be0d 2011-06-20 rsc nil, &iter);
394 5e83be0d 2011-06-20 rsc
395 5e83be0d 2011-06-20 rsc if(kr != KERN_SUCCESS){
396 5e83be0d 2011-06-20 rsc fprint(2, "failed to add matching notification\n");
397 5e83be0d 2011-06-20 rsc return;
398 5e83be0d 2011-06-20 rsc }
399 5e83be0d 2011-06-20 rsc
400 5e83be0d 2011-06-20 rsc RegisterMultitouch(nil, iter);
401 100ec44e 2010-01-04 rsc #endif
402 100ec44e 2010-01-04 rsc }
403 100ec44e 2010-01-04 rsc
404 100ec44e 2010-01-04 rsc Memimage*
405 100ec44e 2010-01-04 rsc attachscreen(char *label, char *winsize)
406 100ec44e 2010-01-04 rsc {
407 100ec44e 2010-01-04 rsc if(label == nil)
408 100ec44e 2010-01-04 rsc label = "gnot a label";
409 100ec44e 2010-01-04 rsc osx.label = strdup(label);
410 100ec44e 2010-01-04 rsc osx.winsize = winsize;
411 100ec44e 2010-01-04 rsc if(osx.screenimage == nil){
412 100ec44e 2010-01-04 rsc screeninit();
413 100ec44e 2010-01-04 rsc if(osx.screenimage == nil)
414 100ec44e 2010-01-04 rsc panic("cannot create OS X screen");
415 100ec44e 2010-01-04 rsc }
416 100ec44e 2010-01-04 rsc return osx.screenimage;
417 100ec44e 2010-01-04 rsc }
418 100ec44e 2010-01-04 rsc
419 100ec44e 2010-01-04 rsc extern int multitouch;
420 100ec44e 2010-01-04 rsc
421 100ec44e 2010-01-04 rsc void
422 100ec44e 2010-01-04 rsc _screeninit(void)
423 100ec44e 2010-01-04 rsc {
424 100ec44e 2010-01-04 rsc CGRect cgr;
425 100ec44e 2010-01-04 rsc OSXRect or;
426 100ec44e 2010-01-04 rsc Rectangle r;
427 100ec44e 2010-01-04 rsc int havemin;
428 100ec44e 2010-01-04 rsc
429 100ec44e 2010-01-04 rsc memimageinit();
430 100ec44e 2010-01-04 rsc
431 100ec44e 2010-01-04 rsc ProcessSerialNumber psn = { 0, kCurrentProcess };
432 100ec44e 2010-01-04 rsc TransformProcessType(&psn, kProcessTransformToForegroundApplication);
433 100ec44e 2010-01-04 rsc SetFrontProcess(&psn);
434 100ec44e 2010-01-04 rsc
435 100ec44e 2010-01-04 rsc cgr = CGDisplayBounds(CGMainDisplayID());
436 100ec44e 2010-01-04 rsc osx.fullscreenr = Rect(0, 0, cgr.size.width, cgr.size.height);
437 100ec44e 2010-01-04 rsc
438 100ec44e 2010-01-04 rsc InitCursor();
439 100ec44e 2010-01-04 rsc
440 100ec44e 2010-01-04 rsc // Create minimal menu with full-screen option.
441 100ec44e 2010-01-04 rsc ClearMenuBar();
442 100ec44e 2010-01-04 rsc CreateStandardWindowMenu(0, &osx.wmenu);
443 100ec44e 2010-01-04 rsc InsertMenu(osx.wmenu, 0);
444 100ec44e 2010-01-04 rsc MenuItemIndex ix;
445 100ec44e 2010-01-04 rsc CreateNewMenu(1004, 0, &osx.vmenu); // XXX 1004?
446 100ec44e 2010-01-04 rsc SetMenuTitleWithCFString(osx.vmenu, CFSTR("View"));
447 100ec44e 2010-01-04 rsc AppendMenuItemTextWithCFString(osx.vmenu,
448 100ec44e 2010-01-04 rsc CFSTR("Full Screen"), 0, CmdFullScreen, &ix);
449 100ec44e 2010-01-04 rsc SetMenuItemCommandKey(osx.vmenu, ix, 0, 'F');
450 100ec44e 2010-01-04 rsc AppendMenuItemTextWithCFString(osx.vmenu,
451 100ec44e 2010-01-04 rsc CFSTR("Cmd-F exits full screen"),
452 100ec44e 2010-01-04 rsc kMenuItemAttrDisabled, CmdFullScreen, &ix);
453 100ec44e 2010-01-04 rsc InsertMenu(osx.vmenu, GetMenuID(osx.wmenu));
454 100ec44e 2010-01-04 rsc DrawMenuBar();
455 100ec44e 2010-01-04 rsc
456 100ec44e 2010-01-04 rsc // Create the window.
457 100ec44e 2010-01-04 rsc r = Rect(0, 0, Dx(osx.fullscreenr)*2/3, Dy(osx.fullscreenr)*2/3);
458 100ec44e 2010-01-04 rsc havemin = 0;
459 100ec44e 2010-01-04 rsc if(osx.winsize && osx.winsize[0]){
460 100ec44e 2010-01-04 rsc if(parsewinsize(osx.winsize, &r, &havemin) < 0)
461 100ec44e 2010-01-04 rsc sysfatal("%r");
462 100ec44e 2010-01-04 rsc }
463 100ec44e 2010-01-04 rsc if(!havemin)
464 100ec44e 2010-01-04 rsc r = rectaddpt(r, Pt((Dx(osx.fullscreenr)-Dx(r))/2, (Dy(osx.fullscreenr)-Dy(r))/2));
465 100ec44e 2010-01-04 rsc or.left = r.min.x;
466 100ec44e 2010-01-04 rsc or.top = r.min.y;
467 100ec44e 2010-01-04 rsc or.right = r.max.x;
468 100ec44e 2010-01-04 rsc or.bottom = r.max.y;
469 100ec44e 2010-01-04 rsc CreateNewWindow(kDocumentWindowClass, WindowAttrs, &or, &osx.window);
470 100ec44e 2010-01-04 rsc setlabel(osx.label);
471 100ec44e 2010-01-04 rsc seticon();
472 100ec44e 2010-01-04 rsc
473 100ec44e 2010-01-04 rsc // Set up the clip board.
474 100ec44e 2010-01-04 rsc if(PasteboardCreate(kPasteboardClipboard, &osx.snarf) != noErr)
475 100ec44e 2010-01-04 rsc panic("pasteboard create");
476 100ec44e 2010-01-04 rsc
477 100ec44e 2010-01-04 rsc // Explain in great detail which events we want to handle.
478 100ec44e 2010-01-04 rsc // Why can't we just have one handler?
479 100ec44e 2010-01-04 rsc const EventTypeSpec quits[] = {
480 100ec44e 2010-01-04 rsc { kEventClassApplication, kEventAppQuit }
481 100ec44e 2010-01-04 rsc };
482 100ec44e 2010-01-04 rsc const EventTypeSpec cmds[] = {
483 100ec44e 2010-01-04 rsc { kEventClassWindow, kEventWindowClosed },
484 100ec44e 2010-01-04 rsc { kEventClassWindow, kEventWindowBoundsChanged },
485 fb243a13 2010-01-14 rsc { kEventClassWindow, kEventWindowDrawContent },
486 100ec44e 2010-01-04 rsc { kEventClassCommand, kEventCommandProcess },
487 100ec44e 2010-01-04 rsc { kEventClassWindow, kEventWindowActivated },
488 100ec44e 2010-01-04 rsc { kEventClassWindow, kEventWindowDeactivated },
489 7d9c0f0f 2010-01-05 rsc { kEventClassWindow, kEventWindowCollapsed },
490 7d9c0f0f 2010-01-05 rsc { kEventClassWindow, kEventWindowExpanded },
491 100ec44e 2010-01-04 rsc };
492 100ec44e 2010-01-04 rsc const EventTypeSpec events[] = {
493 100ec44e 2010-01-04 rsc { kEventClassApplication, kEventAppShown },
494 100ec44e 2010-01-04 rsc { kEventClassKeyboard, kEventRawKeyDown },
495 100ec44e 2010-01-04 rsc { kEventClassKeyboard, kEventRawKeyModifiersChanged },
496 100ec44e 2010-01-04 rsc { kEventClassKeyboard, kEventRawKeyRepeat },
497 100ec44e 2010-01-04 rsc { kEventClassMouse, kEventMouseDown },
498 100ec44e 2010-01-04 rsc { kEventClassMouse, kEventMouseUp },
499 100ec44e 2010-01-04 rsc { kEventClassMouse, kEventMouseMoved },
500 100ec44e 2010-01-04 rsc { kEventClassMouse, kEventMouseDragged },
501 100ec44e 2010-01-04 rsc { kEventClassMouse, kEventMouseWheelMoved },
502 100ec44e 2010-01-04 rsc { 'P9PE', P9PEventLabelUpdate}
503 100ec44e 2010-01-04 rsc };
504 100ec44e 2010-01-04 rsc
505 100ec44e 2010-01-04 rsc InstallApplicationEventHandler(
506 100ec44e 2010-01-04 rsc NewEventHandlerUPP(quithandler),
507 100ec44e 2010-01-04 rsc nelem(quits), quits, nil, nil);
508 100ec44e 2010-01-04 rsc
509 100ec44e 2010-01-04 rsc InstallApplicationEventHandler(
510 100ec44e 2010-01-04 rsc NewEventHandlerUPP(eventhandler),
511 100ec44e 2010-01-04 rsc nelem(events), events, nil, nil);
512 100ec44e 2010-01-04 rsc
513 100ec44e 2010-01-04 rsc InstallWindowEventHandler(osx.window,
514 100ec44e 2010-01-04 rsc NewEventHandlerUPP(cmdhandler),
515 100ec44e 2010-01-04 rsc nelem(cmds), cmds, osx.window, nil);
516 100ec44e 2010-01-04 rsc
517 100ec44e 2010-01-04 rsc // Finally, put the window on the screen.
518 100ec44e 2010-01-04 rsc ShowWindow(osx.window);
519 100ec44e 2010-01-04 rsc ShowMenuBar();
520 100ec44e 2010-01-04 rsc eresized(0);
521 100ec44e 2010-01-04 rsc SelectWindow(osx.window);
522 100ec44e 2010-01-04 rsc
523 100ec44e 2010-01-04 rsc if(multitouch)
524 100ec44e 2010-01-04 rsc InitMultiTouch();
525 d94cc62a 2010-03-04 rsc
526 d94cc62a 2010-03-04 rsc // CoreGraphics pins mouse events to the destination point of a
527 d94cc62a 2010-03-04 rsc // CGWarpMouseCursorPosition (see setmouse) for an interval of time
528 d94cc62a 2010-03-04 rsc // following the move. Disable this by setting the interval to zero
529 d94cc62a 2010-03-04 rsc // seconds.
530 d94cc62a 2010-03-04 rsc CGSetLocalEventsSuppressionInterval(0.0);
531 d94cc62a 2010-03-04 rsc
532 100ec44e 2010-01-04 rsc InitCursor();
533 100ec44e 2010-01-04 rsc }
534 100ec44e 2010-01-04 rsc
535 100ec44e 2010-01-04 rsc static Rendez scr;
536 100ec44e 2010-01-04 rsc static QLock slock;
537 100ec44e 2010-01-04 rsc
538 100ec44e 2010-01-04 rsc void
539 100ec44e 2010-01-04 rsc screeninit(void)
540 100ec44e 2010-01-04 rsc {
541 100ec44e 2010-01-04 rsc scr.l = &slock;
542 100ec44e 2010-01-04 rsc qlock(scr.l);
543 100ec44e 2010-01-04 rsc proccreate(screenproc, nil, 256*1024);
544 100ec44e 2010-01-04 rsc while(osx.window == nil)
545 100ec44e 2010-01-04 rsc rsleep(&scr);
546 100ec44e 2010-01-04 rsc qunlock(scr.l);
547 100ec44e 2010-01-04 rsc }
548 100ec44e 2010-01-04 rsc
549 100ec44e 2010-01-04 rsc static void
550 100ec44e 2010-01-04 rsc screenproc(void *v)
551 100ec44e 2010-01-04 rsc {
552 100ec44e 2010-01-04 rsc qlock(scr.l);
553 100ec44e 2010-01-04 rsc _screeninit();
554 100ec44e 2010-01-04 rsc rwakeup(&scr);
555 100ec44e 2010-01-04 rsc qunlock(scr.l);
556 100ec44e 2010-01-04 rsc RunApplicationEventLoop();
557 100ec44e 2010-01-04 rsc }
558 100ec44e 2010-01-04 rsc
559 100ec44e 2010-01-04 rsc static OSStatus kbdevent(EventRef);
560 100ec44e 2010-01-04 rsc static OSStatus mouseevent(EventRef);
561 100ec44e 2010-01-04 rsc
562 100ec44e 2010-01-04 rsc static OSStatus
563 100ec44e 2010-01-04 rsc cmdhandler(EventHandlerCallRef next, EventRef event, void *arg)
564 100ec44e 2010-01-04 rsc {
565 100ec44e 2010-01-04 rsc return eventhandler(next, event, arg);
566 100ec44e 2010-01-04 rsc }
567 100ec44e 2010-01-04 rsc
568 100ec44e 2010-01-04 rsc static OSStatus
569 100ec44e 2010-01-04 rsc quithandler(EventHandlerCallRef next, EventRef event, void *arg)
570 100ec44e 2010-01-04 rsc {
571 100ec44e 2010-01-04 rsc exit(0);
572 100ec44e 2010-01-04 rsc return 0;
573 100ec44e 2010-01-04 rsc }
574 100ec44e 2010-01-04 rsc
575 100ec44e 2010-01-04 rsc static OSStatus
576 100ec44e 2010-01-04 rsc eventhandler(EventHandlerCallRef next, EventRef event, void *arg)
577 100ec44e 2010-01-04 rsc {
578 100ec44e 2010-01-04 rsc OSStatus result;
579 100ec44e 2010-01-04 rsc
580 100ec44e 2010-01-04 rsc result = CallNextEventHandler(next, event);
581 100ec44e 2010-01-04 rsc
582 100ec44e 2010-01-04 rsc switch(GetEventClass(event)){
583 100ec44e 2010-01-04 rsc
584 100ec44e 2010-01-04 rsc case 'P9PE':
585 100ec44e 2010-01-04 rsc if(GetEventKind(event) == P9PEventLabelUpdate) {
586 100ec44e 2010-01-04 rsc qlock(&osx.labellock);
587 100ec44e 2010-01-04 rsc setlabel(osx.label);
588 100ec44e 2010-01-04 rsc qunlock(&osx.labellock);
589 100ec44e 2010-01-04 rsc return noErr;
590 100ec44e 2010-01-04 rsc } else
591 100ec44e 2010-01-04 rsc return eventNotHandledErr;
592 100ec44e 2010-01-04 rsc
593 100ec44e 2010-01-04 rsc case kEventClassApplication:;
594 100ec44e 2010-01-04 rsc Rectangle r = Rect(0, 0, Dx(osx.screenr), Dy(osx.screenr));
595 100ec44e 2010-01-04 rsc _flushmemscreen(r);
596 100ec44e 2010-01-04 rsc return eventNotHandledErr;
597 100ec44e 2010-01-04 rsc
598 100ec44e 2010-01-04 rsc case kEventClassKeyboard:
599 100ec44e 2010-01-04 rsc return kbdevent(event);
600 100ec44e 2010-01-04 rsc
601 100ec44e 2010-01-04 rsc case kEventClassMouse:
602 100ec44e 2010-01-04 rsc return mouseevent(event);
603 100ec44e 2010-01-04 rsc
604 100ec44e 2010-01-04 rsc case kEventClassCommand:;
605 100ec44e 2010-01-04 rsc HICommand cmd;
606 100ec44e 2010-01-04 rsc GetEventParameter(event, kEventParamDirectObject,
607 100ec44e 2010-01-04 rsc typeHICommand, nil, sizeof cmd, nil, &cmd);
608 100ec44e 2010-01-04 rsc switch(cmd.commandID){
609 100ec44e 2010-01-04 rsc case kHICommandQuit:
610 100ec44e 2010-01-04 rsc exit(0);
611 100ec44e 2010-01-04 rsc
612 100ec44e 2010-01-04 rsc case CmdFullScreen:
613 100ec44e 2010-01-04 rsc fullscreen(1);
614 100ec44e 2010-01-04 rsc break;
615 100ec44e 2010-01-04 rsc
616 100ec44e 2010-01-04 rsc default:
617 100ec44e 2010-01-04 rsc return eventNotHandledErr;
618 100ec44e 2010-01-04 rsc }
619 100ec44e 2010-01-04 rsc break;
620 100ec44e 2010-01-04 rsc
621 100ec44e 2010-01-04 rsc case kEventClassWindow:
622 100ec44e 2010-01-04 rsc switch(GetEventKind(event)){
623 100ec44e 2010-01-04 rsc case kEventWindowClosed:
624 100ec44e 2010-01-04 rsc exit(0);
625 100ec44e 2010-01-04 rsc
626 e055ceb2 2011-06-20 rsc case kEventWindowBoundsChanged:;
627 e055ceb2 2011-06-20 rsc // We see kEventWindowDrawContent
628 e055ceb2 2011-06-20 rsc // if we grow a window but not if we shrink it.
629 e055ceb2 2011-06-20 rsc UInt32 flags;
630 e055ceb2 2011-06-20 rsc GetEventParameter(event, kEventParamAttributes,
631 e055ceb2 2011-06-20 rsc typeUInt32, 0, sizeof flags, 0, &flags);
632 e055ceb2 2011-06-20 rsc int new = (flags & kWindowBoundsChangeSizeChanged) != 0;
633 e055ceb2 2011-06-20 rsc eresized(new);
634 100ec44e 2010-01-04 rsc break;
635 100ec44e 2010-01-04 rsc
636 a61c6933 2010-01-16 rsc case kEventWindowDrawContent:
637 a61c6933 2010-01-16 rsc // Tried using just flushmemimage here, but
638 a61c6933 2010-01-16 rsc // it causes an odd artifact in which making a window
639 a61c6933 2010-01-16 rsc // bigger in both width and height can then only draw
640 a61c6933 2010-01-16 rsc // on the new border: it's like the old window is stuck
641 a61c6933 2010-01-16 rsc // floating on top. Doing a full "get a new window"
642 a61c6933 2010-01-16 rsc // seems to solve the problem.
643 a61c6933 2010-01-16 rsc eresized(1);
644 fb243a13 2010-01-14 rsc break;
645 fb243a13 2010-01-14 rsc
646 100ec44e 2010-01-04 rsc case kEventWindowActivated:
647 7d9c0f0f 2010-01-05 rsc if(!osx.collapsed)
648 7d9c0f0f 2010-01-05 rsc activated(1);
649 100ec44e 2010-01-04 rsc return eventNotHandledErr;
650 100ec44e 2010-01-04 rsc
651 100ec44e 2010-01-04 rsc case kEventWindowDeactivated:
652 7d9c0f0f 2010-01-05 rsc activated(0);
653 7d9c0f0f 2010-01-05 rsc return eventNotHandledErr;
654 7d9c0f0f 2010-01-05 rsc
655 7d9c0f0f 2010-01-05 rsc case kEventWindowCollapsed:
656 7d9c0f0f 2010-01-05 rsc osx.collapsed = 1;
657 100ec44e 2010-01-04 rsc activated(0);
658 100ec44e 2010-01-04 rsc return eventNotHandledErr;
659 100ec44e 2010-01-04 rsc
660 7d9c0f0f 2010-01-05 rsc case kEventWindowExpanded:
661 7d9c0f0f 2010-01-05 rsc osx.collapsed = 0;
662 7d9c0f0f 2010-01-05 rsc activated(1);
663 7d9c0f0f 2010-01-05 rsc return eventNotHandledErr;
664 7d9c0f0f 2010-01-05 rsc
665 100ec44e 2010-01-04 rsc default:
666 100ec44e 2010-01-04 rsc return eventNotHandledErr;
667 100ec44e 2010-01-04 rsc }
668 100ec44e 2010-01-04 rsc break;
669 100ec44e 2010-01-04 rsc }
670 100ec44e 2010-01-04 rsc
671 100ec44e 2010-01-04 rsc return result;
672 100ec44e 2010-01-04 rsc }
673 100ec44e 2010-01-04 rsc
674 100ec44e 2010-01-04 rsc static ulong
675 100ec44e 2010-01-04 rsc msec(void)
676 100ec44e 2010-01-04 rsc {
677 100ec44e 2010-01-04 rsc return nsec()/1000000;
678 100ec44e 2010-01-04 rsc }
679 100ec44e 2010-01-04 rsc
680 100ec44e 2010-01-04 rsc static OSStatus
681 100ec44e 2010-01-04 rsc mouseevent(EventRef event)
682 100ec44e 2010-01-04 rsc {
683 100ec44e 2010-01-04 rsc int wheel;
684 100ec44e 2010-01-04 rsc OSXPoint op;
685 100ec44e 2010-01-04 rsc
686 100ec44e 2010-01-04 rsc GetEventParameter(event, kEventParamMouseLocation,
687 100ec44e 2010-01-04 rsc typeQDPoint, 0, sizeof op, 0, &op);
688 100ec44e 2010-01-04 rsc
689 100ec44e 2010-01-04 rsc osx.xy = subpt(Pt(op.h, op.v), osx.screenr.min);
690 100ec44e 2010-01-04 rsc wheel = 0;
691 100ec44e 2010-01-04 rsc
692 100ec44e 2010-01-04 rsc switch(GetEventKind(event)){
693 100ec44e 2010-01-04 rsc case kEventMouseWheelMoved:;
694 100ec44e 2010-01-04 rsc SInt32 delta;
695 100ec44e 2010-01-04 rsc GetEventParameter(event, kEventParamMouseWheelDelta,
696 100ec44e 2010-01-04 rsc typeSInt32, 0, sizeof delta, 0, &delta);
697 100ec44e 2010-01-04 rsc
698 100ec44e 2010-01-04 rsc // if I have any active touches in my region, I need to ignore the wheel motion.
699 100ec44e 2010-01-04 rsc //int i;
700 100ec44e 2010-01-04 rsc //for(i = 0; i < kNTracks; ++i) {
701 100ec44e 2010-01-04 rsc // if(tracks[i].id != -1 && tracks[i].pos.y > kButtonLimit) break;
702 100ec44e 2010-01-04 rsc //}
703 100ec44e 2010-01-04 rsc //if(i == kNTracks) { // No active touches, go ahead and scroll.
704 100ec44e 2010-01-04 rsc if(delta > 0)
705 100ec44e 2010-01-04 rsc wheel = 8;
706 100ec44e 2010-01-04 rsc else
707 100ec44e 2010-01-04 rsc wheel = 16;
708 100ec44e 2010-01-04 rsc //}
709 100ec44e 2010-01-04 rsc break;
710 100ec44e 2010-01-04 rsc
711 100ec44e 2010-01-04 rsc case kEventMouseDown:
712 100ec44e 2010-01-04 rsc case kEventMouseUp:;
713 100ec44e 2010-01-04 rsc UInt32 but, mod;
714 100ec44e 2010-01-04 rsc GetEventParameter(event, kEventParamMouseChord,
715 100ec44e 2010-01-04 rsc typeUInt32, 0, sizeof but, 0, &but);
716 100ec44e 2010-01-04 rsc GetEventParameter(event, kEventParamKeyModifiers,
717 100ec44e 2010-01-04 rsc typeUInt32, 0, sizeof mod, 0, &mod);
718 100ec44e 2010-01-04 rsc
719 28afa898 2010-02-07 rsc // OS X swaps button 2 and 3
720 28afa898 2010-02-07 rsc but = (but & ~6) | ((but & 4)>>1) | ((but&2)<<1);
721 28afa898 2010-02-07 rsc but = (but & ~((1<<10)-1)) | mouseswap(but & ((1<<10)-1));
722 100ec44e 2010-01-04 rsc if(osx.touched) {
723 100ec44e 2010-01-04 rsc // in multitouch we use the clicks down to enable our
724 100ec44e 2010-01-04 rsc // virtual buttons.
725 28afa898 2010-02-07 rsc if(but & 0x7) {
726 28afa898 2010-02-07 rsc if(but>>29)
727 28afa898 2010-02-07 rsc but = but >> 29;
728 28afa898 2010-02-07 rsc } else
729 100ec44e 2010-01-04 rsc but = 0;
730 100ec44e 2010-01-04 rsc osx.touched = 0;
731 100ec44e 2010-01-04 rsc }
732 100ec44e 2010-01-04 rsc
733 100ec44e 2010-01-04 rsc // Apply keyboard modifiers and pretend it was a real mouse button.
734 100ec44e 2010-01-04 rsc // (Modifiers typed while holding the button go into kbuttons,
735 100ec44e 2010-01-04 rsc // but this one does not.)
736 100ec44e 2010-01-04 rsc if(but == 1){
737 100ec44e 2010-01-04 rsc if(mod & optionKey) {
738 100ec44e 2010-01-04 rsc // Take the ALT away from the keyboard handler.
739 100ec44e 2010-01-04 rsc if(osx.kalting) {
740 100ec44e 2010-01-04 rsc osx.kalting = 0;
741 100ec44e 2010-01-04 rsc keystroke(Kalt);
742 100ec44e 2010-01-04 rsc }
743 100ec44e 2010-01-04 rsc but = 2;
744 100ec44e 2010-01-04 rsc }
745 100ec44e 2010-01-04 rsc else if(mod & cmdKey)
746 100ec44e 2010-01-04 rsc but = 4;
747 100ec44e 2010-01-04 rsc }
748 100ec44e 2010-01-04 rsc osx.buttons = but;
749 100ec44e 2010-01-04 rsc break;
750 100ec44e 2010-01-04 rsc
751 100ec44e 2010-01-04 rsc case kEventMouseMoved:
752 100ec44e 2010-01-04 rsc case kEventMouseDragged:
753 100ec44e 2010-01-04 rsc break;
754 100ec44e 2010-01-04 rsc
755 100ec44e 2010-01-04 rsc default:
756 100ec44e 2010-01-04 rsc return eventNotHandledErr;
757 100ec44e 2010-01-04 rsc }
758 100ec44e 2010-01-04 rsc
759 100ec44e 2010-01-04 rsc mousetrack(osx.xy.x, osx.xy.y, osx.buttons|osx.kbuttons|wheel, msec());
760 100ec44e 2010-01-04 rsc return noErr;
761 100ec44e 2010-01-04 rsc }
762 100ec44e 2010-01-04 rsc
763 100ec44e 2010-01-04 rsc static int keycvt[] =
764 100ec44e 2010-01-04 rsc {
765 100ec44e 2010-01-04 rsc [QZ_IBOOK_ENTER] '\n',
766 100ec44e 2010-01-04 rsc [QZ_RETURN] '\n',
767 100ec44e 2010-01-04 rsc [QZ_ESCAPE] 27,
768 100ec44e 2010-01-04 rsc [QZ_BACKSPACE] '\b',
769 100ec44e 2010-01-04 rsc [QZ_LALT] Kalt,
770 100ec44e 2010-01-04 rsc [QZ_LCTRL] Kctl,
771 100ec44e 2010-01-04 rsc [QZ_LSHIFT] Kshift,
772 100ec44e 2010-01-04 rsc [QZ_F1] KF+1,
773 100ec44e 2010-01-04 rsc [QZ_F2] KF+2,
774 100ec44e 2010-01-04 rsc [QZ_F3] KF+3,
775 100ec44e 2010-01-04 rsc [QZ_F4] KF+4,
776 100ec44e 2010-01-04 rsc [QZ_F5] KF+5,
777 100ec44e 2010-01-04 rsc [QZ_F6] KF+6,
778 100ec44e 2010-01-04 rsc [QZ_F7] KF+7,
779 100ec44e 2010-01-04 rsc [QZ_F8] KF+8,
780 100ec44e 2010-01-04 rsc [QZ_F9] KF+9,
781 100ec44e 2010-01-04 rsc [QZ_F10] KF+10,
782 100ec44e 2010-01-04 rsc [QZ_F11] KF+11,
783 100ec44e 2010-01-04 rsc [QZ_F12] KF+12,
784 100ec44e 2010-01-04 rsc [QZ_INSERT] Kins,
785 100ec44e 2010-01-04 rsc [QZ_DELETE] 0x7F,
786 100ec44e 2010-01-04 rsc [QZ_HOME] Khome,
787 100ec44e 2010-01-04 rsc [QZ_END] Kend,
788 100ec44e 2010-01-04 rsc [QZ_KP_PLUS] '+',
789 100ec44e 2010-01-04 rsc [QZ_KP_MINUS] '-',
790 100ec44e 2010-01-04 rsc [QZ_TAB] '\t',
791 100ec44e 2010-01-04 rsc [QZ_PAGEUP] Kpgup,
792 100ec44e 2010-01-04 rsc [QZ_PAGEDOWN] Kpgdown,
793 100ec44e 2010-01-04 rsc [QZ_UP] Kup,
794 100ec44e 2010-01-04 rsc [QZ_DOWN] Kdown,
795 100ec44e 2010-01-04 rsc [QZ_LEFT] Kleft,
796 100ec44e 2010-01-04 rsc [QZ_RIGHT] Kright,
797 100ec44e 2010-01-04 rsc [QZ_KP_MULTIPLY] '*',
798 100ec44e 2010-01-04 rsc [QZ_KP_DIVIDE] '/',
799 100ec44e 2010-01-04 rsc [QZ_KP_ENTER] '\n',
800 100ec44e 2010-01-04 rsc [QZ_KP_PERIOD] '.',
801 100ec44e 2010-01-04 rsc [QZ_KP0] '0',
802 100ec44e 2010-01-04 rsc [QZ_KP1] '1',
803 100ec44e 2010-01-04 rsc [QZ_KP2] '2',
804 100ec44e 2010-01-04 rsc [QZ_KP3] '3',
805 100ec44e 2010-01-04 rsc [QZ_KP4] '4',
806 100ec44e 2010-01-04 rsc [QZ_KP5] '5',
807 100ec44e 2010-01-04 rsc [QZ_KP6] '6',
808 100ec44e 2010-01-04 rsc [QZ_KP7] '7',
809 100ec44e 2010-01-04 rsc [QZ_KP8] '8',
810 100ec44e 2010-01-04 rsc [QZ_KP9] '9',
811 100ec44e 2010-01-04 rsc };
812 100ec44e 2010-01-04 rsc
813 100ec44e 2010-01-04 rsc static OSStatus
814 100ec44e 2010-01-04 rsc kbdevent(EventRef event)
815 100ec44e 2010-01-04 rsc {
816 100ec44e 2010-01-04 rsc char ch;
817 100ec44e 2010-01-04 rsc UInt32 code;
818 100ec44e 2010-01-04 rsc UInt32 mod;
819 100ec44e 2010-01-04 rsc int k;
820 100ec44e 2010-01-04 rsc
821 100ec44e 2010-01-04 rsc GetEventParameter(event, kEventParamKeyMacCharCodes,
822 100ec44e 2010-01-04 rsc typeChar, nil, sizeof ch, nil, &ch);
823 100ec44e 2010-01-04 rsc GetEventParameter(event, kEventParamKeyCode,
824 100ec44e 2010-01-04 rsc typeUInt32, nil, sizeof code, nil, &code);
825 100ec44e 2010-01-04 rsc GetEventParameter(event, kEventParamKeyModifiers,
826 100ec44e 2010-01-04 rsc typeUInt32, nil, sizeof mod, nil, &mod);
827 100ec44e 2010-01-04 rsc
828 100ec44e 2010-01-04 rsc switch(GetEventKind(event)){
829 100ec44e 2010-01-04 rsc case kEventRawKeyDown:
830 100ec44e 2010-01-04 rsc case kEventRawKeyRepeat:
831 100ec44e 2010-01-04 rsc osx.kalting = 0;
832 100ec44e 2010-01-04 rsc if(mod == cmdKey){
833 100ec44e 2010-01-04 rsc if(ch == 'F' || ch == 'f'){
834 100ec44e 2010-01-04 rsc if(osx.isfullscreen && msec() - osx.fullscreentime > 500)
835 100ec44e 2010-01-04 rsc fullscreen(0);
836 100ec44e 2010-01-04 rsc return noErr;
837 100ec44e 2010-01-04 rsc }
838 100ec44e 2010-01-04 rsc
839 100ec44e 2010-01-04 rsc // Pass most Cmd keys through as Kcmd + ch.
840 100ec44e 2010-01-04 rsc // OS X interprets a few no matter what we do,
841 100ec44e 2010-01-04 rsc // so it is useless to pass them through as keystrokes too.
842 100ec44e 2010-01-04 rsc switch(ch) {
843 100ec44e 2010-01-04 rsc case 'm': // minimize window
844 100ec44e 2010-01-04 rsc case 'h': // hide window
845 100ec44e 2010-01-04 rsc case 'H': // hide others
846 100ec44e 2010-01-04 rsc case 'q': // quit
847 100ec44e 2010-01-04 rsc return eventNotHandledErr;
848 100ec44e 2010-01-04 rsc }
849 100ec44e 2010-01-04 rsc if(' ' <= ch && ch <= '~') {
850 100ec44e 2010-01-04 rsc keystroke(Kcmd + ch);
851 100ec44e 2010-01-04 rsc return noErr;
852 100ec44e 2010-01-04 rsc }
853 100ec44e 2010-01-04 rsc return eventNotHandledErr;
854 100ec44e 2010-01-04 rsc }
855 100ec44e 2010-01-04 rsc k = ch;
856 100ec44e 2010-01-04 rsc if(code < nelem(keycvt) && keycvt[code])
857 100ec44e 2010-01-04 rsc k = keycvt[code];
858 100ec44e 2010-01-04 rsc if(k == 0)
859 100ec44e 2010-01-04 rsc return noErr;
860 100ec44e 2010-01-04 rsc if(k > 0)
861 100ec44e 2010-01-04 rsc keystroke(k);
862 100ec44e 2010-01-04 rsc else{
863 100ec44e 2010-01-04 rsc UniChar uc;
864 100ec44e 2010-01-04 rsc OSStatus s;
865 100ec44e 2010-01-04 rsc
866 100ec44e 2010-01-04 rsc s = GetEventParameter(event, kEventParamKeyUnicodes,
867 100ec44e 2010-01-04 rsc typeUnicodeText, nil, sizeof uc, nil, &uc);
868 100ec44e 2010-01-04 rsc if(s == noErr)
869 100ec44e 2010-01-04 rsc keystroke(uc);
870 100ec44e 2010-01-04 rsc }
871 100ec44e 2010-01-04 rsc break;
872 100ec44e 2010-01-04 rsc
873 100ec44e 2010-01-04 rsc case kEventRawKeyModifiersChanged:
874 100ec44e 2010-01-04 rsc if(!osx.buttons && !osx.kbuttons){
875 100ec44e 2010-01-04 rsc if(mod == optionKey) {
876 100ec44e 2010-01-04 rsc osx.kalting = 1;
877 100ec44e 2010-01-04 rsc keystroke(Kalt);
878 100ec44e 2010-01-04 rsc }
879 100ec44e 2010-01-04 rsc break;
880 100ec44e 2010-01-04 rsc }
881 100ec44e 2010-01-04 rsc
882 100ec44e 2010-01-04 rsc // If the mouse button is being held down, treat
883 100ec44e 2010-01-04 rsc // changes in the keyboard modifiers as changes
884 100ec44e 2010-01-04 rsc // in the mouse buttons.
885 100ec44e 2010-01-04 rsc osx.kbuttons = 0;
886 100ec44e 2010-01-04 rsc if(mod & optionKey)
887 100ec44e 2010-01-04 rsc osx.kbuttons |= 2;
888 100ec44e 2010-01-04 rsc if(mod & cmdKey)
889 100ec44e 2010-01-04 rsc osx.kbuttons |= 4;
890 100ec44e 2010-01-04 rsc mousetrack(osx.xy.x, osx.xy.y, osx.buttons|osx.kbuttons, msec());
891 100ec44e 2010-01-04 rsc break;
892 100ec44e 2010-01-04 rsc }
893 100ec44e 2010-01-04 rsc return noErr;
894 100ec44e 2010-01-04 rsc }
895 100ec44e 2010-01-04 rsc
896 100ec44e 2010-01-04 rsc static void
897 100ec44e 2010-01-04 rsc eresized(int new)
898 100ec44e 2010-01-04 rsc {
899 100ec44e 2010-01-04 rsc Memimage *m;
900 100ec44e 2010-01-04 rsc OSXRect or;
901 100ec44e 2010-01-04 rsc ulong chan;
902 100ec44e 2010-01-04 rsc Rectangle r;
903 100ec44e 2010-01-04 rsc int bpl;
904 100ec44e 2010-01-04 rsc CGDataProviderRef provider;
905 100ec44e 2010-01-04 rsc CGImageRef image;
906 100ec44e 2010-01-04 rsc CGColorSpaceRef cspace;
907 100ec44e 2010-01-04 rsc
908 100ec44e 2010-01-04 rsc GetWindowBounds(osx.window, kWindowContentRgn, &or);
909 100ec44e 2010-01-04 rsc r = Rect(or.left, or.top, or.right, or.bottom);
910 a61c6933 2010-01-16 rsc if(Dx(r) == Dx(osx.screenr) && Dy(r) == Dy(osx.screenr) && !new){
911 100ec44e 2010-01-04 rsc // No need to make new image.
912 100ec44e 2010-01-04 rsc osx.screenr = r;
913 100ec44e 2010-01-04 rsc return;
914 100ec44e 2010-01-04 rsc }
915 100ec44e 2010-01-04 rsc
916 100ec44e 2010-01-04 rsc chan = XBGR32;
917 100ec44e 2010-01-04 rsc m = allocmemimage(Rect(0, 0, Dx(r), Dy(r)), chan);
918 100ec44e 2010-01-04 rsc if(m == nil)
919 100ec44e 2010-01-04 rsc panic("allocmemimage: %r");
920 100ec44e 2010-01-04 rsc if(m->data == nil)
921 100ec44e 2010-01-04 rsc panic("m->data == nil");
922 100ec44e 2010-01-04 rsc bpl = bytesperline(r, 32);
923 100ec44e 2010-01-04 rsc provider = CGDataProviderCreateWithData(0,
924 100ec44e 2010-01-04 rsc m->data->bdata, Dy(r)*bpl, 0);
925 100ec44e 2010-01-04 rsc //cspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
926 100ec44e 2010-01-04 rsc cspace = CGColorSpaceCreateDeviceRGB();
927 100ec44e 2010-01-04 rsc image = CGImageCreate(Dx(r), Dy(r), 8, 32, bpl,
928 100ec44e 2010-01-04 rsc cspace,
929 100ec44e 2010-01-04 rsc kCGImageAlphaNoneSkipLast,
930 100ec44e 2010-01-04 rsc provider, 0, 0, kCGRenderingIntentDefault);
931 100ec44e 2010-01-04 rsc CGColorSpaceRelease(cspace);
932 100ec44e 2010-01-04 rsc CGDataProviderRelease(provider); // CGImageCreate did incref
933 100ec44e 2010-01-04 rsc
934 100ec44e 2010-01-04 rsc mouserect = m->r;
935 100ec44e 2010-01-04 rsc if(new){
936 100ec44e 2010-01-04 rsc mouseresized = 1;
937 100ec44e 2010-01-04 rsc mousetrack(osx.xy.x, osx.xy.y, osx.buttons|osx.kbuttons, msec());
938 100ec44e 2010-01-04 rsc }
939 100ec44e 2010-01-04 rsc // termreplacescreenimage(m);
940 100ec44e 2010-01-04 rsc _drawreplacescreenimage(m); // frees old osx.screenimage if any
941 100ec44e 2010-01-04 rsc if(osx.image)
942 100ec44e 2010-01-04 rsc CGImageRelease(osx.image);
943 100ec44e 2010-01-04 rsc osx.image = image;
944 100ec44e 2010-01-04 rsc osx.screenimage = m;
945 100ec44e 2010-01-04 rsc osx.screenr = r;
946 100ec44e 2010-01-04 rsc
947 e055ceb2 2011-06-20 rsc if(new){
948 e055ceb2 2011-06-20 rsc qlock(&osx.flushlock);
949 e055ceb2 2011-06-20 rsc QDEndCGContext(GetWindowPort(osx.window), &osx.windowctx);
950 e055ceb2 2011-06-20 rsc osx.windowctx = nil;
951 e055ceb2 2011-06-20 rsc qunlock(&osx.flushlock);
952 e055ceb2 2011-06-20 rsc }
953 100ec44e 2010-01-04 rsc }
954 100ec44e 2010-01-04 rsc
955 100ec44e 2010-01-04 rsc void
956 100ec44e 2010-01-04 rsc flushproc(void *v)
957 100ec44e 2010-01-04 rsc {
958 100ec44e 2010-01-04 rsc for(;;){
959 100ec44e 2010-01-04 rsc if(osx.needflush && osx.windowctx && canqlock(&osx.flushlock)){
960 100ec44e 2010-01-04 rsc if(osx.windowctx){
961 100ec44e 2010-01-04 rsc CGContextFlush(osx.windowctx);
962 100ec44e 2010-01-04 rsc osx.needflush = 0;
963 100ec44e 2010-01-04 rsc }
964 100ec44e 2010-01-04 rsc qunlock(&osx.flushlock);
965 100ec44e 2010-01-04 rsc }
966 100ec44e 2010-01-04 rsc usleep(33333);
967 100ec44e 2010-01-04 rsc }
968 100ec44e 2010-01-04 rsc }
969 100ec44e 2010-01-04 rsc
970 100ec44e 2010-01-04 rsc void
971 100ec44e 2010-01-04 rsc _flushmemscreen(Rectangle r)
972 100ec44e 2010-01-04 rsc {
973 100ec44e 2010-01-04 rsc CGRect cgr;
974 100ec44e 2010-01-04 rsc CGImageRef subimg;
975 100ec44e 2010-01-04 rsc
976 100ec44e 2010-01-04 rsc qlock(&osx.flushlock);
977 100ec44e 2010-01-04 rsc if(osx.windowctx == nil){
978 100ec44e 2010-01-04 rsc QDBeginCGContext(GetWindowPort(osx.window), &osx.windowctx);
979 f50c3e95 2010-04-02 rsc if(!osx.flushing) {
980 f50c3e95 2010-04-02 rsc proccreate(flushproc, nil, 256*1024);
981 f50c3e95 2010-04-02 rsc osx.flushing = 1;
982 f50c3e95 2010-04-02 rsc }
983 100ec44e 2010-01-04 rsc }
984 100ec44e 2010-01-04 rsc
985 100ec44e 2010-01-04 rsc cgr.origin.x = r.min.x;
986 100ec44e 2010-01-04 rsc cgr.origin.y = r.min.y;
987 100ec44e 2010-01-04 rsc cgr.size.width = Dx(r);
988 100ec44e 2010-01-04 rsc cgr.size.height = Dy(r);
989 100ec44e 2010-01-04 rsc subimg = CGImageCreateWithImageInRect(osx.image, cgr);
990 100ec44e 2010-01-04 rsc cgr.origin.y = Dy(osx.screenr) - r.max.y; // XXX how does this make any sense?
991 100ec44e 2010-01-04 rsc CGContextDrawImage(osx.windowctx, cgr, subimg);
992 100ec44e 2010-01-04 rsc osx.needflush = 1;
993 100ec44e 2010-01-04 rsc qunlock(&osx.flushlock);
994 100ec44e 2010-01-04 rsc CGImageRelease(subimg);
995 100ec44e 2010-01-04 rsc }
996 100ec44e 2010-01-04 rsc
997 100ec44e 2010-01-04 rsc void
998 100ec44e 2010-01-04 rsc activated(int active)
999 100ec44e 2010-01-04 rsc {
1000 100ec44e 2010-01-04 rsc #ifdef MULTITOUCH
1001 100ec44e 2010-01-04 rsc int i;
1002 100ec44e 2010-01-04 rsc if(active) {
1003 100ec44e 2010-01-04 rsc for(i = 0; i<[osx.devicelist count]; i++) { //iterate available devices
1004 100ec44e 2010-01-04 rsc MTDeviceStart([osx.devicelist objectAtIndex:i], 0); //start sending events
1005 100ec44e 2010-01-04 rsc }
1006 100ec44e 2010-01-04 rsc } else {
1007 7d419a14 2010-01-15 rsc osx.xy.x = -10000;
1008 100ec44e 2010-01-04 rsc for(i = 0; i<[osx.devicelist count]; i++) { //iterate available devices
1009 100ec44e 2010-01-04 rsc MTDeviceStop([osx.devicelist objectAtIndex:i]); //stop sending events
1010 100ec44e 2010-01-04 rsc }
1011 100ec44e 2010-01-04 rsc for(i = 0; i<kNTracks; ++i) {
1012 100ec44e 2010-01-04 rsc tracks[i].id = -1;
1013 100ec44e 2010-01-04 rsc }
1014 100ec44e 2010-01-04 rsc }
1015 100ec44e 2010-01-04 rsc #endif
1016 100ec44e 2010-01-04 rsc osx.active = active;
1017 100ec44e 2010-01-04 rsc }
1018 100ec44e 2010-01-04 rsc
1019 100ec44e 2010-01-04 rsc void
1020 100ec44e 2010-01-04 rsc fullscreen(int wascmd)
1021 100ec44e 2010-01-04 rsc {
1022 100ec44e 2010-01-04 rsc static OSXRect oldrect;
1023 100ec44e 2010-01-04 rsc GDHandle device;
1024 100ec44e 2010-01-04 rsc OSXRect dr;
1025 100ec44e 2010-01-04 rsc
1026 100ec44e 2010-01-04 rsc if(!wascmd)
1027 100ec44e 2010-01-04 rsc return;
1028 100ec44e 2010-01-04 rsc
1029 100ec44e 2010-01-04 rsc if(!osx.isfullscreen){
1030 100ec44e 2010-01-04 rsc GetWindowGreatestAreaDevice(osx.window,
1031 100ec44e 2010-01-04 rsc kWindowTitleBarRgn, &device, nil);
1032 100ec44e 2010-01-04 rsc dr = (*device)->gdRect;
1033 100ec44e 2010-01-04 rsc if(dr.top == 0 && dr.left == 0)
1034 100ec44e 2010-01-04 rsc HideMenuBar();
1035 100ec44e 2010-01-04 rsc GetWindowBounds(osx.window, kWindowContentRgn, &oldrect);
1036 100ec44e 2010-01-04 rsc ChangeWindowAttributes(osx.window,
1037 100ec44e 2010-01-04 rsc kWindowNoTitleBarAttribute,
1038 100ec44e 2010-01-04 rsc kWindowResizableAttribute);
1039 100ec44e 2010-01-04 rsc MoveWindow(osx.window, 0, 0, 1);
1040 100ec44e 2010-01-04 rsc MoveWindow(osx.window, dr.left, dr.top, 0);
1041 100ec44e 2010-01-04 rsc SizeWindow(osx.window,
1042 100ec44e 2010-01-04 rsc dr.right - dr.left,
1043 100ec44e 2010-01-04 rsc dr.bottom - dr.top, 0);
1044 100ec44e 2010-01-04 rsc osx.isfullscreen = 1;
1045 100ec44e 2010-01-04 rsc }else{
1046 100ec44e 2010-01-04 rsc ShowMenuBar();
1047 100ec44e 2010-01-04 rsc ChangeWindowAttributes(osx.window,
1048 100ec44e 2010-01-04 rsc kWindowResizableAttribute,
1049 100ec44e 2010-01-04 rsc kWindowNoTitleBarAttribute);
1050 100ec44e 2010-01-04 rsc SizeWindow(osx.window,
1051 100ec44e 2010-01-04 rsc oldrect.right - oldrect.left,
1052 100ec44e 2010-01-04 rsc oldrect.bottom - oldrect.top, 0);
1053 100ec44e 2010-01-04 rsc MoveWindow(osx.window, oldrect.left, oldrect.top, 0);
1054 100ec44e 2010-01-04 rsc osx.isfullscreen = 0;
1055 100ec44e 2010-01-04 rsc }
1056 100ec44e 2010-01-04 rsc eresized(1);
1057 100ec44e 2010-01-04 rsc }
1058 100ec44e 2010-01-04 rsc
1059 100ec44e 2010-01-04 rsc void
1060 100ec44e 2010-01-04 rsc setmouse(Point p)
1061 100ec44e 2010-01-04 rsc {
1062 100ec44e 2010-01-04 rsc CGPoint cgp;
1063 100ec44e 2010-01-04 rsc
1064 100ec44e 2010-01-04 rsc cgp.x = p.x + osx.screenr.min.x;
1065 100ec44e 2010-01-04 rsc cgp.y = p.y + osx.screenr.min.y;
1066 100ec44e 2010-01-04 rsc CGWarpMouseCursorPosition(cgp);
1067 100ec44e 2010-01-04 rsc osx.xy = p;
1068 100ec44e 2010-01-04 rsc }
1069 100ec44e 2010-01-04 rsc
1070 100ec44e 2010-01-04 rsc void
1071 100ec44e 2010-01-04 rsc setcursor(Cursor *c)
1072 100ec44e 2010-01-04 rsc {
1073 100ec44e 2010-01-04 rsc OSXCursor oc;
1074 100ec44e 2010-01-04 rsc int i;
1075 100ec44e 2010-01-04 rsc
1076 100ec44e 2010-01-04 rsc if(c == nil){
1077 100ec44e 2010-01-04 rsc InitCursor();
1078 100ec44e 2010-01-04 rsc return;
1079 100ec44e 2010-01-04 rsc }
1080 100ec44e 2010-01-04 rsc
1081 100ec44e 2010-01-04 rsc // SetCursor is deprecated, but what replaces it?
1082 100ec44e 2010-01-04 rsc for(i=0; i<16; i++){
1083 100ec44e 2010-01-04 rsc oc.data[i] = ((ushort*)c->set)[i];
1084 100ec44e 2010-01-04 rsc oc.mask[i] = oc.data[i] | ((ushort*)c->clr)[i];
1085 100ec44e 2010-01-04 rsc }
1086 100ec44e 2010-01-04 rsc oc.hotSpot.h = - c->offset.x;
1087 100ec44e 2010-01-04 rsc oc.hotSpot.v = - c->offset.y;
1088 100ec44e 2010-01-04 rsc SetCursor(&oc);
1089 100ec44e 2010-01-04 rsc }
1090 100ec44e 2010-01-04 rsc
1091 100ec44e 2010-01-04 rsc void
1092 100ec44e 2010-01-04 rsc getcolor(ulong i, ulong *r, ulong *g, ulong *b)
1093 100ec44e 2010-01-04 rsc {
1094 100ec44e 2010-01-04 rsc ulong v;
1095 100ec44e 2010-01-04 rsc
1096 100ec44e 2010-01-04 rsc v = 0;
1097 100ec44e 2010-01-04 rsc *r = (v>>16)&0xFF;
1098 100ec44e 2010-01-04 rsc *g = (v>>8)&0xFF;
1099 100ec44e 2010-01-04 rsc *b = v&0xFF;
1100 100ec44e 2010-01-04 rsc }
1101 100ec44e 2010-01-04 rsc
1102 100ec44e 2010-01-04 rsc int
1103 100ec44e 2010-01-04 rsc setcolor(ulong i, ulong r, ulong g, ulong b)
1104 100ec44e 2010-01-04 rsc {
1105 100ec44e 2010-01-04 rsc /* no-op */
1106 100ec44e 2010-01-04 rsc return 0;
1107 100ec44e 2010-01-04 rsc }
1108 100ec44e 2010-01-04 rsc
1109 100ec44e 2010-01-04 rsc
1110 100ec44e 2010-01-04 rsc int
1111 100ec44e 2010-01-04 rsc hwdraw(Memdrawparam *p)
1112 100ec44e 2010-01-04 rsc {
1113 100ec44e 2010-01-04 rsc return 0;
1114 100ec44e 2010-01-04 rsc }
1115 100ec44e 2010-01-04 rsc
1116 100ec44e 2010-01-04 rsc struct {
1117 100ec44e 2010-01-04 rsc QLock lk;
1118 100ec44e 2010-01-04 rsc char buf[SnarfSize];
1119 100ec44e 2010-01-04 rsc Rune rbuf[SnarfSize];
1120 100ec44e 2010-01-04 rsc PasteboardRef apple;
1121 100ec44e 2010-01-04 rsc } clip;
1122 100ec44e 2010-01-04 rsc
1123 100ec44e 2010-01-04 rsc char*
1124 100ec44e 2010-01-04 rsc getsnarf(void)
1125 100ec44e 2010-01-04 rsc {
1126 100ec44e 2010-01-04 rsc char *s;
1127 100ec44e 2010-01-04 rsc CFArrayRef flavors;
1128 100ec44e 2010-01-04 rsc CFDataRef data;
1129 100ec44e 2010-01-04 rsc CFIndex nflavor, ndata, j;
1130 100ec44e 2010-01-04 rsc CFStringRef type;
1131 100ec44e 2010-01-04 rsc ItemCount nitem;
1132 100ec44e 2010-01-04 rsc PasteboardItemID id;
1133 100ec44e 2010-01-04 rsc PasteboardSyncFlags flags;
1134 100ec44e 2010-01-04 rsc UInt32 i;
1135 100ec44e 2010-01-04 rsc u16int *u;
1136 100ec44e 2010-01-04 rsc Fmt fmt;
1137 100ec44e 2010-01-04 rsc Rune r;
1138 100ec44e 2010-01-04 rsc
1139 100ec44e 2010-01-04 rsc /* fprint(2, "applegetsnarf\n"); */
1140 100ec44e 2010-01-04 rsc qlock(&clip.lk);
1141 100ec44e 2010-01-04 rsc clip.apple = osx.snarf;
1142 100ec44e 2010-01-04 rsc if(clip.apple == nil){
1143 100ec44e 2010-01-04 rsc if(PasteboardCreate(kPasteboardClipboard, &clip.apple) != noErr){
1144 100ec44e 2010-01-04 rsc fprint(2, "apple pasteboard create failed\n");
1145 100ec44e 2010-01-04 rsc qunlock(&clip.lk);
1146 100ec44e 2010-01-04 rsc return nil;
1147 100ec44e 2010-01-04 rsc }
1148 100ec44e 2010-01-04 rsc }
1149 100ec44e 2010-01-04 rsc flags = PasteboardSynchronize(clip.apple);
1150 100ec44e 2010-01-04 rsc if(flags&kPasteboardClientIsOwner){
1151 100ec44e 2010-01-04 rsc s = strdup(clip.buf);
1152 100ec44e 2010-01-04 rsc qunlock(&clip.lk);
1153 100ec44e 2010-01-04 rsc return s;
1154 100ec44e 2010-01-04 rsc }
1155 100ec44e 2010-01-04 rsc if(PasteboardGetItemCount(clip.apple, &nitem) != noErr){
1156 100ec44e 2010-01-04 rsc fprint(2, "apple pasteboard get item count failed\n");
1157 100ec44e 2010-01-04 rsc qunlock(&clip.lk);
1158 100ec44e 2010-01-04 rsc return nil;
1159 100ec44e 2010-01-04 rsc }
1160 100ec44e 2010-01-04 rsc for(i=1; i<=nitem; i++){
1161 100ec44e 2010-01-04 rsc if(PasteboardGetItemIdentifier(clip.apple, i, &id) != noErr)
1162 100ec44e 2010-01-04 rsc continue;
1163 100ec44e 2010-01-04 rsc if(PasteboardCopyItemFlavors(clip.apple, id, &flavors) != noErr)
1164 100ec44e 2010-01-04 rsc continue;
1165 100ec44e 2010-01-04 rsc nflavor = CFArrayGetCount(flavors);
1166 100ec44e 2010-01-04 rsc for(j=0; j<nflavor; j++){
1167 100ec44e 2010-01-04 rsc type = (CFStringRef)CFArrayGetValueAtIndex(flavors, j);
1168 100ec44e 2010-01-04 rsc if(!UTTypeConformsTo(type, CFSTR("public.utf16-plain-text")))
1169 100ec44e 2010-01-04 rsc continue;
1170 100ec44e 2010-01-04 rsc if(PasteboardCopyItemFlavorData(clip.apple, id, type, &data) != noErr)
1171 100ec44e 2010-01-04 rsc continue;
1172 100ec44e 2010-01-04 rsc qunlock(&clip.lk);
1173 100ec44e 2010-01-04 rsc ndata = CFDataGetLength(data)/2;
1174 100ec44e 2010-01-04 rsc u = (u16int*)CFDataGetBytePtr(data);
1175 100ec44e 2010-01-04 rsc fmtstrinit(&fmt);
1176 100ec44e 2010-01-04 rsc // decode utf-16. what was apple thinking?
1177 100ec44e 2010-01-04 rsc for(i=0; i<ndata; i++) {
1178 100ec44e 2010-01-04 rsc r = u[i];
1179 100ec44e 2010-01-04 rsc if(0xd800 <= r && r < 0xdc00 && i+1 < ndata && 0xdc00 <= u[i+1] && u[i+1] < 0xe000) {
1180 100ec44e 2010-01-04 rsc r = (((r - 0xd800)<<10) | (u[i+1] - 0xdc00)) + 0x10000;
1181 100ec44e 2010-01-04 rsc i++;
1182 100ec44e 2010-01-04 rsc }
1183 100ec44e 2010-01-04 rsc else if(0xd800 <= r && r < 0xe000)
1184 100ec44e 2010-01-04 rsc r = Runeerror;
1185 100ec44e 2010-01-04 rsc if(r == '\r')
1186 100ec44e 2010-01-04 rsc r = '\n';
1187 100ec44e 2010-01-04 rsc fmtrune(&fmt, r);
1188 100ec44e 2010-01-04 rsc }
1189 100ec44e 2010-01-04 rsc CFRelease(flavors);
1190 100ec44e 2010-01-04 rsc CFRelease(data);
1191 100ec44e 2010-01-04 rsc return fmtstrflush(&fmt);
1192 100ec44e 2010-01-04 rsc }
1193 100ec44e 2010-01-04 rsc CFRelease(flavors);
1194 100ec44e 2010-01-04 rsc }
1195 100ec44e 2010-01-04 rsc qunlock(&clip.lk);
1196 100ec44e 2010-01-04 rsc return nil;
1197 100ec44e 2010-01-04 rsc }
1198 100ec44e 2010-01-04 rsc
1199 100ec44e 2010-01-04 rsc void
1200 100ec44e 2010-01-04 rsc putsnarf(char *s)
1201 100ec44e 2010-01-04 rsc {
1202 100ec44e 2010-01-04 rsc CFDataRef cfdata;
1203 100ec44e 2010-01-04 rsc PasteboardSyncFlags flags;
1204 100ec44e 2010-01-04 rsc u16int *u, *p;
1205 100ec44e 2010-01-04 rsc Rune r;
1206 100ec44e 2010-01-04 rsc int i;
1207 100ec44e 2010-01-04 rsc
1208 100ec44e 2010-01-04 rsc /* fprint(2, "appleputsnarf\n"); */
1209 100ec44e 2010-01-04 rsc
1210 100ec44e 2010-01-04 rsc if(strlen(s) >= SnarfSize)
1211 100ec44e 2010-01-04 rsc return;
1212 100ec44e 2010-01-04 rsc qlock(&clip.lk);
1213 100ec44e 2010-01-04 rsc strcpy(clip.buf, s);
1214 100ec44e 2010-01-04 rsc runesnprint(clip.rbuf, nelem(clip.rbuf), "%s", s);
1215 100ec44e 2010-01-04 rsc clip.apple = osx.snarf;
1216 100ec44e 2010-01-04 rsc if(PasteboardClear(clip.apple) != noErr){
1217 100ec44e 2010-01-04 rsc fprint(2, "apple pasteboard clear failed\n");
1218 100ec44e 2010-01-04 rsc qunlock(&clip.lk);
1219 100ec44e 2010-01-04 rsc return;
1220 100ec44e 2010-01-04 rsc }
1221 100ec44e 2010-01-04 rsc flags = PasteboardSynchronize(clip.apple);
1222 100ec44e 2010-01-04 rsc if((flags&kPasteboardModified) || !(flags&kPasteboardClientIsOwner)){
1223 100ec44e 2010-01-04 rsc fprint(2, "apple pasteboard cannot assert ownership\n");
1224 100ec44e 2010-01-04 rsc qunlock(&clip.lk);
1225 100ec44e 2010-01-04 rsc return;
1226 100ec44e 2010-01-04 rsc }
1227 100ec44e 2010-01-04 rsc u = malloc(runestrlen(clip.rbuf)*4);
1228 100ec44e 2010-01-04 rsc p = u;
1229 100ec44e 2010-01-04 rsc for(i=0; clip.rbuf[i]; i++) {
1230 100ec44e 2010-01-04 rsc r = clip.rbuf[i];
1231 100ec44e 2010-01-04 rsc // convert to utf-16
1232 100ec44e 2010-01-04 rsc if(0xd800 <= r && r < 0xe000)
1233 100ec44e 2010-01-04 rsc r = Runeerror;
1234 100ec44e 2010-01-04 rsc if(r >= 0x10000) {
1235 100ec44e 2010-01-04 rsc r -= 0x10000;
1236 100ec44e 2010-01-04 rsc *p++ = 0xd800 + (r>>10);
1237 100ec44e 2010-01-04 rsc *p++ = 0xdc00 + (r & ((1<<10)-1));
1238 100ec44e 2010-01-04 rsc } else
1239 100ec44e 2010-01-04 rsc *p++ = r;
1240 100ec44e 2010-01-04 rsc }
1241 100ec44e 2010-01-04 rsc cfdata = CFDataCreate(kCFAllocatorDefault,
1242 100ec44e 2010-01-04 rsc (uchar*)u, (p-u)*2);
1243 100ec44e 2010-01-04 rsc free(u);
1244 100ec44e 2010-01-04 rsc if(cfdata == nil){
1245 100ec44e 2010-01-04 rsc fprint(2, "apple pasteboard cfdatacreate failed\n");
1246 100ec44e 2010-01-04 rsc qunlock(&clip.lk);
1247 100ec44e 2010-01-04 rsc return;
1248 100ec44e 2010-01-04 rsc }
1249 100ec44e 2010-01-04 rsc if(PasteboardPutItemFlavor(clip.apple, (PasteboardItemID)1,
1250 100ec44e 2010-01-04 rsc CFSTR("public.utf16-plain-text"), cfdata, 0) != noErr){
1251 100ec44e 2010-01-04 rsc fprint(2, "apple pasteboard putitem failed\n");
1252 100ec44e 2010-01-04 rsc CFRelease(cfdata);
1253 100ec44e 2010-01-04 rsc qunlock(&clip.lk);
1254 100ec44e 2010-01-04 rsc return;
1255 100ec44e 2010-01-04 rsc }
1256 100ec44e 2010-01-04 rsc CFRelease(cfdata);
1257 100ec44e 2010-01-04 rsc qunlock(&clip.lk);
1258 100ec44e 2010-01-04 rsc }
1259 100ec44e 2010-01-04 rsc
1260 100ec44e 2010-01-04 rsc void
1261 100ec44e 2010-01-04 rsc setlabel(char *label)
1262 100ec44e 2010-01-04 rsc {
1263 100ec44e 2010-01-04 rsc CFStringRef cs;
1264 100ec44e 2010-01-04 rsc
1265 100ec44e 2010-01-04 rsc cs = CFStringCreateWithBytes(nil, (uchar*)label, strlen(label), kCFStringEncodingUTF8, false);
1266 100ec44e 2010-01-04 rsc SetWindowTitleWithCFString(osx.window, cs);
1267 100ec44e 2010-01-04 rsc CFRelease(cs);
1268 100ec44e 2010-01-04 rsc }
1269 100ec44e 2010-01-04 rsc
1270 100ec44e 2010-01-04 rsc void
1271 100ec44e 2010-01-04 rsc kicklabel(char *label)
1272 100ec44e 2010-01-04 rsc {
1273 100ec44e 2010-01-04 rsc char *p;
1274 100ec44e 2010-01-04 rsc EventRef e;
1275 100ec44e 2010-01-04 rsc
1276 100ec44e 2010-01-04 rsc p = strdup(label);
1277 100ec44e 2010-01-04 rsc if(p == nil)
1278 100ec44e 2010-01-04 rsc return;
1279 100ec44e 2010-01-04 rsc qlock(&osx.labellock);
1280 100ec44e 2010-01-04 rsc free(osx.label);
1281 100ec44e 2010-01-04 rsc osx.label = p;
1282 100ec44e 2010-01-04 rsc qunlock(&osx.labellock);
1283 100ec44e 2010-01-04 rsc
1284 100ec44e 2010-01-04 rsc CreateEvent(nil, 'P9PE', P9PEventLabelUpdate, 0, kEventAttributeUserEvent, &e);
1285 100ec44e 2010-01-04 rsc PostEventToQueue(GetMainEventQueue(), e, kEventPriorityStandard);
1286 100ec44e 2010-01-04 rsc
1287 100ec44e 2010-01-04 rsc }
1288 100ec44e 2010-01-04 rsc
1289 100ec44e 2010-01-04 rsc static void
1290 100ec44e 2010-01-04 rsc seticon(void)
1291 100ec44e 2010-01-04 rsc {
1292 100ec44e 2010-01-04 rsc CGImageRef im;
1293 100ec44e 2010-01-04 rsc CGDataProviderRef d;
1294 100ec44e 2010-01-04 rsc
1295 100ec44e 2010-01-04 rsc d = CGDataProviderCreateWithData(nil, glenda_png, sizeof glenda_png, nil);
1296 100ec44e 2010-01-04 rsc im = CGImageCreateWithPNGDataProvider(d, nil, true, kCGRenderingIntentDefault);
1297 100ec44e 2010-01-04 rsc if(im)
1298 100ec44e 2010-01-04 rsc SetApplicationDockTileImage(im);
1299 100ec44e 2010-01-04 rsc CGImageRelease(im);
1300 100ec44e 2010-01-04 rsc CGDataProviderRelease(d);
1301 100ec44e 2010-01-04 rsc }
1302 100ec44e 2010-01-04 rsc