1 // in this file, _Rect is os x Rect,
2 // _Point is os x Point
3 #undef Point
4 #define Point _Point
5 #undef Rect
6 #define Rect _Rect
7
8 #include <Carbon/Carbon.h>
9 #include <QuickTime/QuickTime.h> // for full screen
10
11 #undef Rect
12 #undef Point
13
14 #undef nil
15
16
17 #include "u.h"
18 #include "lib.h"
19 #include "kern/dat.h"
20 #include "kern/fns.h"
21 #include "error.h"
22 #include "user.h"
23 #include <draw.h>
24 #include <memdraw.h>
25 #include "screen.h"
26 #include "keyboard.h"
27 #include "keycodes.h"
28
29 #define rWindowResource 128
30
31 #define topLeft(r) (((Point *) &(r))[0])
32 #define botRight(r) (((Point *) &(r))[1])
33
34 extern int mousequeue;
35 static int depth;
36 Boolean gDone;
37 RgnHandle gCursorRegionHdl;
38
39 Memimage *gscreen;
40 Screeninfo screen;
41
42 static int readybit;
43 static Rendez rend;
44
45 ///
46 // menu
47 //
48 static MenuRef windMenu;
49 static MenuRef viewMenu;
50
51 enum {
52 kQuitCmd = 1,
53 kFullScreenCmd = 2,
54 };
55
56 static WindowGroupRef winGroup = NULL;
57 static WindowRef theWindow = NULL;
58 static CGContextRef context;
59 static CGDataProviderRef dataProviderRef;
60 static CGImageRef fullScreenImage;
61 static CGRect devRect;
62 static CGRect bounds;
63 static PasteboardRef appleclip;
64 static _Rect winRect;
65
66 Boolean altPressed = false;
67 Boolean button2 = false;
68 Boolean button3 = false;
69
70
71 static int
isready(void * a)72 isready(void*a)
73 {
74 return readybit;
75 }
76
77 CGContextRef QuartzContext;
78
79 void winproc(void *a);
80
screeninit(void)81 void screeninit(void)
82 {
83 int fmt;
84 int dx, dy;
85 ProcessSerialNumber psn = { 0, kCurrentProcess };
86 TransformProcessType(&psn, kProcessTransformToForegroundApplication);
87 SetFrontProcess(&psn);
88
89 memimageinit();
90 depth = 32; // That's all this code deals with for now
91 screen.depth = 32;
92 fmt = XBGR32; //XRGB32;
93
94 devRect = CGDisplayBounds(CGMainDisplayID());
95 // devRect.origin.x = 0;
96 // devRect.origin.y = 0;
97 // devRect.size.width = 1024;
98 // devRect.size.height = 768;
99 dx = devRect.size.width;
100 dy = devRect.size.height;
101
102 gscreen = allocmemimage(Rect(0,0,dx,dy), fmt);
103 dataProviderRef = CGDataProviderCreateWithData(0, gscreen->data->bdata,
104 dx * dy * 4, 0);
105 fullScreenImage = CGImageCreate(dx, dy, 8, 32, dx * 4,
106 CGColorSpaceCreateDeviceRGB(),
107 kCGImageAlphaNoneSkipLast,
108 dataProviderRef, 0, 0, kCGRenderingIntentDefault);
109
110 kproc("osxscreen", winproc, 0);
111 ksleep(&rend, isready, 0);
112 }
113
114 // No wonder Apple sells so many wide displays!
115 static OSStatus ApplicationQuitEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
116 static OSStatus MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
117 static OSStatus MainWindowCommandHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
118
119 void
window_resized()120 window_resized()
121 {
122 GetWindowBounds(theWindow, kWindowContentRgn, &winRect );
123
124 bounds = CGRectMake(0, 0, winRect.right-winRect.left, winRect.bottom - winRect.top);
125 }
126
127
winproc(void * a)128 void winproc(void *a)
129 {
130 winRect.left = 30;
131 winRect.top = 60;
132 winRect.bottom = (devRect.size.height * 0.75) + winRect.top;
133 winRect.right = (devRect.size.width * 0.75) + winRect.left;
134
135 ClearMenuBar();
136 InitCursor();
137
138 CreateStandardWindowMenu(0, &windMenu);
139 InsertMenu(windMenu, 0);
140
141 MenuItemIndex index;
142 CreateNewMenu(1004, 0, &viewMenu);
143 SetMenuTitleWithCFString(viewMenu, CFSTR("View"));
144 AppendMenuItemTextWithCFString(viewMenu, CFSTR("Full Screen"), 0,
145 kFullScreenCmd, &index);
146 SetMenuItemCommandKey(viewMenu, index, 0, 'F');
147 InsertMenu(viewMenu, GetMenuID(windMenu));
148
149 DrawMenuBar();
150 uint32_t windowAttrs = 0
151 | kWindowCloseBoxAttribute
152 | kWindowCollapseBoxAttribute
153 | kWindowResizableAttribute
154 | kWindowStandardHandlerAttribute
155 | kWindowFullZoomAttribute
156 ;
157
158 CreateNewWindow(kDocumentWindowClass, windowAttrs, &winRect, &theWindow);
159 CreateWindowGroup(0, &winGroup);
160 SetWindowGroup(theWindow, winGroup);
161
162 SetWindowTitleWithCFString(theWindow, CFSTR("Drawterm"));
163
164 if(PasteboardCreate(kPasteboardClipboard, &appleclip) != noErr)
165 sysfatal("pasteboard create failed");
166
167 const EventTypeSpec quit_events[] = {
168 { kEventClassApplication, kEventAppQuit }
169 };
170 const EventTypeSpec commands[] = {
171 { kEventClassWindow, kEventWindowClosed },
172 { kEventClassWindow, kEventWindowBoundsChanged },
173 { kEventClassCommand, kEventCommandProcess }
174 };
175 const EventTypeSpec events[] = {
176 { kEventClassKeyboard, kEventRawKeyDown },
177 { kEventClassKeyboard, kEventRawKeyModifiersChanged },
178 { kEventClassKeyboard, kEventRawKeyRepeat },
179 { kEventClassMouse, kEventMouseDown },
180 { kEventClassMouse, kEventMouseUp },
181 { kEventClassMouse, kEventMouseMoved },
182 { kEventClassMouse, kEventMouseDragged },
183 { kEventClassMouse, kEventMouseWheelMoved },
184 };
185
186 InstallApplicationEventHandler (
187 NewEventHandlerUPP (ApplicationQuitEventHandler),
188 GetEventTypeCount(quit_events),
189 quit_events,
190 NULL,
191 NULL);
192
193 InstallApplicationEventHandler (
194 NewEventHandlerUPP (MainWindowEventHandler),
195 GetEventTypeCount(events),
196 events,
197 NULL,
198 NULL);
199 InstallWindowEventHandler (
200 theWindow,
201 NewEventHandlerUPP (MainWindowCommandHandler),
202 GetEventTypeCount(commands),
203 commands,
204 theWindow,
205 NULL);
206
207 ShowWindow(theWindow);
208 ShowMenuBar();
209 window_resized();
210 SelectWindow(theWindow);
211 terminit();
212 // Run the event loop
213 readybit = 1;
214 wakeup(&rend);
215 RunApplicationEventLoop();
216
217 }
218
convert_key(UInt32 key,UInt32 charcode)219 static inline int convert_key(UInt32 key, UInt32 charcode)
220 {
221 switch(key) {
222 case QZ_IBOOK_ENTER:
223 case QZ_RETURN: return '\n';
224 case QZ_ESCAPE: return 27;
225 case QZ_BACKSPACE: return '\b';
226 case QZ_LALT: return Kalt;
227 case QZ_LCTRL: return Kctl;
228 case QZ_LSHIFT: return Kshift;
229 case QZ_F1: return KF+1;
230 case QZ_F2: return KF+2;
231 case QZ_F3: return KF+3;
232 case QZ_F4: return KF+4;
233 case QZ_F5: return KF+5;
234 case QZ_F6: return KF+6;
235 case QZ_F7: return KF+7;
236 case QZ_F8: return KF+8;
237 case QZ_F9: return KF+9;
238 case QZ_F10: return KF+10;
239 case QZ_F11: return KF+11;
240 case QZ_F12: return KF+12;
241 case QZ_INSERT: return Kins;
242 case QZ_DELETE: return 0x7F;
243 case QZ_HOME: return Khome;
244 case QZ_END: return Kend;
245 case QZ_KP_PLUS: return '+';
246 case QZ_KP_MINUS: return '-';
247 case QZ_TAB: return '\t';
248 case QZ_PAGEUP: return Kpgup;
249 case QZ_PAGEDOWN: return Kpgdown;
250 case QZ_UP: return Kup;
251 case QZ_DOWN: return Kdown;
252 case QZ_LEFT: return Kleft;
253 case QZ_RIGHT: return Kright;
254 case QZ_KP_MULTIPLY: return '*';
255 case QZ_KP_DIVIDE: return '/';
256 case QZ_KP_ENTER: return '\n';
257 case QZ_KP_PERIOD: return '.';
258 case QZ_KP0: return '0';
259 case QZ_KP1: return '1';
260 case QZ_KP2: return '2';
261 case QZ_KP3: return '3';
262 case QZ_KP4: return '4';
263 case QZ_KP5: return '5';
264 case QZ_KP6: return '6';
265 case QZ_KP7: return '7';
266 case QZ_KP8: return '8';
267 case QZ_KP9: return '9';
268 default: return charcode;
269 }
270 }
271
272 void
sendbuttons(int b,int x,int y)273 sendbuttons(int b, int x, int y)
274 {
275 int i;
276 lock(&mouse.lk);
277 i = mouse.wi;
278 if(mousequeue) {
279 if(i == mouse.ri || mouse.lastb != b || mouse.trans) {
280 mouse.wi = (i+1)%Mousequeue;
281 if(mouse.wi == mouse.ri)
282 mouse.ri = (mouse.ri+1)%Mousequeue;
283 mouse.trans = mouse.lastb != b;
284 } else {
285 i = (i-1+Mousequeue)%Mousequeue;
286 }
287 } else {
288 mouse.wi = (i+1)%Mousequeue;
289 mouse.ri = i;
290 }
291 mouse.queue[i].xy.x = x;
292 mouse.queue[i].xy.y = y;
293 mouse.queue[i].buttons = b;
294 mouse.queue[i].msec = ticks();
295 mouse.lastb = b;
296 unlock(&mouse.lk);
297 wakeup(&mouse.r);
298 }
299
300 static Ptr fullScreenRestore;
301 static int amFullScreen = 0;
302 static WindowRef oldWindow = NULL;
303
304 static void
leave_full_screen()305 leave_full_screen()
306 {
307 if (amFullScreen) {
308 EndFullScreen(fullScreenRestore, 0);
309 theWindow = oldWindow;
310 ShowWindow(theWindow);
311 amFullScreen = 0;
312 window_resized();
313 Rectangle rect = { { 0, 0 },
314 { bounds.size.width,
315 bounds.size.height} };
316 drawqlock();
317 flushmemscreen(rect);
318 drawqunlock();
319 }
320 }
321
322 static void
full_screen()323 full_screen()
324 {
325 if (!amFullScreen) {
326 oldWindow = theWindow;
327 HideWindow(theWindow);
328 BeginFullScreen(&fullScreenRestore, 0, 0, 0, &theWindow, 0, 0);
329 amFullScreen = 1;
330 window_resized();
331 Rectangle rect = { { 0, 0 },
332 { bounds.size.width,
333 bounds.size.height} };
334 drawqlock();
335 flushmemscreen(rect);
336 drawqunlock();
337 }
338 }
339
340 // catch quit events to handle quits from menu, Cmd+Q, applescript, and task switcher
ApplicationQuitEventHandler(EventHandlerCallRef nextHandler,EventRef event,void * userData)341 static OSStatus ApplicationQuitEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
342 {
343 exit(0);
344 // QuitApplicationEventLoop();
345 return noErr;
346 }
347
MainWindowEventHandler(EventHandlerCallRef nextHandler,EventRef event,void * userData)348 static OSStatus MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
349 {
350 OSStatus result = noErr;
351 result = CallNextEventHandler(nextHandler, event);
352 UInt32 class = GetEventClass (event);
353 UInt32 kind = GetEventKind (event);
354 static uint32_t mousebuttons = 0; // bitmask of buttons currently down
355 static uint32_t mouseX = 0;
356 static uint32_t mouseY = 0;
357
358 if(class == kEventClassKeyboard) {
359 char macCharCodes;
360 UInt32 macKeyCode;
361 UInt32 macKeyModifiers;
362
363 GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar,
364 NULL, sizeof(macCharCodes), NULL, &macCharCodes);
365 GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL,
366 sizeof(macKeyCode), NULL, &macKeyCode);
367 GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL,
368 sizeof(macKeyModifiers), NULL, &macKeyModifiers);
369 switch(kind) {
370 case kEventRawKeyModifiersChanged:
371 if (macKeyModifiers == (controlKey | optionKey)) leave_full_screen();
372
373 switch(macKeyModifiers & (optionKey | cmdKey)) {
374 case (optionKey | cmdKey):
375 /* due to chording we need to handle the case when both
376 * modifier keys are pressed at the same time.
377 * currently it's only 2-3 snarf and the 3-2 noop
378 */
379 altPressed = true;
380 if(mousebuttons & 1 || mousebuttons & 2 || mousebuttons & 4) {
381 mousebuttons |= 2; /* set button 2 */
382 mousebuttons |= 4; /* set button 3 */
383 button2 = true;
384 button3 = true;
385 sendbuttons(mousebuttons, mouseX, mouseY);
386 }
387 break;
388 case optionKey:
389 altPressed = true;
390 if(mousebuttons & 1 || mousebuttons & 4) {
391 mousebuttons |= 2; /* set button 2 */
392 button2 = true;
393 sendbuttons(mousebuttons, mouseX, mouseY);
394 }
395 break;
396 case cmdKey:
397 if(mousebuttons & 1 || mousebuttons & 2) {
398 mousebuttons |= 4; /* set button 3 */
399 button3 = true;
400 sendbuttons(mousebuttons, mouseX, mouseY);
401 }
402 break;
403 case 0:
404 default:
405 if(button2 || button3) {
406 if(button2) {
407 mousebuttons &= ~2; /* clear button 2 */
408 button2 = false;
409 altPressed = false;
410 }
411 if(button3) {
412 mousebuttons &= ~4; /* clear button 3 */
413 button3 = false;
414 }
415 sendbuttons(mousebuttons, mouseX, mouseY);
416 }
417 if(altPressed) {
418 kbdputc(kbdq, Kalt);
419 altPressed = false;
420 }
421 break;
422 }
423 break;
424 case kEventRawKeyDown:
425 case kEventRawKeyRepeat:
426 if(macKeyModifiers != cmdKey) {
427 int key = convert_key(macKeyCode, macCharCodes);
428 if (key != -1) kbdputc(kbdq, key);
429 } else
430 result = eventNotHandledErr;
431 break;
432 default:
433 break;
434 }
435 }
436 else if(class == kEventClassMouse) {
437 _Point mousePos;
438
439 GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
440 0, sizeof mousePos, 0, &mousePos);
441
442 switch (kind) {
443 case kEventMouseWheelMoved:
444 {
445 int32_t wheeldelta;
446 GetEventParameter(event,kEventParamMouseWheelDelta,typeSInt32,
447 0,sizeof(wheeldelta), 0, &wheeldelta);
448 mouseX = mousePos.h - winRect.left;
449 mouseY = mousePos.v - winRect.top;
450 sendbuttons(wheeldelta>0 ? 8 : 16, mouseX, mouseY);
451 break;
452 }
453 case kEventMouseUp:
454 case kEventMouseDown:
455 {
456 uint32_t buttons;
457 uint32_t modifiers;
458 GetEventParameter(event, kEventParamKeyModifiers, typeUInt32,
459 0, sizeof(modifiers), 0, &modifiers);
460 GetEventParameter(event, kEventParamMouseChord, typeUInt32,
461 0, sizeof buttons, 0, &buttons);
462 /* simulate other buttons via alt/apple key. like x11 */
463 if(modifiers & optionKey) {
464 mousebuttons = ((buttons & 1) ? 2 : 0);
465 altPressed = false;
466 } else if(modifiers & cmdKey)
467 mousebuttons = ((buttons & 1) ? 4 : 0);
468 else
469 mousebuttons = (buttons & 1);
470
471 mousebuttons |= ((buttons & 2)<<1);
472 mousebuttons |= ((buttons & 4)>>1);
473
474 } /* Fallthrough */
475 case kEventMouseMoved:
476 case kEventMouseDragged:
477 mouseX = mousePos.h - winRect.left;
478 mouseY = mousePos.v - winRect.top;
479 sendbuttons(mousebuttons, mouseX, mouseY);
480 break;
481 default:
482 result = eventNotHandledErr;
483 break;
484 }
485 }
486 return result;
487 }
488
489
490 //default window command handler (from menus)
MainWindowCommandHandler(EventHandlerCallRef nextHandler,EventRef event,void * userData)491 static OSStatus MainWindowCommandHandler(EventHandlerCallRef nextHandler,
492 EventRef event, void *userData)
493 {
494 OSStatus result = noErr;
495 UInt32 class = GetEventClass (event);
496 UInt32 kind = GetEventKind (event);
497
498 result = CallNextEventHandler(nextHandler, event);
499
500 if(class == kEventClassCommand)
501 {
502 HICommand theHICommand;
503 GetEventParameter( event, kEventParamDirectObject, typeHICommand,
504 NULL, sizeof( HICommand ), NULL, &theHICommand );
505
506 switch ( theHICommand.commandID )
507 {
508 case kHICommandQuit:
509 exit(0);
510 break;
511
512 case kFullScreenCmd:
513 full_screen();
514 break;
515
516 default:
517 result = eventNotHandledErr;
518 break;
519 }
520 }
521 else if(class == kEventClassWindow)
522 {
523 WindowRef window;
524 _Rect rectPort = {0,0,0,0};
525
526 GetEventParameter(event, kEventParamDirectObject, typeWindowRef,
527 NULL, sizeof(WindowRef), NULL, &window);
528
529 if(window)
530 {
531 GetPortBounds(GetWindowPort(window), &rectPort);
532 }
533
534 switch (kind)
535 {
536 case kEventWindowClosed:
537 // send a quit carbon event instead of directly calling cleanexit
538 // so that all quits are done in ApplicationQuitEventHandler
539 {
540 EventRef quitEvent;
541 CreateEvent(NULL,
542 kEventClassApplication,
543 kEventAppQuit,
544 0,
545 kEventAttributeNone,
546 &quitEvent);
547 EventTargetRef target;
548 target = GetApplicationEventTarget();
549 SendEventToEventTarget(quitEvent, target);
550 }
551 break;
552
553 //resize window
554 case kEventWindowBoundsChanged:
555 window_resized();
556 Rectangle rect = { { 0, 0 },
557 { bounds.size.width,
558 bounds.size.height} };
559 drawqlock();
560 flushmemscreen(rect);
561 drawqunlock();
562 break;
563
564 default:
565 result = eventNotHandledErr;
566 break;
567 }
568 }
569
570 return result;
571 }
572
573 void
flushmemscreen(Rectangle r)574 flushmemscreen(Rectangle r)
575 {
576 // sanity check. Trips from the initial "terminal"
577 if (r.max.x < r.min.x || r.max.y < r.min.y) return;
578
579 screenload(r, gscreen->depth, byteaddr(gscreen, ZP), ZP,
580 gscreen->width*sizeof(ulong));
581 }
582
583 uchar*
attachscreen(Rectangle * r,ulong * chan,int * depth,int * width,int * softscreen,void ** X)584 attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen, void **X)
585 {
586 *r = gscreen->r;
587 *chan = gscreen->chan;
588 *depth = gscreen->depth;
589 *width = gscreen->width;
590 *softscreen = 1;
591
592 return gscreen->data->bdata;
593 }
594
595 // PAL - no palette handling. Don't intend to either.
596 void
getcolor(ulong i,ulong * r,ulong * g,ulong * b)597 getcolor(ulong i, ulong *r, ulong *g, ulong *b)
598 {
599
600 // PAL: Certainly wrong to return a grayscale.
601 *r = i;
602 *g = i;
603 *b = i;
604 }
605
606 void
setcolor(ulong index,ulong red,ulong green,ulong blue)607 setcolor(ulong index, ulong red, ulong green, ulong blue)
608 {
609 assert(0);
610 }
611
612
613 static char snarf[3*SnarfSize+1];
614 static Rune rsnarf[SnarfSize+1];
615
616 char*
clipread(void)617 clipread(void)
618 {
619 CFDataRef cfdata;
620 OSStatus err = noErr;
621 ItemCount nItems;
622
623 // Wow. This is ridiculously complicated.
624 PasteboardSynchronize(appleclip);
625 if((err = PasteboardGetItemCount(appleclip, &nItems)) != noErr) {
626 fprint(2, "apple pasteboard GetItemCount failed - Error %d\n", err);
627 return 0;
628 }
629
630 uint32_t i;
631 // Yes, based at 1. Silly API.
632 for(i = 1; i <= nItems; ++i) {
633 PasteboardItemID itemID;
634 CFArrayRef flavorTypeArray;
635 CFIndex flavorCount;
636
637 if((err = PasteboardGetItemIdentifier(appleclip, i, &itemID)) != noErr){
638 fprint(2, "Can't get pasteboard item identifier: %d\n", err);
639 return 0;
640 }
641
642 if((err = PasteboardCopyItemFlavors(appleclip, itemID, &flavorTypeArray))!=noErr){
643 fprint(2, "Can't copy pasteboard item flavors: %d\n", err);
644 return 0;
645 }
646
647 flavorCount = CFArrayGetCount(flavorTypeArray);
648 CFIndex flavorIndex;
649 for(flavorIndex = 0; flavorIndex < flavorCount; ++flavorIndex){
650 CFStringRef flavorType;
651 flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex);
652 if (UTTypeConformsTo(flavorType, CFSTR("public.utf16-plain-text"))){
653 if((err = PasteboardCopyItemFlavorData(appleclip, itemID,
654 CFSTR("public.utf16-plain-text"), &cfdata)) != noErr){
655 fprint(2, "apple pasteboard CopyItem failed - Error %d\n", err);
656 return 0;
657 }
658 CFIndex length = CFDataGetLength(cfdata);
659 if (length > sizeof rsnarf) length = sizeof rsnarf;
660 CFDataGetBytes(cfdata, CFRangeMake(0, length), (uint8_t *)rsnarf);
661 snprint(snarf, sizeof snarf, "%.*S", length/sizeof(Rune), rsnarf);
662 char *s = snarf;
663 while (*s) {
664 if (*s == '\r') *s = '\n';
665 s++;
666 }
667 CFRelease(cfdata);
668 return strdup(snarf);
669 }
670 }
671 }
672 return 0;
673 }
674
675 int
clipwrite(char * snarf)676 clipwrite(char *snarf)
677 {
678 CFDataRef cfdata;
679 PasteboardSyncFlags flags;
680
681 runesnprint(rsnarf, nelem(rsnarf), "%s", snarf);
682 if(PasteboardClear(appleclip) != noErr){
683 fprint(2, "apple pasteboard clear failed\n");
684 return 0;
685 }
686 flags = PasteboardSynchronize(appleclip);
687 if((flags&kPasteboardModified) || !(flags&kPasteboardClientIsOwner)){
688 fprint(2, "apple pasteboard cannot assert ownership\n");
689 return 0;
690 }
691 cfdata = CFDataCreate(kCFAllocatorDefault,
692 (uchar*)rsnarf, runestrlen(rsnarf)*2);
693 if(cfdata == nil){
694 fprint(2, "apple pasteboard cfdatacreate failed\n");
695 return 0;
696 }
697 if(PasteboardPutItemFlavor(appleclip, (PasteboardItemID)1,
698 CFSTR("public.utf16-plain-text"), cfdata, 0) != noErr){
699 fprint(2, "apple pasteboard putitem failed\n");
700 CFRelease(cfdata);
701 return 0;
702 }
703 CFRelease(cfdata);
704 return 1;
705 }
706
707
708 void
mouseset(Point xy)709 mouseset(Point xy)
710 {
711 CGPoint pnt;
712 pnt.x = xy.x + winRect.left;
713 pnt.y = xy.y + winRect.top;
714 CGWarpMouseCursorPosition(pnt);
715 }
716
717 void
screenload(Rectangle r,int depth,uchar * p,Point pt,int step)718 screenload(Rectangle r, int depth, uchar *p, Point pt, int step)
719 {
720 CGRect rbounds;
721 rbounds.size.width = r.max.x - r.min.x;
722 rbounds.size.height = r.max.y - r.min.y;
723 rbounds.origin.x = r.min.x;
724 rbounds.origin.y = r.min.y;
725
726 if(depth != gscreen->depth)
727 panic("screenload: bad ldepth");
728
729 QDBeginCGContext( GetWindowPort(theWindow), &context);
730
731 // The sub-image is relative to our whole screen image.
732 CGImageRef subimg = CGImageCreateWithImageInRect(fullScreenImage, rbounds);
733
734 // Drawing the sub-image is relative to the window.
735 rbounds.origin.y = winRect.bottom - winRect.top - r.min.y - rbounds.size.height;
736 CGContextDrawImage(context, rbounds, subimg);
737 CGContextFlush(context);
738 CGImageRelease(subimg);
739 QDEndCGContext( GetWindowPort(theWindow), &context);
740
741 }
742
743 // PAL: these don't work.
744 // SetCursor and InitCursor are marked as deprecated in 10.4, and I can't for the
745 // life of me find out what has replaced them.
746 void
setcursor(void)747 setcursor(void)
748 {
749 Cursor crsr;
750 int i;
751
752 for(i=0; i<16; i++){
753 crsr.data[i] = ((ushort*)cursor.set)[i];
754 crsr.mask[i] = crsr.data[i] | ((ushort*)cursor.clr)[i];
755 }
756 crsr.hotSpot.h = -cursor.offset.x;
757 crsr.hotSpot.v = -cursor.offset.y;
758 SetCursor(&crsr);
759 }
760
761 void
cursorarrow(void)762 cursorarrow(void)
763 {
764 InitCursor();
765 }
766