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