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