Visibility functions better implemented now. All goes through
authorDiederick Niehorster <dcnieho@gmail.com>
Fri, 1 Mar 2013 10:31:34 +0000 (10:31 +0000)
committerDiederick Niehorster <dcnieho@gmail.com>
Fri, 1 Mar 2013 10:31:34 +0000 (10:31 +0000)
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: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@1541 7f0cb862-5218-0410-a997-914c9d46530a

progs/demos/Resizer/Resizer.cpp
src/fg_window.c
src/mswin/fg_internal_mswin.h
src/mswin/fg_main_mswin.c
src/mswin/fg_window_mswin.c
src/x11/fg_window_x11.c

index 0ee64ba..2835022 100644 (file)
@@ -14,6 +14,7 @@ void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY );
 void Redisplay();\r
 void Reshape(int width, int height);\r
 void Position(int x, int y);\r
+void WindowStatus(int state);\r
 \r
 \r
 \r
@@ -31,6 +32,12 @@ void DrawQuad()
     glEnd();\r
 }\r
 \r
+void UnhideTimer(int window)\r
+{\r
+    glutSetWindow(window);\r
+    glutShowWindow();\r
+}\r
+\r
 void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY )\r
 {\r
     switch (cChar)\r
@@ -119,6 +126,7 @@ void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY )
             glutDisplayFunc( Redisplay );\r
             glutReshapeFunc( Reshape );\r
             glutPositionFunc( Position );\r
+            glutWindowStatusFunc( WindowStatus );\r
         }\r
         else\r
         {\r
@@ -133,6 +141,26 @@ void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY )
         break;\r
 \r
 \r
+    case 'i':\r
+    case 'I':\r
+        glutIconifyWindow();\r
+        break;\r
+\r
+\r
+    case 'h':\r
+    case 'H':\r
+        if (nChildWindow!=-1 && cChar=='h') /* Capital H always hides the main window*/\r
+        {\r
+            glutSetWindow(nChildWindow);\r
+            glutTimerFunc(2000, UnhideTimer, nChildWindow);\r
+        }\r
+        else\r
+        {\r
+            glutSetWindow(nWindow);\r
+            glutTimerFunc(2000, UnhideTimer, nWindow);\r
+        }\r
+        glutHideWindow();\r
+\r
     default:\r
         break;\r
     }\r
@@ -172,6 +200,12 @@ void Position(int x, int y)
         x, y);\r
 }\r
 \r
+void WindowStatus(int state)\r
+{\r
+    int win = glutGetWindow();\r
+    printf("windowstatus (win %i): %i\n",win,state);\r
+}\r
+\r
 void Redisplay(void)\r
 {\r
     int win = glutGetWindow();\r
@@ -228,8 +262,8 @@ void Timer(int unused)
         nWidth, nHeight,\r
         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);
 }\r
 \r
 \r
@@ -259,6 +293,7 @@ int main(int argc, char* argv[])
     glutDisplayFunc( Redisplay );\r
     glutReshapeFunc( Reshape );\r
     glutPositionFunc( Position );\r
+    glutWindowStatusFunc( WindowStatus );\r
 \r
     glutTimerFunc(300, Timer, 0);\r
 \r
index 9760858..3b61192 100644 (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;
index fb6b1b7..3e7d5c7 100644 (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 */
 };
 
 
index a791222..85492f7 100644 (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   :
index 6a86848..dd4d3a8 100644 (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 );
 }
 
 
@@ -750,6 +750,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
      * decorations into account.
@@ -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);
 }
 
 /*
index 2afe99e..6f927c2 100644 (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;
 }
 
 /*