Moving some Windows-specific code out of "freeglut_main.c" into the Windows-specific...
[freeglut] / src / mswin / freeglut_init_mswin.c
1 /*\r
2  * freeglut_init_mswin.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: Thu Jan 19, 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 "freeglut_internal_mswin.h"\r
30 \r
31 \r
32 /*\r
33  * A call to this function should initialize all the display stuff...\r
34  */\r
35 void fghInitialize( const char* displayName )\r
36 {\r
37     WNDCLASS wc;\r
38     ATOM atom;\r
39 \r
40     /* What we need to do is to initialize the fgDisplay global structure here. */\r
41     fgDisplay.Instance = GetModuleHandle( NULL );\r
42     fgDisplay.DisplayName= displayName ? strdup(displayName) : 0 ;\r
43     atom = GetClassInfo( fgDisplay.Instance, _T("FREEGLUT"), &wc );\r
44 \r
45     if( atom == 0 )\r
46     {\r
47         ZeroMemory( &wc, sizeof(WNDCLASS) );\r
48 \r
49         /*\r
50          * Each of the windows should have its own device context, and we\r
51          * want redraw events during Vertical and Horizontal Resizes by\r
52          * the user.\r
53          *\r
54          * XXX Old code had "| CS_DBCLCKS" commented out.  Plans for the\r
55          * XXX future?  Dead-end idea?\r
56          */\r
57         wc.lpfnWndProc    = fgWindowProc;\r
58         wc.cbClsExtra     = 0;\r
59         wc.cbWndExtra     = 0;\r
60         wc.hInstance      = fgDisplay.Instance;\r
61         wc.hIcon          = LoadIcon( fgDisplay.Instance, _T("GLUT_ICON") );\r
62 \r
63 #if defined(_WIN32_WCE)\r
64         wc.style          = CS_HREDRAW | CS_VREDRAW;\r
65 #else\r
66         wc.style          = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;\r
67         if (!wc.hIcon)\r
68           wc.hIcon        = LoadIcon( NULL, IDI_WINLOGO );\r
69 #endif\r
70 \r
71         wc.hCursor        = LoadCursor( NULL, IDC_ARROW );\r
72         wc.hbrBackground  = NULL;\r
73         wc.lpszMenuName   = NULL;\r
74         wc.lpszClassName  = _T("FREEGLUT");\r
75 \r
76         /* Register the window class */\r
77         atom = RegisterClass( &wc );\r
78         FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Not Registered", "fghInitialize" );\r
79     }\r
80 \r
81     /* The screen dimensions can be obtained via GetSystemMetrics() calls */\r
82     fgDisplay.ScreenWidth  = GetSystemMetrics( SM_CXSCREEN );\r
83     fgDisplay.ScreenHeight = GetSystemMetrics( SM_CYSCREEN );\r
84 \r
85     {\r
86         HWND desktop = GetDesktopWindow( );\r
87         HDC  context = GetDC( desktop );\r
88 \r
89         fgDisplay.ScreenWidthMM  = GetDeviceCaps( context, HORZSIZE );\r
90         fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE );\r
91 \r
92         ReleaseDC( desktop, context );\r
93     }\r
94     /* If we have a DisplayName try to use it for metrics */\r
95     if( fgDisplay.DisplayName )\r
96     {\r
97         HDC context = CreateDC(fgDisplay.DisplayName,0,0,0);\r
98         if( context )\r
99         {\r
100             fgDisplay.ScreenWidth  = GetDeviceCaps( context, HORZRES );\r
101             fgDisplay.ScreenHeight = GetDeviceCaps( context, VERTRES );\r
102             fgDisplay.ScreenWidthMM  = GetDeviceCaps( context, HORZSIZE );\r
103             fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE );\r
104             DeleteDC(context);\r
105         }\r
106         else\r
107             fgWarning("fghInitialize: "\r
108                       "CreateDC failed, Screen size info may be incorrect\n"\r
109           "This is quite likely caused by a bad '-display' parameter");\r
110       \r
111     }\r
112     /* Set the timer granularity to 1 ms */\r
113     timeBeginPeriod ( 1 );\r
114 \r
115 \r
116     fgState.Initialised = GL_TRUE;\r
117 \r
118     /* Avoid registering atexit callback on Win32 as it results in an access\r
119      * violation due to calling into a module which has been unloaded.\r
120      * Any cleanup isn't needed on Windows anyway, the OS takes care of it.c\r
121      * see: http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx\r
122      */\r
123 /*    atexit(fgDeinitialize); */\r
124 \r
125     /* InputDevice uses GlutTimerFunc(), so fgState.Initialised must be TRUE */\r
126     fgInitialiseInputDevices();\r
127 }\r
128 \r
129 \r
130 \r
131 /* Platform-Specific Deinitialization Functions: */\r
132 extern void fghCloseInputDevices ( void );\r
133 \r
134 void fghDeinitialiseInputDevices ( void )\r
135 {\r
136 #if !defined(_WIN32_WCE)\r
137         fghCloseInputDevices ();\r
138 #endif /* !defined(_WIN32_WCE) */\r
139     fgState.JoysticksInitialised = GL_FALSE;\r
140     fgState.InputDevsInitialised = GL_FALSE;\r
141 }\r
142 \r
143 void fghCloseDisplay ( void )\r
144 {\r
145     if( fgDisplay.DisplayName )\r
146     {\r
147         free( fgDisplay.DisplayName );\r
148         fgDisplay.DisplayName = NULL;\r
149     }\r
150 \r
151     /* Reset the timer granularity */\r
152     timeEndPeriod ( 1 );\r
153 }\r
154 \r
155 \r
156 \r
157 /*\r
158  * Everything down to the end of the next two functions is copied from the X sources.\r
159  */\r
160 \r
161 /*\r
162 \r
163 Copyright 1985, 1986, 1987,1998  The Open Group\r
164 \r
165 Permission to use, copy, modify, distribute, and sell this software and its\r
166 documentation for any purpose is hereby granted without fee, provided that\r
167 the above copyright notice appear in all copies and that both that\r
168 copyright notice and this permission notice appear in supporting\r
169 documentation.\r
170 \r
171 The above copyright notice and this permission notice shall be included\r
172 in all copies or substantial portions of the Software.\r
173 \r
174 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
175 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
176 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
177 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR\r
178 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\r
179 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\r
180 OTHER DEALINGS IN THE SOFTWARE.\r
181 \r
182 Except as contained in this notice, the name of The Open Group shall\r
183 not be used in advertising or otherwise to promote the sale, use or\r
184 other dealings in this Software without prior written authorization\r
185 from The Open Group.\r
186 \r
187 */\r
188 \r
189 #define NoValue         0x0000\r
190 #define XValue          0x0001\r
191 #define YValue          0x0002\r
192 #define WidthValue      0x0004\r
193 #define HeightValue     0x0008\r
194 #define AllValues       0x000F\r
195 #define XNegative       0x0010\r
196 #define YNegative       0x0020\r
197 \r
198 /*\r
199  *    XParseGeometry parses strings of the form\r
200  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where\r
201  *   width, height, xoffset, and yoffset are unsigned integers.\r
202  *   Example:  "=80x24+300-49"\r
203  *   The equal sign is optional.\r
204  *   It returns a bitmask that indicates which of the four values\r
205  *   were actually found in the string.  For each value found,\r
206  *   the corresponding argument is updated;  for each value\r
207  *   not found, the corresponding argument is left unchanged.\r
208  */\r
209 \r
210 static int\r
211 ReadInteger(char *string, char **NextString)\r
212 {\r
213     register int Result = 0;\r
214     int Sign = 1;\r
215 \r
216     if (*string == '+')\r
217         string++;\r
218     else if (*string == '-')\r
219     {\r
220         string++;\r
221         Sign = -1;\r
222     }\r
223     for (; (*string >= '0') && (*string <= '9'); string++)\r
224     {\r
225         Result = (Result * 10) + (*string - '0');\r
226     }\r
227     *NextString = string;\r
228     if (Sign >= 0)\r
229         return Result;\r
230     else\r
231         return -Result;\r
232 }\r
233 \r
234 int XParseGeometry (\r
235     const char *string,\r
236     int *x,\r
237     int *y,\r
238     unsigned int *width,    /* RETURN */\r
239     unsigned int *height)    /* RETURN */\r
240 {\r
241     int mask = NoValue;\r
242     register char *strind;\r
243     unsigned int tempWidth = 0, tempHeight = 0;\r
244     int tempX = 0, tempY = 0;\r
245     char *nextCharacter;\r
246 \r
247     if ( (string == NULL) || (*string == '\0'))\r
248       return mask;\r
249     if (*string == '=')\r
250         string++;  /* ignore possible '=' at beg of geometry spec */\r
251 \r
252     strind = (char *)string;\r
253     if (*strind != '+' && *strind != '-' && *strind != 'x') {\r
254         tempWidth = ReadInteger(strind, &nextCharacter);\r
255         if (strind == nextCharacter)\r
256             return 0;\r
257         strind = nextCharacter;\r
258         mask |= WidthValue;\r
259     }\r
260 \r
261     if (*strind == 'x' || *strind == 'X') {\r
262         strind++;\r
263         tempHeight = ReadInteger(strind, &nextCharacter);\r
264         if (strind == nextCharacter)\r
265             return 0;\r
266         strind = nextCharacter;\r
267         mask |= HeightValue;\r
268     }\r
269 \r
270     if ((*strind == '+') || (*strind == '-')) {\r
271         if (*strind == '-') {\r
272             strind++;\r
273             tempX = -ReadInteger(strind, &nextCharacter);\r
274             if (strind == nextCharacter)\r
275                 return 0;\r
276             strind = nextCharacter;\r
277             mask |= XNegative;\r
278         }\r
279         else\r
280         {\r
281             strind++;\r
282             tempX = ReadInteger(strind, &nextCharacter);\r
283             if (strind == nextCharacter)\r
284                 return 0;\r
285             strind = nextCharacter;\r
286         }\r
287         mask |= XValue;\r
288         if ((*strind == '+') || (*strind == '-')) {\r
289             if (*strind == '-') {\r
290                 strind++;\r
291                 tempY = -ReadInteger(strind, &nextCharacter);\r
292                 if (strind == nextCharacter)\r
293                     return 0;\r
294                 strind = nextCharacter;\r
295                 mask |= YNegative;\r
296             }\r
297             else\r
298             {\r
299                 strind++;\r
300                 tempY = ReadInteger(strind, &nextCharacter);\r
301                 if (strind == nextCharacter)\r
302                     return 0;\r
303                 strind = nextCharacter;\r
304             }\r
305             mask |= YValue;\r
306         }\r
307     }\r
308 \r
309     /* If strind isn't at the end of the string the it's an invalid\r
310        geometry specification. */\r
311 \r
312     if (*strind != '\0') return 0;\r
313 \r
314     if (mask & XValue)\r
315         *x = tempX;\r
316     if (mask & YValue)\r
317         *y = tempY;\r
318     if (mask & WidthValue)\r
319         *width = tempWidth;\r
320     if (mask & HeightValue)\r
321         *height = tempHeight;\r
322     return mask;\r
323 }\r
324 \r
325 \r
326 \r