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 72 isready(void*a) 73 { 74 return readybit; 75 } 76 77 CGContextRef QuartzContext; 78 79 void winproc(void *a); 80 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 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 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 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 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 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 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 341 static OSStatus ApplicationQuitEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData) 342 { 343 exit(0); 344 // QuitApplicationEventLoop(); 345 return noErr; 346 } 347 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) 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 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* 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 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 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* 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 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 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 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 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 762 cursorarrow(void) 763 { 764 InitCursor(); 765 } 766