1/* 2 * tkMacOSXXStubs.c -- 3 * 4 * This file contains most of the X calls called by Tk. Many of these 5 * calls are just stubs and either don't make sense on the Macintosh or 6 * their implamentation just doesn't do anything. Other calls will 7 * eventually be moved into other files. 8 * 9 * Copyright (c) 1995-1997 Sun Microsystems, Inc. 10 * Copyright 2001-2009, Apple Inc. 11 * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net> 12 * 13 * See the file "license.terms" for information on usage and redistribution 14 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 15 * 16 * RCS: @(#) $Id$ 17 */ 18 19#include "tkMacOSXPrivate.h" 20#include "tkMacOSXEvent.h" 21 22#include <IOKit/IOKitLib.h> 23#include <IOKit/hidsystem/IOHIDShared.h> 24 25/* 26 * Because this file is still under major development Debugger statements are 27 * used through out this file. The define TCL_DEBUG will decide whether the 28 * debugger statements actually call the debugger or not. 29 */ 30 31#ifndef TCL_DEBUG 32# define Debugger() 33#endif 34 35#define ROOT_ID 10 36 37CGFloat tkMacOSXZeroScreenHeight = 0; 38CGFloat tkMacOSXZeroScreenTop = 0; 39 40/* 41 * Declarations of static variables used in this file. 42 */ 43 44static TkDisplay *gMacDisplay = NULL; 45 /* Macintosh display. */ 46static const char *macScreenName = ":0"; 47 /* Default name of macintosh display. */ 48 49/* 50 * Forward declarations of procedures used in this file. 51 */ 52 53static XID MacXIdAlloc(Display *display); 54static int DefaultErrorHandler(Display *display, 55 XErrorEvent *err_evt); 56 57/* 58 * Other declarations 59 */ 60 61static int DestroyImage(XImage *image); 62static unsigned long ImageGetPixel(XImage *image, int x, int y); 63static int ImagePutPixel(XImage *image, int x, int y, 64 unsigned long pixel); 65 66/* 67 *---------------------------------------------------------------------- 68 * 69 * TkMacOSXDisplayChanged -- 70 * 71 * Called to set up initial screen info or when an event indicated 72 * display (screen) change. 73 * 74 * Results: 75 * None. 76 * 77 * Side effects: 78 * May change info regarding the screen. 79 * 80 *---------------------------------------------------------------------- 81 */ 82 83void 84TkMacOSXDisplayChanged( 85 Display *display) 86{ 87 Screen *screen; 88 NSArray *nsScreens; 89 90 91 if (display == NULL || display->screens == NULL) { 92 return; 93 } 94 screen = display->screens; 95 96 nsScreens = [NSScreen screens]; 97 if (nsScreens && [nsScreens count]) { 98 NSScreen *s = [nsScreens objectAtIndex:0]; 99 NSRect bounds = [s frame], visible = [s visibleFrame]; 100 NSRect maxBounds = NSZeroRect; 101 102 tkMacOSXZeroScreenHeight = bounds.size.height; 103 tkMacOSXZeroScreenTop = tkMacOSXZeroScreenHeight - 104 (visible.origin.y + visible.size.height); 105 106 screen->root_depth = NSBitsPerPixelFromDepth([s depth]); 107 screen->width = bounds.size.width; 108 screen->height = bounds.size.height; 109 screen->mwidth = (bounds.size.width * 254 + 360) / 720; 110 screen->mheight = (bounds.size.height * 254 + 360) / 720; 111 112 for (s in nsScreens) { 113 maxBounds = NSUnionRect(maxBounds, [s visibleFrame]); 114 } 115 *((NSRect *)screen->ext_data) = maxBounds; 116 } 117} 118 119/* 120 *---------------------------------------------------------------------- 121 * 122 * TkpOpenDisplay -- 123 * 124 * Create the Display structure and fill it with device specific 125 * information. 126 * 127 * Results: 128 * Returns a Display structure on success or NULL on failure. 129 * 130 * Side effects: 131 * Allocates a new Display structure. 132 * 133 *---------------------------------------------------------------------- 134 */ 135 136TkDisplay * 137TkpOpenDisplay( 138 const char *display_name) 139{ 140 Display *display; 141 Screen *screen; 142 int fd = 0; 143 static NSRect maxBounds = {{0, 0}, {0, 0}}; 144 static char vendor[25] = ""; 145 NSArray *cgVers; 146 NSAutoreleasePool *pool; 147 148 if (gMacDisplay != NULL) { 149 if (strcmp(gMacDisplay->display->display_name, display_name) == 0) { 150 return gMacDisplay; 151 } else { 152 return NULL; 153 } 154 } 155 156 display = (Display *) ckalloc(sizeof(Display)); 157 screen = (Screen *) ckalloc(sizeof(Screen)); 158 bzero(display, sizeof(Display)); 159 bzero(screen, sizeof(Screen)); 160 161 display->resource_alloc = MacXIdAlloc; 162 display->request = 0; 163 display->qlen = 0; 164 display->fd = fd; 165 display->screens = screen; 166 display->nscreens = 1; 167 display->default_screen = 0; 168 display->display_name = (char *) macScreenName; 169 170 pool = [NSAutoreleasePool new]; 171 cgVers = [[[NSBundle bundleWithIdentifier:@"com.apple.CoreGraphics"] 172 objectForInfoDictionaryKey:@"CFBundleShortVersionString"] 173 componentsSeparatedByString:@"."]; 174 if ([cgVers count] >= 2) { 175 display->proto_major_version = [[cgVers objectAtIndex:1] integerValue]; 176 } 177 if ([cgVers count] >= 3) { 178 display->proto_minor_version = [[cgVers objectAtIndex:2] integerValue]; 179 } 180 if (!vendor[0]) { 181 snprintf(vendor, sizeof(vendor), "Apple AppKit %s %g", 182 ([NSGarbageCollector defaultCollector] ? "GC" : "RR"), 183 NSAppKitVersionNumber); 184 } 185 display->vendor = vendor; 186 Gestalt(gestaltSystemVersion, (SInt32 *) &display->release); 187 188 /* 189 * These screen bits never change 190 */ 191 screen->root = ROOT_ID; 192 screen->display = display; 193 screen->black_pixel = 0x00000000 | PIXEL_MAGIC << 24; 194 screen->white_pixel = 0x00FFFFFF | PIXEL_MAGIC << 24; 195 screen->ext_data = (XExtData *) &maxBounds; 196 197 screen->root_visual = (Visual *) ckalloc(sizeof(Visual)); 198 screen->root_visual->visualid = 0; 199 screen->root_visual->class = TrueColor; 200 screen->root_visual->red_mask = 0x00FF0000; 201 screen->root_visual->green_mask = 0x0000FF00; 202 screen->root_visual->blue_mask = 0x000000FF; 203 screen->root_visual->bits_per_rgb = 24; 204 screen->root_visual->map_entries = 256; 205 206 /* 207 * Initialize screen bits that may change 208 */ 209 210 TkMacOSXDisplayChanged(display); 211 212 gMacDisplay = (TkDisplay *) ckalloc(sizeof(TkDisplay)); 213 214 /* 215 * This is the quickest way to make sure that all the *Init flags get 216 * properly initialized 217 */ 218 219 bzero(gMacDisplay, sizeof(TkDisplay)); 220 gMacDisplay->display = display; 221 [pool drain]; 222 return gMacDisplay; 223} 224 225/* 226 *---------------------------------------------------------------------- 227 * 228 * TkpCloseDisplay -- 229 * 230 * Deallocates a display structure created by TkpOpenDisplay. 231 * 232 * Results: 233 * None. 234 * 235 * Side effects: 236 * Frees memory. 237 * 238 *---------------------------------------------------------------------- 239 */ 240 241void 242TkpCloseDisplay( 243 TkDisplay *displayPtr) 244{ 245 Display *display = displayPtr->display; 246 247 if (gMacDisplay != displayPtr) { 248 Tcl_Panic("TkpCloseDisplay: tried to call TkpCloseDisplay on bad display"); 249 } 250 251 gMacDisplay = NULL; 252 if (display->screens != NULL) { 253 if (display->screens->root_visual != NULL) { 254 ckfree((char *) display->screens->root_visual); 255 } 256 ckfree((char *) display->screens); 257 } 258 ckfree((char *) display); 259} 260 261/* 262 *---------------------------------------------------------------------- 263 * 264 * TkClipCleanup -- 265 * 266 * This procedure is called to cleanup resources associated with claiming 267 * clipboard ownership and for receiving selection get results. This 268 * function is called in tkWindow.c. This has to be called by the display 269 * cleanup function because we still need the access display elements. 270 * 271 * Results: 272 * None. 273 * 274 * Side effects: 275 * Resources are freed - the clipboard may no longer be used. 276 * 277 *---------------------------------------------------------------------- 278 */ 279 280void 281TkClipCleanup( 282 TkDisplay *dispPtr) /* display associated with clipboard */ 283{ 284 /* 285 * Make sure that the local scrap is transfered to the global scrap if 286 * needed. 287 */ 288 289 [NSApp tkProvidePasteboard:dispPtr]; 290 291 if (dispPtr->clipWindow != NULL) { 292 Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom, 293 dispPtr->applicationAtom); 294 Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom, 295 dispPtr->windowAtom); 296 297 Tk_DestroyWindow(dispPtr->clipWindow); 298 Tcl_Release(dispPtr->clipWindow); 299 dispPtr->clipWindow = NULL; 300 } 301} 302 303/* 304 *---------------------------------------------------------------------- 305 * 306 * MacXIdAlloc -- 307 * 308 * This procedure is invoked by Xlib as the resource allocator for a 309 * display. 310 * 311 * Results: 312 * The return value is an X resource identifier that isn't currently in 313 * use. 314 * 315 * Side effects: 316 * The identifier is removed from the stack of free identifiers, if it 317 * was previously on the stack. 318 * 319 *---------------------------------------------------------------------- 320 */ 321 322static XID 323MacXIdAlloc( 324 Display *display) /* Display for which to allocate. */ 325{ 326 static long int cur_id = 100; 327 /* 328 * Some special XIds are reserved 329 * - this is why we start at 100 330 */ 331 332 return ++cur_id; 333} 334 335/* 336 *---------------------------------------------------------------------- 337 * 338 * TkpWindowWasRecentlyDeleted -- 339 * 340 * Tries to determine whether the given window was recently deleted. 341 * Called from the generic code error handler to attempt to deal with 342 * async BadWindow errors under some circumstances. 343 * 344 * Results: 345 * Always 0, we do not keep this information on the Mac, so we do not 346 * know whether the window was destroyed. 347 * 348 * Side effects: 349 * None. 350 * 351 *---------------------------------------------------------------------- 352 */ 353 354int 355TkpWindowWasRecentlyDeleted( 356 Window win, 357 TkDisplay *dispPtr) 358{ 359 return 0; 360} 361 362/* 363 *---------------------------------------------------------------------- 364 * 365 * DefaultErrorHandler -- 366 * 367 * This procedure is the default X error handler. Tk uses it's own error 368 * handler so this call should never be called. 369 * 370 * Results: 371 * None. 372 * 373 * Side effects: 374 * This function will call panic and exit. 375 * 376 *---------------------------------------------------------------------- 377 */ 378 379static int 380DefaultErrorHandler( 381 Display* display, 382 XErrorEvent* err_evt) 383{ 384 /* 385 * This call should never be called. Tk replaces it with its own error 386 * handler. 387 */ 388 389 Tcl_Panic("Warning hit bogus error handler!"); 390 return 0; 391} 392 393char * 394XGetAtomName( 395 Display * display, 396 Atom atom) 397{ 398 display->request++; 399 return NULL; 400} 401 402int 403_XInitImageFuncPtrs( 404 XImage *image) 405{ 406 return 0; 407} 408 409XErrorHandler 410XSetErrorHandler( 411 XErrorHandler handler) 412{ 413 return DefaultErrorHandler; 414} 415 416Window 417XRootWindow( 418 Display *display, 419 int screen_number) 420{ 421 display->request++; 422 return ROOT_ID; 423} 424 425int 426XGetGeometry( 427 Display *display, 428 Drawable d, 429 Window *root_return, 430 int *x_return, 431 int *y_return, 432 unsigned int *width_return, 433 unsigned int *height_return, 434 unsigned int *border_width_return, 435 unsigned int *depth_return) 436{ 437 TkWindow *winPtr = ((MacDrawable *) d)->winPtr; 438 439 display->request++; 440 *root_return = ROOT_ID; 441 if (winPtr) { 442 *x_return = Tk_X(winPtr); 443 *y_return = Tk_Y(winPtr); 444 *width_return = Tk_Width(winPtr); 445 *height_return = Tk_Height(winPtr); 446 *border_width_return = winPtr->changes.border_width; 447 *depth_return = Tk_Depth(winPtr); 448 } else { 449 CGSize size = ((MacDrawable *) d)->size; 450 *x_return = 0; 451 *y_return = 0; 452 *width_return = size.width; 453 *height_return = size.height; 454 *border_width_return = 0; 455 *depth_return = 32; 456 } 457 return 1; 458} 459 460void 461XChangeProperty( 462 Display* display, 463 Window w, 464 Atom property, 465 Atom type, 466 int format, 467 int mode, 468 _Xconst unsigned char* data, 469 int nelements) 470{ 471 Debugger(); 472} 473 474void 475XSelectInput( 476 Display* display, 477 Window w, 478 long event_mask) 479{ 480 Debugger(); 481} 482 483void 484XBell( 485 Display* display, 486 int percent) 487{ 488 NSBeep(); 489} 490 491#if 0 492void 493XSetWMNormalHints( 494 Display* display, 495 Window w, 496 XSizeHints* hints) 497{ 498 /* 499 * Do nothing. Shouldn't even be called. 500 */ 501} 502 503XSizeHints * 504XAllocSizeHints(void) 505{ 506 /* 507 * Always return NULL. Tk code checks to see if NULL is returned & does 508 * nothing if it is. 509 */ 510 511 return NULL; 512} 513#endif 514 515GContext 516XGContextFromGC( 517 GC gc) 518{ 519 /* 520 * TODO: currently a no-op 521 */ 522 523 return 0; 524} 525 526Status 527XSendEvent( 528 Display* display, 529 Window w, 530 Bool propagate, 531 long event_mask, 532 XEvent* event_send) 533{ 534 Debugger(); 535 return 0; 536} 537 538void 539XClearWindow( 540 Display* display, 541 Window w) 542{ 543} 544 545/* 546void 547XDrawPoint( 548 Display* display, 549 Drawable d, 550 GC gc, 551 int x, 552 int y) 553{ 554} 555 556void 557XDrawPoints( 558 Display* display, 559 Drawable d, 560 GC gc, 561 XPoint* points, 562 int npoints, 563 int mode) 564{ 565} 566*/ 567 568void 569XWarpPointer( 570 Display* display, 571 Window src_w, 572 Window dest_w, 573 int src_x, 574 int src_y, 575 unsigned int src_width, 576 unsigned int src_height, 577 int dest_x, 578 int dest_y) 579{ 580} 581 582void 583XQueryColor( 584 Display* display, 585 Colormap colormap, 586 XColor* def_in_out) 587{ 588 unsigned long p; 589 unsigned char r, g, b; 590 XColor *d = def_in_out; 591 592 p = d->pixel; 593 r = (p & 0x00FF0000) >> 16; 594 g = (p & 0x0000FF00) >> 8; 595 b = (p & 0x000000FF); 596 d->red = (r << 8) | r; 597 d->green = (g << 8) | g; 598 d->blue = (b << 8) | b; 599 d->flags = DoRed|DoGreen|DoBlue; 600 d->pad = 0; 601} 602 603void 604XQueryColors( 605 Display* display, 606 Colormap colormap, 607 XColor* defs_in_out, 608 int ncolors) 609{ 610 int i; 611 unsigned long p; 612 unsigned char r, g, b; 613 XColor *d = defs_in_out; 614 615 for (i = 0; i < ncolors; i++, d++) { 616 p = d->pixel; 617 r = (p & 0x00FF0000) >> 16; 618 g = (p & 0x0000FF00) >> 8; 619 b = (p & 0x000000FF); 620 d->red = (r << 8) | r; 621 d->green = (g << 8) | g; 622 d->blue = (b << 8) | b; 623 d->flags = DoRed|DoGreen|DoBlue; 624 d->pad = 0; 625 } 626} 627 628int 629XQueryTree(display, w, root_return, parent_return, children_return, 630 nchildren_return) 631 Display* display; 632 Window w; 633 Window* root_return; 634 Window* parent_return; 635 Window** children_return; 636 unsigned int* nchildren_return; 637{ 638 return 0; 639} 640 641 642int 643XGetWindowProperty( 644 Display *display, 645 Window w, 646 Atom property, 647 long long_offset, 648 long long_length, 649 Bool delete, 650 Atom req_type, 651 Atom *actual_type_return, 652 int *actual_format_return, 653 unsigned long *nitems_return, 654 unsigned long *bytes_after_return, 655 unsigned char ** prop_return) 656{ 657 display->request++; 658 *actual_type_return = None; 659 *actual_format_return = *bytes_after_return = 0; 660 *nitems_return = 0; 661 return 0; 662} 663 664void 665XRefreshKeyboardMapping( 666 XMappingEvent *x) 667{ 668 /* used by tkXEvent.c */ 669 Debugger(); 670} 671 672void 673XSetIconName( 674 Display* display, 675 Window w, 676 const char *icon_name) 677{ 678 /* 679 * This is a no-op, no icon name for Macs. 680 */ 681 display->request++; 682} 683 684void 685XForceScreenSaver( 686 Display* display, 687 int mode) 688{ 689 /* 690 * This function is just a no-op. It is defined to reset the screen saver. 691 * However, there is no real way to do this on a Mac. Let me know if there 692 * is! 693 */ 694 695 display->request++; 696} 697 698void 699Tk_FreeXId( 700 Display *display, 701 XID xid) 702{ 703 /* no-op function needed for stubs implementation. */ 704} 705 706int 707XSync( 708 Display *display, 709 Bool flag) 710{ 711 TkMacOSXFlushWindows(); 712 display->request++; 713 return 0; 714} 715 716#if 0 717int 718XSetClipRectangles( 719 Display *d, 720 GC gc, 721 int clip_x_origin, 722 int clip_y_origin, 723 XRectangle* rectangles, 724 int n, 725 int ordering) 726{ 727 TkRegion clipRgn = TkCreateRegion(); 728 729 while (n--) { 730 XRectangle rect = *rectangles; 731 732 rect.x += clip_x_origin; 733 rect.y += clip_y_origin; 734 TkUnionRectWithRegion(&rect, clipRgn, clipRgn); 735 rectangles++; 736 } 737 TkSetRegion(d, gc, clipRgn); 738 TkDestroyRegion(clipRgn); 739 return 1; 740} 741#endif 742 743/* 744 *---------------------------------------------------------------------- 745 * 746 * TkGetServerInfo -- 747 * 748 * Given a window, this procedure returns information about the window 749 * server for that window. This procedure provides the guts of the "winfo 750 * server" command. 751 * 752 * Results: 753 * None. 754 * 755 * Side effects: 756 * None. 757 * 758 *---------------------------------------------------------------------- 759 */ 760 761void 762TkGetServerInfo( 763 Tcl_Interp *interp, /* The server information is returned in this 764 * interpreter's result. */ 765 Tk_Window tkwin) /* Token for window; this selects a particular 766 * display and server. */ 767{ 768 char buffer[5 + TCL_INTEGER_SPACE * 2]; 769 char buffer2[11 + TCL_INTEGER_SPACE]; 770 771 snprintf(buffer, sizeof(buffer), "CG%d.%d ", 772 ProtocolVersion(Tk_Display(tkwin)), 773 ProtocolRevision(Tk_Display(tkwin))); 774 snprintf(buffer2, sizeof(buffer2), " Mac OS X %x", 775 VendorRelease(Tk_Display(tkwin))); 776 Tcl_AppendResult(interp, buffer, ServerVendor(Tk_Display(tkwin)), 777 buffer2, NULL); 778} 779 780#pragma mark XImage handling 781 782/* 783 *---------------------------------------------------------------------- 784 * 785 * XCreateImage -- 786 * 787 * Allocates storage for a new XImage. 788 * 789 * Results: 790 * Returns a newly allocated XImage. 791 * 792 * Side effects: 793 * None. 794 * 795 *---------------------------------------------------------------------- 796 */ 797 798XImage * 799XCreateImage( 800 Display* display, 801 Visual* visual, 802 unsigned int depth, 803 int format, 804 int offset, 805 char* data, 806 unsigned int width, 807 unsigned int height, 808 int bitmap_pad, 809 int bytes_per_line) 810{ 811 XImage *ximage; 812 813 display->request++; 814 ximage = (XImage *) ckalloc(sizeof(XImage)); 815 816 ximage->height = height; 817 ximage->width = width; 818 ximage->depth = depth; 819 ximage->xoffset = offset; 820 ximage->format = format; 821 ximage->data = data; 822 823 if (format == ZPixmap) { 824 ximage->bits_per_pixel = 32; 825 ximage->bitmap_unit = 32; 826 } else { 827 ximage->bits_per_pixel = 1; 828 ximage->bitmap_unit = 8; 829 } 830 if (bitmap_pad) { 831 ximage->bitmap_pad = bitmap_pad; 832 } else { 833 /* Use 16 byte alignment for best Quartz perfomance */ 834 ximage->bitmap_pad = 128; 835 } 836 if (bytes_per_line) { 837 ximage->bytes_per_line = bytes_per_line; 838 } else { 839 ximage->bytes_per_line = ((width * ximage->bits_per_pixel + 840 (ximage->bitmap_pad - 1)) >> 3) & 841 ~((ximage->bitmap_pad >> 3) - 1); 842 } 843#ifdef WORDS_BIGENDIAN 844 ximage->byte_order = MSBFirst; 845 ximage->bitmap_bit_order = MSBFirst; 846#else 847 ximage->byte_order = LSBFirst; 848 ximage->bitmap_bit_order = LSBFirst; 849#endif 850 ximage->red_mask = 0x00FF0000; 851 ximage->green_mask = 0x0000FF00; 852 ximage->blue_mask = 0x000000FF; 853 ximage->obdata = NULL; 854 ximage->f.create_image = NULL; 855 ximage->f.destroy_image = DestroyImage; 856 ximage->f.get_pixel = ImageGetPixel; 857 ximage->f.put_pixel = ImagePutPixel; 858 ximage->f.sub_image = NULL; 859 ximage->f.add_pixel = NULL; 860 861 return ximage; 862} 863 864/* 865 *---------------------------------------------------------------------- 866 * 867 * XGetImage -- 868 * 869 * This function copies data from a pixmap or window into an XImage. 870 * 871 * Results: 872 * Returns a newly allocated image containing the data from the given 873 * rectangle of the given drawable. 874 * 875 * Side effects: 876 * None. 877 * 878 *---------------------------------------------------------------------- 879 */ 880 881XImage * 882XGetImage( 883 Display *display, 884 Drawable d, 885 int x, 886 int y, 887 unsigned int width, 888 unsigned int height, 889 unsigned long plane_mask, 890 int format) 891{ 892 MacDrawable *macDraw = (MacDrawable *) d; 893 XImage * imagePtr = NULL; 894 Pixmap pixmap = (Pixmap) NULL; 895 Tk_Window win = (Tk_Window) macDraw->winPtr; 896 GC gc; 897 char * data = NULL; 898 int depth = 32; 899 int offset = 0; 900 int bitmap_pad = 0; 901 int bytes_per_line = 0; 902 903 if (format == ZPixmap) { 904 if (width > 0 && height > 0) { 905 /* 906 * Tk_GetPixmap fails for zero width or height. 907 */ 908 909 pixmap = Tk_GetPixmap(display, d, width, height, depth); 910 } 911 if (win) { 912 XGCValues values; 913 914 gc = Tk_GetGC(win, 0, &values); 915 } else { 916 gc = XCreateGC(display, pixmap, 0, NULL); 917 } 918 if (pixmap) { 919 CGContextRef context; 920 921 XCopyArea(display, d, pixmap, gc, x, y, width, height, 0, 0); 922 context = ((MacDrawable *) pixmap)->context; 923 if (context) { 924 data = CGBitmapContextGetData(context); 925 bytes_per_line = CGBitmapContextGetBytesPerRow(context); 926 } 927 } 928 if (data) { 929 imagePtr = XCreateImage(display, NULL, depth, format, offset, 930 data, width, height, bitmap_pad, bytes_per_line); 931 932 /* 933 * Track Pixmap underlying the XImage in the unused obdata field 934 * so that we can treat XImages coming from XGetImage specially. 935 */ 936 937 imagePtr->obdata = (XPointer) pixmap; 938 } else if (pixmap) { 939 Tk_FreePixmap(display, pixmap); 940 } 941 if (!win) { 942 XFreeGC(display, gc); 943 } 944 } else { 945 TkMacOSXDbgMsg("Invalid image format"); 946 } 947 return imagePtr; 948} 949 950/* 951 *---------------------------------------------------------------------- 952 * 953 * DestroyImage -- 954 * 955 * Destroys storage associated with an image. 956 * 957 * Results: 958 * None. 959 * 960 * Side effects: 961 * Deallocates the image. 962 * 963 *---------------------------------------------------------------------- 964 */ 965 966static int 967DestroyImage( 968 XImage *image) 969{ 970 if (image) { 971 if (image->obdata) { 972 Tk_FreePixmap((Display*) gMacDisplay, (Pixmap) image->obdata); 973 } else if (image->data) { 974 ckfree(image->data); 975 } 976 ckfree((char*) image); 977 } 978 return 0; 979} 980 981/* 982 *---------------------------------------------------------------------- 983 * 984 * ImageGetPixel -- 985 * 986 * Get a single pixel from an image. 987 * 988 * Results: 989 * Returns the 32 bit pixel value. 990 * 991 * Side effects: 992 * None. 993 * 994 *---------------------------------------------------------------------- 995 */ 996 997static unsigned long 998ImageGetPixel( 999 XImage *image, 1000 int x, 1001 int y) 1002{ 1003 unsigned char r = 0, g = 0, b = 0; 1004 1005 if (image && image->data) { 1006 unsigned char *srcPtr = ((unsigned char*) image->data) 1007 + (y * image->bytes_per_line) 1008 + (((image->xoffset + x) * image->bits_per_pixel) / NBBY); 1009 1010 switch (image->bits_per_pixel) { 1011 case 32: { 1012 r = (*((unsigned int*) srcPtr) >> 16) & 0xff; 1013 g = (*((unsigned int*) srcPtr) >> 8) & 0xff; 1014 b = (*((unsigned int*) srcPtr) ) & 0xff; 1015 /*if (image->byte_order == LSBFirst) { 1016 r = srcPtr[2]; g = srcPtr[1]; b = srcPtr[0]; 1017 } else { 1018 r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3]; 1019 }*/ 1020 break; 1021 } 1022 case 16: 1023 r = (*((unsigned short*) srcPtr) >> 7) & 0xf8; 1024 g = (*((unsigned short*) srcPtr) >> 2) & 0xf8; 1025 b = (*((unsigned short*) srcPtr) << 3) & 0xf8; 1026 break; 1027 case 8: 1028 r = (*srcPtr << 2) & 0xc0; 1029 g = (*srcPtr << 4) & 0xc0; 1030 b = (*srcPtr << 6) & 0xc0; 1031 r |= r >> 2 | r >> 4 | r >> 6; 1032 g |= g >> 2 | g >> 4 | g >> 6; 1033 b |= b >> 2 | b >> 4 | b >> 6; 1034 break; 1035 case 4: { 1036 unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4); 1037 r = (c & 0x04) ? 0xff : 0; 1038 g = (c & 0x02) ? 0xff : 0; 1039 b = (c & 0x01) ? 0xff : 0; 1040 break; 1041 } 1042 case 1: 1043 r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0; 1044 break; 1045 } 1046 } 1047 return (PIXEL_MAGIC << 24) | (r << 16) | (g << 8) | b; 1048} 1049 1050/* 1051 *---------------------------------------------------------------------- 1052 * 1053 * ImagePutPixel -- 1054 * 1055 * Set a single pixel in an image. 1056 * 1057 * Results: 1058 * None. 1059 * 1060 * Side effects: 1061 * None. 1062 * 1063 *---------------------------------------------------------------------- 1064 */ 1065 1066static int 1067ImagePutPixel( 1068 XImage *image, 1069 int x, 1070 int y, 1071 unsigned long pixel) 1072{ 1073 if (image && image->data) { 1074 unsigned char r = ((pixel & image->red_mask) >> 16) & 0xff; 1075 unsigned char g = ((pixel & image->green_mask) >> 8) & 0xff; 1076 unsigned char b = ((pixel & image->blue_mask) ) & 0xff; 1077 unsigned char *dstPtr = ((unsigned char*) image->data) 1078 + (y * image->bytes_per_line) 1079 + (((image->xoffset + x) * image->bits_per_pixel) / NBBY); 1080 1081 switch (image->bits_per_pixel) { 1082 case 32: 1083 *((unsigned int*) dstPtr) = (0xff << 24) | (r << 16) | 1084 (g << 8) | b; 1085 /*if (image->byte_order == LSBFirst) { 1086 dstPtr[3] = 0xff; dstPtr[2] = r; dstPtr[1] = g; dstPtr[0] = b; 1087 } else { 1088 dstPtr[0] = 0xff; dstPtr[1] = r; dstPtr[2] = g; dstPtr[3] = b; 1089 }*/ 1090 break; 1091 case 16: 1092 *((unsigned short*) dstPtr) = ((r & 0xf8) << 7) | 1093 ((g & 0xf8) << 2) | ((b & 0xf8) >> 3); 1094 break; 1095 case 8: 1096 *dstPtr = ((r & 0xc0) >> 2) | ((g & 0xc0) >> 4) | 1097 ((b & 0xc0) >> 6); 1098 break; 1099 case 4: { 1100 unsigned char c = ((r & 0x80) >> 5) | ((g & 0x80) >> 6) | 1101 ((b & 0x80) >> 7); 1102 *dstPtr = (x % 2) ? ((*dstPtr & 0xf0) | (c & 0x0f)) : 1103 ((*dstPtr & 0x0f) | ((c << 4) & 0xf0)); 1104 break; 1105 } 1106 case 1: 1107 *dstPtr = ((r|g|b) & 0x80) ? (*dstPtr | (0x80 >> (x % 8))) : 1108 (*dstPtr & ~(0x80 >> (x % 8))); 1109 break; 1110 } 1111 } 1112 return 0; 1113} 1114 1115/* 1116 *---------------------------------------------------------------------- 1117 * 1118 * XChangeWindowAttributes, XSetWindowBackground, 1119 * XSetWindowBackgroundPixmap, XSetWindowBorder, XSetWindowBorderPixmap, 1120 * XSetWindowBorderWidth, XSetWindowColormap 1121 * 1122 * These functions are all no-ops. They all have equivalent Tk calls that 1123 * should always be used instead. 1124 * 1125 * Results: 1126 * None. 1127 * 1128 * Side effects: 1129 * None. 1130 * 1131 *---------------------------------------------------------------------- 1132 */ 1133 1134void 1135XChangeWindowAttributes( 1136 Display *display, 1137 Window w, 1138 unsigned long value_mask, 1139 XSetWindowAttributes *attributes) 1140{ 1141} 1142 1143void 1144XSetWindowBackground( 1145 Display *display, 1146 Window window, 1147 unsigned long value) 1148{ 1149} 1150 1151void 1152XSetWindowBackgroundPixmap( 1153 Display *display, 1154 Window w, 1155 Pixmap background_pixmap) 1156{ 1157} 1158 1159void 1160XSetWindowBorder( 1161 Display *display, 1162 Window w, 1163 unsigned long border_pixel) 1164{ 1165} 1166 1167void 1168XSetWindowBorderPixmap( 1169 Display *display, 1170 Window w, 1171 Pixmap border_pixmap) 1172{ 1173} 1174 1175void 1176XSetWindowBorderWidth( 1177 Display *display, 1178 Window w, 1179 unsigned int width) 1180{ 1181} 1182 1183void 1184XSetWindowColormap( 1185 Display *display, 1186 Window w, 1187 Colormap colormap) 1188{ 1189 Debugger(); 1190} 1191 1192Status 1193XStringListToTextProperty( 1194 char **list, 1195 int count, 1196 XTextProperty *text_prop_return) 1197{ 1198 Debugger(); 1199 return (Status) 0; 1200} 1201 1202void 1203XSetWMClientMachine( 1204 Display *display, 1205 Window w, 1206 XTextProperty *text_prop) 1207{ 1208 Debugger(); 1209} 1210 1211XIC 1212XCreateIC(void) 1213{ 1214 Debugger(); 1215 return (XIC) 0; 1216} 1217 1218/* 1219 *---------------------------------------------------------------------- 1220 * 1221 * TkGetDefaultScreenName -- 1222 * 1223 * Returns the name of the screen that Tk should use during 1224 * initialization. 1225 * 1226 * Results: 1227 * Returns a statically allocated string. 1228 * 1229 * Side effects: 1230 * None. 1231 * 1232 *---------------------------------------------------------------------- 1233 */ 1234 1235const char * 1236TkGetDefaultScreenName( 1237 Tcl_Interp *interp, /* Not used. */ 1238 const char *screenName) /* If NULL, use default string. */ 1239{ 1240#if 0 1241 if ((screenName == NULL) || (screenName[0] == '\0')) { 1242 screenName = macScreenName; 1243 } 1244 return screenName; 1245#endif 1246 return macScreenName; 1247} 1248 1249/* 1250 *---------------------------------------------------------------------- 1251 * 1252 * Tk_GetUserInactiveTime -- 1253 * 1254 * Return the number of milliseconds the user was inactive. 1255 * 1256 * Results: 1257 * The number of milliseconds the user has been inactive, or -1 if 1258 * querying the inactive time is not supported. 1259 * 1260 * Side effects: 1261 * None. 1262 *---------------------------------------------------------------------- 1263 */ 1264 1265long 1266Tk_GetUserInactiveTime( 1267 Display *dpy) 1268{ 1269 io_registry_entry_t regEntry; 1270 CFMutableDictionaryRef props = NULL; 1271 CFTypeRef timeObj; 1272 long ret = -1l; 1273 uint64_t time; 1274 IOReturn result; 1275 1276 regEntry = IOServiceGetMatchingService(kIOMasterPortDefault, 1277 IOServiceMatching("IOHIDSystem")); 1278 1279 if (regEntry == 0) { 1280 return -1l; 1281 } 1282 1283 result = IORegistryEntryCreateCFProperties(regEntry, &props, 1284 kCFAllocatorDefault, 0); 1285 IOObjectRelease(regEntry); 1286 1287 if (result != KERN_SUCCESS || props == NULL) { 1288 return -1l; 1289 } 1290 1291 timeObj = CFDictionaryGetValue(props, CFSTR("HIDIdleTime")); 1292 1293 if (timeObj) { 1294 CFTypeID type = CFGetTypeID(timeObj); 1295 1296 if (type == CFDataGetTypeID()) { /* Jaguar */ 1297 CFDataGetBytes((CFDataRef) timeObj, 1298 CFRangeMake(0, sizeof(time)), (UInt8 *) &time); 1299 /* Convert nanoseconds to milliseconds. */ 1300 /* ret /= kMillisecondScale; */ 1301 ret = (long) (time/kMillisecondScale); 1302 } else if (type == CFNumberGetTypeID()) { /* Panther+ */ 1303 CFNumberGetValue((CFNumberRef)timeObj, 1304 kCFNumberSInt64Type, &time); 1305 /* Convert nanoseconds to milliseconds. */ 1306 /* ret /= kMillisecondScale; */ 1307 ret = (long) (time/kMillisecondScale); 1308 } else { 1309 ret = -1l; 1310 } 1311 } 1312 /* Cleanup */ 1313 CFRelease(props); 1314 1315 return ret; 1316} 1317 1318/* 1319 *---------------------------------------------------------------------- 1320 * 1321 * Tk_ResetUserInactiveTime -- 1322 * 1323 * Reset the user inactivity timer 1324 * 1325 * Results: 1326 * none 1327 * 1328 * Side effects: 1329 * The user inactivity timer of the underlaying windowing system is reset 1330 * to zero. 1331 * 1332 *---------------------------------------------------------------------- 1333 */ 1334 1335void 1336Tk_ResetUserInactiveTime( 1337 Display *dpy) 1338{ 1339 IOGPoint loc; 1340 kern_return_t kr; 1341 NXEvent nullEvent = {NX_NULLEVENT, {0, 0}, 0, -1, 0}; 1342 enum { kNULLEventPostThrottle = 10 }; 1343 static io_connect_t io_connection = MACH_PORT_NULL; 1344 1345 if (io_connection == MACH_PORT_NULL) { 1346 io_service_t service = IOServiceGetMatchingService( 1347 kIOMasterPortDefault, IOServiceMatching(kIOHIDSystemClass)); 1348 1349 if (service == MACH_PORT_NULL) { 1350 return; 1351 } 1352 kr = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, 1353 &io_connection); 1354 IOObjectRelease(service); 1355 if (kr != KERN_SUCCESS) { 1356 return; 1357 } 1358 } 1359 kr = IOHIDPostEvent(io_connection, NX_NULLEVENT, loc, &nullEvent.data, 1360 FALSE, 0, FALSE); 1361} 1362 1363/* 1364 * Local Variables: 1365 * mode: c 1366 * c-basic-offset: 4 1367 * fill-column: 79 1368 * coding: utf-8 1369 * End: 1370 */ 1371