1 
2 /* Copyright (c) Mark J. Kilgard, 1995. */
3 
4 /* This program is freely distributable without licensing fees
5    and is provided without guarantee or warrantee expressed or
6    implied. This program is -not- in the public domain. */
7 
8 #include <GL/glut.h>
9 #include "glutint.h"
10 #include <X11/Xatom.h>  /* For XA_CURSOR */
11 #include <X11/cursorfont.h>
12 
13 typedef struct _CursorTable {
14   int glyph;
15   Cursor cursor;
16 } CursorTable;
17 
18 static CursorTable cursorTable[] = {
19   {XC_arrow, None},		  /* GLUT_CURSOR_RIGHT_ARROW */
20   {XC_top_left_arrow, None},	  /* GLUT_CURSOR_LEFT_ARROW */
21   {XC_hand1, None},		  /* GLUT_CURSOR_INFO */
22   {XC_pirate, None},		  /* GLUT_CURSOR_DESTROY */
23   {XC_question_arrow, None},	  /* GLUT_CURSOR_HELP */
24   {XC_exchange, None},		  /* GLUT_CURSOR_CYCLE */
25   {XC_spraycan, None},		  /* GLUT_CURSOR_SPRAY */
26   {XC_watch, None},		  /* GLUT_CURSOR_WAIT */
27   {XC_xterm, None},		  /* GLUT_CURSOR_TEXT */
28   {XC_crosshair, None},		  /* GLUT_CURSOR_CROSSHAIR */
29   {XC_sb_v_double_arrow, None},	  /* GLUT_CURSOR_UP_DOWN */
30   {XC_sb_h_double_arrow, None},	  /* GLUT_CURSOR_LEFT_RIGHT */
31   {XC_top_side, None},		  /* GLUT_CURSOR_TOP_SIDE */
32   {XC_bottom_side, None},	  /* GLUT_CURSOR_BOTTOM_SIDE */
33   {XC_left_side, None},		  /* GLUT_CURSOR_LEFT_SIDE */
34   {XC_right_side, None},	  /* GLUT_CURSOR_RIGHT_SIDE */
35   {XC_top_left_corner, None},	  /* GLUT_CURSOR_TOP_LEFT_CORNER */
36   {XC_top_right_corner, None},	  /* GLUT_CURSOR_TOP_RIGHT_CORNER */
37   {XC_bottom_right_corner, None}, /* GLUT_CURSOR_BOTTOM_RIGHT_CORNER */
38   {XC_bottom_left_corner, None},  /* GLUT_CURSOR_BOTTOM_LEFT_CORNER */
39 };
40 
41 static Cursor blankCursor = None;
42 static Cursor fullCrosshairCusor = None;
43 
44 static Cursor
getFullCrosshairCursor(void)45 getFullCrosshairCursor(void)
46 {
47   Cursor cursor;
48   Atom crosshairAtom, actualType;
49   int rc, actualFormat;
50   unsigned long n, left;
51   unsigned long *value;
52 
53   if (fullCrosshairCusor == None) {
54     crosshairAtom = XInternAtom(__glutDisplay,
55       "_SGI_CROSSHAIR_CURSOR", True);
56     if (crosshairAtom != None) {
57       value = 0;        /* Make compiler happy. */
58       rc = XGetWindowProperty(__glutDisplay, __glutRoot,
59         crosshairAtom, 0, 1, False, XA_CURSOR, &actualType,
60         &actualFormat, &n, &left, (unsigned char **) &value);
61       if (rc == Success && actualFormat == 32 && n >= 1) {
62         cursor = value[0];
63         XFree(value);
64         return cursor;
65       }
66     }
67   }
68   return XCreateFontCursor(__glutDisplay, XC_crosshair);
69 }
70 
71 static Cursor
makeBlankCursor(void)72 makeBlankCursor(void)
73 {
74   static char data[1] =
75   {0};
76   Cursor cursor;
77   Pixmap blank;
78   XColor dummy;
79 
80   blank = XCreateBitmapFromData(__glutDisplay, __glutRoot,
81     data, 1, 1);
82   if (blank == None)
83     __glutFatalError("out of memory.");
84   cursor = XCreatePixmapCursor(__glutDisplay, blank, blank,
85     &dummy, &dummy, 0, 0);
86   XFreePixmap(__glutDisplay, blank);
87 
88   return cursor;
89 }
90 
91 void
glutSetCursor(int cursor)92 glutSetCursor(int cursor)
93 {
94   Cursor xcursor=None;
95 
96   if (cursor >= 0 &&
97     cursor < sizeof(cursorTable) / sizeof(cursorTable[0])) {
98     if (cursorTable[cursor].cursor == None)
99       cursorTable[cursor].cursor = XCreateFontCursor(__glutDisplay,
100         cursorTable[cursor].glyph);
101     xcursor = cursorTable[cursor].cursor;
102   } else {
103     /* Special cases. */
104     switch (cursor) {
105     case GLUT_CURSOR_INHERIT:
106       xcursor = None;
107       break;
108     case GLUT_CURSOR_NONE:
109       if (blankCursor == None)
110         blankCursor = makeBlankCursor();
111       xcursor = blankCursor;
112       break;
113     case GLUT_CURSOR_FULL_CROSSHAIR:
114       if (fullCrosshairCusor == None)
115         fullCrosshairCusor = getFullCrosshairCursor();
116       xcursor = fullCrosshairCusor;
117       break;
118     }
119   }
120   __glutCurrentWindow->cursor = cursor;
121   XDefineCursor(__glutDisplay,
122     __glutCurrentWindow->win, xcursor);
123   XFlush(__glutDisplay);
124 }
125