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