- moving to a new way of handling window changes (position, size, visibility)

- we now use a work list and all actions queued up in that list get executed in the main loop, just before redraws are called
- simplified redrawing on windows, now no longer doing so in response to WM_PAINT message. This allows us to full control over when we draw
- now simplified use of state variables in X11 and andriod
- resize, reposition etc callback now processed thru notify checkers that call callback only if needed
- worklist also has an init work type which is executed once for every window, just before the window receives its first draw. This gets rid of hacks to call the reshape function once (that only worked for windows that are created before mainloop is entered)
- in init work processor we also check for presence of draw callback as not having one is an error following GLUT.
- some cleanup in general

git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1577 7f0cb862-5218-0410-a997-914c9d46530a
This commit is contained in:
dcnieho 2013-04-04 01:56:39 +00:00
parent 52bd423f58
commit 0685ee4d0d
18 changed files with 1341 additions and 1137 deletions

1
.gitattributes vendored
View File

@ -107,7 +107,6 @@ freeglut/freeglut/src/fg_input_devices.c svn_keywords=Author+Date+Id+Revision
freeglut/freeglut/src/fg_internal.h svn_keywords=Author+Date+Id+Revision
freeglut/freeglut/src/fg_joystick.c svn_keywords=Author+Date+Id+Revision
freeglut/freeglut/src/fg_main.c svn_keywords=Author+Date+Id+Revision
freeglut/freeglut/src/fg_main.h -text
freeglut/freeglut/src/fg_menu.c svn_keywords=Author+Date+Id+Revision
freeglut/freeglut/src/fg_misc.c svn_keywords=Author+Date+Id+Revision
freeglut/freeglut/src/fg_overlay.c svn_keywords=Author+Date+Id+Revision

View File

@ -4,10 +4,6 @@
int nWindow, nChildWindow = -1;
int nLoopMain = 0;
int nPosX, nPosY;
int nWidth, nHeight;
GLboolean bChildPosDone = GL_FALSE, bChildSizeDone = GL_FALSE;
void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY );
@ -21,14 +17,14 @@ void WindowStatus(int state);
void DrawQuad()
{
nWidth = glutGet(GLUT_WINDOW_WIDTH);
nHeight = glutGet(GLUT_WINDOW_HEIGHT);
int width = glutGet(GLUT_WINDOW_WIDTH);
int height = glutGet(GLUT_WINDOW_HEIGHT);
glBegin(GL_QUADS);
glVertex2d(nWidth*.25, nHeight*.75);
glVertex2d(nWidth*.75, nHeight*.75);
glVertex2d(nWidth*.75, nHeight*.25);
glVertex2d(nWidth*.25, nHeight*.25);
glVertex2d(width*.25, height*.75);
glVertex2d(width*.75, height*.75);
glVertex2d(width*.75, height*.25);
glVertex2d(width*.25, height*.25);
glEnd();
}
@ -38,6 +34,12 @@ void UnhideTimer(int window)
glutShowWindow();
}
void ChangeTitleTimer(int unused)
{
glutSetIconTitle("new icon title");
glutSetWindowTitle("new test title");
}
void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY )
{
switch (cChar)
@ -72,7 +74,7 @@ void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY )
{
glutSetWindow(nWindow);
printf("main window resize\n");
if (nWidth<400)
if (glutGet(GLUT_WINDOW_WIDTH)<400)
glutReshapeWindow(600,300);
else
glutReshapeWindow(300,300);
@ -103,7 +105,7 @@ void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY )
* the client area is at a different position if the window has borders
* and/or a title bar.
*/
if (nPosX<400)
if (glutGet(GLUT_WINDOW_X)<400)
glutPositionWindow(600,300);
else
glutPositionWindow(300,300);
@ -112,16 +114,47 @@ void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY )
break;
case 'd':
case 'D':
if (nChildWindow!=-1 && cChar=='d') /* Capital D always moves+resizes the main window*/
{
glutSetWindow(nChildWindow);
if (!bChildPosDone)
glutPositionWindow(glutGet(GLUT_WINDOW_X)+50,glutGet(GLUT_WINDOW_Y)+50);
else
glutPositionWindow(glutGet(GLUT_WINDOW_X)-50,glutGet(GLUT_WINDOW_Y)-50);
bChildPosDone = !bChildPosDone;
if (!bChildSizeDone)
glutReshapeWindow(glutGet(GLUT_WINDOW_WIDTH)+50,glutGet(GLUT_WINDOW_HEIGHT)+50);
else
glutReshapeWindow(glutGet(GLUT_WINDOW_WIDTH)-50,glutGet(GLUT_WINDOW_HEIGHT)-50);
bChildSizeDone = !bChildSizeDone;
}
else
{
if (glutGet(GLUT_WINDOW_X)<400)
glutPositionWindow(600,300);
else
glutPositionWindow(300,300);
if (glutGet(GLUT_WINDOW_WIDTH)<400)
glutReshapeWindow(600,300);
else
glutReshapeWindow(300,300);
}
break;
case 'c':
case 'C':
if (nChildWindow==-1)
{
int width = glutGet(GLUT_WINDOW_WIDTH);
int height = glutGet(GLUT_WINDOW_HEIGHT);
/* open child window */
printf("open child window\n");
nWidth = glutGet(GLUT_WINDOW_WIDTH);
nHeight = glutGet(GLUT_WINDOW_HEIGHT);
nChildWindow = glutCreateSubWindow(nWindow,(int)(nWidth*.35),(int)(nHeight*.35),(int)(nWidth*.3),(int)(nHeight*.3));
nChildWindow = glutCreateSubWindow(nWindow,(int)(width*.35),(int)(height*.35),(int)(width*.3),(int)(height*.3));
glutKeyboardFunc( SampleKeyboard );
glutDisplayFunc( Redisplay );
glutReshapeFunc( Reshape );
@ -144,6 +177,7 @@ void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY )
case 'i':
case 'I':
glutIconifyWindow();
glutTimerFunc(1500, ChangeTitleTimer, 0);
break;
@ -175,7 +209,7 @@ void Reshape(int width, int height)
{
int win = glutGetWindow();
printf("reshape %s, %dx%d\n",win==nWindow?"main":"child",
printf("reshape %s, client area: %dx%d\n",win==nWindow?"main":"child",
width, height);
glViewport(0,0,width,height);
@ -185,9 +219,21 @@ void Reshape(int width, int height)
if (win==nWindow && nChildWindow!=-1)
{
/* Put child window in right place */
int x = (int)(width*.35), y=(int)(height*.35), w=(int)(width*.3), h = (int)(height*.3);
if (bChildPosDone)
{
x += 50;
y += 50;
}
if (bChildSizeDone)
{
w += 50;
h += 50;
}
glutSetWindow(nChildWindow);
glutPositionWindow((int)(width*.35),(int)(height*.35));
glutReshapeWindow((int)(width*.3),(int)(height*.3));
glutPositionWindow(x,y);
glutReshapeWindow(w,h);
glutSetWindow(nWindow);
}
}
@ -196,7 +242,7 @@ void Position(int x, int y)
{
int win = glutGetWindow();
printf("position, %s: (%d,%d)\n",win==nWindow?"top-left of main":"top-left of child relative to parent",
printf("position, %s: (%d,%d)\n",win==nWindow?"top-left (non-client) of main":"top-left of child relative to parent",
x, y);
}
@ -232,12 +278,14 @@ void Redisplay(void)
void Timer(int unused)
{
int win = glutGetWindow();
int x, y;
int width, height;
int border, caption;
nPosX = glutGet(GLUT_WINDOW_X);
nPosY = glutGet(GLUT_WINDOW_Y);
nWidth = glutGet(GLUT_WINDOW_WIDTH);
nHeight = glutGet(GLUT_WINDOW_HEIGHT);
x = glutGet(GLUT_WINDOW_X);
y = glutGet(GLUT_WINDOW_Y);
width = glutGet(GLUT_WINDOW_WIDTH);
height = glutGet(GLUT_WINDOW_HEIGHT);
border = glutGet(GLUT_WINDOW_BORDER_WIDTH);
caption = glutGet(GLUT_WINDOW_HEADER_HEIGHT);
/* returned position is top-left of client area, to get top-left of
@ -253,14 +301,14 @@ void Timer(int unused)
/* printf("window border: %dpx, caption: %dpx\n",border,caption); */
if (win==nWindow)
printf("main window %dx%d, top-left of client at: (%d,%d), of window at: (%d,%d)\n",
nWidth, nHeight,
nPosX ,nPosY,
nPosX-border,
nPosY-border-caption);
width, height,
x ,y,
x-border,
y-border-caption);
else
printf("child window %dx%d, top-left of client at: (%d,%d), relative to parent\n",
nWidth, nHeight,
nPosX ,nPosY);
width, height,
x ,y);
/* (re)set the timer callback and ask glut to call it in 500 ms */
glutTimerFunc(500, Timer, 0);
@ -287,6 +335,7 @@ int main(int argc, char* argv[])
glutInitWindowSize(200,200);
nWindow = glutCreateWindow("test");
glutSetIconTitle("test icon title");
printf("main window id: %d\n", nWindow);
glutKeyboardFunc( SampleKeyboard );

View File

@ -106,8 +106,7 @@ struct tagSFG_PlatformJoystick
typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState;
struct tagSFG_PlatformWindowState
{
int32_t LastHeight;
int32_t LastWidth;
char unused;
};
#endif /* FREEGLUT_INTERNAL_ANDROID_H */

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,4 @@
void fgPlatformCreateWindow ( SFG_Window *window )
{
fghPlatformCreateWindowEGL(window);
window->State.pWState.LastWidth = -1;
window->State.pWState.LastHeight = -1;
}

View File

@ -32,8 +32,6 @@
#include "egl/fg_window_egl.h"
#include <android/native_app_glue/android_native_app_glue.h>
extern void fghRedrawWindow(SFG_Window *window);
/*
* Opens a window. Requires a SFG_Window object created and attached
* to the freeglut structure. OpenGL context is created here.
@ -95,14 +93,6 @@ void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height )
fprintf(stderr, "fgPlatformReshapeWindow: STUB\n");
}
/*
* A static helper function to execute display callback for a window
*/
void fgPlatformDisplayWindow ( SFG_Window *window )
{
fghRedrawWindow ( window ) ;
}
/*
* Closes a window, destroying the frame and OpenGL context
*/
@ -113,25 +103,25 @@ void fgPlatformCloseWindow( SFG_Window* window )
}
/*
* This function makes the current window visible
* This function makes the specified window visible
*/
void fgPlatformGlutShowWindow( void )
void fgPlatformShowWindow( void )
{
fprintf(stderr, "fgPlatformGlutShowWindow: STUB\n");
fprintf(stderr, "fgPlatformShowWindow: STUB\n");
}
/*
* This function hides the current window
* This function hides the specified window
*/
void fgPlatformGlutHideWindow( void )
void fgPlatformHideWindow( SFG_Window *window )
{
fprintf(stderr, "fgPlatformGlutHideWindow: STUB\n");
fprintf(stderr, "fgPlatformHideWindow: STUB\n");
}
/*
* Iconify the current window (top-level windows only)
* Iconify the specified window (top-level windows only)
*/
void fgPlatformGlutIconifyWindow( void )
void fgPlatformIconifyWindow( SFG_Window *window )
{
fprintf(stderr, "fgPlatformGlutIconifyWindow: STUB\n");
}
@ -152,49 +142,33 @@ void fgPlatformGlutSetIconTitle( const char* title )
fprintf(stderr, "fgPlatformGlutSetIconTitle: STUB\n");}
/*
* Change the current window's position
* Change the specified window's position
*/
void fgPlatformGlutPositionWindow( int x, int y )
void fgPlatformPositionWindow( SFG_Window *window, int x, int y )
{
fprintf(stderr, "fgPlatformGlutPositionWindow: STUB\n");
fprintf(stderr, "fgPlatformPositionWindow: STUB\n");
}
/*
* Lowers the current window (by Z order change)
* Lowers the specified window (by Z order change)
*/
void fgPlatformGlutPushWindow( void )
void fgPlatformPushWindow( SFG_Window *window )
{
fprintf(stderr, "fgPlatformGlutPushWindow: STUB\n");
fprintf(stderr, "fgPlatformPushWindow: STUB\n");
}
/*
* Raises the current window (by Z order change)
* Raises the specified window (by Z order change)
*/
void fgPlatformGlutPopWindow( void )
void fgPlatformPopWindow( SFG_Window *window )
{
fprintf(stderr, "fgPlatformGlutPopWindow: STUB\n");
}
/*
* Resize the current window so that it fits the whole screen
*/
void fgPlatformGlutFullScreen( SFG_Window *win )
{
fprintf(stderr, "fgPlatformGlutFullScreen: STUB\n");
}
/*
* If we are fullscreen, resize the current window back to its original size
*/
void fgPlatformGlutLeaveFullScreen( SFG_Window *win )
{
fprintf(stderr, "fgPlatformGlutLeaveFullScreen: STUB\n");
fprintf(stderr, "fgPlatformPopWindow: STUB\n");
}
/*
* Toggle the window's full screen state.
*/
void fgPlatformGlutFullScreenToggle( SFG_Window *win )
void fgPlatformFullScreenToggle( SFG_Window *win )
{
fprintf(stderr, "fgPlatformGlutFullScreenToggle: STUB\n");
fprintf(stderr, "fgPlatformFullScreenToggle: STUB\n");
}

View File

@ -28,15 +28,6 @@
#include <GL/freeglut.h>
#include "fg_internal.h"
/*
* TODO BEFORE THE STABLE RELEASE:
*
* glutGameModeString() -- missing
* glutEnterGameMode() -- X11 version
* glutLeaveGameMode() -- is that correct?
* glutGameModeGet() -- is that correct?
*/
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
extern void fgPlatformRememberState( void );

View File

@ -382,19 +382,86 @@ struct tagSFG_Context
};
typedef struct tagSFG_WindowState SFG_WindowState;
struct tagSFG_WindowState
/*
* Bitmasks indicating the different kinds of
* actions that can be scheduled for a window.
*/
#define GLUT_INIT_WORK (1<<0)
#define GLUT_VISIBILITY_WORK (1<<1)
#define GLUT_POSITION_WORK (1<<2)
#define GLUT_SIZE_WORK (1<<3)
#define GLUT_ZORDER_WORK (1<<4)
#define GLUT_FULL_SCREEN_WORK (1<<5)
/*
* An enumeration containing the state of the GLUT execution:
* initializing, running, or stopping
*/
typedef enum
{
/* Note that on Windows, sizes always refer to the client area, thus without the window decorations */
DesireHiddenState,
DesireIconicState,
DesireNormalState
} fgDesiredVisibility ;
/*
* There is considerable confusion about the "right thing to
* do" concerning window size and position. GLUT itself is
* not consistent between Windows and UNIX/X11; since
* platform independence is a virtue for "freeglut", we
* decided to break with GLUT's behaviour.
*
* Under UNIX/X11, it is apparently not possible to get the
* window border sizes in order to subtract them off the
* window's initial position until some time after the window
* has been created. Therefore we decided on the following
* behaviour, both under Windows and under UNIX/X11:
* - When you create a window with position (x,y) and size
* (w,h), the upper left hand corner of the outside of the
* window is at (x,y) and the size of the drawable area is
* (w,h).
* - When you query the size and position of the window--as
* is happening here for Windows--"freeglut" will return
* the size of the drawable area--the (w,h) that you
* specified when you created the window--and the coordinates
* of the upper left hand corner of the drawable area, i.e.
* of the client rect--which is NOT the (x,y) you specified.
*/
typedef struct tagSFG_WindowState SFG_WindowState;
struct tagSFG_WindowState /* as per notes above, sizes always refer to the client area (thus without the window decorations) */
{
/* window state - size, position, look */
int Xpos; /* Window's top-left of client area, X-coordinate */
int Ypos; /* Window's top-left of client area, Y-coordinate */
int Width; /* Window's width in pixels */
int Height; /* The same about the height */
GLboolean Visible; /* Is the window visible now? Not using fgVisibilityState as we only care if visible or not */
int Cursor; /* The currently selected cursor style */
GLboolean IsFullscreen; /* is the window fullscreen? */
/* FreeGLUT operations are deferred, that is, window moving, resizing,
* Z-order changing, making full screen or not do not happen immediately
* upon the user's request, but only in the next iteration of the main
* loop, before the display callback is called. This allows multiple
* reshape, position, etc requests to be combined into one and is
* compatible with the way GLUT does things. Callbacks get triggered
* based on the feedback/messages/notifications from the window manager.
* Below here we define what work should be done, as well as the relevant
* parameters for this work.
*/
unsigned int WorkMask; /* work (resize, etc) to be done on the window */
int DesiredXpos; /* desired X location */
int DesiredYpos; /* desired Y location */
int DesiredWidth; /* desired window width */
int DesiredHeight; /* desired window height */
int DesiredZOrder; /* desired window Z Order position */
fgDesiredVisibility DesiredVisibility;/* desired visibility (hidden, iconic, shown/normal) */
SFG_PlatformWindowState pWState; /* Window width/height (X11) or rectangle/style (Windows) from before a resize, and other stuff only needed on specific platforms */
GLboolean Redisplay; /* Do we have to redisplay? */
GLboolean Visible; /* Is the window visible now */
int Cursor; /* The currently selected cursor */
long JoystickPollRate; /* The joystick polling rate */
fg_time_t JoystickLastPoll; /* When the last poll happened */
@ -402,13 +469,6 @@ struct tagSFG_WindowState
int MouseX, MouseY; /* The most recent mouse position */
GLboolean IgnoreKeyRepeat; /* Whether to ignore key repeat. */
GLboolean KeyRepeating; /* Currently in repeat mode */
GLboolean NeedToResize; /* Do we need to resize the window? */
GLboolean IsFullscreen; /* is the window fullscreen? */
GLboolean NeedToInitContext; /* are OpenGL context/resources loaded? */
GLboolean VisualizeNormals; /* When drawing objects, draw vectors representing the normals as well? */
};

View File

@ -54,8 +54,7 @@
# define MIN(a,b) (((a)<(b)) ? (a) : (b))
#endif
extern void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height );
extern void fgPlatformDisplayWindow ( SFG_Window *window );
extern void fgPlatformProcessWork ( SFG_Window *window );
extern fg_time_t fgPlatformSystemTime ( void );
extern void fgPlatformSleepForEvents( fg_time_t msec );
extern void fgPlatformProcessSingleEvent ( void );
@ -66,71 +65,120 @@ extern void fgPlatformMainLoopPreliminaryWork ( void );
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
static void fghReshapeWindow ( SFG_Window *window, int width, int height )
void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify)
{
SFG_Window *current_window = fgStructure.CurrentWindow;
GLboolean notify = GL_FALSE;
freeglut_return_if_fail( window != NULL );
if( width != window->State.Width ||
height != window->State.Height )
{
window->State.Width = width;
window->State.Height = height;
fgPlatformReshapeWindow ( window, width, height );
notify = GL_TRUE;
}
/*
* Force a window redraw. In Windows at least this is only a partial
* solution: if the window is increasing in size in either dimension,
* the already-drawn part does not get drawn again and things look funny.
* But without this we get this bad behaviour whenever we resize the
* window.
* DN: Hmm.. the above sounds like a concern only in single buffered mode...
*/
window->State.Redisplay = GL_TRUE;
if (notify || forceNotify)
{
SFG_Window *saved_window = fgStructure.CurrentWindow;
if( window->IsMenu )
fgSetWindow( current_window );
INVOKE_WCB( *window, Reshape, ( width, height ) );
/*
* Force a window redraw. In Windows at least this is only a partial
* solution: if the window is increasing in size in either dimension,
* the already-drawn part does not get drawn again and things look funny.
* But without this we get this bad behaviour whenever we resize the
* window.
* DN: Hmm.. the above sounds like a concern only in single buffered mode...
*/
glutPostRedisplay( );
if( window->IsMenu )
fgSetWindow( saved_window );
}
}
void fghOnPositionNotify(SFG_Window *window, int x, int y, GLboolean forceNotify)
{
GLboolean notify = GL_FALSE;
if( x != window->State.Xpos ||
y != window->State.Ypos )
{
window->State.Xpos = x;
window->State.Ypos = y;
notify = GL_TRUE;
}
if (notify || forceNotify)
{
SFG_Window *saved_window = fgStructure.CurrentWindow;
INVOKE_WCB( *window, Position, ( x, y ) );
fgSetWindow( saved_window );
}
}
/*
* Calls a window's redraw method. This is used when
* a redraw is forced by the incoming window messages.
* a redraw is forced by the incoming window messages,
* or if a redisplay is otherwise pending.
* this is lean and mean without checks as it is
* currently only called from fghcbDisplayWindow which
* only calls this if the window is visible and needs
* a redisplay.
* Note that the fgSetWindow call on Windows makes the
* right device context current on windows, allowing
* direct drawing without BeginPaint/EndPaint in the
* WM_PAINT handler.
*/
void fghRedrawWindow ( SFG_Window *window )
{
SFG_Window *current_window = fgStructure.CurrentWindow;
freeglut_return_if_fail( window );
if( window->State.NeedToInitContext ) {
INVOKE_WCB( *window, InitContext, ());
window->State.NeedToInitContext = GL_FALSE;
}
freeglut_return_if_fail( FETCH_WCB ( *window, Display ) );
window->State.Redisplay = GL_FALSE;
freeglut_return_if_fail( window->State.Visible );
fgSetWindow( window );
if( window->State.NeedToResize )
{
/* Set need to resize to false before calling fghReshapeWindow, otherwise
in the case the user's reshape callback calls glutReshapeWindow,
his request would get canceled after fghReshapeWindow gets called.
*/
window->State.NeedToResize = GL_FALSE;
fghReshapeWindow(
window,
window->State.Width,
window->State.Height
);
}
INVOKE_WCB( *window, Display, ( ) );
fgSetWindow( current_window );
}
void fghRedrawWindowAndChildren ( SFG_Window *window )
{
SFG_Window* child;
fghRedrawWindow(window);
for( child = ( SFG_Window * )window->Children.First;
child;
child = ( SFG_Window * )child->Node.Next )
{
fghRedrawWindowAndChildren(child);
}
}
static void fghcbProcessWork( SFG_Window *window,
SFG_Enumerator *enumerator )
{
if( window->State.WorkMask )
fgPlatformProcessWork ( window );
fgEnumSubWindows( window, fghcbProcessWork, enumerator );
}
/*
* Make all windows process their work list
*/
static void fghProcessWork( void )
{
SFG_Enumerator enumerator;
enumerator.found = GL_FALSE;
enumerator.data = NULL;
fgEnumWindows( fghcbProcessWork, &enumerator );
}
static void fghcbDisplayWindow( SFG_Window *window,
SFG_Enumerator *enumerator )
@ -139,7 +187,7 @@ static void fghcbDisplayWindow( SFG_Window *window,
window->State.Visible )
{
window->State.Redisplay = GL_FALSE;
fgPlatformDisplayWindow ( window );
fghRedrawWindow ( window );
}
fgEnumSubWindows( window, fghcbDisplayWindow, enumerator );
@ -376,12 +424,18 @@ static void fghSleepForEvents( void )
*/
void FGAPIENTRY glutMainLoopEvent( void )
{
/* Process input */
fgPlatformProcessSingleEvent ();
if( fgState.Timers.First )
fghCheckTimers( );
if (fgState.NumActiveJoysticks>0) /* If zero, don't poll joysticks */
fghCheckJoystickPolls( );
/* Perform work on the window (position, reshape, etc) */
fghProcessWork( );
/* Display */
fghDisplayAll( );
fgCloseWindows( );

View File

@ -56,17 +56,8 @@ extern void fgPlatformOpenWindow( SFG_Window* window, const char* title,
GLboolean sizeUse, int w, int h,
GLboolean gameMode, GLboolean isSubWindow );
extern void fgPlatformCloseWindow( SFG_Window* window );
extern void fgPlatformGlutShowWindow( void );
extern void fgPlatformGlutHideWindow( void );
extern void fgPlatformGlutIconifyWindow( void );
extern void fgPlatformGlutSetWindowTitle( const char* title );
extern void fgPlatformGlutSetIconTitle( const char* title );
extern void fgPlatformGlutPositionWindow( int x, int y );
extern void fgPlatformGlutPushWindow( void );
extern void fgPlatformGlutPopWindow( void );
extern void fgPlatformGlutFullScreen( SFG_Window *win );
extern void fgPlatformGlutLeaveFullScreen( SFG_Window *win );
extern void fgPlatformGlutFullScreenToggle( SFG_Window *win );
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
@ -152,7 +143,7 @@ void fgOpenWindow( SFG_Window* window, const char* title,
fgInitGL2();
window->State.NeedToInitContext = GL_TRUE;
window->State.WorkMask |= GLUT_INIT_WORK;
}
/*
@ -301,7 +292,8 @@ void FGAPIENTRY glutShowWindow( void )
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutShowWindow" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutShowWindow" );
fgPlatformGlutShowWindow ();
fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK;
fgStructure.CurrentWindow->State.DesiredVisibility = DesireNormalState;
fgStructure.CurrentWindow->State.Redisplay = GL_TRUE;
}
@ -314,7 +306,8 @@ void FGAPIENTRY glutHideWindow( void )
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutHideWindow" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutHideWindow" );
fgPlatformGlutHideWindow ();
fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK;
fgStructure.CurrentWindow->State.DesiredVisibility = DesireHiddenState;
fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;
}
@ -327,7 +320,8 @@ void FGAPIENTRY glutIconifyWindow( void )
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIconifyWindow" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutIconifyWindow" );
fgPlatformGlutIconifyWindow ();
fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK;
fgStructure.CurrentWindow->State.DesiredVisibility = DesireIconicState;
fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;
}
@ -373,9 +367,9 @@ void FGAPIENTRY glutReshapeWindow( int width, int height )
glutLeaveFullScreen();
}
fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
fgStructure.CurrentWindow->State.Width = width ;
fgStructure.CurrentWindow->State.Height = height;
fgStructure.CurrentWindow->State.WorkMask |= GLUT_SIZE_WORK;
fgStructure.CurrentWindow->State.DesiredWidth = width ;
fgStructure.CurrentWindow->State.DesiredHeight = height;
}
/*
@ -392,7 +386,9 @@ void FGAPIENTRY glutPositionWindow( int x, int y )
glutLeaveFullScreen();
}
fgPlatformGlutPositionWindow ( x, y );
fgStructure.CurrentWindow->State.WorkMask |= GLUT_POSITION_WORK;
fgStructure.CurrentWindow->State.DesiredXpos = x;
fgStructure.CurrentWindow->State.DesiredYpos = y;
}
/*
@ -403,7 +399,8 @@ void FGAPIENTRY glutPushWindow( void )
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPushWindow" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPushWindow" );
fgPlatformGlutPushWindow ();
fgStructure.CurrentWindow->State.WorkMask |= GLUT_ZORDER_WORK;
fgStructure.CurrentWindow->State.DesiredZOrder = -1;
}
/*
@ -414,7 +411,8 @@ void FGAPIENTRY glutPopWindow( void )
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPopWindow" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPopWindow" );
fgPlatformGlutPopWindow ();
fgStructure.CurrentWindow->State.WorkMask |= GLUT_ZORDER_WORK;
fgStructure.CurrentWindow->State.DesiredZOrder = 1;
}
/*
@ -441,12 +439,13 @@ void FGAPIENTRY glutFullScreen( void )
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 during first entering GameMode
* only exception is when first entering GameMode
*/
return;
}
fgPlatformGlutFullScreen ( win );
if (!win->State.IsFullscreen)
win->State.WorkMask |= GLUT_FULL_SCREEN_WORK;
}
/*
@ -454,14 +453,11 @@ void FGAPIENTRY glutFullScreen( void )
*/
void FGAPIENTRY glutLeaveFullScreen( void )
{
SFG_Window *win;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
win = fgStructure.CurrentWindow;
fgPlatformGlutLeaveFullScreen ( win );
if (fgStructure.CurrentWindow->State.IsFullscreen)
fgStructure.CurrentWindow->State.WorkMask |= GLUT_FULL_SCREEN_WORK;
}
/*
@ -469,14 +465,10 @@ void FGAPIENTRY glutLeaveFullScreen( void )
*/
void FGAPIENTRY glutFullScreenToggle( void )
{
SFG_Window *win;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreenToggle" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreenToggle" );
win = fgStructure.CurrentWindow;
fgPlatformGlutFullScreenToggle ( win );
fgStructure.CurrentWindow->State.WorkMask |= GLUT_FULL_SCREEN_WORK;
}
/*

View File

@ -97,7 +97,6 @@ struct tagSFG_PlatformWindowState
BOOL OldMaximized; /* window maximized state - stored before the window is made fullscreen */
GLboolean MouseTracking; /* Needed for generating GLUT_ENTERED and GLUT_LEFT entry func callbacks on windows */
GLboolean WindowFuncCalled; /* Indicate whether windowStatus/visibility func was notified that this window was created */
/* Need to store window titles to emulate
* glutSetIconTitle/glutSetWindowTitle as Windows has only

View File

@ -28,8 +28,12 @@
#include <GL/freeglut.h>
#include "../fg_internal.h"
extern void fghRedrawWindow ( SFG_Window *window );
extern void fghRedrawWindowAndChildren ( SFG_Window *window );
extern void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify);
extern void fghOnPositionNotify(SFG_Window *window, int x, int y, GLboolean forceNotify);
extern void fghComputeWindowRectFromClientArea_QueryWindow( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside );
extern void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside );
extern void fgNewWGLCreateContext( SFG_Window* window );
extern GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
@ -128,17 +132,14 @@ void fgPlatformProcessSingleEvent ( void )
static void fghUpdateWindowStatus(SFG_Window *window, GLboolean visState)
static void fghPlatformOnWindowStatusNotify(SFG_Window *window, GLboolean visState, GLboolean forceNotify)
{
GLboolean notify = GL_FALSE;
SFG_Window* child;
if (window->State.Visible != visState)
{
window->State.Visible = visState;
/* On win32 we only have two states, window displayed and window not displayed (iconified)
* We map these to GLUT_FULLY_RETAINED and GLUT_HIDDEN respectively.
*/
INVOKE_WCB( *window, WindowStatus, ( visState ? GLUT_FULLY_RETAINED:GLUT_HIDDEN ) );
/* If top level window (not a subwindow/child), and icon title text available, switch titles based on visibility state */
if (!window->Parent && window->State.pWState.IconTitle)
@ -150,24 +151,30 @@ static void fghUpdateWindowStatus(SFG_Window *window, GLboolean visState)
/* not visible, set icon title */
SetWindowText( window->Window.Handle, window->State.pWState.IconTitle );
}
notify = GL_TRUE;
}
/* Also set visibility state for children */
if (notify || forceNotify)
{
SFG_Window *saved_window = fgStructure.CurrentWindow;
/* On win32 we only have two states, window displayed and window not displayed (iconified)
* We map these to GLUT_FULLY_RETAINED and GLUT_HIDDEN respectively.
*/
INVOKE_WCB( *window, WindowStatus, ( visState ? GLUT_FULLY_RETAINED:GLUT_HIDDEN ) );
fgSetWindow( saved_window );
}
/* Also set windowStatus/visibility state for children */
for( child = ( SFG_Window * )window->Children.First;
child;
child = ( SFG_Window * )child->Node.Next )
{
fghUpdateWindowStatus(child, visState);
fghPlatformOnWindowStatusNotify(child, visState, GL_FALSE); /* No need to propagate forceNotify. Childs get this from their own INIT_WORK */
}
}
void fghNotifyWindowStatus(SFG_Window *window)
{
INVOKE_WCB( *window, WindowStatus, ( window->State.Visible?GLUT_FULLY_RETAINED:GLUT_HIDDEN ) );
/* Don't notify children, they get their own just before first time they're drawn */
}
void fgPlatformMainLoopPreliminaryWork ( void )
{
/* no-op */
@ -447,21 +454,6 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
#endif
}
window->State.NeedToResize = GL_TRUE;
/* if we used CW_USEDEFAULT (thats a negative value) for the size
* of the window, query the window now for the size at which it
* was created.
*/
if( ( window->State.Width < 0 ) || ( window->State.Height < 0 ) )
{
SFG_Window *current_window = fgStructure.CurrentWindow;
fgSetWindow( window );
window->State.Width = glutGet( GLUT_WINDOW_WIDTH );
window->State.Height = glutGet( GLUT_WINDOW_HEIGHT );
fgSetWindow( current_window );
}
ReleaseDC( window->Window.Handle, window->Window.pContext.Device );
#if defined(_WIN32_WCE)
@ -488,48 +480,71 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
/* Update visibility state of the window */
if (wParam==SIZE_MINIMIZED)
fghUpdateWindowStatus(window,GL_FALSE);
fghPlatformOnWindowStatusNotify(window,GL_FALSE,GL_FALSE);
else if (wParam==SIZE_RESTORED && !window->State.Visible)
fghUpdateWindowStatus(window,GL_TRUE);
fghPlatformOnWindowStatusNotify(window,GL_TRUE,GL_FALSE);
/* Check window visible, we don't want to resize when the user or glutIconifyWindow minimized the window */
/* Check window visible, we don't want do anything when we get a WM_SIZE because the user or glutIconifyWindow minimized the window */
if( window->State.Visible )
{
/* get old values first to compare to below */
int width = window->State.Width, height=window->State.Height;
int width, height;
#if defined(_WIN32_WCE)
window->State.Width = HIWORD(lParam);
window->State.Height = LOWORD(lParam);
width = HIWORD(lParam);
height = LOWORD(lParam);
#else
window->State.Width = LOWORD(lParam);
window->State.Height = HIWORD(lParam);
width = LOWORD(lParam);
height = HIWORD(lParam);
#endif /* defined(_WIN32_WCE) */
if (width!=window->State.Width || height!=window->State.Height)
{
SFG_Window* saved_window = fgStructure.CurrentWindow;
/* size changed, call reshape callback */
INVOKE_WCB( *window, Reshape, ( width, height ) );
glutPostRedisplay( );
if( window->IsMenu )
fgSetWindow( saved_window );
}
/* Update state and call callback, if there was a change */
fghOnReshapeNotify(window, width, height, GL_FALSE);
}
/* according to docs, should return 0 */
lRet = 0;
break;
case WM_SIZING:
{
/* User resize-dragging the window, call reshape callback and
* force redisplay so display keeps running during dragging.
* Screen still wont update when not moving the cursor though...
*/
/* PRECT prect = (PRECT) lParam; */
RECT rect;
/* printf("WM_SIZING: nc-area: %i,%i\n",prect->right-prect->left,prect->bottom-prect->top); */
/* Get client area, the rect in lParam is including non-client area. */
fghGetClientArea(&rect,window,FALSE);
/* We'll get a WM_SIZE as well, but as state has
* already been updated here, the fghOnReshapeNotify
* in the handler for that message doesn't do anything.
*/
fghOnReshapeNotify(window, rect.right-rect.left, rect.bottom-rect.top, GL_FALSE);
/* Now directly call the drawing function to update
* window and window's childs.
* This mimics the WM_PAINT messages that are received during
* resizing. Note that we don't have a WM_MOVING handler
* as move-dragging doesn't generate WM_MOVE or WM_PAINT
* messages until the mouse is released.
*/
fghRedrawWindowAndChildren(window);
}
/* according to docs, should return TRUE */
lRet = TRUE;
break;
case WM_MOVE:
{
SFG_Window* saved_window = fgStructure.CurrentWindow;
RECT windowRect;
/* Check window is minimized, we don't want to call the position callback when the user or glutIconifyWindow minimized the window */
if (!IsIconic(window->Window.Handle))
{
/* Get top-left of non-client area of window, matching coordinates of
RECT windowRect;
/* lParam contains coordinates of top-left of client area.
* Get top-left of non-client area of window, matching coordinates of
* glutInitPosition and glutPositionWindow, but not those of
* glutGet(GLUT_WINDOW_X) and glutGet(GLUT_WINDOW_Y), which return
* top-left of client area.
@ -548,8 +563,8 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
windowRect.top = topleft.y;
}
INVOKE_WCB( *window, Position, ( windowRect.left, windowRect.top ) );
fgSetWindow(saved_window);
/* Update state and call callback, if there was a change */
fghOnPositionNotify(window, windowRect.left, windowRect.top, GL_FALSE);
}
}
@ -642,12 +657,12 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
/* printf("WM_SHOWWINDOW, shown? %i, source: %i\n",wParam,lParam); */
if (wParam)
{
fghUpdateWindowStatus(window, GL_TRUE);
fghPlatformOnWindowStatusNotify(window, GL_TRUE, GL_FALSE);
window->State.Redisplay = GL_TRUE;
}
else
{
fghUpdateWindowStatus(window, GL_FALSE);
fghPlatformOnWindowStatusNotify(window, GL_FALSE, GL_FALSE);
window->State.Redisplay = GL_FALSE;
}
break;
@ -655,19 +670,21 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
case WM_PAINT:
{
RECT rect;
/* As per docs, upon receiving WM_PAINT, first check if the update region is not empty before you call BeginPaint */
if (GetUpdateRect(hWnd,&rect,FALSE))
{
/* As per docs, upon receiving WM_PAINT, first check if the update region is not empty before you call BeginPaint */
/* Dummy begin/end paint to validate rect that needs
* redrawing, then signal that a redisplay is needed.
* This allows us full control about when we do any
* redrawing, and is the same as what original GLUT
* does.
*/
PAINTSTRUCT ps;
/* Turn on the visibility in case it was turned off somehow */
window->State.Visible = GL_TRUE;
InvalidateRect( hWnd, NULL, GL_FALSE );
BeginPaint( hWnd, &ps );
fghRedrawWindow( window );
EndPaint( hWnd, &ps );
window->State.Redisplay = GL_TRUE;
}
lRet = 0; /* As per docs, should return 0 */
}
@ -1108,3 +1125,238 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
return lRet;
}
/* Step through the work list */
void fgPlatformProcessWork(SFG_Window *window)
{
unsigned int workMask = window->State.WorkMask;
/* Now clear it so that any callback generated by the actions below can set work again */
window->State.WorkMask = 0;
/* This is before the first display callback: call a few callbacks to inform user of window size, position, etc
* we know this is before the first display callback of a window as for all windows GLUT_INIT_WORK is set when
* they are opened, and work is done before displaying in the mainloop.
*/
if (workMask & GLUT_INIT_WORK)
{
RECT windowRect;
/* Notify windowStatus/visibility */
fghPlatformOnWindowStatusNotify(window, window->State.Visible, GL_TRUE);
/* get and notify window's position */
GetWindowRect(window->Window.Handle,&windowRect);
fghOnPositionNotify(window, windowRect.left, windowRect.top, GL_TRUE);
/* get and notify window's size */
GetClientRect(window->Window.Handle,&windowRect);
fghOnReshapeNotify(window, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top, GL_TRUE);
/* Call init context callback */
INVOKE_WCB( *window, InitContext, ());
/* Lastly, check if we have a display callback, error out if not
* This is the right place to do it, as the redisplay will be
* next right after we exit this function, so there is no more
* opportunity for the user to register a callback for this window.
*/
if (!FETCH_WCB(*window, Display))
fgError ( "ERROR: No display callback registered for window %d\n", window->ID );
}
/* On windows we can position, resize and change z order at the same time */
if (workMask & (GLUT_POSITION_WORK|GLUT_SIZE_WORK|GLUT_ZORDER_WORK|GLUT_FULL_SCREEN_WORK))
{
UINT flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER;
HWND insertAfter = HWND_TOP;
RECT clientRect;
#if !defined(_WIN32_WCE) /* FIXME: what about WinCE */
if (workMask & GLUT_FULL_SCREEN_WORK)
{
/* This asks us to toggle fullscreen mode */
flags |= SWP_FRAMECHANGED;
if (window->State.IsFullscreen)
{
/* If we are fullscreen, resize the current window back to its original size */
/* printf("OldRect %i,%i to %i,%i\n",window->State.pWState.OldRect.left,window->State.pWState.OldRect.top,window->State.pWState.OldRect.right,window->State.pWState.OldRect.bottom); */
/* restore style of window before making it fullscreen */
SetWindowLong(window->Window.Handle, GWL_STYLE, window->State.pWState.OldStyle);
SetWindowLong(window->Window.Handle, GWL_EXSTYLE, window->State.pWState.OldStyleEx);
/* Then set up resize/reposition, unless user already queued up reshape/position work */
if (!(workMask & GLUT_POSITION_WORK))
{
workMask |= GLUT_POSITION_WORK;
window->State.DesiredXpos = window->State.pWState.OldRect.left;
window->State.DesiredYpos = window->State.pWState.OldRect.top;
}
if (!(workMask & GLUT_SIZE_WORK))
{
workMask |= GLUT_SIZE_WORK;
window->State.DesiredWidth = window->State.pWState.OldRect.right - window->State.pWState.OldRect.left;
window->State.DesiredHeight = window->State.pWState.OldRect.bottom - window->State.pWState.OldRect.top;
}
/* We'll finish off the fullscreen operation below after the other GLUT_POSITION_WORK|GLUT_SIZE_WORK|GLUT_ZORDER_WORK */
}
else
{
/* we are currently not fullscreen, go to fullscreen:
* remove window decoration and then maximize
*/
RECT rect;
HMONITOR hMonitor;
MONITORINFO mi;
/* save current window rect, style, exstyle and maximized state */
window->State.pWState.OldMaximized = !!IsZoomed(window->Window.Handle);
if (window->State.pWState.OldMaximized)
/* We force the window into restored mode before going
* fullscreen because Windows doesn't seem to hide the
* taskbar if the window is in the maximized state.
*/
SendMessage(window->Window.Handle, WM_SYSCOMMAND, SC_RESTORE, 0);
fghGetClientArea( &window->State.pWState.OldRect, window, GL_TRUE );
window->State.pWState.OldStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
window->State.pWState.OldStyleEx = GetWindowLong(window->Window.Handle, GWL_EXSTYLE);
/* remove decorations from style */
SetWindowLong(window->Window.Handle, GWL_STYLE,
window->State.pWState.OldStyle & ~(WS_CAPTION | WS_THICKFRAME));
SetWindowLong(window->Window.Handle, GWL_EXSTYLE,
window->State.pWState.OldStyleEx & ~(WS_EX_DLGMODALFRAME |
WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
/* For fullscreen mode, find the monitor that is covered the most
* by the window and get its rect as the resize target.
*/
GetWindowRect(window->Window.Handle, &rect);
hMonitor= MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST);
mi.cbSize = sizeof(mi);
GetMonitorInfo(hMonitor, &mi);
rect = mi.rcMonitor;
/* then setup window resize, overwriting other work queued on the window */
window->State.WorkMask |= GLUT_POSITION_WORK | GLUT_SIZE_WORK;
window->State.WorkMask &= ~GLUT_ZORDER_WORK;
window->State.DesiredXpos = rect.left;
window->State.DesiredYpos = rect.top;
window->State.DesiredWidth = rect.right - rect.left;
window->State.DesiredHeight = rect.bottom - rect.top;
}
}
#endif /*!defined(_WIN32_WCE) */
/* Now deal with normal position, reshape and z order requests (some might have been set when handling GLUT_FULLSCREEN_WORK above */
{
/* get rect describing window's current position and size,
* in screen coordinates and in FreeGLUT format
* (size (right-left, bottom-top) is client area size, top and left
* are outside of window including decorations).
*/
fghGetClientArea( &clientRect, window, TRUE );
if (workMask & GLUT_POSITION_WORK)
{
flags &= ~SWP_NOMOVE;
/* Move rect so that top-left is at requested position */
/* This also automatically makes sure that child window requested coordinates are relative
* to top-left of parent's client area (needed input for SetWindowPos on child windows),
* so no need to further correct rect for child windows below (childs don't have decorations either).
*/
OffsetRect(&clientRect,window->State.DesiredXpos-clientRect.left,window->State.DesiredYpos-clientRect.top);
}
if (workMask & GLUT_SIZE_WORK)
{
flags &= ~SWP_NOSIZE;
/* Note on maximizing behavior of Windows: the resize borders are off
* the screen such that the client area extends all the way from the
* leftmost corner to the rightmost corner to maximize screen real
* estate. A caption is still shown however to allow interaction with
* the window controls. This is default behavior of Windows that
* FreeGLUT sticks with. To alter, one would have to check if
* WS_MAXIMIZE style is set when a resize event is triggered, and
* then manually correct the windowRect to put the borders back on
* screen.
*/
/* Set new size of window, WxH specify client area */
clientRect.right = clientRect.left + window->State.DesiredWidth;
clientRect.bottom = clientRect.top + window->State.DesiredHeight;
}
if (workMask & GLUT_ZORDER_WORK)
{
flags &= ~SWP_NOZORDER;
/* Could change this to push it down or up one window at a time with some
* more code using GetWindow with GW_HWNDPREV and GW_HWNDNEXT.
* What would be consistent with X11? Win32 GLUT does what we do here...
*/
if (window->State.DesiredZOrder < 0)
insertAfter = HWND_BOTTOM;
}
}
/* Adjust for window decorations
* Child windows don't have decoration, so no need to correct
*/
if (!window->Parent)
/* get the window rect from this to feed to SetWindowPos, correct for window decorations */
fghComputeWindowRectFromClientArea_QueryWindow(&clientRect,window,TRUE);
/* Do the requested positioning, moving, and z order push/pop. */
SetWindowPos( window->Window.Handle,
insertAfter,
clientRect.left, clientRect.top,
clientRect.right - clientRect.left,
clientRect.bottom- clientRect.top,
flags
);
/* Finish off the fullscreen operation we were doing, if any */
if (workMask & GLUT_FULL_SCREEN_WORK)
{
if (window->State.IsFullscreen)
{
/* leaving fullscreen, restore maximized state, if any */
if (window->State.pWState.OldMaximized)
SendMessage(window->Window.Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
window->State.IsFullscreen = GL_FALSE;
}
else
window->State.IsFullscreen = GL_TRUE;
}
}
if (workMask & GLUT_VISIBILITY_WORK)
{
/* Visibility status of window gets updated in the WM_SHOWWINDOW and WM_SIZE handlers */
int cmdShow = 0;
SFG_Window *win = window;
switch (window->State.DesiredVisibility)
{
case DesireHiddenState:
cmdShow = SW_HIDE;
break;
case DesireIconicState:
cmdShow = SW_MINIMIZE;
/* Call on top-level window */
while (win->Parent)
win = win->Parent;
break;
case DesireNormalState:
cmdShow = SW_SHOW;
break;
}
ShowWindow( win->Window.Handle, cmdShow );
}
}

View File

@ -29,7 +29,7 @@
#include <GL/freeglut.h>
#include "../fg_internal.h"
extern void fghGetClientArea( RECT *clientRect, const SFG_Window *window );
extern void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside );
extern SFG_Window* fghWindowUnderCursor(SFG_Window *window);
@ -77,7 +77,7 @@ void fgPlatformCheckMenuDeactivate()
*/
POINT mouse_pos;
RECT clientArea;
fghGetClientArea(&clientArea,menu->ParentWindow);
fghGetClientArea(&clientArea,menu->ParentWindow, FALSE);
GetCursorPos(&mouse_pos);
if ( !PtInRect( &clientArea, mouse_pos ) )
fgDeactivateMenu(menu->ParentWindow);

View File

@ -37,7 +37,7 @@ extern GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
* and the window rect from the client area given the style of the window
* (or a valid window pointer from which the style can be queried).
*/
extern void fghGetClientArea( RECT *clientRect, const SFG_Window *window );
extern void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside );
extern void fghGetStyleFromWindow( const SFG_Window *window, DWORD *windowStyle, DWORD *windowExStyle );
extern void fghComputeWindowRectFromClientArea_UseStyle( RECT *clientRect, const DWORD windowStyle, const DWORD windowExStyle, BOOL posIsOutside );
@ -161,17 +161,7 @@ int fgPlatformGlutGet ( GLenum eWhat )
case GLUT_WINDOW_Y:
{
/*
* There is considerable confusion about the "right thing to
* do" concerning window size and position. GLUT itself is
* not consistent between Windows and UNIX/X11; since
* platform independence is a virtue for "freeglut", we
* decided to break with GLUT's behaviour.
*
* Under UNIX/X11, it is apparently not possible to get the
* window border sizes in order to subtract them off the
* window's initial position until some time after the window
* has been created. Therefore we decided on the following
* behaviour, both under Windows and under UNIX/X11:
* NB:
* - When you create a window with position (x,y) and size
* (w,h), the upper left hand corner of the outside of the
* window is at (x,y) and the size of the drawable area is
@ -213,11 +203,20 @@ int fgPlatformGlutGet ( GLenum eWhat )
break;
case GLUT_WINDOW_WIDTH:
freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 );
return fgStructure.CurrentWindow->State.Width;
case GLUT_WINDOW_HEIGHT:
{
RECT winRect;
freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 );
return fgStructure.CurrentWindow->State.Height;
GetClientRect( fgStructure.CurrentWindow->Window.Handle, &winRect);
switch( eWhat )
{
case GLUT_WINDOW_WIDTH: return winRect.right-winRect.left;
case GLUT_WINDOW_HEIGHT: return winRect.bottom-winRect.top;
}
}
break;
case GLUT_WINDOW_BORDER_WIDTH :
case GLUT_WINDOW_BORDER_HEIGHT :
@ -240,7 +239,7 @@ int fgPlatformGlutGet ( GLenum eWhat )
/* Also get window rect (including non-client area) */
if (fgStructure.CurrentWindow && fgStructure.CurrentWindow->Window.Handle)
{
fghGetClientArea(&clientRect,fgStructure.CurrentWindow);
fghGetClientArea(&clientRect,fgStructure.CurrentWindow, FALSE);
GetWindowRect(fgStructure.CurrentWindow->Window.Handle,&winRect);
}
else

View File

@ -84,7 +84,6 @@ typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShar
typedef BOOL (WINAPI *pRegisterTouchWindow)(HWND,ULONG);
static pRegisterTouchWindow fghRegisterTouchWindow = (pRegisterTouchWindow)0xDEADBEEF;
#endif
extern void fghNotifyWindowStatus(SFG_Window *window);
/*
@ -458,8 +457,12 @@ void fghComputeWindowRectFromClientArea_QueryWindow( RECT *clientRect, const SFG
* specified window. Output is position of corners of client area (drawable area) on the screen.
* Does not touch clientRect if window pointer or window handle is NULL.
* (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable area.
* if posIsOutside is true, the output client Rect will follow freeGLUT's window
* specification convention in which the top-left corner is at the outside of
* the window, while the size (rect.right-rect.left,rect.bottom-rect.top) remains to be the
* size of the drawable area.
*/
void fghGetClientArea( RECT *clientRect, const SFG_Window *window )
void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside )
{
POINT topLeftClient = {0,0};
@ -467,10 +470,21 @@ void fghGetClientArea( RECT *clientRect, const SFG_Window *window )
/* Get size of client rect */
GetClientRect(window->Window.Handle, clientRect);
/* Get position of top-left of client area on the screen */
ClientToScreen(window->Window.Handle,&topLeftClient);
/* Add top-left offset */
OffsetRect(clientRect,topLeftClient.x,topLeftClient.y);
if (posIsOutside)
{
RECT windowRect;
/* Get position of outside of window, including decorations */
GetWindowRect(window->Window.Handle,&windowRect);
/* Add top-left offset */
OffsetRect(clientRect,windowRect.left,windowRect.top);
}
else
{
/* Get position of top-left of client area on the screen */
ClientToScreen(window->Window.Handle,&topLeftClient);
/* Add top-left offset */
OffsetRect(clientRect,topLeftClient.x,topLeftClient.y);
}
}
@ -622,7 +636,7 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
}
if( !sizeUse )
{
if( ! window->IsMenu )
if( !window->IsMenu )
{
w = CW_USEDEFAULT;
h = CW_USEDEFAULT;
@ -630,9 +644,6 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
else /* fail safe - Windows can make a window of size (0, 0) */
w = h = 300; /* default window size */
}
/* store requested client area width and height */
window->State.Width = w;
window->State.Height = h;
#if !defined(_WIN32_WCE) /* no decorations for windows CE */
if( sizeUse )
@ -697,6 +708,8 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
);
#endif /* defined(_WIN32_WCE) */
/* WM_CREATE message got sent and was handled by window proc */
if( !( window->Window.Handle ) )
fgError( "Failed to create a window (%s)!", title );
@ -740,99 +753,6 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
}
void fgPlatformDisplayWindow ( SFG_Window *window )
{
/* This immediately generates a WM_PAINT message upon which we call the display callbacks to redraw the window */
RedrawWindow(
window->Window.Handle, NULL, NULL,
RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_UPDATENOW
);
}
void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height )
{
RECT windowRect;
/*
* HACK HACK HACK:
* Before we do anything else, check if this is a newly created window
* that did not have its windowStatus/visibility func called yet
* we do that on first paint, but because I want to keep the paint
* operation as lean as possible, we do it here. The first paint
* goes together with a first resize call before the display callback
* is called, so this is just in time. Shitty place to do it, but this
* is the only reliable way I can think of to call the callback upon
* first draw of the window.
* More broadly speaking, I know this is an ugly hack, but I'm not sure
* what else to do about it. Depending on WM_ACTIVATE would not work
* as not all windows get this when you are opening multiple before the
* mainloop starts. WM_SHOWWINDOW looked like an interesting candidate,
* but it is generated and processed before glutCreate(Sub)Window
* returns, so no callback can yet be set on the window.
*/
/* Check windowStatus/visibility func has been notified that window is visible (deferred from creation time to give user opportunity to register callbacks) */
if (!window->State.pWState.WindowFuncCalled)
{
fghNotifyWindowStatus(window);
window->State.pWState.WindowFuncCalled = GL_TRUE;
}
/*
* For windowed mode, get the current position of the
* window and resize taking the size of the frame
* decorations into account.
*
* Note on maximizing behavior of Windows: the resize borders are off
* the screen such that the client area extends all the way from the
* leftmost corner to the rightmost corner to maximize screen real
* estate. A caption is still shown however to allow interaction with
* the window controls. This is default behavior of Windows that
* FreeGLUT sticks with. To alter, one would have to check if
* WS_MAXIMIZE style is set when a resize event is triggered, and
* then manually correct the windowRect to put the borders back on
* screen.
*/
/* "GetWindowRect" returns the pixel coordinates of the outside of the window */
GetWindowRect( window->Window.Handle, &windowRect );
/* Create rect in FreeGLUT format, (X,Y) topleft outside window, WxH of client area */
windowRect.right = windowRect.left+width;
windowRect.bottom = windowRect.top+height;
if (window->Parent == NULL)
/* get the window rect from this to feed to SetWindowPos, correct for window decorations */
fghComputeWindowRectFromClientArea_QueryWindow(&windowRect,window,TRUE);
else
{
/* correct rect for position client area of parent window
* (SetWindowPos input for child windows is in coordinates
* relative to the parent's client area).
* Child windows don't have decoration, so no need to correct
* for them.
*/
RECT parentRect;
fghGetClientArea( &parentRect, window->Parent );
OffsetRect(&windowRect,-parentRect.left,-parentRect.top);
}
/* Do the actual resizing */
SetWindowPos( window->Window.Handle,
HWND_TOP,
windowRect.left, windowRect.top,
windowRect.right - windowRect.left,
windowRect.bottom- windowRect.top,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
SWP_NOZORDER
);
/* Set new width and height so we can test for that in WM_SIZE message handler and don't do anything if not needed */
window->State.Width = width;
window->State.Height = height;
}
/*
* Closes a window, destroying the frame and OpenGL context
*/
@ -873,38 +793,6 @@ void fgPlatformCloseWindow( SFG_Window* window )
}
/*
* This function makes the current window visible
*/
void fgPlatformGlutShowWindow( void )
{
ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_SHOW );
}
/*
* This function hides the current window
*/
void fgPlatformGlutHideWindow( void )
{
ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_HIDE );
}
/*
* Iconify the current window (top-level windows only)
*/
void fgPlatformGlutIconifyWindow( void )
{
SFG_Window *win = fgStructure.CurrentWindow;
/* Call on parent window */
while (win->Parent)
win = win->Parent;
/* Visibility status of window gets updated in the WM_SHOWWINDOW handler */
ShowWindow(win->Window.Handle, SW_MINIMIZE);
}
/*
* Set the current window's title
*/
@ -943,188 +831,6 @@ void fgPlatformGlutSetIconTitle( const char* title )
fgStructure.CurrentWindow->State.pWState.IconTitle = strdup(title);
}
/*
* Change the current window's position
*/
void fgPlatformGlutPositionWindow( int x, int y )
{
RECT winRect;
/* "GetWindowRect" returns the pixel coordinates of the outside of the window */
GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
MoveWindow(
fgStructure.CurrentWindow->Window.Handle,
x,
y,
winRect.right - winRect.left,
winRect.bottom - winRect.top,
TRUE
);
}
/*
* Lowers the current window (by Z order change)
*/
void fgPlatformGlutPushWindow( void )
{
SetWindowPos(
fgStructure.CurrentWindow->Window.Handle,
HWND_BOTTOM,
0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE
);
}
/*
* Raises the current window (by Z order change)
*/
void fgPlatformGlutPopWindow( void )
{
SetWindowPos(
fgStructure.CurrentWindow->Window.Handle,
HWND_TOP,
0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE
);
}
/*
* Resize the current window so that it fits the whole screen
*/
void fgPlatformGlutFullScreen( SFG_Window *win )
{
#if !defined(_WIN32_WCE) /* FIXME: what about WinCE */
if (glutGet(GLUT_FULL_SCREEN))
{
/* Leave full screen state before entering fullscreen again (resizing?) */
glutLeaveFullScreen();
}
{
#if(WINVER >= 0x0500) /* Windows 2000 or later */
RECT rect;
HMONITOR hMonitor;
MONITORINFO mi;
/* For fullscreen mode, first remove all window decoration
* and set style to popup so it will overlap the taskbar
* then force to maximize on the screen on which it has the most
* overlap.
*/
/* save current window rect, style, exstyle and maximized state */
win->State.pWState.OldMaximized = !!IsZoomed(win->Window.Handle);
if (win->State.pWState.OldMaximized)
/* We force the window into restored mode before going
* fullscreen because Windows doesn't seem to hide the
* taskbar if the window is in the maximized state.
*/
SendMessage(win->Window.Handle, WM_SYSCOMMAND, SC_RESTORE, 0);
GetWindowRect( win->Window.Handle, &win->State.pWState.OldRect );
win->State.pWState.OldStyle = GetWindowLong(win->Window.Handle, GWL_STYLE);
win->State.pWState.OldStyleEx = GetWindowLong(win->Window.Handle, GWL_EXSTYLE);
/* remove decorations from style */
SetWindowLong(win->Window.Handle, GWL_STYLE,
win->State.pWState.OldStyle & ~(WS_CAPTION | WS_THICKFRAME));
SetWindowLong(win->Window.Handle, GWL_EXSTYLE,
win->State.pWState.OldStyleEx & ~(WS_EX_DLGMODALFRAME |
WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
/* For fullscreen mode, find the monitor that is covered the most
* by the window and get its rect as the resize target.
*/
hMonitor= MonitorFromRect(&win->State.pWState.OldRect, MONITOR_DEFAULTTONEAREST);
mi.cbSize = sizeof(mi);
GetMonitorInfo(hMonitor, &mi);
rect = mi.rcMonitor;
#else /* if (WINVER >= 0x0500) */
RECT rect;
/* For fullscreen mode, force the top-left corner to 0,0
* and adjust the window rectangle so that the client area
* covers the whole screen.
*/
rect.left = 0;
rect.top = 0;
rect.right = fgDisplay.ScreenWidth;
rect.bottom = fgDisplay.ScreenHeight;
AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN, FALSE );
#endif /* (WINVER >= 0x0500) */
/*
* then resize window
* SWP_NOACTIVATE Do not activate the window
* SWP_NOOWNERZORDER Do not change position in z-order
* SWP_NOSENDCHANGING Suppress WM_WINDOWPOSCHANGING message
* SWP_NOZORDER Retains the current Z order (ignore 2nd param)
*/
SetWindowPos( fgStructure.CurrentWindow->Window.Handle,
HWND_TOP,
rect.left,
rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
SWP_NOZORDER
);
win->State.IsFullscreen = GL_TRUE;
}
#endif
}
/*
* If we are fullscreen, resize the current window back to its original size
*/
void fgPlatformGlutLeaveFullScreen( SFG_Window *win )
{
#if !defined(_WIN32_WCE) /* FIXME: what about WinCE */
if (!glutGet(GLUT_FULL_SCREEN))
{
/* nothing to do */
return;
}
/* restore style of window before making it fullscreen */
SetWindowLong(win->Window.Handle, GWL_STYLE, win->State.pWState.OldStyle);
SetWindowLong(win->Window.Handle, GWL_EXSTYLE, win->State.pWState.OldStyleEx);
/* Then resize */
SetWindowPos(win->Window.Handle,
HWND_TOP,
win->State.pWState.OldRect.left,
win->State.pWState.OldRect.top,
win->State.pWState.OldRect.right - win->State.pWState.OldRect.left,
win->State.pWState.OldRect.bottom - win->State.pWState.OldRect.top,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
SWP_NOZORDER
);
if (win->State.pWState.OldMaximized)
SendMessage(win->Window.Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
win->State.IsFullscreen = GL_FALSE;
#endif
}
/*
* Toggle the window's full screen state.
*/
void fgPlatformGlutFullScreenToggle( SFG_Window *win )
{
if (!win->State.IsFullscreen)
glutFullScreen();
else
glutLeaveFullScreen();
}
/* -- PLATFORM-SPECIFIC INTERFACE FUNCTION -------------------------------------------------- */

View File

@ -113,6 +113,7 @@ struct tagSFG_PlatformWindowState
{
int OldWidth; /* Window width from before a resize */
int OldHeight; /* " height " " " " */
GLboolean KeyRepeating; /* Currently in repeat mode? */
};

View File

@ -56,6 +56,17 @@
# define MIN(a,b) (((a)<(b)) ? (a) : (b))
#endif
extern void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify);
extern void fghOnPositionNotify(SFG_Window *window, int x, int y, GLboolean forceNotify);
extern void fgPlatformFullScreenToggle( SFG_Window *win );
extern void fgPlatformPositionWindow( SFG_Window *window, int x, int y );
extern void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height );
extern void fgPlatformPushWindow( SFG_Window *window );
extern void fgPlatformPopWindow( SFG_Window *window );
extern void fgPlatformHideWindow( SFG_Window *window );
extern void fgPlatformIconifyWindow( SFG_Window *window );
extern void fgPlatformShowWindow( SFG_Window *window );
/* used in the event handling code to match and discard stale mouse motion events */
static Bool match_motion(Display *dpy, XEvent *xev, XPointer arg);
@ -63,8 +74,7 @@ static Bool match_motion(Display *dpy, XEvent *xev, XPointer arg);
* TODO BEFORE THE STABLE RELEASE:
*
* There are some issues concerning window redrawing under X11, and maybe
* some events are not handled. The Win32 version lacks some more features,
* but seems acceptable for not demanding purposes.
* some events are not handled.
*
* Need to investigate why the X11 version breaks out with an error when
* closing a window (using the window manager, not glutDestroyWindow)...
@ -644,29 +654,25 @@ void fgPlatformProcessSingleEvent ( void )
case CreateNotify:
case ConfigureNotify:
{
int width, height;
int width, height, x, y;
if( event.type == CreateNotify ) {
GETWINDOW( xcreatewindow );
width = event.xcreatewindow.width;
height = event.xcreatewindow.height;
x = event.xcreatewindow.x;
y = event.xcreatewindow.y;
} else {
GETWINDOW( xconfigure );
width = event.xconfigure.width;
height = event.xconfigure.height;
x = event.xconfigure.x;
y = event.xconfigure.y;
}
if( ( width != window->State.pWState.OldWidth ) ||
( height != window->State.pWState.OldHeight ) )
{
SFG_Window *current_window = fgStructure.CurrentWindow;
window->State.pWState.OldWidth = width;
window->State.pWState.OldHeight = height;
INVOKE_WCB( *window, Reshape, ( width, height ) );
glutPostRedisplay( );
if( window->IsMenu )
fgSetWindow( current_window );
}
/* Update state and call callback, if there was a change */
fghOnPositionNotify(window, x, y, GL_FALSE);
/* Update state and call callback, if there was a change */
fghOnReshapeNotify(window, width, height, GL_FALSE);
}
break;
@ -918,20 +924,20 @@ void fgPlatformProcessSingleEvent ( void )
if ( event.xkey.keycode<256 ) /* XQueryKeymap is limited to 256 keycodes */
{
if ( keys[event.xkey.keycode>>3] & (1<<(event.xkey.keycode%8)) )
window->State.KeyRepeating = GL_TRUE;
window->State.pWState.KeyRepeating = GL_TRUE;
else
window->State.KeyRepeating = GL_FALSE;
window->State.pWState.KeyRepeating = GL_FALSE;
}
}
}
else
window->State.KeyRepeating = GL_FALSE;
window->State.pWState.KeyRepeating = GL_FALSE;
/* Cease processing this event if it is auto repeated */
if (window->State.KeyRepeating)
if (window->State.pWState.KeyRepeating)
{
if (event.type == KeyPress) window->State.KeyRepeating = GL_FALSE;
if (event.type == KeyPress) window->State.pWState.KeyRepeating = GL_FALSE;
break;
}
@ -1071,3 +1077,72 @@ void fgPlatformMainLoopPreliminaryWork ( void )
{
}
/* Step through the work list */
void fgPlatformProcessWork(SFG_Window *window)
{
unsigned int workMask = window->State.WorkMask;
/* Now clear it so that any callback generated by the actions below can set work again */
window->State.WorkMask = 0;
/* This is before the first display callback: call a few callbacks to inform user of window size, position, etc
* we know this is before the first display callback of a window as for all windows GLUT_INIT_WORK is set when
* they are opened, and work is done before displaying in the mainloop.
*/
if (workMask & GLUT_INIT_WORK)
{
/* Notify windowStatus/visibility, position and size get notified on window creation with message handlers above
* XXX CHECK: do the messages happen too early like on windows, so client code cannot have registered
* a callback yet and the message is thus never received by client?
*/
/* Call init context callback */
INVOKE_WCB( *window, InitContext, ());
/* Lastly, check if we have a display callback, error out if not
* This is the right place to do it, as the redisplay will be
* next right after we exit this function, so there is no more
* opportunity for the user to register a callback for this window.
*/
if (!FETCH_WCB(*window, Display))
fgError ( "ERROR: No display callback registered for window %d\n", window->ID );
}
if (workMask & GLUT_FULL_SCREEN_WORK)
fgPlatformFullScreenToggle( window );
if (workMask & GLUT_POSITION_WORK)
fgPlatformPositionWindow( window, window->State.DesiredXpos, window->State.DesiredYpos );
if (workMask & GLUT_SIZE_WORK)
fgPlatformReshapeWindow ( window, window->State.DesiredWidth, window->State.DesiredHeight );
if (workMask & GLUT_ZORDER_WORK)
{
if (window->State.DesiredZOrder < 0)
fgPlatformPushWindow( window );
else
fgPlatformPopWindow( window );
}
if (workMask & GLUT_VISIBILITY_WORK)
{
/* Visibility status of window gets updated in the window message handlers above
* XXX: is this really the case? check
*/
SFG_Window *win = window;
switch (window->State.DesiredVisibility)
{
case DesireHiddenState:
fgPlatformHideWindow( window );
break;
case DesireIconicState:
/* Call on top-level window */
while (win->Parent)
win = win->Parent;
fgPlatformIconifyWindow( win );
break;
case DesireNormalState:
fgPlatformShowWindow( window );
break;
}
}
}

View File

@ -32,8 +32,6 @@
#include <unistd.h> /* usleep */
#include "../fg_internal.h"
extern void fghRedrawWindow(SFG_Window *window);
#ifdef EGL_VERSION_1_0
#include "egl/fg_window_egl.h"
#define fghCreateNewContext fghCreateNewContextEGL
@ -48,11 +46,14 @@ static int fghResizeFullscrToggle(void)
if(glutGet(GLUT_FULL_SCREEN)) {
/* restore original window size */
SFG_Window *win = fgStructure.CurrentWindow;
fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
fgStructure.CurrentWindow->State.Width = win->State.pWState.OldWidth;
fgStructure.CurrentWindow->State.Height = win->State.pWState.OldHeight;
fgStructure.CurrentWindow->State.WorkMask = GLUT_SIZE_WORK;
fgStructure.CurrentWindow->State.DesiredWidth = win->State.pWState.OldWidth;
fgStructure.CurrentWindow->State.DesiredHeight = win->State.pWState.OldHeight;
} else {
fgStructure.CurrentWindow->State.pWState.OldWidth = win->State.Width;
fgStructure.CurrentWindow->State.pWState.OldHeight = win->State.Height;
/* resize the window to cover the entire screen */
XGetWindowAttributes(fgDisplay.pDisplay.Display,
fgStructure.CurrentWindow->Window.Handle,
@ -382,15 +383,6 @@ void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height )
}
/*
* A static helper function to execute display callback for a window
*/
void fgPlatformDisplayWindow ( SFG_Window *window )
{
fghRedrawWindow ( window ) ;
}
/*
* Closes a window, destroying the frame and OpenGL context
*/
@ -412,35 +404,35 @@ void fgPlatformCloseWindow( SFG_Window* window )
/*
* This function makes the current window visible
* This function makes the specified window visible
*/
void fgPlatformGlutShowWindow( void )
void fgPlatformShowWindow( SFG_Window *window )
{
XMapWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
XMapWindow( fgDisplay.pDisplay.Display, window->Window.Handle );
XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
}
/*
* This function hides the current window
* This function hides the specified window
*/
void fgPlatformGlutHideWindow( void )
void fgPlatformHideWindow( SFG_Window *window )
{
if( fgStructure.CurrentWindow->Parent == NULL )
if( window->Parent == NULL )
XWithdrawWindow( fgDisplay.pDisplay.Display,
fgStructure.CurrentWindow->Window.Handle,
window->Window.Handle,
fgDisplay.pDisplay.Screen );
else
XUnmapWindow( fgDisplay.pDisplay.Display,
fgStructure.CurrentWindow->Window.Handle );
window->Window.Handle );
XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
}
/*
* Iconify the current window (top-level windows only)
* Iconify the specified window (top-level windows only)
*/
void fgPlatformGlutIconifyWindow( void )
void fgPlatformIconifyWindow( SFG_Window *window )
{
XIconifyWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
XIconifyWindow( fgDisplay.pDisplay.Display, window->Window.Handle,
fgDisplay.pDisplay.Screen );
XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
@ -490,59 +482,35 @@ void fgPlatformGlutSetIconTitle( const char* title )
}
/*
* Change the current window's position
* Change the specified window's position
*/
void fgPlatformGlutPositionWindow( int x, int y )
void fgPlatformPositionWindow( SFG_Window *window, int x, int y )
{
XMoveWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
XMoveWindow( fgDisplay.pDisplay.Display, window->Window.Handle,
x, y );
XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
}
/*
* Lowers the current window (by Z order change)
* Lowers the specified window (by Z order change)
*/
void fgPlatformGlutPushWindow( void )
void fgPlatformPushWindow( SFG_Window *window )
{
XLowerWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
XLowerWindow( fgDisplay.pDisplay.Display, window->Window.Handle );
}
/*
* Raises the current window (by Z order change)
* Raises the specified window (by Z order change)
*/
void fgPlatformGlutPopWindow( void )
void fgPlatformPopWindow( SFG_Window *window )
{
XRaiseWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
}
/*
* Resize the current window so that it fits the whole screen
*/
void fgPlatformGlutFullScreen( SFG_Window *win )
{
if(!glutGet(GLUT_FULL_SCREEN)) {
if(fghToggleFullscreen() != -1) {
win->State.IsFullscreen = GL_TRUE;
}
}
}
/*
* If we are fullscreen, resize the current window back to its original size
*/
void fgPlatformGlutLeaveFullScreen( SFG_Window *win )
{
if(glutGet(GLUT_FULL_SCREEN)) {
if(fghToggleFullscreen() != -1) {
win->State.IsFullscreen = GL_FALSE;
}
}
XRaiseWindow( fgDisplay.pDisplay.Display, window->Window.Handle );
}
/*
* Toggle the window's full screen state.
*/
void fgPlatformGlutFullScreenToggle( SFG_Window *win )
void fgPlatformFullScreenToggle( SFG_Window *win )
{
if(fghToggleFullscreen() != -1) {
win->State.IsFullscreen = !win->State.IsFullscreen;