Fixing call to "fghGetProcAddress" by giving the new name of the function
[freeglut] / src / x11 / freeglut_cursor_x11.c
1 /*\r
2  * freeglut_cursor_x11.c\r
3  *\r
4  * The Windows-specific mouse cursor related stuff.\r
5  *\r
6  * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.\r
7  * Written by John F. Fay, <fayjf@sourceforge.net>\r
8  * Creation date: Sun Feb 5, 2012\r
9  *\r
10  * Permission is hereby granted, free of charge, to any person obtaining a\r
11  * copy of this software and associated documentation files (the "Software"),\r
12  * to deal in the Software without restriction, including without limitation\r
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
14  * and/or sell copies of the Software, and to permit persons to whom the\r
15  * Software is furnished to do so, subject to the following conditions:\r
16  *\r
17  * The above copyright notice and this permission notice shall be included\r
18  * in all copies or substantial portions of the Software.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\r
23  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
24  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
26  */\r
27 \r
28 #include <GL/freeglut.h>\r
29 #include "../Common/freeglut_internal.h"\r
30 \r
31 /* This code is for Posix/X11, Solaris, and OSX */\r
32 #include <X11/cursorfont.h>\r
33 \r
34 /*\r
35  * A factory method for an empty cursor\r
36  */\r
37 static Cursor getEmptyCursor( void )\r
38 {\r
39     static Cursor cursorNone = None;\r
40     if( cursorNone == None ) {\r
41         char cursorNoneBits[ 32 ];\r
42         XColor dontCare;\r
43         Pixmap cursorNonePixmap;\r
44         memset( cursorNoneBits, 0, sizeof( cursorNoneBits ) );\r
45         memset( &dontCare, 0, sizeof( dontCare ) );\r
46         cursorNonePixmap = XCreateBitmapFromData ( fgDisplay.pDisplay.Display,\r
47                                                    fgDisplay.pDisplay.RootWindow,\r
48                                                    cursorNoneBits, 16, 16 );\r
49         if( cursorNonePixmap != None ) {\r
50             cursorNone = XCreatePixmapCursor( fgDisplay.pDisplay.Display,\r
51                                               cursorNonePixmap, cursorNonePixmap,\r
52                                               &dontCare, &dontCare, 0, 0 );\r
53             XFreePixmap( fgDisplay.pDisplay.Display, cursorNonePixmap );\r
54         }\r
55     }\r
56     return cursorNone;\r
57 }\r
58 \r
59 typedef struct tag_cursorCacheEntry cursorCacheEntry;\r
60 struct tag_cursorCacheEntry {\r
61     unsigned int cursorShape;    /* an XC_foo value */\r
62     Cursor cachedCursor;         /* None if the corresponding cursor has\r
63                                     not been created yet */\r
64 };\r
65 \r
66 /*\r
67  * Note: The arrangement of the table below depends on the fact that\r
68  * the "normal" GLUT_CURSOR_* values start a 0 and are consecutive.\r
69  */ \r
70 static cursorCacheEntry cursorCache[] = {\r
71     { XC_arrow,               None }, /* GLUT_CURSOR_RIGHT_ARROW */\r
72     { XC_top_left_arrow,      None }, /* GLUT_CURSOR_LEFT_ARROW */\r
73     { XC_hand1,               None }, /* GLUT_CURSOR_INFO */\r
74     { XC_pirate,              None }, /* GLUT_CURSOR_DESTROY */\r
75     { XC_question_arrow,      None }, /* GLUT_CURSOR_HELP */\r
76     { XC_exchange,            None }, /* GLUT_CURSOR_CYCLE */\r
77     { XC_spraycan,            None }, /* GLUT_CURSOR_SPRAY */\r
78     { XC_watch,               None }, /* GLUT_CURSOR_WAIT */\r
79     { XC_xterm,               None }, /* GLUT_CURSOR_TEXT */\r
80     { XC_crosshair,           None }, /* GLUT_CURSOR_CROSSHAIR */\r
81     { XC_sb_v_double_arrow,   None }, /* GLUT_CURSOR_UP_DOWN */\r
82     { XC_sb_h_double_arrow,   None }, /* GLUT_CURSOR_LEFT_RIGHT */\r
83     { XC_top_side,            None }, /* GLUT_CURSOR_TOP_SIDE */\r
84     { XC_bottom_side,         None }, /* GLUT_CURSOR_BOTTOM_SIDE */\r
85     { XC_left_side,           None }, /* GLUT_CURSOR_LEFT_SIDE */\r
86     { XC_right_side,          None }, /* GLUT_CURSOR_RIGHT_SIDE */\r
87     { XC_top_left_corner,     None }, /* GLUT_CURSOR_TOP_LEFT_CORNER */\r
88     { XC_top_right_corner,    None }, /* GLUT_CURSOR_TOP_RIGHT_CORNER */\r
89     { XC_bottom_right_corner, None }, /* GLUT_CURSOR_BOTTOM_RIGHT_CORNER */\r
90     { XC_bottom_left_corner,  None }  /* GLUT_CURSOR_BOTTOM_LEFT_CORNER */\r
91 };\r
92 \r
93 void fgPlatformSetCursor ( SFG_Window *window, int cursorID )\r
94 {\r
95     Cursor cursor;\r
96     /*\r
97      * XXX FULL_CROSSHAIR demotes to plain CROSSHAIR. Old GLUT allows\r
98      * for this, but if there is a system that easily supports a full-\r
99      * window (or full-screen) crosshair, we might consider it.\r
100      */\r
101     int cursorIDToUse =\r
102         ( cursorID == GLUT_CURSOR_FULL_CROSSHAIR ) ? GLUT_CURSOR_CROSSHAIR : cursorID;\r
103 \r
104     if( ( cursorIDToUse >= 0 ) &&\r
105         ( cursorIDToUse < sizeof( cursorCache ) / sizeof( cursorCache[0] ) ) ) {\r
106         cursorCacheEntry *entry = &cursorCache[ cursorIDToUse ];\r
107         if( entry->cachedCursor == None ) {\r
108             entry->cachedCursor =\r
109                 XCreateFontCursor( fgDisplay.pDisplay.Display, entry->cursorShape );\r
110         }\r
111         cursor = entry->cachedCursor;\r
112     } else {\r
113         switch( cursorIDToUse )\r
114         {\r
115         case GLUT_CURSOR_NONE:\r
116             cursor = getEmptyCursor( );\r
117             break;\r
118 \r
119         case GLUT_CURSOR_INHERIT:\r
120             cursor = None;\r
121             break;\r
122 \r
123         default:\r
124             fgError( "Unknown cursor type: %d", cursorIDToUse );\r
125             return;\r
126         }\r
127     }\r
128 \r
129     if ( cursorIDToUse == GLUT_CURSOR_INHERIT ) {\r
130         XUndefineCursor( fgDisplay.pDisplay.Display, window->Window.Handle );\r
131     } else if ( cursor != None ) {\r
132         XDefineCursor( fgDisplay.pDisplay.Display, window->Window.Handle, cursor );\r
133     } else if ( cursorIDToUse != GLUT_CURSOR_NONE ) {\r
134         fgError( "Failed to create cursor" );\r
135     }\r
136 }\r
137 \r
138 \r
139 void fgPlatformWarpPointer ( int x, int y )\r
140 {\r
141     XWarpPointer(\r
142         fgDisplay.pDisplay.Display,\r
143         None,\r
144         fgStructure.CurrentWindow->Window.Handle,\r
145         0, 0, 0, 0,\r
146         x, y\r
147     );\r
148     /* Make the warp visible immediately. */\r
149     XFlush( fgDisplay.pDisplay.Display );\r
150 }\r
151 \r