WM_SETFOCUS should not change focus to child instead, then all input goes to child...
[freeglut] / src / mswin / fg_main_mswin.c
index 4052bcd..92f653e 100644 (file)
@@ -176,21 +176,19 @@ static LRESULT fghWindowProcKeyPress(SFG_Window *window, UINT uMsg, GLboolean ke
                          rControl = 0, rShift = 0, rAlt = 0;
 
     int keypress = -1;
-    POINT mouse_pos ;
     
     /* if keydown, check for repeat */
+    /* If repeat is globally switched off, it cannot be switched back on per window.
+     * But if it is globally switched on, it can be switched off per window. This matches
+     * GLUT's behavior on X11, but not Nate Robbins' win32 GLUT, as he didn't implement the
+     * global state switch.
+     */
     if( keydown && ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE ) && (HIWORD(lParam) & KF_REPEAT) )
         return 1;
     
     /* Remember the current modifiers state so user can query it from their callback */
     fgState.Modifiers = fgPlatformGetModifiers( );
 
-    /* Get mouse position roughly at time of keypress */
-    GetCursorPos( &mouse_pos );
-    ScreenToClient( window->Window.Handle, &mouse_pos );
-    window->State.MouseX = mouse_pos.x;
-    window->State.MouseY = mouse_pos.y;
-
     /* Convert the Win32 keystroke codes to GLUTtish way */
 #   define KEY(a,b) case a: keypress = b; break;
 
@@ -323,6 +321,37 @@ static LRESULT fghWindowProcKeyPress(SFG_Window *window, UINT uMsg, GLboolean ke
         return 1;
 }
 
+void fghWindowUnderCursor(SFG_Window *window, SFG_Window **child_window)
+{
+    /* Check if the current window that the mouse is over is a child window
+     * of the window the message was sent to.
+     */
+    if (window && window->Children.First)
+    {
+        POINT mouse_pos;
+        SFG_WindowHandleType hwnd;
+        SFG_Window* temp_window;
+
+        /* Get mouse position at time of message */
+        DWORD mouse_pos_Dword = GetMessagePos();
+        mouse_pos.x = GET_X_LPARAM(mouse_pos_Dword);
+        mouse_pos.y = GET_Y_LPARAM(mouse_pos_Dword);
+        ScreenToClient( window->Window.Handle, &mouse_pos );
+        
+        hwnd = ChildWindowFromPoint(window->Window.Handle, mouse_pos);
+        if (hwnd && hwnd!=window->Window.Handle)   /* can be NULL if mouse outside parent by the time we get here, or can be same as parent if we didn't find a child */
+        {
+            temp_window = fgWindowByHandle(hwnd);
+            if (temp_window)    /* Verify we got a FreeGLUT window */
+            {
+                *child_window = temp_window;
+                /* ChildWindowFromPoint only searches immediate children, so search again to see if actually in grandchild or further descendant */
+                fghWindowUnderCursor(temp_window,child_window);
+            }
+        }
+    }
+}
+
 /*
  * The window procedure for handling Win32 events
  */
@@ -347,22 +376,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
      * we make sure that we process callbacks on the child window instead.
      * This mirrors how GLUT does things.
      */
-    if (window && window->Children.First)
-    {
-        POINT mouse_pos;
-        SFG_WindowHandleType hwnd;
-        SFG_Window* temp_window;
-
-        GetCursorPos( &mouse_pos );
-        ScreenToClient( window->Window.Handle, &mouse_pos );
-        hwnd = ChildWindowFromPoint(window->Window.Handle, mouse_pos);
-        if (hwnd)   /* can be NULL if mouse outside parent by the time we get here */
-        {
-            temp_window = fgWindowByHandle(hwnd);
-            if (temp_window && temp_window->Parent)    /* Verify we got a child window */
-                child_window = temp_window;
-        }
-    }
+    fghWindowUnderCursor(window, &child_window);
     
     switch( uMsg )
     {
@@ -509,20 +523,8 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
 
         lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
 
-        if (child_window)
-        {
-            /* If we're dealing with a child window, make sure it has input focus instead, set it here. */
-            SetFocus(child_window->Window.Handle);
-            SetActiveWindow( child_window->Window.Handle );
-            INVOKE_WCB( *child_window, Entry, ( GLUT_ENTERED ) );
-            UpdateWindow ( child_window->Window.Handle );
-        }
-        else
-        {
-            SetActiveWindow( window->Window.Handle );
-            INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) );
-        }
-        /* Always request update on main window to be safe */
+        SetActiveWindow( window->Window.Handle );
+        INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) );
         UpdateWindow ( hWnd );
 
         break;
@@ -542,6 +544,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));
         if (LOWORD(wParam) != WA_INACTIVE)
         {
 /*            printf("WM_ACTIVATE: fgSetCursor( %p, %d)\n", window,
@@ -736,8 +739,11 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
     {
         int wheel_number = LOWORD( wParam );
         short ticks = ( short )HIWORD( wParam );
-               fgState.MouseWheelTicks += ticks;
 
+        if (child_window)
+            window = child_window;
+
+               fgState.MouseWheelTicks += ticks;
         if ( abs ( fgState.MouseWheelTicks ) >= WHEEL_DELTA )
                {
                        int direction = ( fgState.MouseWheelTicks > 0 ) ? 1 : -1;
@@ -791,16 +797,12 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
 
     case WM_SYSKEYDOWN:
     case WM_KEYDOWN:
-        if (child_window)
-            window = child_window;
-        lRet = fghWindowProcKeyPress(window,uMsg,GL_TRUE,wParam,lParam);
+        lRet = fghWindowProcKeyPress(child_window?child_window:window,uMsg,GL_TRUE,wParam,lParam);
     break;
 
     case WM_SYSKEYUP:
     case WM_KEYUP:
-        if (child_window)
-            window = child_window;
-        lRet = fghWindowProcKeyPress(window,uMsg,GL_FALSE,wParam,lParam);
+        lRet = fghWindowProcKeyPress(child_window?child_window:window,uMsg,GL_FALSE,wParam,lParam);
     break;
 
     case WM_SYSCHAR: