/* * fg_window.c * * Window management methods. * * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. * Written by Pawel W. Olszta, * Creation date: Fri Dec 3 1999 * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define FREEGLUT_BUILDING_LIB #include #include "fg_internal.h" #include "fg_gl2.h" /* * TODO BEFORE THE STABLE RELEASE: * * fgSetupPixelFormat -- ignores the display mode settings * fgOpenWindow() -- check the Win32 version, -iconic handling! * fgCloseWindow() -- check the Win32 version * glutCreateWindow() -- Check when default position and size is {-1,-1} * glutCreateSubWindow() -- Check when default position and size is {-1,-1} * glutDestroyWindow() -- check the Win32 version * glutSetWindow() -- check the Win32 version * glutSetWindowTitle() -- check the Win32 version * glutSetIconTitle() -- check the Win32 version * glutShowWindow() -- check the Win32 version * glutHideWindow() -- check the Win32 version * glutIconifyWindow() -- check the Win32 version * glutPushWindow() -- check the Win32 version * glutPopWindow() -- check the Win32 version */ extern void fgPlatformSetWindow ( SFG_Window *window ); extern void fgPlatformOpenWindow( SFG_Window* window, const char* title, GLboolean positionUse, int x, int y, GLboolean sizeUse, int w, int h, GLboolean gameMode, GLboolean isSubWindow ); extern void fgPlatformCloseWindow( SFG_Window* window ); extern void fgPlatformGlutSetWindowTitle( const char* title ); extern void fgPlatformGlutSetIconTitle( const char* title ); /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ int fghIsLegacyContextRequested( void ) { return fgState.MajorVersion < 2 || (fgState.MajorVersion == 2 && fgState.MinorVersion <= 1); } int fghNumberOfAuxBuffersRequested( void ) { if ( fgState.DisplayMode & GLUT_AUX4 ) { return 4; } if ( fgState.DisplayMode & GLUT_AUX3 ) { return 3; } if ( fgState.DisplayMode & GLUT_AUX2 ) { return 2; } if ( fgState.DisplayMode & GLUT_AUX1 ) { /* NOTE: Same as GLUT_AUX! */ return fgState.AuxiliaryBufferNumber; } return 0; } int fghMapBit( int mask, int from, int to ) { return ( mask & from ) ? to : 0; } void fghContextCreationError( void ) { fgError( "Unable to create OpenGL %d.%d context (flags %x, profile %x)", fgState.MajorVersion, fgState.MinorVersion, fgState.ContextFlags, fgState.ContextProfile ); } /* -- SYSTEM-DEPENDENT PRIVATE FUNCTIONS ------------------------------------ */ /* * Sets the OpenGL context and the fgStructure "Current Window" pointer to * the window structure passed in. */ void fgSetWindow ( SFG_Window *window ) { fgPlatformSetWindow ( window ); fgStructure.CurrentWindow = window; } /* * Opens a window. Requires a SFG_Window object created and attached * to the freeglut structure. OpenGL context is created here. */ void fgOpenWindow( SFG_Window* window, const char* title, GLboolean positionUse, int x, int y, GLboolean sizeUse, int w, int h, GLboolean gameMode, GLboolean isSubWindow ) { fgPlatformOpenWindow( window, title, positionUse, x, y, sizeUse, w, h, gameMode, isSubWindow ); fgSetWindow( window ); #ifndef EGL_VERSION_1_0 window->Window.DoubleBuffered = ( fgState.DisplayMode & GLUT_DOUBLE ) ? 1 : 0; if ( ! window->Window.DoubleBuffered ) { glDrawBuffer ( GL_FRONT ); glReadBuffer ( GL_FRONT ); } #else /* - EGL is always double-buffered */ /* - No glDrawBuffer/glReadBuffer in GLES */ window->Window.DoubleBuffered = 1; #endif window->Window.attribute_v_coord = -1; window->Window.attribute_v_normal = -1; window->Window.attribute_v_texture = -1; fgInitGL2(); window->State.WorkMask |= GLUT_INIT_WORK; } /* * Closes a window, destroying the frame and OpenGL context */ void fgCloseWindow( SFG_Window* window ) { /* if we're in gamemode and we're closing the gamemode window, * call glutLeaveGameMode first to make sure the gamemode is * properly closed before closing the window */ if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==window->ID) glutLeaveGameMode(); fgPlatformCloseWindow ( window ); } /* -- INTERFACE FUNCTIONS -------------------------------------------------- */ /* * Creates a new top-level freeglut window */ int FGAPIENTRY glutCreateWindow( const char* title ) { /* XXX GLUT does not exit; it simply calls "glutInit" quietly if the * XXX application has not already done so. The "freeglut" community * XXX decided not to go this route (freeglut-developer e-mail from * XXX Steve Baker, 12/16/04, 4:22 PM CST, "Re: [Freeglut-developer] * XXX Desired 'freeglut' behaviour when there is no current window" */ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateWindow" ); return fgCreateWindow( NULL, title, fgState.Position.Use, fgState.Position.X, fgState.Position.Y, fgState.Size.Use, fgState.Size.X, fgState.Size.Y, GL_FALSE, GL_FALSE )->ID; } /* * This function creates a sub window. */ int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h ) { int ret = 0; SFG_Window* window = NULL; SFG_Window* parent = NULL; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateSubWindow" ); parent = fgWindowByID( parentID ); freeglut_return_val_if_fail( parent != NULL, 0 ); if ( x < 0 ) { x = parent->State.Width + x ; if ( w >= 0 ) x -= w ; } if ( w < 0 ) w = parent->State.Width - x + w ; if ( w < 0 ) { x += w ; w = -w ; } if ( y < 0 ) { y = parent->State.Height + y ; if ( h >= 0 ) y -= h ; } if ( h < 0 ) h = parent->State.Height - y + h ; if ( h < 0 ) { y += h ; h = -h ; } window = fgCreateWindow( parent, "", GL_TRUE, x, y, GL_TRUE, w, h, GL_FALSE, GL_FALSE ); ret = window->ID; return ret; } /* * Destroys a window and all of its subwindows */ void FGAPIENTRY glutDestroyWindow( int windowID ) { SFG_Window* window; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDestroyWindow" ); window = fgWindowByID( windowID ); freeglut_return_if_fail( window != NULL ); { fgExecutionState ExecState = fgState.ExecState; fgAddToWindowDestroyList( window ); fgState.ExecState = ExecState; } } /* * This function selects the specified window as the current window */ void FGAPIENTRY glutSetWindow( int ID ) { SFG_Window* window = NULL; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindow" ); if( fgStructure.CurrentWindow != NULL ) if( fgStructure.CurrentWindow->ID == ID ) return; window = fgWindowByID( ID ); if( window == NULL ) { fgWarning( "glutSetWindow(): window ID %d not found!", ID ); return; } fgSetWindow( window ); } /* * This function returns the ID number of the current window, 0 if none exists */ int FGAPIENTRY glutGetWindow( void ) { SFG_Window *win = fgStructure.CurrentWindow; /* * Since GLUT did not throw an error if this function was called without a prior call to * "glutInit", this function shouldn't do so here. Instead let us return a zero. * See Feature Request "[ 1307049 ] glutInit check". */ if ( ! fgState.Initialised ) return 0; while ( win && win->IsMenu ) win = win->Parent; return win ? win->ID : 0; } /* * This function makes the current window visible */ void FGAPIENTRY glutShowWindow( void ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutShowWindow" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutShowWindow" ); fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK; fgStructure.CurrentWindow->State.DesiredVisibility = DesireNormalState; fgStructure.CurrentWindow->State.WorkMask |= GLUT_DISPLAY_WORK; } /* * This function hides the current window */ void FGAPIENTRY glutHideWindow( void ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutHideWindow" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutHideWindow" ); fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK; fgStructure.CurrentWindow->State.DesiredVisibility = DesireHiddenState; fgStructure.CurrentWindow->State.WorkMask &= ~GLUT_DISPLAY_WORK; } /* * Iconify the current window (top-level windows only) */ void FGAPIENTRY glutIconifyWindow( void ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIconifyWindow" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutIconifyWindow" ); fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK; fgStructure.CurrentWindow->State.DesiredVisibility = DesireIconicState; fgStructure.CurrentWindow->State.WorkMask &= ~GLUT_DISPLAY_WORK; } /* * Set the current window's title */ void FGAPIENTRY glutSetWindowTitle( const char* title ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowTitle" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowTitle" ); if( ! fgStructure.CurrentWindow->Parent ) { fgPlatformGlutSetWindowTitle ( title ); } } /* * Set the current window's iconified title */ void FGAPIENTRY glutSetIconTitle( const char* title ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetIconTitle" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetIconTitle" ); if( ! fgStructure.CurrentWindow->Parent ) { fgPlatformGlutSetIconTitle ( title ); } } /* * This function sets the clipboard content to the UTF-8 encoded text. */ void FGAPIENTRY glutSetClipboard(int selection, const char *text) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetClipboard" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetClipboard" ); fgPlatformSetClipboard(selection, text); } /* * This function returns the clipboard content as UTF-8 encoded text, * or NULL if no content was available. */ const char* FGAPIENTRY glutGetClipboard(int selection) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetClipboard" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutGetClipboard" ); return fgPlatformGetClipboard(selection); } /* * Change the current window's size */ void FGAPIENTRY glutReshapeWindow( int width, int height ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeWindow" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutReshapeWindow" ); if (glutGet(GLUT_FULL_SCREEN)) { /* Leave full screen state before resizing. */ glutLeaveFullScreen(); } fgStructure.CurrentWindow->State.WorkMask |= GLUT_SIZE_WORK; fgStructure.CurrentWindow->State.DesiredWidth = width ; fgStructure.CurrentWindow->State.DesiredHeight = height; } /* * Change the current window's position */ void FGAPIENTRY glutPositionWindow( int x, int y ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPositionWindow" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPositionWindow" ); if (glutGet(GLUT_FULL_SCREEN)) { /* Leave full screen state before moving. */ glutLeaveFullScreen(); } fgStructure.CurrentWindow->State.WorkMask |= GLUT_POSITION_WORK; fgStructure.CurrentWindow->State.DesiredXpos = x; fgStructure.CurrentWindow->State.DesiredYpos = y; } /* * Lowers the current window (by Z order change) */ void FGAPIENTRY glutPushWindow( void ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPushWindow" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPushWindow" ); fgStructure.CurrentWindow->State.WorkMask |= GLUT_ZORDER_WORK; fgStructure.CurrentWindow->State.DesiredZOrder = -1; } /* * Raises the current window (by Z order change) */ void FGAPIENTRY glutPopWindow( void ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPopWindow" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPopWindow" ); fgStructure.CurrentWindow->State.WorkMask |= GLUT_ZORDER_WORK; fgStructure.CurrentWindow->State.DesiredZOrder = 1; } /* * Resize the current window so that it fits the whole screen */ void FGAPIENTRY glutFullScreen( void ) { SFG_Window *win; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" ); win = fgStructure.CurrentWindow; if (win->Parent) { /* Child windows cannot be made fullscreen, consistent with GLUT's behavior * Also, what would it mean for a child window to be fullscreen, given that it * is confined to its parent? */ fgWarning("glutFullScreen called on a child window, ignoring..."); return; } else if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==win->ID && win->State.IsFullscreen) { /* Ignore fullscreen call on GameMode window, those are always fullscreen already * only exception is when first entering GameMode */ return; } if (!win->State.IsFullscreen) win->State.WorkMask |= GLUT_FULL_SCREEN_WORK; } /* * If we are fullscreen, resize the current window back to its original size */ void FGAPIENTRY glutLeaveFullScreen( void ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" ); if (fgStructure.CurrentWindow->State.IsFullscreen) fgStructure.CurrentWindow->State.WorkMask |= GLUT_FULL_SCREEN_WORK; } /* * Toggle the window's full screen state. */ void FGAPIENTRY glutFullScreenToggle( void ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreenToggle" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreenToggle" ); fgStructure.CurrentWindow->State.WorkMask |= GLUT_FULL_SCREEN_WORK; } /* * A.Donev: Set and retrieve the window's user data */ void* FGAPIENTRY glutGetWindowData( void ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetWindowData" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutGetWindowData" ); return fgStructure.CurrentWindow->UserData; } void FGAPIENTRY glutSetWindowData(void* data) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowData" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowData" ); fgStructure.CurrentWindow->UserData = data; } /*** END OF FILE ***/