Visibility functions better implemented now. All goes through

WM_SHOWWINDOW except for a newly created window (WM_SHOWWINDOW is too
early for callback then). I now have a state variable that indicates
whether visibility has been notified yet for a new window. This
notification gets done just before the window is first drawn. This
removes the need for fgPlatformMainLoopPreliminaryWork on windows, and
it also works for windows created when the mainloop is already running


git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1541 7f0cb862-5218-0410-a997-914c9d46530a
This commit is contained in:
dcnieho 2013-03-01 10:31:34 +00:00
parent c7656b8659
commit 7caa405f57
6 changed files with 103 additions and 55 deletions

View File

@ -14,6 +14,7 @@ void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY );
void Redisplay();
void Reshape(int width, int height);
void Position(int x, int y);
void WindowStatus(int state);
@ -31,6 +32,12 @@ void DrawQuad()
glEnd();
}
void UnhideTimer(int window)
{
glutSetWindow(window);
glutShowWindow();
}
void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY )
{
switch (cChar)
@ -119,6 +126,7 @@ void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY )
glutDisplayFunc( Redisplay );
glutReshapeFunc( Reshape );
glutPositionFunc( Position );
glutWindowStatusFunc( WindowStatus );
}
else
{
@ -133,6 +141,26 @@ void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY )
break;
case 'i':
case 'I':
glutIconifyWindow();
break;
case 'h':
case 'H':
if (nChildWindow!=-1 && cChar=='h') /* Capital H always hides the main window*/
{
glutSetWindow(nChildWindow);
glutTimerFunc(2000, UnhideTimer, nChildWindow);
}
else
{
glutSetWindow(nWindow);
glutTimerFunc(2000, UnhideTimer, nWindow);
}
glutHideWindow();
default:
break;
}
@ -172,6 +200,12 @@ void Position(int x, int y)
x, y);
}
void WindowStatus(int state)
{
int win = glutGetWindow();
printf("windowstatus (win %i): %i\n",win,state);
}
void Redisplay(void)
{
int win = glutGetWindow();
@ -228,8 +262,8 @@ void Timer(int unused)
nWidth, nHeight,
nPosX ,nPosY);
/* (re)set the timer callback and ask glut to call it in 1 second */
glutTimerFunc(300, Timer, 0);
/* (re)set the timer callback and ask glut to call it in 500 ms */
glutTimerFunc(500, Timer, 0);
}
@ -259,6 +293,7 @@ int main(int argc, char* argv[])
glutDisplayFunc( Redisplay );
glutReshapeFunc( Reshape );
glutPositionFunc( Position );
glutWindowStatusFunc( WindowStatus );
glutTimerFunc(300, Timer, 0);

View File

@ -326,8 +326,6 @@ void FGAPIENTRY glutIconifyWindow( void )
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIconifyWindow" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutIconifyWindow" );
fgStructure.CurrentWindow->State.Visible = GL_FALSE;
fgPlatformGlutIconifyWindow ();
fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;

View File

@ -97,6 +97,7 @@ 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 */
};

View File

@ -147,47 +147,16 @@ static void fghUpdateWindowStatus(SFG_Window *window, GLboolean visState)
}
}
static void fghNotifyWindowStatus(SFG_Window *window)
void fghNotifyWindowStatus(SFG_Window *window)
{
SFG_Window* child;
INVOKE_WCB( *window, WindowStatus, ( window->State.Visible?GLUT_FULLY_RETAINED:GLUT_HIDDEN ) );
/* Also notify children */
for( child = ( SFG_Window * )window->Children.First;
child;
child = ( SFG_Window * )child->Node.Next )
{
fghNotifyWindowStatus(child);
}
/* Don't notify children, they get their own just before first time they're drawn */
}
void fgPlatformMainLoopPreliminaryWork ( void )
{
SFG_Window *window = (SFG_Window *)fgStructure.Windows.First ;
/*
* Processing before the main loop: If there is a window which is open and
* which has a visibility/windowStatus callback, call it to inform the client
* code that the window is visible. 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.
*/
while( window )
{
if ( FETCH_WCB( *window, WindowStatus ) )
{
SFG_Window *current_window = fgStructure.CurrentWindow ;
fghNotifyWindowStatus(window);
fgSetWindow( current_window );
}
window = (SFG_Window *)window->Node.Next ;
}
/* no-op */
}
@ -501,12 +470,15 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
break;
case WM_SIZE:
//printf("WM_SIZE (ID: %i): wParam: %i, new size: %ix%i \n",window->ID,wParam,LOWORD(lParam),HIWORD(lParam));
/*
* If the window is visible, then it is the user manually resizing it.
* If it is not, then it is the system sending us a dummy resize with
* zero dimensions on a "glutIconifyWindow" call.
*/
/* printf("WM_SIZE (ID: %i): wParam: %i, new size: %ix%i \n",window->ID,wParam,LOWORD(lParam),HIWORD(lParam)); */
/* Update visibility state of the window */
if (wParam==SIZE_MINIMIZED)
fghUpdateWindowStatus(window,GL_FALSE);
else if (wParam==SIZE_RESTORED && !window->State.Visible)
fghUpdateWindowStatus(window,GL_TRUE);
/* Check window visible, we don't want to resize when the user or glutIconifyWindow minimized the window */
if( window->State.Visible )
{
/* get old values first to compare to below */
@ -533,8 +505,8 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
SFG_Window* saved_window = fgStructure.CurrentWindow;
RECT windowRect;
/* Check window visible, we don't want to call the position callback when the user minimized the window */
if (window->State.Visible)
/* 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
* glutInitPosition and glutPositionWindow, but not those of
@ -559,6 +531,9 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
fgSetWindow(saved_window);
}
}
/* according to docs, should return 0 */
lRet = 0;
break;
case WM_SETFOCUS:
@ -644,9 +619,17 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
break;
case WM_SHOWWINDOW:
//printf("WM_SHOWWINDOW\n");
fghUpdateWindowStatus(window, GL_TRUE);
window->State.Redisplay = GL_TRUE;
/* printf("WM_SHOWWINDOW, shown? %i, source: %i\n",wParam,lParam); */
if (wParam)
{
fghUpdateWindowStatus(window, GL_TRUE);
window->State.Redisplay = GL_TRUE;
}
else
{
fghUpdateWindowStatus(window, GL_FALSE);
window->State.Redisplay = GL_FALSE;
}
break;
case WM_PAINT:
@ -988,8 +971,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
case SC_MINIMIZE :
/* User has clicked on the "-" to minimize the window */
/* Turn off the visibility */
fghUpdateWindowStatus(window, GL_FALSE);
/* Turning off the visibility is handled in WM_SIZE handler */
break ;
@ -1022,7 +1004,6 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
break ;
case SC_RESTORE :
fghUpdateWindowStatus(window, GL_TRUE);
break ;
case SC_TASKLIST :

View File

@ -84,6 +84,7 @@ 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);
/*
@ -731,8 +732,7 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
fgState.ForceIconic ? SW_SHOWMINIMIZED : SW_SHOWNORMAL );
#endif /* defined(_WIN32_WCE) */
UpdateWindow( window->Window.Handle );
ShowCursor( TRUE ); /* XXX Old comments say "hide cursor"! */
ShowCursor( TRUE );
}
@ -749,6 +749,30 @@ 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
@ -860,7 +884,14 @@ void fgPlatformGlutHideWindow( void )
*/
void fgPlatformGlutIconifyWindow( void )
{
ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_MINIMIZE );
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);
}
/*

View File

@ -443,6 +443,8 @@ void fgPlatformGlutIconifyWindow( void )
XIconifyWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
fgDisplay.pDisplay.Screen );
XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
fgStructure.CurrentWindow->State.Visible = GL_FALSE;
}
/*