XParseGeometry include now compiles with windows (VS2010, didn't touch
[freeglut] / src / Common / freeglut_window.c
1 /*
2  * freeglut_window.c
3  *
4  * Window management methods.
5  *
6  * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
7  * Written by Pawel W. Olszta, <olszta@sourceforge.net>
8  * Creation date: Fri Dec 3 1999
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 "freeglut_internal.h"
31
32 #if defined(_WIN32_WCE)
33 #   include <Aygshell.h>
34 #   ifdef FREEGLUT_LIB_PRAGMAS
35 #       pragma comment( lib, "Aygshell.lib" )
36 #   endif
37 #endif /* defined(_WIN32_WCE) */
38
39
40 /*
41  * TODO BEFORE THE STABLE RELEASE:
42  *
43  *  fgSetupPixelFormat      -- ignores the display mode settings
44  *  fgOpenWindow()          -- check the Win32 version, -iconic handling!
45  *  fgCloseWindow()         -- check the Win32 version
46  *  glutCreateWindow()      -- Check when default position and size is {-1,-1}
47  *  glutCreateSubWindow()   -- Check when default position and size is {-1,-1}
48  *  glutDestroyWindow()     -- check the Win32 version
49  *  glutSetWindow()         -- check the Win32 version
50  *  glutSetWindowTitle()    -- check the Win32 version
51  *  glutSetIconTitle()      -- check the Win32 version
52  *  glutShowWindow()        -- check the Win32 version
53  *  glutHideWindow()        -- check the Win32 version
54  *  glutIconifyWindow()     -- check the Win32 version
55  *  glutPushWindow()        -- check the Win32 version
56  *  glutPopWindow()         -- check the Win32 version
57  */
58
59
60 extern void fgPlatformSetWindow ( SFG_Window *window );
61 extern void fgPlatformOpenWindow( SFG_Window* window, const char* title,
62                                   GLboolean positionUse, int x, int y,
63                                   GLboolean sizeUse, int w, int h,
64                                   GLboolean gameMode, GLboolean isSubWindow );
65 extern void fgPlatformCloseWindow( SFG_Window* window );
66 extern void fgPlatformGlutShowWindow( void );
67 extern void fgPlatformGlutHideWindow( void );
68 extern void fgPlatformGlutIconifyWindow( void );
69 extern void fgPlatformGlutSetWindowTitle( const char* title );
70 extern void fgPlatformGlutSetIconTitle( const char* title );
71 extern void fgPlatformGlutPositionWindow( int x, int y );
72 extern void fgPlatformGlutPushWindow( void );
73 extern void fgPlatformGlutPopWindow( void );
74 extern void fgPlatformGlutFullScreen( SFG_Window *win );
75 extern void fgPlatformGlutLeaveFullScreen( SFG_Window *win );
76 extern void fgPlatformGlutFullScreenToggle( SFG_Window *win );
77
78
79 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
80
81 int fghIsLegacyContextVersionRequested( void )
82 {
83   return fgState.MajorVersion < 2 || (fgState.MajorVersion == 2 && fgState.MinorVersion <= 1);
84 }
85
86 int fghIsLegacyContextRequested( void )
87 {
88   return fghIsLegacyContextVersionRequested() &&
89          fgState.ContextFlags == 0 &&
90          fgState.ContextProfile == 0;
91 }
92
93 int fghNumberOfAuxBuffersRequested( void )
94 {
95   if ( fgState.DisplayMode & GLUT_AUX4 ) {
96     return 4;
97   }
98   if ( fgState.DisplayMode & GLUT_AUX3 ) {
99     return 3;
100   }
101   if ( fgState.DisplayMode & GLUT_AUX2 ) {
102     return 2;
103   }
104   if ( fgState.DisplayMode & GLUT_AUX1 ) { /* NOTE: Same as GLUT_AUX! */
105     return fgState.AuxiliaryBufferNumber;
106   }
107   return 0;
108 }
109
110 int fghMapBit( int mask, int from, int to )
111 {
112   return ( mask & from ) ? to : 0;
113
114 }
115
116 void fghContextCreationError( void )
117 {
118     fgError( "Unable to create OpenGL %d.%d context (flags %x, profile %x)",
119              fgState.MajorVersion, fgState.MinorVersion, fgState.ContextFlags,
120              fgState.ContextProfile );
121 }
122
123
124 /* -- SYSTEM-DEPENDENT PRIVATE FUNCTIONS ------------------------------------ */
125
126 /*
127  * Sets the OpenGL context and the fgStructure "Current Window" pointer to
128  * the window structure passed in.
129  */
130 void fgSetWindow ( SFG_Window *window )
131 {
132         fgPlatformSetWindow ( window );
133
134     fgStructure.CurrentWindow = window;
135 }
136
137 /*
138  * Opens a window. Requires a SFG_Window object created and attached
139  * to the freeglut structure. OpenGL context is created here.
140  */
141 void fgOpenWindow( SFG_Window* window, const char* title,
142                    GLboolean positionUse, int x, int y,
143                    GLboolean sizeUse, int w, int h,
144                    GLboolean gameMode, GLboolean isSubWindow )
145 {
146         fgPlatformOpenWindow( window, title,
147                    positionUse, x, y,
148                    sizeUse, w, h,
149                    gameMode, isSubWindow );
150
151     fgSetWindow( window );
152
153     window->Window.DoubleBuffered =
154         ( fgState.DisplayMode & GLUT_DOUBLE ) ? 1 : 0;
155
156     if ( ! window->Window.DoubleBuffered )
157     {
158         glDrawBuffer ( GL_FRONT );
159         glReadBuffer ( GL_FRONT );
160     }
161 }
162
163 /*
164  * Closes a window, destroying the frame and OpenGL context
165  */
166 void fgCloseWindow( SFG_Window* window )
167 {
168     /* if we're in gamemode and we're closing the gamemode window,
169      * call glutLeaveGameMode first to make sure the gamemode is
170      * properly closed before closing the window
171      */
172     if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==window->ID)
173         glutLeaveGameMode();
174
175         fgPlatformCloseWindow ( window );
176 }
177
178
179 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
180
181 /*
182  * Creates a new top-level freeglut window
183  */
184 int FGAPIENTRY glutCreateWindow( const char* title )
185 {
186     /* XXX GLUT does not exit; it simply calls "glutInit" quietly if the
187      * XXX application has not already done so.  The "freeglut" community
188      * XXX decided not to go this route (freeglut-developer e-mail from
189      * XXX Steve Baker, 12/16/04, 4:22 PM CST, "Re: [Freeglut-developer]
190      * XXX Desired 'freeglut' behaviour when there is no current window"
191      */
192     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateWindow" );
193
194     return fgCreateWindow( NULL, title, fgState.Position.Use,
195                            fgState.Position.X, fgState.Position.Y,
196                            fgState.Size.Use, fgState.Size.X, fgState.Size.Y,
197                            GL_FALSE, GL_FALSE )->ID;
198 }
199
200 /*
201  * This function creates a sub window.
202  */
203 int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h )
204 {
205     int ret = 0;
206     SFG_Window* window = NULL;
207     SFG_Window* parent = NULL;
208
209     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateSubWindow" );
210     parent = fgWindowByID( parentID );
211     freeglut_return_val_if_fail( parent != NULL, 0 );
212     if ( x < 0 )
213     {
214         x = parent->State.Width + x ;
215         if ( w >= 0 ) x -= w ;
216     }
217
218     if ( w < 0 ) w = parent->State.Width - x + w ;
219     if ( w < 0 )
220     {
221         x += w ;
222         w = -w ;
223     }
224
225     if ( y < 0 )
226     {
227         y = parent->State.Height + y ;
228         if ( h >= 0 ) y -= h ;
229     }
230
231     if ( h < 0 ) h = parent->State.Height - y + h ;
232     if ( h < 0 )
233     {
234         y += h ;
235         h = -h ;
236     }
237
238     window = fgCreateWindow( parent, "", GL_TRUE, x, y, GL_TRUE, w, h, GL_FALSE, GL_FALSE );
239     ret = window->ID;
240
241     return ret;
242 }
243
244 /*
245  * Destroys a window and all of its subwindows
246  */
247 void FGAPIENTRY glutDestroyWindow( int windowID )
248 {
249     SFG_Window* window;
250     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDestroyWindow" );
251     window = fgWindowByID( windowID );
252     freeglut_return_if_fail( window != NULL );
253     {
254         fgExecutionState ExecState = fgState.ExecState;
255         fgAddToWindowDestroyList( window );
256         fgState.ExecState = ExecState;
257     }
258 }
259
260 /*
261  * This function selects the specified window as the current window
262  */
263 void FGAPIENTRY glutSetWindow( int ID )
264 {
265     SFG_Window* window = NULL;
266
267     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindow" );
268     if( fgStructure.CurrentWindow != NULL )
269         if( fgStructure.CurrentWindow->ID == ID )
270             return;
271
272     window = fgWindowByID( ID );
273     if( window == NULL )
274     {
275         fgWarning( "glutSetWindow(): window ID %d not found!", ID );
276         return;
277     }
278
279     fgSetWindow( window );
280 }
281
282 /*
283  * This function returns the ID number of the current window, 0 if none exists
284  */
285 int FGAPIENTRY glutGetWindow( void )
286 {
287     SFG_Window *win = fgStructure.CurrentWindow;
288     /*
289      * Since GLUT did not throw an error if this function was called without a prior call to
290      * "glutInit", this function shouldn't do so here.  Instead let us return a zero.
291      * See Feature Request "[ 1307049 ] glutInit check".
292      */
293     if ( ! fgState.Initialised )
294         return 0;
295
296     while ( win && win->IsMenu )
297         win = win->Parent;
298     return win ? win->ID : 0;
299 }
300
301 /*
302  * This function makes the current window visible
303  */
304 void FGAPIENTRY glutShowWindow( void )
305 {
306     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutShowWindow" );
307     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutShowWindow" );
308
309         fgPlatformGlutShowWindow ();
310
311     fgStructure.CurrentWindow->State.Redisplay = GL_TRUE;
312 }
313
314 /*
315  * This function hides the current window
316  */
317 void FGAPIENTRY glutHideWindow( void )
318 {
319     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutHideWindow" );
320     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutHideWindow" );
321
322         fgPlatformGlutHideWindow ();
323
324     fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;
325 }
326
327 /*
328  * Iconify the current window (top-level windows only)
329  */
330 void FGAPIENTRY glutIconifyWindow( void )
331 {
332     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIconifyWindow" );
333     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutIconifyWindow" );
334
335     fgStructure.CurrentWindow->State.Visible   = GL_FALSE;
336
337         fgPlatformGlutIconifyWindow ();
338
339     fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;
340 }
341
342 /*
343  * Set the current window's title
344  */
345 void FGAPIENTRY glutSetWindowTitle( const char* title )
346 {
347     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowTitle" );
348     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowTitle" );
349     if( ! fgStructure.CurrentWindow->Parent )
350     {
351                 fgPlatformGlutSetWindowTitle ( title );
352     }
353 }
354
355 /*
356  * Set the current window's iconified title
357  */
358 void FGAPIENTRY glutSetIconTitle( const char* title )
359 {
360     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetIconTitle" );
361     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetIconTitle" );
362
363     if( ! fgStructure.CurrentWindow->Parent )
364     {
365                 fgPlatformGlutSetIconTitle ( title );
366     }
367 }
368
369 /*
370  * Change the current window's size
371  */
372 void FGAPIENTRY glutReshapeWindow( int width, int height )
373 {
374     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeWindow" );
375     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutReshapeWindow" );
376
377     if (glutGet(GLUT_FULL_SCREEN))
378     {
379       /*  Leave full screen state before resizing. */
380       glutLeaveFullScreen();
381     }
382
383     fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
384     fgStructure.CurrentWindow->State.Width  = width ;
385     fgStructure.CurrentWindow->State.Height = height;
386 }
387
388 /*
389  * Change the current window's position
390  */
391 void FGAPIENTRY glutPositionWindow( int x, int y )
392 {
393     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPositionWindow" );
394     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPositionWindow" );
395
396     if (glutGet(GLUT_FULL_SCREEN))
397     {
398       /*  Leave full screen state before moving. */
399       glutLeaveFullScreen();
400     }
401
402         fgPlatformGlutPositionWindow ( x, y );
403 }
404
405 /*
406  * Lowers the current window (by Z order change)
407  */
408 void FGAPIENTRY glutPushWindow( void )
409 {
410     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPushWindow" );
411     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPushWindow" );
412
413         fgPlatformGlutPushWindow ();
414 }
415
416 /*
417  * Raises the current window (by Z order change)
418  */
419 void FGAPIENTRY glutPopWindow( void )
420 {
421     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPopWindow" );
422     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPopWindow" );
423
424         fgPlatformGlutPopWindow ();
425 }
426
427 /*
428  * Resize the current window so that it fits the whole screen
429  */
430 void FGAPIENTRY glutFullScreen( void )
431 {
432     SFG_Window *win;
433
434     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
435     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
436
437     win = fgStructure.CurrentWindow;
438
439     if (win->Parent)
440     {
441         /* Child windows cannot be made fullscreen, consistent with GLUT's behavior
442          * Also, what would it mean for a child window to be fullscreen, given that it
443          * is confined to its parent?
444          */
445         fgWarning("glutFullScreen called on a child window, ignoring...");
446         return;
447     }
448     else if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==win->ID)
449     {
450         /* Ignore fullscreen call on GameMode window, those are always fullscreen already */
451         return;
452     }
453
454         fgPlatformGlutFullScreen ( win );
455 }
456
457 /*
458  * If we are fullscreen, resize the current window back to its original size
459  */
460 void FGAPIENTRY glutLeaveFullScreen( void )
461 {
462     SFG_Window *win;
463
464     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
465     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
466
467     win = fgStructure.CurrentWindow;
468
469         fgPlatformGlutLeaveFullScreen ( win );
470 }
471
472 /*
473  * Toggle the window's full screen state.
474  */
475 void FGAPIENTRY glutFullScreenToggle( void )
476 {
477     SFG_Window *win;
478
479     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreenToggle" );
480     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreenToggle" );
481
482     win = fgStructure.CurrentWindow;
483
484         fgPlatformGlutFullScreenToggle ( win );
485 }
486
487 /*
488  * A.Donev: Set and retrieve the window's user data
489  */
490 void* FGAPIENTRY glutGetWindowData( void )
491 {
492     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetWindowData" );
493     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutGetWindowData" );
494     return fgStructure.CurrentWindow->UserData;
495 }
496
497 void FGAPIENTRY glutSetWindowData(void* data)
498 {
499     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowData" );
500     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowData" );
501     fgStructure.CurrentWindow->UserData = data;
502 }
503
504 /*** END OF FILE ***/