Visibility functions better implemented now. All goes through
[freeglut] / src / mswin / fg_main_mswin.c
index baf4b3b..85492f7 100644 (file)
@@ -128,33 +128,37 @@ void fgPlatformProcessSingleEvent ( void )
 
 
 
-void fgPlatformMainLoopPreliminaryWork ( void )
+static void fghUpdateWindowStatus(SFG_Window *window, GLboolean visState)
 {
-    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 callback, call it.  I know this is an ugly hack,
-     * but I'm not sure what else to do about it.  Ideally we should leave
-     * something uninitialized in the create window code and initialize it in
-     * the main loop, and have that initialization create a "WM_ACTIVATE"
-     * message.  Then we would put the visibility callback code in the
-     * "case WM_ACTIVATE" block below.         - John Fay -- 10/24/02
-     */
-    while( window )
-    {
-        if ( FETCH_WCB( *window, Visibility ) )
-        {
-            SFG_Window *current_window = fgStructure.CurrentWindow ;
+    SFG_Window* child;
 
-            INVOKE_WCB( *window, Visibility, ( window->State.Visible ) );
-            fgSetWindow( current_window );
-        }
+    if (window->State.Visible != visState)
+    {
+        window->State.Visible = visState;
+        INVOKE_WCB( *window, WindowStatus, ( visState ? GLUT_FULLY_RETAINED:GLUT_HIDDEN ) );
+    }
 
-        window = (SFG_Window *)window->Node.Next ;
+    /* Also set visibility state for children */
+    for( child = ( SFG_Window * )window->Children.First;
+         child;
+         child = ( SFG_Window * )child->Node.Next )
+    {
+        fghUpdateWindowStatus(child, visState);
     }
 }
 
+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 */
+}
+
 
 /*
  * Determine a GLUT modifier mask based on MS-WINDOWS system info.
@@ -466,11 +470,15 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
         break;
 
     case WM_SIZE:
-        /*
-         * 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 */
@@ -488,29 +496,44 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
                 window->State.NeedToResize = GL_TRUE;
         }
 
+        /* according to docs, should return 0 */
+        lRet = 0;
         break;
 
     case WM_MOVE:
         {
             SFG_Window* saved_window = fgStructure.CurrentWindow;
             RECT windowRect;
-            GetWindowRect( window->Window.Handle, &windowRect );
-            
-            if (window->Parent)
+
+            /* 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))
             {
-                /* For child window, we should return relative to upper-left
-                * of parent's client area.
-                */
-                POINT topleft = {windowRect.left,windowRect.top};
-
-                ScreenToClient(window->Parent->Window.Handle,&topleft);
-                windowRect.left = topleft.x;
-                windowRect.top  = topleft.y;
-            }
+                /* 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.
+                 */
+                GetWindowRect( window->Window.Handle, &windowRect );
+            
+                if (window->Parent)
+                {
+                    /* For child window, we should return relative to upper-left
+                     * of parent's client area.
+                     */
+                    POINT topleft = {windowRect.left,windowRect.top};
 
-            INVOKE_WCB( *window, Position, ( windowRect.left, windowRect.top ) );
-            fgSetWindow(saved_window);
+                    ScreenToClient(window->Parent->Window.Handle,&topleft);
+                    windowRect.left = topleft.x;
+                    windowRect.top  = topleft.y;
+                }
+
+                INVOKE_WCB( *window, Position, ( windowRect.left, windowRect.top ) );
+                fgSetWindow(saved_window);
+            }
         }
+
+        /* according to docs, should return 0 */
+        lRet = 0;
         break;
 
     case WM_SETFOCUS:
@@ -535,7 +558,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
 
 #if 0
     case WM_ACTIVATE:
-        //printf("WM_ACTIVATE: %x %d %d\n",lParam, HIWORD(wParam), LOWORD(wParam));
+        //printf("WM_ACTIVATE: %x (ID: %i) %d %d\n",lParam, window->ID, HIWORD(wParam), LOWORD(wParam));
         if (LOWORD(wParam) != WA_INACTIVE)
         {
 /*            printf("WM_ACTIVATE: fgSetCursor( %p, %d)\n", window,
@@ -596,8 +619,17 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
         break;
 
     case WM_SHOWWINDOW:
-        window->State.Visible = 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:
@@ -605,6 +637,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
         PAINTSTRUCT ps;
         /* Turn on the visibility in case it was turned off somehow */
         window->State.Visible = GL_TRUE;
+
         InvalidateRect( hWnd, NULL, GL_FALSE ); /* Make sure whole window is repainted. Bit of a hack, but a safe one from what google turns up... */
         BeginPaint( hWnd, &ps );
         fghRedrawWindow( window );
@@ -624,17 +657,6 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
          */
         return 0;
 
-    case WM_CANCELMODE:
-        /*
-         * The window manager sends this message when it detects a change
-         * that requires that an application cancel any modal state it has
-         * entered. If we've called SetCapture in the mouse button handler,
-         * call ReleaseCapture.
-         */
-        if (setCaptureActive)
-            ReleaseCapture();
-        break;
-
     case WM_MOUSEMOVE:
     {
 #if defined(_WIN32_WCE)
@@ -883,8 +905,9 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
         if (!lParam || !fgWindowByHandle((HWND)lParam))
             /* Capture released or capture taken by non-FreeGLUT window */
             setCaptureActive = 0;
-        /* User has finished resizing the window, force a redraw */
-        INVOKE_WCB( *window, Display, ( ) );
+        /* Docs advise a redraw */
+        InvalidateRect( hWnd, NULL, GL_FALSE );
+        UpdateWindow(hWnd);
         lRet = 0;   /* Per docs, should return zero */
         break;
 
@@ -948,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 */
-                window->State.Visible = GL_FALSE ;
+                /* Turning off the visibility is handled in WM_SIZE handler */
 
                 break ;