diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2018-01-02 21:03:49 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2018-01-02 21:03:49 (GMT) |
commit | 914501b5b992e7b6c7e0a4c958712a8ba9cab41c (patch) | |
tree | edbc059b9557d5fdb79e5a5c47889bc54708da53 /tk8.6/macosx/tkMacOSXCursor.c | |
parent | f88c190a01bc7f57e79dfaf91a3c0c48c2031549 (diff) | |
download | blt-914501b5b992e7b6c7e0a4c958712a8ba9cab41c.zip blt-914501b5b992e7b6c7e0a4c958712a8ba9cab41c.tar.gz blt-914501b5b992e7b6c7e0a4c958712a8ba9cab41c.tar.bz2 |
upgrade to tcl/tk 8.6.8
Diffstat (limited to 'tk8.6/macosx/tkMacOSXCursor.c')
-rw-r--r-- | tk8.6/macosx/tkMacOSXCursor.c | 595 |
1 files changed, 595 insertions, 0 deletions
diff --git a/tk8.6/macosx/tkMacOSXCursor.c b/tk8.6/macosx/tkMacOSXCursor.c new file mode 100644 index 0000000..b6394b7 --- /dev/null +++ b/tk8.6/macosx/tkMacOSXCursor.c @@ -0,0 +1,595 @@ +/* + * tkMacOSXCursor.c -- + * + * This file contains Macintosh specific cursor related routines. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001-2009, Apple Inc. + * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net> + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tkMacOSXPrivate.h" +#include "tkMacOSXCursors.h" +#include "tkMacOSXXCursors.h" + +/* + * Mac Cursor Types. + */ + +#define NONE -1 /* Hidden cursor */ +#define SELECTOR 1 /* NSCursor class method */ +#define IMAGENAMED 2 /* Named NSImage */ +#define IMAGEPATH 3 /* Path to NSImage */ +#define IMAGEBITMAP 4 /* Pointer to 16x16 cursor bitmap data */ + +#define pix 16 /* Pixel width & height of cursor bitmap data */ + +/* + * The following data structure contains the system specific data necessary to + * control Windows cursors. + */ + +typedef struct { + TkCursor info; /* Generic cursor info used by tkCursor.c */ + NSCursor *macCursor; /* Macintosh cursor */ + int type; /* Type of Mac cursor */ +} TkMacOSXCursor; + +/* + * The table below is used to map from the name of a predefined cursor + * to a NSCursor. + */ + +struct CursorName { + const char *name; + const int kind; + id id1, id2; + NSPoint hotspot; +}; + +#define MacCursorData(n) ((id)tkMacOSXCursors[TK_MAC_CURSOR_##n]) +#define MacXCursorData(n) ((id)tkMacOSXXCursors[TK_MAC_XCURSOR_##n]) + +static const struct CursorName cursorNames[] = { + {"none", NONE, nil}, + {"arrow", SELECTOR, @"arrowCursor"}, + {"top_left_arrow", SELECTOR, @"arrowCursor"}, + {"left_ptr", SELECTOR, @"arrowCursor"}, + {"copyarrow", SELECTOR, @"dragCopyCursor", @"_copyDragCursor"}, + {"aliasarrow", SELECTOR, @"dragLinkCursor", @"_linkDragCursor"}, + {"contextualmenuarrow", SELECTOR, @"contextualMenuCursor"}, + {"movearrow", SELECTOR, @"_moveCursor"}, + {"ibeam", SELECTOR, @"IBeamCursor"}, + {"text", SELECTOR, @"IBeamCursor"}, + {"xterm", SELECTOR, @"IBeamCursor"}, + {"cross", SELECTOR, @"crosshairCursor"}, + {"crosshair", SELECTOR, @"crosshairCursor"}, + {"cross-hair", SELECTOR, @"crosshairCursor"}, + {"tcross", SELECTOR, @"crosshairCursor"}, + {"hand", SELECTOR, @"openHandCursor"}, + {"openhand", SELECTOR, @"openHandCursor"}, + {"closedhand", SELECTOR, @"closedHandCursor"}, + {"fist", SELECTOR, @"closedHandCursor"}, + {"pointinghand", SELECTOR, @"pointingHandCursor"}, + {"resize", SELECTOR, @"arrowCursor"}, + {"resizeleft", SELECTOR, @"resizeLeftCursor"}, + {"resizeright", SELECTOR, @"resizeRightCursor"}, + {"resizeleftright", SELECTOR, @"resizeLeftRightCursor"}, + {"resizeup", SELECTOR, @"resizeUpCursor"}, + {"resizedown", SELECTOR, @"resizeDownCursor"}, + {"resizeupdown", SELECTOR, @"resizeUpDownCursor"}, + {"resizebottomleft", SELECTOR, @"_bottomLeftResizeCursor"}, + {"resizetopleft", SELECTOR, @"_topLeftResizeCursor"}, + {"resizebottomright", SELECTOR, @"_bottomRightResizeCursor"}, + {"resizetopright", SELECTOR, @"_topRightResizeCursor"}, + {"notallowed", SELECTOR, @"operationNotAllowedCursor"}, + {"poof", SELECTOR, @"disappearingItemCursor"}, + {"wait", SELECTOR, @"busyButClickableCursor"}, + {"spinning", SELECTOR, @"busyButClickableCursor"}, + {"countinguphand", SELECTOR, @"busyButClickableCursor"}, + {"countingdownhand", SELECTOR, @"busyButClickableCursor"}, + {"countingupanddownhand", SELECTOR, @"busyButClickableCursor"}, + {"help", IMAGENAMED, @"NSHelpCursor", nil, {8, 8}}, +// {"hand", IMAGEBITMAP, MacCursorData(hand)}, + {"bucket", IMAGEBITMAP, MacCursorData(bucket)}, + {"cancel", IMAGEBITMAP, MacCursorData(cancel)}, +// {"resize", IMAGEBITMAP, MacCursorData(resize)}, + {"eyedrop", IMAGEBITMAP, MacCursorData(eyedrop)}, + {"eyedrop-full", IMAGEBITMAP, MacCursorData(eyedrop_full)}, + {"zoom-in", IMAGEBITMAP, MacCursorData(zoom_in)}, + {"zoom-out", IMAGEBITMAP, MacCursorData(zoom_out)}, + {"X_cursor", IMAGEBITMAP, MacXCursorData(X_cursor)}, +// {"arrow", IMAGEBITMAP, MacXCursorData(arrow)}, + {"based_arrow_down", IMAGEBITMAP, MacXCursorData(based_arrow_down)}, + {"based_arrow_up", IMAGEBITMAP, MacXCursorData(based_arrow_up)}, + {"boat", IMAGEBITMAP, MacXCursorData(boat)}, + {"bogosity", IMAGEBITMAP, MacXCursorData(bogosity)}, + {"bottom_left_corner", IMAGEBITMAP, MacXCursorData(bottom_left_corner)}, + {"bottom_right_corner", IMAGEBITMAP, MacXCursorData(bottom_right_corner)}, + {"bottom_side", IMAGEBITMAP, MacXCursorData(bottom_side)}, + {"bottom_tee", IMAGEBITMAP, MacXCursorData(bottom_tee)}, + {"box_spiral", IMAGEBITMAP, MacXCursorData(box_spiral)}, + {"center_ptr", IMAGEBITMAP, MacXCursorData(center_ptr)}, + {"circle", IMAGEBITMAP, MacXCursorData(circle)}, + {"clock", IMAGEBITMAP, MacXCursorData(clock)}, + {"coffee_mug", IMAGEBITMAP, MacXCursorData(coffee_mug)}, +// {"cross", IMAGEBITMAP, MacXCursorData(cross)}, + {"cross_reverse", IMAGEBITMAP, MacXCursorData(cross_reverse)}, +// {"crosshair", IMAGEBITMAP, MacXCursorData(crosshair)}, + {"diamond_cross", IMAGEBITMAP, MacXCursorData(diamond_cross)}, + {"dot", IMAGEBITMAP, MacXCursorData(dot)}, + {"dotbox", IMAGEBITMAP, MacXCursorData(dotbox)}, + {"double_arrow", IMAGEBITMAP, MacXCursorData(double_arrow)}, + {"draft_large", IMAGEBITMAP, MacXCursorData(draft_large)}, + {"draft_small", IMAGEBITMAP, MacXCursorData(draft_small)}, + {"draped_box", IMAGEBITMAP, MacXCursorData(draped_box)}, + {"exchange", IMAGEBITMAP, MacXCursorData(exchange)}, + {"fleur", IMAGEBITMAP, MacXCursorData(fleur)}, + {"gobbler", IMAGEBITMAP, MacXCursorData(gobbler)}, + {"gumby", IMAGEBITMAP, MacXCursorData(gumby)}, + {"hand1", IMAGEBITMAP, MacXCursorData(hand1)}, + {"hand2", IMAGEBITMAP, MacXCursorData(hand2)}, + {"heart", IMAGEBITMAP, MacXCursorData(heart)}, + {"icon", IMAGEBITMAP, MacXCursorData(icon)}, + {"iron_cross", IMAGEBITMAP, MacXCursorData(iron_cross)}, +// {"left_ptr", IMAGEBITMAP, MacXCursorData(left_ptr)}, + {"left_side", IMAGEBITMAP, MacXCursorData(left_side)}, + {"left_tee", IMAGEBITMAP, MacXCursorData(left_tee)}, + {"leftbutton", IMAGEBITMAP, MacXCursorData(leftbutton)}, + {"ll_angle", IMAGEBITMAP, MacXCursorData(ll_angle)}, + {"lr_angle", IMAGEBITMAP, MacXCursorData(lr_angle)}, + {"man", IMAGEBITMAP, MacXCursorData(man)}, + {"middlebutton", IMAGEBITMAP, MacXCursorData(middlebutton)}, + {"mouse", IMAGEBITMAP, MacXCursorData(mouse)}, + {"pencil", IMAGEBITMAP, MacXCursorData(pencil)}, + {"pirate", IMAGEBITMAP, MacXCursorData(pirate)}, + {"plus", IMAGEBITMAP, MacXCursorData(plus)}, + {"question_arrow", IMAGEBITMAP, MacXCursorData(question_arrow)}, + {"right_ptr", IMAGEBITMAP, MacXCursorData(right_ptr)}, + {"right_side", IMAGEBITMAP, MacXCursorData(right_side)}, + {"right_tee", IMAGEBITMAP, MacXCursorData(right_tee)}, + {"rightbutton", IMAGEBITMAP, MacXCursorData(rightbutton)}, + {"rtl_logo", IMAGEBITMAP, MacXCursorData(rtl_logo)}, + {"sailboat", IMAGEBITMAP, MacXCursorData(sailboat)}, + {"sb_down_arrow", IMAGEBITMAP, MacXCursorData(sb_down_arrow)}, + {"sb_h_double_arrow", IMAGEBITMAP, MacXCursorData(sb_h_double_arrow)}, + {"sb_left_arrow", IMAGEBITMAP, MacXCursorData(sb_left_arrow)}, + {"sb_right_arrow", IMAGEBITMAP, MacXCursorData(sb_right_arrow)}, + {"sb_up_arrow", IMAGEBITMAP, MacXCursorData(sb_up_arrow)}, + {"sb_v_double_arrow", IMAGEBITMAP, MacXCursorData(sb_v_double_arrow)}, + {"shuttle", IMAGEBITMAP, MacXCursorData(shuttle)}, + {"sizing", IMAGEBITMAP, MacXCursorData(sizing)}, + {"spider", IMAGEBITMAP, MacXCursorData(spider)}, + {"spraycan", IMAGEBITMAP, MacXCursorData(spraycan)}, + {"star", IMAGEBITMAP, MacXCursorData(star)}, + {"target", IMAGEBITMAP, MacXCursorData(target)}, +// {"tcross", IMAGEBITMAP, MacXCursorData(tcross)}, +// {"top_left_arrow", IMAGEBITMAP, MacXCursorData(top_left_arrow)}, + {"top_left_corner", IMAGEBITMAP, MacXCursorData(top_left_corner)}, + {"top_right_corner", IMAGEBITMAP, MacXCursorData(top_right_corner)}, + {"top_side", IMAGEBITMAP, MacXCursorData(top_side)}, + {"top_tee", IMAGEBITMAP, MacXCursorData(top_tee)}, + {"trek", IMAGEBITMAP, MacXCursorData(trek)}, + {"ul_angle", IMAGEBITMAP, MacXCursorData(ul_angle)}, + {"umbrella", IMAGEBITMAP, MacXCursorData(umbrella)}, + {"ur_angle", IMAGEBITMAP, MacXCursorData(ur_angle)}, + {"watch", IMAGEBITMAP, MacXCursorData(watch)}, +// {"xterm", IMAGEBITMAP, MacXCursorData(xterm)}, + {NULL} +}; + +/* + * Declarations of static variables used in this file. + */ + +static TkMacOSXCursor * gCurrentCursor = NULL; + /* A pointer to the current cursor. */ +static int gResizeOverride = false; + /* A boolean indicating whether we should use + * the resize cursor during installations. */ +static int gTkOwnsCursor = true;/* A boolean indicating whether Tk owns the + * cursor. If not (for instance, in the case + * where a Tk window is embedded in another + * app's window, and the cursor is out of the + * tk window, we will not attempt to adjust + * the cursor. */ + +/* + * Declarations of procedures local to this file + */ + +static void FindCursorByName(TkMacOSXCursor *macCursorPtr, const char *string); + +/* + *---------------------------------------------------------------------- + * + * FindCursorByName -- + * + * Retrieve a system cursor by name, and fill the macCursorPtr + * structure. If the cursor cannot be found, the macCursor field + * will be nil. + * + * Results: + * Fills the macCursorPtr record. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +FindCursorByName( + TkMacOSXCursor *macCursorPtr, + const char *name) +{ + NSString *path = nil; + NSImage *image = nil; + NSPoint hotSpot = NSZeroPoint; + int haveHotSpot = 0, result = TCL_ERROR; + NSCursor *macCursor = nil; + + if (name[0] == '@') { + /* + * System cursor of type @filename + */ + + macCursorPtr->type = IMAGEPATH; + path = [NSString stringWithUTF8String:&name[1]]; + } else { + Tcl_Obj *strPtr = Tcl_NewStringObj(name, -1); + int idx; + + result = Tcl_GetIndexFromObjStruct(NULL, strPtr, cursorNames, + sizeof(struct CursorName), NULL, TCL_EXACT, &idx); + Tcl_DecrRefCount(strPtr); + if (result == TCL_OK) { + macCursorPtr->type = cursorNames[idx].kind; + switch (cursorNames[idx].kind) { + case SELECTOR: { + SEL selector = NSSelectorFromString(cursorNames[idx].id1); + if ([NSCursor respondsToSelector:selector]) { + macCursor = [[NSCursor performSelector:selector] retain]; + } else if (cursorNames[idx].id2) { + selector = NSSelectorFromString(cursorNames[idx].id2); + if ([NSCursor respondsToSelector:selector]) { + macCursor = [[NSCursor performSelector:selector] retain]; + } + } + break; + } + case IMAGENAMED: + image = [[NSImage imageNamed:cursorNames[idx].id1] retain]; + hotSpot = cursorNames[idx].hotspot; + haveHotSpot = 1; + break; + case IMAGEPATH: + path = [NSApp tkFrameworkImagePath:cursorNames[idx].id1]; + break; + case IMAGEBITMAP: { + unsigned char *bitmap = (unsigned char *)(cursorNames[idx].id1); + NSBitmapImageRep *bitmapImageRep = NULL; + CGImageRef img = NULL, mask = NULL, maskedImg = NULL; + static const CGFloat decodeWB[] = {1, 0}; + CGColorSpaceRef colorspace = CGColorSpaceCreateWithName( + kCGColorSpaceGenericGray); + CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, + bitmap, pix*pix/8, NULL); + if (provider) { + img = CGImageCreate(pix, pix, 1, 1, pix/8, colorspace, + kCGBitmapByteOrderDefault, provider, decodeWB, 0, + kCGRenderingIntentDefault); + CFRelease(provider); + } + provider = CGDataProviderCreateWithData(NULL, bitmap + + pix*pix/8, pix*pix/8, NULL); + if (provider) { + mask = CGImageMaskCreate(pix, pix, 1, 1, pix/8, provider, + decodeWB, 0); + CFRelease(provider); + } + if (img && mask) { + maskedImg = CGImageCreateWithMask(img, mask); + } + if (maskedImg) { + bitmapImageRep = [[NSBitmapImageRep alloc] + initWithCGImage:maskedImg]; + CFRelease(maskedImg); + } + if (mask) { CFRelease(mask); } + if (img) { CFRelease(img); } + if (colorspace) { CFRelease(colorspace); } + if (bitmapImageRep) { + image = [[NSImage alloc] initWithSize:NSMakeSize(pix, pix)]; + [image addRepresentation:bitmapImageRep]; + [bitmapImageRep release]; + } + uint16_t *hotSpotData = (uint16_t*)(bitmap + 2*pix*pix/8); + hotSpot.y = CFSwapInt16BigToHost(*hotSpotData++); + hotSpot.x = CFSwapInt16BigToHost(*hotSpotData); + haveHotSpot = 1; + break; + } + } + } + } + if (path) { + image = [[NSImage alloc] initWithContentsOfFile:path]; + } + if (!image && !macCursor && result != TCL_OK) { + macCursorPtr->type = IMAGENAMED; + image = [[NSImage imageNamed:[NSString stringWithUTF8String:name]] + retain]; + haveHotSpot = 0; + } + if (image) { + if (!haveHotSpot && [[path pathExtension] isEqualToString:@"cur"]) { + NSData *data = [NSData dataWithContentsOfFile:path]; + if ([data length] > 14) { + uint16_t *hotSpotData = (uint16_t*)((char*) [data bytes] + 10); + hotSpot.x = CFSwapInt16LittleToHost(*hotSpotData++); + hotSpot.y = CFSwapInt16LittleToHost(*hotSpotData); + haveHotSpot = 1; + } + } + if (!haveHotSpot) { + NSSize size = [image size]; + hotSpot.x = size.width * 0.5; + hotSpot.y = size.height * 0.5; + } + hotSpot.y = -hotSpot.y; + macCursor = [[NSCursor alloc] initWithImage:image hotSpot:hotSpot]; + [image release]; + } + macCursorPtr->macCursor = macCursor; +} + +/* + *---------------------------------------------------------------------- + * + * TkGetCursorByName -- + * + * Retrieve a system cursor by name. + * + * Results: + * Returns a new cursor, or NULL on errors. + * + * Side effects: + * Allocates a new cursor. + * + *---------------------------------------------------------------------- + */ + +TkCursor * +TkGetCursorByName( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tk_Window tkwin, /* Window in which cursor will be used. */ + Tk_Uid string) /* Description of cursor. See manual entry + * for details on legal syntax. */ +{ + TkMacOSXCursor *macCursorPtr = NULL; + const char **argv = NULL; + int argc; + + /* + * All cursor names are valid lists of one element (for + * TkX11-compatibility), even unadorned system cursor names. + */ + + if (Tcl_SplitList(interp, string, &argc, &argv) == TCL_OK) { + if (argc) { + macCursorPtr = ckalloc(sizeof(TkMacOSXCursor)); + macCursorPtr->info.cursor = (Tk_Cursor) macCursorPtr; + macCursorPtr->macCursor = nil; + macCursorPtr->type = 0; + FindCursorByName(macCursorPtr, argv[0]); + } + ckfree(argv); + } + if (!macCursorPtr || (!macCursorPtr->macCursor && + macCursorPtr->type != NONE)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "bad cursor spec \"%s\"", string)); + Tcl_SetErrorCode(interp, "TK", "VALUE", "CURSOR", NULL); + if (macCursorPtr) { + ckfree(macCursorPtr); + macCursorPtr = NULL; + } + } + return (TkCursor *) macCursorPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkCreateCursorFromData -- + * + * Creates a cursor from the source and mask bits. + * + * Results: + * Returns a new cursor, or NULL on errors. + * + * Side effects: + * Allocates a new cursor. + * + *---------------------------------------------------------------------- + */ + +TkCursor * +TkCreateCursorFromData( + Tk_Window tkwin, /* Window in which cursor will be used. */ + const char *source, /* Bitmap data for cursor shape. */ + const char *mask, /* Bitmap data for cursor mask. */ + int width, int height, /* Dimensions of cursor. */ + int xHot, int yHot, /* Location of hot-spot in cursor. */ + XColor fgColor, /* Foreground color for cursor. */ + XColor bgColor) /* Background color for cursor. */ +{ + return NULL; +} + +/* + *---------------------------------------------------------------------- + * + * TkpFreeCursor -- + * + * This procedure is called to release a cursor allocated by + * TkGetCursorByName. + * + * Results: + * None. + * + * Side effects: + * The cursor data structure is deallocated. + * + *---------------------------------------------------------------------- + */ + +void +TkpFreeCursor( + TkCursor *cursorPtr) +{ + TkMacOSXCursor *macCursorPtr = (TkMacOSXCursor *) cursorPtr; + + [macCursorPtr->macCursor release]; + macCursorPtr->macCursor = NULL; + if (macCursorPtr == gCurrentCursor) { + gCurrentCursor = NULL; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXInstallCursor -- + * + * Installs either the current cursor as defined by TkpSetCursor or a + * resize cursor as the cursor the Macintosh should currently display. + * + * Results: + * None. + * + * Side effects: + * Changes the Macintosh mouse cursor. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXInstallCursor( + int resizeOverride) +{ + TkMacOSXCursor *macCursorPtr = gCurrentCursor; + static int cursorHidden = 0; + int cursorNone = 0; + + gResizeOverride = resizeOverride; + + if (resizeOverride || !macCursorPtr) { + [[NSCursor arrowCursor] set]; + } else { + switch (macCursorPtr->type) { + case NONE: + if (!cursorHidden) { + cursorHidden = 1; + [NSCursor hide]; + } + cursorNone = 1; + break; + case SELECTOR: + case IMAGENAMED: + case IMAGEPATH: + case IMAGEBITMAP: + default: + [macCursorPtr->macCursor set]; + break; + } + } + if (cursorHidden && !cursorNone) { + cursorHidden = 0; + [NSCursor unhide]; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpSetCursor -- + * + * Set the current cursor and install it. + * + * Results: + * None. + * + * Side effects: + * Changes the current cursor. + * + *---------------------------------------------------------------------- + */ + +void +TkpSetCursor( + TkpCursor cursor) +{ + int cursorChanged = 1; + + if (!gTkOwnsCursor) { + return; + } + + if (cursor == None) { + /* + * This is a little tricky. We can't really tell whether + * gCurrentCursor is NULL because it was NULL last time around or + * because we just freed the current cursor. So if the input cursor is + * NULL, we always need to reset it, we can't trust the cursorChanged + * logic. + */ + + gCurrentCursor = NULL; + } else { + if (gCurrentCursor == (TkMacOSXCursor *) cursor) { + cursorChanged = 0; + } + gCurrentCursor = (TkMacOSXCursor *) cursor; + } + + if (Tk_MacOSXIsAppInFront() && cursorChanged) { + TkMacOSXInstallCursor(gResizeOverride); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tk_MacOSXTkOwnsCursor -- + * + * Sets whether Tk has the right to adjust the cursor. + * + * Results: + * None. + * + * Side effects: + * May keep Tk from changing the cursor. + * + *---------------------------------------------------------------------- + */ + +void +Tk_MacOSXTkOwnsCursor( + int tkOwnsIt) +{ + gTkOwnsCursor = tkOwnsIt; +} + +/* + * Local Variables: + * mode: objc + * c-basic-offset: 4 + * fill-column: 79 + * coding: utf-8 + * End: + */ |