diff options
Diffstat (limited to 'carbon/tkMacOSXCursor.c')
-rw-r--r-- | carbon/tkMacOSXCursor.c | 487 |
1 files changed, 487 insertions, 0 deletions
diff --git a/carbon/tkMacOSXCursor.c b/carbon/tkMacOSXCursor.c new file mode 100644 index 0000000..c465764 --- /dev/null +++ b/carbon/tkMacOSXCursor.c @@ -0,0 +1,487 @@ +/* + * tkMacOSXCursor.c -- + * + * This file contains Macintosh specific cursor related routines. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006-2007 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" + +/* + * There are three different ways to set the cursor on the Mac. The default + * theme cursors (listed in cursorNames below), color resource cursors, & + * normal cursors. + */ + +#define NONE -1 /* Hidden cursor */ +#define THEME 0 /* Theme cursors */ +#define ANIMATED 1 /* Animated theme cursors */ +#define COLOR 2 /* Cursors of type crsr. */ +#define NORMAL 3 /* Cursors of type CURS. */ + +/* + * 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 */ + Handle macCursor; /* Resource containing Macintosh cursor. For + * theme cursors, this is -1. */ + int type; /* Type of Mac cursor: for theme cursors this + * is the theme cursor constant, otherwise one + * of crsr or CURS. */ + int count; /* For animating cursors, the count for the + * cursor. */ +} TkMacOSXCursor; + +/* + * The table below is used to map from the name of a predefined cursor + * to its resource identifier. + */ + +struct CursorName { + const char *name; + int id; +}; + +static struct CursorName noneCursorName = {"none", 0}; + +static struct CursorName themeCursorNames[] = { + {"arrow", kThemeArrowCursor}, + {"copyarrow", kThemeCopyArrowCursor}, + {"aliasarrow", kThemeAliasArrowCursor}, + {"contextualmenuarrow", kThemeContextualMenuArrowCursor}, + {"ibeam", kThemeIBeamCursor}, + {"text", kThemeIBeamCursor}, + {"xterm", kThemeIBeamCursor}, + {"cross", kThemeCrossCursor}, + {"crosshair", kThemeCrossCursor}, + {"cross-hair", kThemeCrossCursor}, + {"plus", kThemePlusCursor}, + {"closedhand", kThemeClosedHandCursor}, + {"openhand", kThemeOpenHandCursor}, + {"pointinghand", kThemePointingHandCursor}, + {"resizeleft", kThemeResizeLeftCursor}, + {"resizeright", kThemeResizeRightCursor}, + {"resizeleftright", kThemeResizeLeftRightCursor}, + {"resizeup", kThemeResizeUpCursor}, + {"resizedown", kThemeResizeDownCursor}, + {"resizeupdown", kThemeResizeUpDownCursor}, + {"notallowed", kThemeNotAllowedCursor}, + {"poof", kThemePoofCursor}, + {NULL, 0} +}; + +static struct CursorName animatedThemeCursorNames[] = { + {"watch", kThemeWatchCursor}, + {"countinguphand", kThemeCountingUpHandCursor}, + {"countingdownhand", kThemeCountingDownHandCursor}, + {"countingupanddownhand", kThemeCountingUpAndDownHandCursor}, + {"spinning", kThemeSpinningCursor}, + {NULL, 0} +}; + +/* + * 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 + * NULL. The function first attempts to load a color cursor. If that + * fails it will attempt to load a black & white cursor. + * + * Results: + * Fills the macCursorPtr record. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +FindCursorByName( + TkMacOSXCursor *macCursorPtr, + const char *string) +{ + Handle resource; + Str255 curName; + int destWrote, inCurLen; + Tcl_Encoding encoding; + + inCurLen = strlen(string); + if (inCurLen > 255) { + return; + } + + /* + * macRoman is the encoding that the resource fork uses. + */ + + encoding = Tcl_GetEncoding(NULL, "macRoman"); + Tcl_UtfToExternal(NULL, encoding, string, inCurLen, 0, NULL, + (char *) &curName[1], 255, NULL, &destWrote, NULL); + curName[0] = destWrote; + Tcl_FreeEncoding(encoding); + + resource = GetNamedResource('crsr', curName); + if (resource) { + short id; + Str255 theName; + ResType theType; + + GetResInfo(resource, &id, &theType, theName); + macCursorPtr->macCursor = (Handle) GetCCursor(id); + macCursorPtr->type = COLOR; + } else { + macCursorPtr->macCursor = GetNamedResource('CURS', curName); + macCursorPtr->type = NORMAL; + } +} + +/* + *---------------------------------------------------------------------- + * + * 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. */ +{ + struct CursorName *namePtr; + TkMacOSXCursor *macCursorPtr; + int count = -1; + + macCursorPtr = ckalloc(sizeof(TkMacOSXCursor)); + macCursorPtr->info.cursor = (Tk_Cursor) macCursorPtr; + + /* + * To find a cursor we must first determine if it is one of the builtin + * cursors or the standard arrow cursor. Otherwise, we attempt to load the + * cursor as a named Mac resource. + */ + + if (strcmp(noneCursorName.name, string) == 0) { + namePtr = &noneCursorName; + macCursorPtr->type = NONE; + } else { + for (namePtr = themeCursorNames; namePtr->name != NULL; namePtr++) { + if (strcmp(namePtr->name, string) == 0) { + macCursorPtr->type = THEME; + break; + } + } + } + + if (namePtr->name == NULL) { + for (namePtr = animatedThemeCursorNames; + namePtr->name != NULL; namePtr++) { + int namelen = strlen(namePtr->name); + + if (strncmp(namePtr->name, string, namelen) == 0) { + const char *numPtr = string + namelen; + + if (*numPtr) { + int result = Tcl_GetInt(NULL, numPtr, &count); + + if (result != TCL_OK) { + continue; + } + } + macCursorPtr->type = ANIMATED; + break; + } + } + } + + if (namePtr->name != NULL) { + macCursorPtr->macCursor = (Handle) namePtr; + macCursorPtr->count = count; + } else { + FindCursorByName(macCursorPtr, string); + + if (macCursorPtr->macCursor == NULL) { + const char **argv; + int argc; + + /* + * The user may be trying to specify an XCursor with fore & back + * colors. We don't want this to be an error, so pick off the + * first word, and try again. + */ + + if (Tcl_SplitList(interp, string, &argc, &argv) == TCL_OK ) { + if (argc > 1) { + FindCursorByName(macCursorPtr, argv[0]); + } + ckfree(argv); + } + } + } + + if (macCursorPtr->macCursor == NULL) { + ckfree(macCursorPtr); + Tcl_AppendResult(interp, "bad cursor spec \"", string, "\"", NULL); + return 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; + + switch (macCursorPtr->type) { + case COLOR: + DisposeCCursor((CCrsrHandle) macCursorPtr->macCursor); + break; + case NORMAL: + ReleaseResource(macCursorPtr->macCursor); + break; + } + + 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; + CCrsrHandle ccursor; + CursHandle cursor; + static unsigned int cursorStep = 0; + static int cursorHidden = 0; + int cursorNone = 0; + + gResizeOverride = resizeOverride; + + if (resizeOverride) { + cursor = (CursHandle) GetNamedResource('CURS', "\presize"); + if (cursor) { + SetCursor(*cursor); + } else { + TkMacOSXDbgMsg("Resize cursor failed: %d", ResError()); + } + } else if (macCursorPtr == NULL) { + SetThemeCursor(kThemeArrowCursor); + } else { + struct CursorName *namePtr; + + switch (macCursorPtr->type) { + case NONE: + if (!cursorHidden) { + cursorHidden = 1; + HideCursor(); + } + cursorNone = 1; + break; + case THEME: + namePtr = (struct CursorName *) macCursorPtr->macCursor; + SetThemeCursor(namePtr->id); + break; + case ANIMATED: + namePtr = (struct CursorName *) macCursorPtr->macCursor; + if (macCursorPtr->count == -1) { + SetAnimatedThemeCursor(namePtr->id, cursorStep++); + } else { + SetAnimatedThemeCursor(namePtr->id, macCursorPtr->count); + } + break; + case COLOR: + ccursor = (CCrsrHandle) macCursorPtr->macCursor; + SetCCursor(ccursor); + break; + case NORMAL: + cursor = (CursHandle) macCursorPtr->macCursor; + SetCursor(*cursor); + break; + } + } + if (cursorHidden && !cursorNone) { + cursorHidden = 0; + ShowCursor(); + } +} + +/* + *---------------------------------------------------------------------- + * + * 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; +} |