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