1c041511dScube 2c041511dScube/* Copyright (c) Mark J. Kilgard, 1995, 1998. */ 3c041511dScube 4c041511dScube/* This program is freely distributable without licensing fees 5c041511dScube and is provided without guarantee or warrantee expressed or 6c041511dScube implied. This program is -not- in the public domain. */ 7c041511dScube 8c041511dScube#include "glutint.h" 9c041511dScube 10c041511dScube#if !defined(_WIN32) 11c041511dScube#include <X11/Xatom.h> /* For XA_CURSOR */ 12c041511dScube#include <X11/cursorfont.h> 13c041511dScube#endif 14c041511dScube 15c041511dScubetypedef struct _CursorTable { 16c041511dScube#if defined(_WIN32) 17c041511dScube char* glyph; 18c041511dScube#else 19c041511dScube int glyph; 20c041511dScube#endif 21c041511dScube Cursor cursor; 22c041511dScube} CursorTable; 23c041511dScube/* *INDENT-OFF* */ 24c041511dScube 25c041511dScubestatic CursorTable cursorTable[] = { 26c041511dScube {XC_arrow, None}, /* GLUT_CURSOR_RIGHT_ARROW */ 27c041511dScube {XC_top_left_arrow, None}, /* GLUT_CURSOR_LEFT_ARROW */ 28c041511dScube {XC_hand1, None}, /* GLUT_CURSOR_INFO */ 29c041511dScube {XC_pirate, None}, /* GLUT_CURSOR_DESTROY */ 30c041511dScube {XC_question_arrow, None}, /* GLUT_CURSOR_HELP */ 31c041511dScube {XC_exchange, None}, /* GLUT_CURSOR_CYCLE */ 32c041511dScube {XC_spraycan, None}, /* GLUT_CURSOR_SPRAY */ 33c041511dScube {XC_watch, None}, /* GLUT_CURSOR_WAIT */ 34c041511dScube {XC_xterm, None}, /* GLUT_CURSOR_TEXT */ 35c041511dScube {XC_crosshair, None}, /* GLUT_CURSOR_CROSSHAIR */ 36c041511dScube {XC_sb_v_double_arrow, None}, /* GLUT_CURSOR_UP_DOWN */ 37c041511dScube {XC_sb_h_double_arrow, None}, /* GLUT_CURSOR_LEFT_RIGHT */ 38c041511dScube {XC_top_side, None}, /* GLUT_CURSOR_TOP_SIDE */ 39c041511dScube {XC_bottom_side, None}, /* GLUT_CURSOR_BOTTOM_SIDE */ 40c041511dScube {XC_left_side, None}, /* GLUT_CURSOR_LEFT_SIDE */ 41c041511dScube {XC_right_side, None}, /* GLUT_CURSOR_RIGHT_SIDE */ 42c041511dScube {XC_top_left_corner, None}, /* GLUT_CURSOR_TOP_LEFT_CORNER */ 43c041511dScube {XC_top_right_corner, None}, /* GLUT_CURSOR_TOP_RIGHT_CORNER */ 44c041511dScube {XC_bottom_right_corner, None}, /* GLUT_CURSOR_BOTTOM_RIGHT_CORNER */ 45c041511dScube {XC_bottom_left_corner, None}, /* GLUT_CURSOR_BOTTOM_LEFT_CORNER */ 46c041511dScube}; 47c041511dScube/* *INDENT-ON* */ 48c041511dScube 49c041511dScube#if !defined(_WIN32) 50c041511dScubestatic Cursor blankCursor = None; 51c041511dScubestatic Cursor fullCrosshairCusor = None; 52c041511dScube 53c041511dScube/* SGI X server's support a special property called the 54c041511dScube _SGI_CROSSHAIR_CURSOR that when installed as a window's 55c041511dScube cursor, becomes a full screen crosshair cursor. SGI 56c041511dScube has special cursor generation hardware for this case. */ 57c041511dScubestatic Cursor 58c041511dScubegetFullCrosshairCursor(void) 59c041511dScube{ 60c041511dScube Cursor cursor; 61c041511dScube Atom crosshairAtom, actualType; 62c041511dScube int rc, actualFormat; 63c041511dScube unsigned long n, left; 64c041511dScube unsigned char *value; 65c041511dScube 66c041511dScube if (fullCrosshairCusor == None) { 67c041511dScube crosshairAtom = XInternAtom(__glutDisplay, 68c041511dScube "_SGI_CROSSHAIR_CURSOR", True); 69c041511dScube if (crosshairAtom != None) { 70c041511dScube value = 0; /* Make compiler happy. */ 71c041511dScube rc = XGetWindowProperty(__glutDisplay, __glutRoot, 72c041511dScube crosshairAtom, 0, 1, False, XA_CURSOR, &actualType, 73c041511dScube &actualFormat, &n, &left, &value); 74c041511dScube if (rc == Success && actualFormat == 32 && n >= 1) { 75c041511dScube cursor = ((unsigned long *)value)[0]; 76c041511dScube XFree(value); 77c041511dScube return cursor; 78c041511dScube } 79c041511dScube } 80c041511dScube } 81c041511dScube return XCreateFontCursor(__glutDisplay, XC_crosshair); 82c041511dScube} 83c041511dScube 84c041511dScube/* X11 forces you to create a blank cursor if you want 85c041511dScube to disable the cursor. */ 86c041511dScubestatic Cursor 87c041511dScubemakeBlankCursor(void) 88c041511dScube{ 89c041511dScube static char data[1] = 90c041511dScube {0}; 91c041511dScube Cursor cursor; 92c041511dScube Pixmap blank; 93c041511dScube XColor dummy; 94c041511dScube 95c041511dScube blank = XCreateBitmapFromData(__glutDisplay, __glutRoot, 96c041511dScube data, 1, 1); 97c041511dScube if (blank == None) 98c041511dScube __glutFatalError("out of memory."); 99c041511dScube cursor = XCreatePixmapCursor(__glutDisplay, blank, blank, 100c041511dScube &dummy, &dummy, 0, 0); 101c041511dScube XFreePixmap(__glutDisplay, blank); 102c041511dScube 103c041511dScube return cursor; 104c041511dScube} 105c041511dScube#endif /* !_WIN32 */ 106c041511dScube 107c041511dScube/* Win32 and X11 use this same function to accomplish 108c041511dScube fairly different tasks. X11 lets you just define the 109c041511dScube cursor for a window and the window system takes care 110c041511dScube of making sure that the window's cursor is installed 111c041511dScube when the mouse is in the window. Win32 requires the 112c041511dScube application to handle a WM_SETCURSOR message to install 113c041511dScube the right cursor when windows are entered. Think of 114c041511dScube the Win32 __glutSetCursor (called from __glutWindowProc) 115c041511dScube as "install cursor". Think of the X11 __glutSetCursor 116c041511dScube (called from glutSetCursor) as "define cursor". */ 117c041511dScubevoid 118c041511dScube__glutSetCursor(GLUTwindow *window) 119c041511dScube{ 120c041511dScube int cursor = window->cursor; 121c041511dScube Cursor xcursor = 0; 122c041511dScube 123c041511dScube if (cursor >= 0 && 124c041511dScube cursor < sizeof(cursorTable) / sizeof(cursorTable[0])) { 125c041511dScube if (cursorTable[cursor].cursor == None) { 126c041511dScube cursorTable[cursor].cursor = XCreateFontCursor(__glutDisplay, 127c041511dScube cursorTable[cursor].glyph); 128c041511dScube } 129c041511dScube xcursor = cursorTable[cursor].cursor; 130c041511dScube } else { 131c041511dScube /* Special cases. */ 132c041511dScube switch (cursor) { 133c041511dScube case GLUT_CURSOR_INHERIT: 134c041511dScube#if defined(_WIN32) 135c041511dScube while (window->parent) { 136c041511dScube window = window->parent; 137c041511dScube if (window->cursor != GLUT_CURSOR_INHERIT) { 138c041511dScube __glutSetCursor(window); 139c041511dScube return; 140c041511dScube } 141c041511dScube } 142c041511dScube /* XXX Default to an arrow cursor. Is this 143c041511dScube right or should we be letting the default 144c041511dScube window proc be installing some system cursor? */ 145c041511dScube xcursor = cursorTable[0].cursor; 146c041511dScube if (xcursor == NULL) { 147c041511dScube xcursor = 148c041511dScube cursorTable[0].cursor = 149c041511dScube LoadCursor(NULL, cursorTable[0].glyph); 150c041511dScube } 151c041511dScube#else 152c041511dScube xcursor = None; 153c041511dScube#endif 154c041511dScube break; 155c041511dScube case GLUT_CURSOR_NONE: 156c041511dScube#if defined(_WIN32) 157c041511dScube xcursor = NULL; 158c041511dScube#else 159c041511dScube if (blankCursor == None) { 160c041511dScube blankCursor = makeBlankCursor(); 161c041511dScube } 162c041511dScube xcursor = blankCursor; 163c041511dScube#endif 164c041511dScube break; 165c041511dScube case GLUT_CURSOR_FULL_CROSSHAIR: 166c041511dScube#if defined(_WIN32) 167c041511dScube xcursor = (HICON) IDC_CROSS; 168c041511dScube#else 169c041511dScube if (fullCrosshairCusor == None) { 170c041511dScube fullCrosshairCusor = getFullCrosshairCursor(); 171c041511dScube } 172c041511dScube xcursor = fullCrosshairCusor; 173c041511dScube#endif 174c041511dScube break; 175c041511dScube } 176c041511dScube } 177c041511dScube XDefineCursor(__glutDisplay, 178c041511dScube window->win, xcursor); 179c041511dScube XFlush(__glutDisplay); 180c041511dScube} 181c041511dScube 182c041511dScube/* CENTRY */ 183c041511dScubevoid GLUTAPIENTRY 184c041511dScubeglutSetCursor(int cursor) 185c041511dScube{ 186c041511dScube#ifdef _WIN32 187c041511dScube POINT point; 188c041511dScube 189c041511dScube __glutCurrentWindow->cursor = cursor; 190c041511dScube /* Are we in the window right now? If so, 191c041511dScube install the cursor. */ 192c041511dScube GetCursorPos(&point); 193c041511dScube if (__glutCurrentWindow->win == WindowFromPoint(point)) { 194c041511dScube __glutSetCursor(__glutCurrentWindow); 195c041511dScube } 196c041511dScube#else 197c041511dScube __glutCurrentWindow->cursor = cursor; 198c041511dScube __glutSetCursor(__glutCurrentWindow); 199c041511dScube#endif 200c041511dScube} 201c041511dScube/* ENDCENTRY */ 202