eBookReaderSwitch/mupdf/thirdparty/freeglut/src/fg_window.c

519 lines
15 KiB
C
Raw Normal View History

/*
* fg_window.c
*
* Window management methods.
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* 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 <GL/freeglut.h>
#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 ***/