MenuStatusCallback when menu was closed did not return location of pointer relative...
[freeglut] / src / mswin / fg_main_mswin.c
index be412ba..4ee9008 100644 (file)
@@ -135,7 +135,21 @@ static void fghUpdateWindowStatus(SFG_Window *window, GLboolean visState)
     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)
+        {
+            if (visState)
+                /* visible, set window title */
+                SetWindowText( window->Window.Handle, window->State.pWState.WindowTitle );
+            else
+                /* not visible, set icon title */
+                SetWindowText( window->Window.Handle, window->State.pWState.IconTitle );
+        }
     }
 
     /* Also set visibility state for children */
@@ -147,47 +161,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 */
 }
 
 
@@ -366,7 +349,7 @@ static SFG_Window* fghWindowUnderCursor(SFG_Window *window)
      */
     if (window && window->Children.First)   /* This window has childs */
     {
-        SFG_WindowHandleType hwnd;
+        HWND hwnd;
         SFG_Window* child_window;
 
         /* Get mouse position at time of message */
@@ -501,12 +484,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,9 +519,14 @@ 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 
+                 * glutGet(GLUT_WINDOW_X) and glutGet(GLUT_WINDOW_Y), which return
+                 * top-left of client area.
+                 */
                 GetWindowRect( window->Window.Handle, &windowRect );
             
                 if (window->Parent)
@@ -554,6 +545,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:
@@ -607,7 +601,9 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
                  */
                 if (FETCH_WCB( *window, Entry ))
                 {
+                    SFG_Window* saved_window = fgStructure.CurrentWindow;
                     INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) );
+                    fgSetWindow(saved_window);
 
                     tme.cbSize = sizeof(TRACKMOUSEEVENT);
                     tme.dwFlags = TME_LEAVE;
@@ -639,21 +635,37 @@ 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:
     {
-        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 );
-        EndPaint( hWnd, &ps );
+        RECT rect;
+
+        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 */
+            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 );
+        }
+        lRet = 0;   /* As per docs, should return 0 */
     }
     break;
 
@@ -671,12 +683,13 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
 
     case WM_MOUSEMOVE:
     {
+        /* Per docs, use LOWORD/HIWORD for WinCE and GET_X_LPARAM/GET_Y_LPARAM for desktop windows */
 #if defined(_WIN32_WCE)
-        window->State.MouseX = 320-HIWORD( lParam );
+        window->State.MouseX = 320-HIWORD( lParam );    /* XXX: Docs say x should be loword and y hiword? */
         window->State.MouseY = LOWORD( lParam );
 #else
-        window->State.MouseX = LOWORD( lParam );
-        window->State.MouseY = HIWORD( lParam );
+        window->State.MouseX = GET_X_LPARAM( lParam );
+        window->State.MouseY = GET_Y_LPARAM( lParam );
 #endif /* defined(_WIN32_WCE) */
         /* Restrict to [-32768, 32767] to match X11 behaviour       */
         /* See comment in "freeglut_developer" mailing list 10/4/04 */
@@ -714,12 +727,13 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
         GLboolean pressed = GL_TRUE;
         int button;
 
+        /* Per docs, use LOWORD/HIWORD for WinCE and GET_X_LPARAM/GET_Y_LPARAM for desktop windows */
 #if defined(_WIN32_WCE)
-        window->State.MouseX = 320-HIWORD( lParam );
+        window->State.MouseX = 320-HIWORD( lParam );    /* XXX: Docs say x should be loword and y hiword? */
         window->State.MouseY = LOWORD( lParam );
 #else
-        window->State.MouseX = LOWORD( lParam );
-        window->State.MouseY = HIWORD( lParam );
+        window->State.MouseX = GET_X_LPARAM( lParam );
+        window->State.MouseY = GET_Y_LPARAM( lParam );
 #endif /* defined(_WIN32_WCE) */
 
         /* Restrict to [-32768, 32767] to match X11 behaviour       */
@@ -822,9 +836,22 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
 
     case WM_MOUSEWHEEL:
     {
-        SFG_Window *child_window = NULL;
-        int wheel_number = LOWORD( wParam );
-        short ticks = ( short )HIWORD( wParam );
+        int wheel_number = 0;   /* Only one scroll wheel on windows */
+#if defined(_WIN32_WCE)
+        int modkeys = LOWORD(wParam); 
+        short ticks = (short)HIWORD(wParam);
+        /* commented out as should not be needed here, mouse motion is processed in WM_MOUSEMOVE first:
+        xPos = LOWORD(lParam);  -- straight from docs, not consistent with mouse nutton and mouse motion above (which i think is wrong)
+        yPos = HIWORD(lParam);
+        */
+#else
+        /* int modkeys = GET_KEYSTATE_WPARAM( wParam ); */
+        short ticks = GET_WHEEL_DELTA_WPARAM( wParam );
+        /* commented out as should not be needed here, mouse motion is processed in WM_MOUSEMOVE first:
+        window->State.MouseX = GET_X_LPARAM( lParam );
+        window->State.MouseY = GET_Y_LPARAM( lParam );
+        */
+#endif /* defined(_WIN32_WCE) */
 
         window = fghWindowUnderCursor(window);
 
@@ -877,6 +904,8 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
 
             fgState.Modifiers = INVALID_MODIFIERS;
                }
+        /* Per docs, should return zero */
+        lRet = 0;
     }
     break ;
 
@@ -923,30 +952,6 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
         lRet = 0;   /* Per docs, should return zero */
         break;
 
-        /* Other messages that I have seen and which are not handled already */
-    case WM_SETTEXT:  /* 0x000c */
-        lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
-        /* Pass it on to "DefWindowProc" to set the window text */
-        break;
-
-    case WM_GETTEXT:  /* 0x000d */
-        /* Ideally we would copy the title of the window into "lParam" */
-        /* strncpy ( (char *)lParam, "Window Title", wParam );
-           lRet = ( wParam > 12 ) ? 12 : wParam;  */
-        /* the number of characters copied */
-        lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
-        break;
-
-    case WM_GETTEXTLENGTH:  /* 0x000e */
-        /* Ideally we would get the length of the title of the window */
-        lRet = 12;
-        /* the number of characters in "Window Title\0" (see above) */
-        break;
-
-    case WM_ERASEBKGND:  /* 0x0014 */
-        lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
-        break;
-
 #if !defined(_WIN32_WCE)
     case WM_SYNCPAINT:  /* 0x0088 */
         /* Another window has moved, need to update this one */
@@ -955,12 +960,6 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
         /* Help screen says this message must be passed to "DefWindowProc" */
         break;
 
-    case WM_NCPAINT:  /* 0x0085 */
-      /* Need to update the border of this window */
-        lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
-        /* Pass it on to "DefWindowProc" to repaint a standard border */
-        break;
-
     case WM_SYSCOMMAND :  /* 0x0112 */
         {
           /*
@@ -983,8 +982,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 ;
 
@@ -1017,7 +1015,6 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
                 break ;
 
             case SC_RESTORE    :
-                fghUpdateWindowStatus(window, GL_TRUE);
                 break ;
 
             case SC_TASKLIST   :