#include "glutint.h"
#if !defined(_WIN32)
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#endif
typedef struct _CursorTable {
#if defined(_WIN32)
char* glyph;
#else
int glyph;
#endif
Cursor cursor;
} CursorTable;
static CursorTable cursorTable[] = {
{XC_arrow, None},
{XC_top_left_arrow, None},
{XC_hand1, None},
{XC_pirate, None},
{XC_question_arrow, None},
{XC_exchange, None},
{XC_spraycan, None},
{XC_watch, None},
{XC_xterm, None},
{XC_crosshair, None},
{XC_sb_v_double_arrow, None},
{XC_sb_h_double_arrow, None},
{XC_top_side, None},
{XC_bottom_side, None},
{XC_left_side, None},
{XC_right_side, None},
{XC_top_left_corner, None},
{XC_top_right_corner, None},
{XC_bottom_right_corner, None},
{XC_bottom_left_corner, None},
};
#if !defined(_WIN32)
static Cursor blankCursor = None;
static Cursor fullCrosshairCusor = None;
static Cursor
getFullCrosshairCursor(void)
{
Cursor cursor;
Atom crosshairAtom, actualType;
int rc, actualFormat;
unsigned long n, left;
unsigned char *value;
if (fullCrosshairCusor == None) {
crosshairAtom = XInternAtom(__glutDisplay,
"_SGI_CROSSHAIR_CURSOR", True);
if (crosshairAtom != None) {
value = 0;
rc = XGetWindowProperty(__glutDisplay, __glutRoot,
crosshairAtom, 0, 1, False, XA_CURSOR, &actualType,
&actualFormat, &n, &left, &value);
if (rc == Success && actualFormat == 32 && n >= 1) {
cursor = ((unsigned long *)value)[0];
XFree(value);
return cursor;
}
}
}
return XCreateFontCursor(__glutDisplay, XC_crosshair);
}
static Cursor
makeBlankCursor(void)
{
static char data[1] =
{0};
Cursor cursor;
Pixmap blank;
XColor dummy;
blank = XCreateBitmapFromData(__glutDisplay, __glutRoot,
data, 1, 1);
if (blank == None)
__glutFatalError("out of memory.");
cursor = XCreatePixmapCursor(__glutDisplay, blank, blank,
&dummy, &dummy, 0, 0);
XFreePixmap(__glutDisplay, blank);
return cursor;
}
#endif
void
__glutSetCursor(GLUTwindow *window)
{
int cursor = window->cursor;
Cursor xcursor = 0;
if (cursor >= 0 &&
cursor < sizeof(cursorTable) / sizeof(cursorTable[0])) {
if (cursorTable[cursor].cursor == None) {
cursorTable[cursor].cursor = XCreateFontCursor(__glutDisplay,
cursorTable[cursor].glyph);
}
xcursor = cursorTable[cursor].cursor;
} else {
switch (cursor) {
case GLUT_CURSOR_INHERIT:
#if defined(_WIN32)
while (window->parent) {
window = window->parent;
if (window->cursor != GLUT_CURSOR_INHERIT) {
__glutSetCursor(window);
return;
}
}
xcursor = cursorTable[0].cursor;
if (xcursor == NULL) {
xcursor =
cursorTable[0].cursor =
LoadCursor(NULL, cursorTable[0].glyph);
}
#else
xcursor = None;
#endif
break;
case GLUT_CURSOR_NONE:
#if defined(_WIN32)
xcursor = NULL;
#else
if (blankCursor == None) {
blankCursor = makeBlankCursor();
}
xcursor = blankCursor;
#endif
break;
case GLUT_CURSOR_FULL_CROSSHAIR:
#if defined(_WIN32)
xcursor = (HICON) IDC_CROSS;
#else
if (fullCrosshairCusor == None) {
fullCrosshairCusor = getFullCrosshairCursor();
}
xcursor = fullCrosshairCusor;
#endif
break;
}
}
XDefineCursor(__glutDisplay,
window->win, xcursor);
XFlush(__glutDisplay);
}
void GLUTAPIENTRY
glutSetCursor(int cursor)
{
#ifdef _WIN32
POINT point;
__glutCurrentWindow->cursor = cursor;
GetCursorPos(&point);
if (__glutCurrentWindow->win == WindowFromPoint(point)) {
__glutSetCursor(__glutCurrentWindow);
}
#else
__glutCurrentWindow->cursor = cursor;
__glutSetCursor(__glutCurrentWindow);
#endif
}