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