4 * Window management methods.
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
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:
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
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.
28 #define FREEGLUT_BUILDING_LIB
29 #include <GL/freeglut.h>
30 #include "fg_internal.h"
34 * TODO BEFORE THE STABLE RELEASE:
36 * fgSetupPixelFormat -- ignores the display mode settings
37 * fgOpenWindow() -- check the Win32 version, -iconic handling!
38 * fgCloseWindow() -- check the Win32 version
39 * glutCreateWindow() -- Check when default position and size is {-1,-1}
40 * glutCreateSubWindow() -- Check when default position and size is {-1,-1}
41 * glutDestroyWindow() -- check the Win32 version
42 * glutSetWindow() -- check the Win32 version
43 * glutSetWindowTitle() -- check the Win32 version
44 * glutSetIconTitle() -- check the Win32 version
45 * glutShowWindow() -- check the Win32 version
46 * glutHideWindow() -- check the Win32 version
47 * glutIconifyWindow() -- check the Win32 version
48 * glutPushWindow() -- check the Win32 version
49 * glutPopWindow() -- check the Win32 version
53 extern void fgPlatformSetWindow ( SFG_Window *window );
54 extern void fgPlatformOpenWindow( SFG_Window* window, const char* title,
55 GLboolean positionUse, int x, int y,
56 GLboolean sizeUse, int w, int h,
57 GLboolean gameMode, GLboolean isSubWindow );
58 extern void fgPlatformCloseWindow( SFG_Window* window );
59 extern void fgPlatformGlutSetWindowTitle( const char* title );
60 extern void fgPlatformGlutSetIconTitle( const char* title );
63 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
65 int fghIsLegacyContextRequested( void )
67 return fgState.MajorVersion < 2 || (fgState.MajorVersion == 2 && fgState.MinorVersion <= 1);
70 int fghNumberOfAuxBuffersRequested( void )
72 if ( fgState.DisplayMode & GLUT_AUX4 ) {
75 if ( fgState.DisplayMode & GLUT_AUX3 ) {
78 if ( fgState.DisplayMode & GLUT_AUX2 ) {
81 if ( fgState.DisplayMode & GLUT_AUX1 ) { /* NOTE: Same as GLUT_AUX! */
82 return fgState.AuxiliaryBufferNumber;
87 int fghMapBit( int mask, int from, int to )
89 return ( mask & from ) ? to : 0;
93 void fghContextCreationError( void )
95 fgError( "Unable to create OpenGL %d.%d context (flags %x, profile %x)",
96 fgState.MajorVersion, fgState.MinorVersion, fgState.ContextFlags,
97 fgState.ContextProfile );
101 /* -- SYSTEM-DEPENDENT PRIVATE FUNCTIONS ------------------------------------ */
104 * Sets the OpenGL context and the fgStructure "Current Window" pointer to
105 * the window structure passed in.
107 void fgSetWindow ( SFG_Window *window )
109 fgPlatformSetWindow ( window );
111 fgStructure.CurrentWindow = window;
115 * Opens a window. Requires a SFG_Window object created and attached
116 * to the freeglut structure. OpenGL context is created here.
118 void fgOpenWindow( SFG_Window* window, const char* title,
119 GLboolean positionUse, int x, int y,
120 GLboolean sizeUse, int w, int h,
121 GLboolean gameMode, GLboolean isSubWindow )
123 fgPlatformOpenWindow( window, title,
126 gameMode, isSubWindow );
128 fgSetWindow( window );
130 #ifndef EGL_VERSION_1_0
131 window->Window.DoubleBuffered =
132 ( fgState.DisplayMode & GLUT_DOUBLE ) ? 1 : 0;
134 if ( ! window->Window.DoubleBuffered )
136 glDrawBuffer ( GL_FRONT );
137 glReadBuffer ( GL_FRONT );
140 /* - EGL is always double-buffered */
141 /* - No glDrawBuffer/glReadBuffer in GLES */
142 window->Window.DoubleBuffered = 1;
144 window->Window.attribute_v_coord = -1;
145 window->Window.attribute_v_normal = -1;
146 window->Window.attribute_v_texture = -1;
150 window->State.WorkMask |= GLUT_INIT_WORK;
154 * Closes a window, destroying the frame and OpenGL context
156 void fgCloseWindow( SFG_Window* window )
158 /* if we're in gamemode and we're closing the gamemode window,
159 * call glutLeaveGameMode first to make sure the gamemode is
160 * properly closed before closing the window
162 if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==window->ID)
165 fgPlatformCloseWindow ( window );
169 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
172 * Creates a new top-level freeglut window
174 int FGAPIENTRY glutCreateWindow( const char* title )
176 /* XXX GLUT does not exit; it simply calls "glutInit" quietly if the
177 * XXX application has not already done so. The "freeglut" community
178 * XXX decided not to go this route (freeglut-developer e-mail from
179 * XXX Steve Baker, 12/16/04, 4:22 PM CST, "Re: [Freeglut-developer]
180 * XXX Desired 'freeglut' behaviour when there is no current window")
182 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateWindow" );
184 return fgCreateWindow( NULL, title,
185 fgState.Position.Use, fgState.Position.X, fgState.Position.Y,
186 fgState.Size.Use, fgState.Size.X, fgState.Size.Y,
187 GL_FALSE, GL_FALSE )->ID;
191 * This function creates a sub window.
193 int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h )
196 SFG_Window* window = NULL;
197 SFG_Window* parent = NULL;
199 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateSubWindow" );
200 parent = fgWindowByID( parentID );
201 freeglut_return_val_if_fail( parent != NULL, 0 );
203 if ( fgState.AllowNegativeWindowPosition )
205 /* XXX This results in different widths/heights than if AllowNegativeWindowPosition
206 * XXX was false. The "freeglut" community defined this logic.
207 * XXX (freeglut-developer e-mail from Diederick C. Niehorster, 11/15/2015, 4:06 PM EST.
208 * XXX "Re: [Freeglut-developer] glutInitWindowPosition with negative coordinate(s)")
211 if ( w < 0 ) w = parent->State.Width + w ;
212 if ( h < 0 ) h = parent->State.Height + h ;
218 x = parent->State.Width + x ;
219 if ( w > 0 ) x -= w ;
222 if ( w < 0 ) w = parent->State.Width - x + w ;
231 y = parent->State.Height + y ;
232 if ( h > 0 ) y -= h ;
235 if ( h < 0 ) h = parent->State.Height - y + h ;
243 window = fgCreateWindow( parent, "",
246 GL_FALSE, GL_FALSE );
253 * Destroys a window and all of its subwindows
255 void FGAPIENTRY glutDestroyWindow( int windowID )
258 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDestroyWindow" );
259 window = fgWindowByID( windowID );
260 freeglut_return_if_fail( window != NULL );
262 fgExecutionState ExecState = fgState.ExecState;
263 fgAddToWindowDestroyList( window );
264 fgState.ExecState = ExecState;
269 * This function selects the specified window as the current window
271 void FGAPIENTRY glutSetWindow( int ID )
273 SFG_Window* window = NULL;
275 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindow" );
276 if( fgStructure.CurrentWindow != NULL )
277 if( fgStructure.CurrentWindow->ID == ID )
280 window = fgWindowByID( ID );
283 fgWarning( "glutSetWindow(): window ID %d not found!", ID );
287 fgSetWindow( window );
291 * This function returns the ID number of the current window, 0 if none exists
293 int FGAPIENTRY glutGetWindow( void )
295 SFG_Window *win = fgStructure.CurrentWindow;
297 * Since GLUT did not throw an error if this function was called without a prior call to
298 * "glutInit", this function shouldn't do so here. Instead let us return a zero.
299 * See Feature Request "[ 1307049 ] glutInit check".
301 if ( ! fgState.Initialised )
304 while ( win && win->IsMenu )
306 return win ? win->ID : 0;
310 * This function makes the current window visible
312 void FGAPIENTRY glutShowWindow( void )
314 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutShowWindow" );
315 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutShowWindow" );
317 fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK;
318 fgStructure.CurrentWindow->State.DesiredVisibility = DesireNormalState;
320 fgStructure.CurrentWindow->State.WorkMask |= GLUT_DISPLAY_WORK;
324 * This function hides the current window
326 void FGAPIENTRY glutHideWindow( void )
328 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutHideWindow" );
329 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutHideWindow" );
331 fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK;
332 fgStructure.CurrentWindow->State.DesiredVisibility = DesireHiddenState;
334 fgStructure.CurrentWindow->State.WorkMask &= ~GLUT_DISPLAY_WORK;
338 * Iconify the current window (top-level windows only)
340 void FGAPIENTRY glutIconifyWindow( void )
342 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIconifyWindow" );
343 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutIconifyWindow" );
345 fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK;
346 fgStructure.CurrentWindow->State.DesiredVisibility = DesireIconicState;
348 fgStructure.CurrentWindow->State.WorkMask &= ~GLUT_DISPLAY_WORK;
352 * Set the current window's title
354 void FGAPIENTRY glutSetWindowTitle( const char* title )
356 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowTitle" );
357 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowTitle" );
358 if( ! fgStructure.CurrentWindow->Parent )
360 fgPlatformGlutSetWindowTitle ( title );
365 * Set the current window's iconified title
367 void FGAPIENTRY glutSetIconTitle( const char* title )
369 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetIconTitle" );
370 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetIconTitle" );
372 if( ! fgStructure.CurrentWindow->Parent )
374 fgPlatformGlutSetIconTitle ( title );
379 * Change the current window's size
381 void FGAPIENTRY glutReshapeWindow( int width, int height )
383 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeWindow" );
384 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutReshapeWindow" );
386 if (glutGet(GLUT_FULL_SCREEN))
388 /* Leave full screen state before resizing. */
389 glutLeaveFullScreen();
392 fgStructure.CurrentWindow->State.WorkMask |= GLUT_SIZE_WORK;
393 fgStructure.CurrentWindow->State.DesiredWidth = width ;
394 fgStructure.CurrentWindow->State.DesiredHeight = height;
398 * Change the current window's position
400 void FGAPIENTRY glutPositionWindow( int x, int y )
402 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPositionWindow" );
403 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPositionWindow" );
405 if (glutGet(GLUT_FULL_SCREEN))
407 /* Leave full screen state before moving. */
408 glutLeaveFullScreen();
411 fgStructure.CurrentWindow->State.WorkMask |= GLUT_POSITION_WORK;
412 fgStructure.CurrentWindow->State.DesiredXpos = x;
413 fgStructure.CurrentWindow->State.DesiredYpos = y;
417 * Lowers the current window (by Z order change)
419 void FGAPIENTRY glutPushWindow( void )
421 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPushWindow" );
422 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPushWindow" );
424 fgStructure.CurrentWindow->State.WorkMask |= GLUT_ZORDER_WORK;
425 fgStructure.CurrentWindow->State.DesiredZOrder = -1;
429 * Raises the current window (by Z order change)
431 void FGAPIENTRY glutPopWindow( void )
433 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPopWindow" );
434 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPopWindow" );
436 fgStructure.CurrentWindow->State.WorkMask |= GLUT_ZORDER_WORK;
437 fgStructure.CurrentWindow->State.DesiredZOrder = 1;
441 * Resize the current window so that it fits the whole screen
443 void FGAPIENTRY glutFullScreen( void )
447 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
448 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
450 win = fgStructure.CurrentWindow;
454 /* Child windows cannot be made fullscreen, consistent with GLUT's behavior
455 * Also, what would it mean for a child window to be fullscreen, given that it
456 * is confined to its parent?
458 fgWarning("glutFullScreen called on a child window, ignoring...");
461 else if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==win->ID && win->State.IsFullscreen)
463 /* Ignore fullscreen call on GameMode window, those are always fullscreen already
464 * only exception is when first entering GameMode
469 if (!win->State.IsFullscreen)
470 win->State.WorkMask |= GLUT_FULL_SCREEN_WORK;
474 * If we are fullscreen, resize the current window back to its original size
476 void FGAPIENTRY glutLeaveFullScreen( void )
478 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
479 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
481 if (fgStructure.CurrentWindow->State.IsFullscreen)
482 fgStructure.CurrentWindow->State.WorkMask |= GLUT_FULL_SCREEN_WORK;
486 * Toggle the window's full screen state.
488 void FGAPIENTRY glutFullScreenToggle( void )
490 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreenToggle" );
491 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreenToggle" );
493 fgStructure.CurrentWindow->State.WorkMask |= GLUT_FULL_SCREEN_WORK;
497 * A.Donev: Set and retrieve the window's user data
499 void* FGAPIENTRY glutGetWindowData( void )
501 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetWindowData" );
502 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutGetWindowData" );
503 return fgStructure.CurrentWindow->UserData;
506 void FGAPIENTRY glutSetWindowData(void* data)
508 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowData" );
509 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowData" );
510 fgStructure.CurrentWindow->UserData = data;
513 /*** END OF FILE ***/