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>
8 100ec44e 2010-01-04 rsc #undef offsetof
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"
24 100ec44e 2010-01-04 rsc AUTOFRAMEWORK(Carbon)
25 100ec44e 2010-01-04 rsc AUTOFRAMEWORK(Cocoa)
27 100ec44e 2010-01-04 rsc #ifdef MULTITOUCH
28 ecb01aca 2010-01-26 rsc AUTOFRAMEWORK(MultitouchSupport)
31 100ec44e 2010-01-04 rsc #define panic sysfatal
33 100ec44e 2010-01-04 rsc extern Rectangle mouserect;
37 100ec44e 2010-01-04 rsc char *winsize;
38 100ec44e 2010-01-04 rsc QLock labellock;
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;
48 100ec44e 2010-01-04 rsc int kbuttons;
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;
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;
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
72 100ec44e 2010-01-04 rsc typedef struct {
77 100ec44e 2010-01-04 rsc typedef struct {
78 100ec44e 2010-01-04 rsc mtPoint position;
79 100ec44e 2010-01-04 rsc mtPoint velocity;
83 100ec44e 2010-01-04 rsc Some reversed engineered informations from MultiTouchSupport.framework
85 100ec44e 2010-01-04 rsc typedef struct
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
104 100ec44e 2010-01-04 rsc //a reference pointer for the multitouch device
105 100ec44e 2010-01-04 rsc typedef void *MTDeviceRef;
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);
110 100ec44e 2010-01-04 rsc //returns a pointer to the default device (the trackpad?)
111 100ec44e 2010-01-04 rsc MTDeviceRef MTDeviceCreateDefault(void);
113 100ec44e 2010-01-04 rsc //returns a CFMutableArrayRef array of all multitouch devices
114 100ec44e 2010-01-04 rsc CFMutableArrayRef MTDeviceCreateList(void);
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);
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);
123 100ec44e 2010-01-04 rsc #define kNTracks 10
124 100ec44e 2010-01-04 rsc struct TouchTrack {
126 100ec44e 2010-01-04 rsc float firstThreshTime;
127 100ec44e 2010-01-04 rsc mtPoint pos;
128 100ec44e 2010-01-04 rsc } tracks[kNTracks];
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 */
135 100ec44e 2010-01-04 rsc findTrack(int id)
138 100ec44e 2010-01-04 rsc for(i = 0; i < kNTracks; ++i)
139 100ec44e 2010-01-04 rsc if(tracks[i].id == id)
144 100ec44e 2010-01-04 rsc #define kMoveSensitivity 0.05f
147 100ec44e 2010-01-04 rsc moved(mtPoint a, mtPoint b)
149 100ec44e 2010-01-04 rsc if(fabs(a.x - b.x) > kMoveSensitivity)
151 100ec44e 2010-01-04 rsc if(fabs(a.y - b.y) > kMoveSensitivity)
157 100ec44e 2010-01-04 rsc classifyTouch(Touch *t)
162 100ec44e 2010-01-04 rsc p = t->normalized.position;
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);
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.
176 100ec44e 2010-01-04 rsc if(t->size == 0) { // lost touch
177 100ec44e 2010-01-04 rsc tracks[i].id = -1;
180 100ec44e 2010-01-04 rsc if(t->size < kSizeSensitivity) {
181 100ec44e 2010-01-04 rsc tracks[i].firstThreshTime = t->timestamp;
183 100ec44e 2010-01-04 rsc if((t->timestamp - tracks[i].firstThreshTime) < kTimeSensitivity) {
186 28afa898 2010-02-07 rsc if(p.y > kButtonLimit && t->size > kSizeSensitivity) {
187 100ec44e 2010-01-04 rsc if(p.x < 0.35)
189 100ec44e 2010-01-04 rsc if(p.x > 0.65)
191 100ec44e 2010-01-04 rsc if(p.x > 0.35 && p.x < 0.65)
197 100ec44e 2010-01-04 rsc static ulong msec(void);
200 100ec44e 2010-01-04 rsc touchCallback(int device, Touch *data, int nFingers, double timestamp, int frame)
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;
206 100ec44e 2010-01-04 rsc CGEventRef e;
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))
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,
223 100ec44e 2010-01-04 rsc CGEventPost(kCGSessionEventTap, e);
224 100ec44e 2010-01-04 rsc CFRelease(e);
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,
231 100ec44e 2010-01-04 rsc CGEventPost(kCGSessionEventTap, e);
232 100ec44e 2010-01-04 rsc CFRelease(e);
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,
239 100ec44e 2010-01-04 rsc CGEventPost(kCGSessionEventTap, e);
240 100ec44e 2010-01-04 rsc CFRelease(e);
242 100ec44e 2010-01-04 rsc return delta != 0;
248 100ec44e 2010-01-04 rsc extern int multitouch;
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
262 100ec44e 2010-01-04 rsc P9PEventLabelUpdate = 1
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);
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*);
277 100ec44e 2010-01-04 rsc CmdFullScreen = 1,
280 100ec44e 2010-01-04 rsc void screeninit(void);
281 100ec44e 2010-01-04 rsc void _flushmemscreen(Rectangle r);
284 100ec44e 2010-01-04 rsc InitMultiTouch(void)
286 100ec44e 2010-01-04 rsc #ifdef MULTITOUCH
290 100ec44e 2010-01-04 rsc * Setup multitouch queues
292 100ec44e 2010-01-04 rsc if(!multitouch)
295 100ec44e 2010-01-04 rsc for(i = 0; i<kNTracks; ++i)
296 100ec44e 2010-01-04 rsc tracks[i].id = -1;
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
306 100ec44e 2010-01-04 rsc attachscreen(char *label, char *winsize)
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");
317 100ec44e 2010-01-04 rsc return osx.screenimage;
320 100ec44e 2010-01-04 rsc extern int multitouch;
323 100ec44e 2010-01-04 rsc _screeninit(void)
327 100ec44e 2010-01-04 rsc Rectangle r;
328 100ec44e 2010-01-04 rsc int havemin;
330 100ec44e 2010-01-04 rsc memimageinit();
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);
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);
339 100ec44e 2010-01-04 rsc InitCursor();
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();
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");
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);
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");
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 }
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 },
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}
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);
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);
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);
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);
424 100ec44e 2010-01-04 rsc if(multitouch)
425 100ec44e 2010-01-04 rsc InitMultiTouch();
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
431 d94cc62a 2010-03-04 rsc CGSetLocalEventsSuppressionInterval(0.0);
433 100ec44e 2010-01-04 rsc InitCursor();
436 100ec44e 2010-01-04 rsc static Rendez scr;
437 100ec44e 2010-01-04 rsc static QLock slock;
440 100ec44e 2010-01-04 rsc screeninit(void)
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);
451 100ec44e 2010-01-04 rsc screenproc(void *v)
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();
460 100ec44e 2010-01-04 rsc static OSStatus kbdevent(EventRef);
461 100ec44e 2010-01-04 rsc static OSStatus mouseevent(EventRef);
463 100ec44e 2010-01-04 rsc static OSStatus
464 100ec44e 2010-01-04 rsc cmdhandler(EventHandlerCallRef next, EventRef event, void *arg)
466 100ec44e 2010-01-04 rsc return eventhandler(next, event, arg);
469 100ec44e 2010-01-04 rsc static OSStatus
470 100ec44e 2010-01-04 rsc quithandler(EventHandlerCallRef next, EventRef event, void *arg)
476 100ec44e 2010-01-04 rsc static OSStatus
477 100ec44e 2010-01-04 rsc eventhandler(EventHandlerCallRef next, EventRef event, void *arg)
479 100ec44e 2010-01-04 rsc OSStatus result;
481 100ec44e 2010-01-04 rsc result = CallNextEventHandler(next, event);
483 100ec44e 2010-01-04 rsc switch(GetEventClass(event)){
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;
492 100ec44e 2010-01-04 rsc return eventNotHandledErr;
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;
499 100ec44e 2010-01-04 rsc case kEventClassKeyboard:
500 100ec44e 2010-01-04 rsc return kbdevent(event);
502 100ec44e 2010-01-04 rsc case kEventClassMouse:
503 100ec44e 2010-01-04 rsc return mouseevent(event);
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:
513 100ec44e 2010-01-04 rsc case CmdFullScreen:
514 100ec44e 2010-01-04 rsc fullscreen(1);
518 100ec44e 2010-01-04 rsc return eventNotHandledErr;
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:
527 100ec44e 2010-01-04 rsc case kEventWindowBoundsChanged:
528 cbcec5ad 2011-01-12 rsc eresized(0);
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);
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;
546 100ec44e 2010-01-04 rsc case kEventWindowDeactivated:
547 7d9c0f0f 2010-01-05 rsc activated(0);
548 7d9c0f0f 2010-01-05 rsc return eventNotHandledErr;
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;
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;
561 100ec44e 2010-01-04 rsc return eventNotHandledErr;
566 100ec44e 2010-01-04 rsc return result;
569 100ec44e 2010-01-04 rsc static ulong
572 100ec44e 2010-01-04 rsc return nsec()/1000000;
575 100ec44e 2010-01-04 rsc static OSStatus
576 100ec44e 2010-01-04 rsc mouseevent(EventRef event)
579 100ec44e 2010-01-04 rsc OSXPoint op;
581 100ec44e 2010-01-04 rsc GetEventParameter(event, kEventParamMouseLocation,
582 100ec44e 2010-01-04 rsc typeQDPoint, 0, sizeof op, 0, &op);
584 100ec44e 2010-01-04 rsc osx.xy = subpt(Pt(op.h, op.v), osx.screenr.min);
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);
593 100ec44e 2010-01-04 rsc // if I have any active touches in my region, I need to ignore the wheel motion.
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;
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)
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);
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) {
622 28afa898 2010-02-07 rsc but = but >> 29;
625 100ec44e 2010-01-04 rsc osx.touched = 0;
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);
640 100ec44e 2010-01-04 rsc else if(mod & cmdKey)
643 100ec44e 2010-01-04 rsc osx.buttons = but;
646 100ec44e 2010-01-04 rsc case kEventMouseMoved:
647 100ec44e 2010-01-04 rsc case kEventMouseDragged:
651 100ec44e 2010-01-04 rsc return eventNotHandledErr;
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;
658 100ec44e 2010-01-04 rsc static int keycvt[] =
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',
708 100ec44e 2010-01-04 rsc static OSStatus
709 100ec44e 2010-01-04 rsc kbdevent(EventRef event)
712 100ec44e 2010-01-04 rsc UInt32 code;
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);
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;
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;
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;
748 100ec44e 2010-01-04 rsc return eventNotHandledErr;
751 100ec44e 2010-01-04 rsc if(code < nelem(keycvt) && keycvt[code])
752 100ec44e 2010-01-04 rsc k = keycvt[code];
754 100ec44e 2010-01-04 rsc return noErr;
756 100ec44e 2010-01-04 rsc keystroke(k);
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);
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);
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());
788 100ec44e 2010-01-04 rsc return noErr;
792 100ec44e 2010-01-04 rsc eresized(int new)
794 100ec44e 2010-01-04 rsc Memimage *m;
797 100ec44e 2010-01-04 rsc Rectangle r;
799 100ec44e 2010-01-04 rsc CGDataProviderRef provider;
800 100ec44e 2010-01-04 rsc CGImageRef image;
801 100ec44e 2010-01-04 rsc CGColorSpaceRef cspace;
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;
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,
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
829 100ec44e 2010-01-04 rsc mouserect = m->r;
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());
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;
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);
852 100ec44e 2010-01-04 rsc flushproc(void *v)
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;
860 100ec44e 2010-01-04 rsc qunlock(&osx.flushlock);
862 100ec44e 2010-01-04 rsc usleep(33333);
867 100ec44e 2010-01-04 rsc _flushmemscreen(Rectangle r)
870 100ec44e 2010-01-04 rsc CGImageRef subimg;
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;
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);
894 100ec44e 2010-01-04 rsc activated(int active)
896 100ec44e 2010-01-04 rsc #ifdef MULTITOUCH
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
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
907 100ec44e 2010-01-04 rsc for(i = 0; i<kNTracks; ++i) {
908 100ec44e 2010-01-04 rsc tracks[i].id = -1;
912 100ec44e 2010-01-04 rsc osx.active = active;
916 100ec44e 2010-01-04 rsc fullscreen(int wascmd)
918 100ec44e 2010-01-04 rsc static OSXRect oldrect;
919 100ec44e 2010-01-04 rsc GDHandle device;
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;
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;
952 100ec44e 2010-01-04 rsc eresized(1);
956 100ec44e 2010-01-04 rsc setmouse(Point p)
958 100ec44e 2010-01-04 rsc CGPoint cgp;
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);
967 100ec44e 2010-01-04 rsc setcursor(Cursor *c)
969 100ec44e 2010-01-04 rsc OSXCursor oc;
972 100ec44e 2010-01-04 rsc if(c == nil){
973 100ec44e 2010-01-04 rsc InitCursor();
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];
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);
988 100ec44e 2010-01-04 rsc getcolor(ulong i, ulong *r, ulong *g, ulong *b)
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;
999 100ec44e 2010-01-04 rsc setcolor(ulong i, ulong r, ulong g, ulong b)
1001 100ec44e 2010-01-04 rsc /* no-op */
1007 100ec44e 2010-01-04 rsc hwdraw(Memdrawparam *p)
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;
1020 100ec44e 2010-01-04 rsc getsnarf(void)
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;
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;
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);
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;
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)
1059 100ec44e 2010-01-04 rsc if(PasteboardCopyItemFlavors(clip.apple, id, &flavors) != noErr)
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")))
1066 100ec44e 2010-01-04 rsc if(PasteboardCopyItemFlavorData(clip.apple, id, type, &data) != noErr)
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++) {
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;
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')
1083 100ec44e 2010-01-04 rsc fmtrune(&fmt, r);
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);
1089 100ec44e 2010-01-04 rsc CFRelease(flavors);
1091 100ec44e 2010-01-04 rsc qunlock(&clip.lk);
1092 100ec44e 2010-01-04 rsc return nil;
1096 100ec44e 2010-01-04 rsc putsnarf(char *s)
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;
1104 100ec44e 2010-01-04 rsc /* fprint(2, "appleputsnarf\n"); */
1106 100ec44e 2010-01-04 rsc if(strlen(s) >= SnarfSize)
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);
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);
1123 100ec44e 2010-01-04 rsc u = malloc(runestrlen(clip.rbuf)*4);
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));
1137 100ec44e 2010-01-04 rsc cfdata = CFDataCreate(kCFAllocatorDefault,
1138 100ec44e 2010-01-04 rsc (uchar*)u, (p-u)*2);
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);
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);
1152 100ec44e 2010-01-04 rsc CFRelease(cfdata);
1153 100ec44e 2010-01-04 rsc qunlock(&clip.lk);
1157 100ec44e 2010-01-04 rsc setlabel(char *label)
1159 100ec44e 2010-01-04 rsc CFStringRef cs;
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);
1167 100ec44e 2010-01-04 rsc kicklabel(char *label)
1170 100ec44e 2010-01-04 rsc EventRef e;
1172 100ec44e 2010-01-04 rsc p = strdup(label);
1173 100ec44e 2010-01-04 rsc if(p == nil)
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);
1180 100ec44e 2010-01-04 rsc CreateEvent(nil, 'P9PE', P9PEventLabelUpdate, 0, kEventAttributeUserEvent, &e);
1181 100ec44e 2010-01-04 rsc PostEventToQueue(GetMainEventQueue(), e, kEventPriorityStandard);
1185 100ec44e 2010-01-04 rsc static void
1186 100ec44e 2010-01-04 rsc seticon(void)
1188 100ec44e 2010-01-04 rsc CGImageRef im;
1189 100ec44e 2010-01-04 rsc CGDataProviderRef d;
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);
1194 100ec44e 2010-01-04 rsc SetApplicationDockTileImage(im);
1195 100ec44e 2010-01-04 rsc CGImageRelease(im);
1196 100ec44e 2010-01-04 rsc CGDataProviderRelease(d);