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