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