diff --git a/freeglut/freeglut/progs/demos/Resizer/Resizer.cpp b/freeglut/freeglut/progs/demos/Resizer/Resizer.cpp index 0ee64ba..2835022 100644 --- a/freeglut/freeglut/progs/demos/Resizer/Resizer.cpp +++ b/freeglut/freeglut/progs/demos/Resizer/Resizer.cpp @@ -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); diff --git a/freeglut/freeglut/src/fg_window.c b/freeglut/freeglut/src/fg_window.c index 9760858..3b61192 100644 --- a/freeglut/freeglut/src/fg_window.c +++ b/freeglut/freeglut/src/fg_window.c @@ -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; diff --git a/freeglut/freeglut/src/mswin/fg_internal_mswin.h b/freeglut/freeglut/src/mswin/fg_internal_mswin.h index fb6b1b7..3e7d5c7 100644 --- a/freeglut/freeglut/src/mswin/fg_internal_mswin.h +++ b/freeglut/freeglut/src/mswin/fg_internal_mswin.h @@ -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 */ }; diff --git a/freeglut/freeglut/src/mswin/fg_main_mswin.c b/freeglut/freeglut/src/mswin/fg_main_mswin.c index a791222..85492f7 100644 --- a/freeglut/freeglut/src/mswin/fg_main_mswin.c +++ b/freeglut/freeglut/src/mswin/fg_main_mswin.c @@ -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 : diff --git a/freeglut/freeglut/src/mswin/fg_window_mswin.c b/freeglut/freeglut/src/mswin/fg_window_mswin.c index 6a86848..dd4d3a8 100644 --- a/freeglut/freeglut/src/mswin/fg_window_mswin.c +++ b/freeglut/freeglut/src/mswin/fg_window_mswin.c @@ -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); } /* diff --git a/freeglut/freeglut/src/x11/fg_window_x11.c b/freeglut/freeglut/src/x11/fg_window_x11.c index 2afe99e..6f927c2 100644 --- a/freeglut/freeglut/src/x11/fg_window_x11.c +++ b/freeglut/freeglut/src/x11/fg_window_x11.c @@ -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; } /*