now also closing menus when non-client area is pressed (thanks for
[freeglut] / src / mswin / fg_main_mswin.c
index 4fe5538..3afc655 100644 (file)
@@ -228,6 +228,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
     SFG_Window* window;
     PAINTSTRUCT ps;
     LRESULT lRet = 1;
+    GLboolean gotChild = GL_FALSE;
 
     FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Event Handler" ) ;
 
@@ -251,7 +252,12 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
         GetCursorPos( &mouse_pos );
         ScreenToClient( window->Window.Handle, &mouse_pos );
         hwnd = ChildWindowFromPoint(window->Window.Handle, mouse_pos);
-        window = fgWindowByHandle(hwnd);
+        if (hwnd)   /* can be NULL if mouse outside parent by the time we get here */
+        {
+            window = fgWindowByHandle(hwnd);
+            if (window->Parent)
+                gotChild = GL_TRUE;
+        }
     }
 
     if ( window )
@@ -485,21 +491,61 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
 
     case WM_SETFOCUS:
 /*        printf("WM_SETFOCUS: %p\n", window ); */
+        if (gotChild)
+            /* If child should have focus instead, set it here. */
+            SetFocus(window->Window.Handle);
+
         lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
         INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) );
 
-               UpdateWindow ( hWnd );
+        UpdateWindow ( hWnd );
+        if (gotChild)
+            UpdateWindow ( window->Window.Handle );
         break;
 
     case WM_KILLFOCUS:
-/*        printf("WM_KILLFOCUS: %p\n", window ); */
-        lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
-        INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) );
+        {
+            SFG_Menu* menu = NULL;
+/*            printf("WM_KILLFOCUS: %p\n", window ); */
+            lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+            INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) );
 
-        if( window->IsMenu &&
-            window->ActiveMenu && window->ActiveMenu->IsActive )
-            fgUpdateMenuHighlight( window->ActiveMenu );
+            /* If we have an open menu, see if the open menu should be closed
+             * when focus was lost because user either switched
+             * application or FreeGLUT window (if one is running multiple
+             * windows). If so, close menu the active menu.
+             */
+            if ( fgStructure.Menus.First )
+                menu = fgGetActiveMenu();
 
+            if ( menu )
+            {
+                SFG_Window* wnd = NULL;
+                HWND hwnd = GetFocus();  /* Get window with current focus - NULL for non freeglut windows */
+                if (hwnd)
+                    /* See which of our windows it is */
+                    wnd = fgWindowByHandle(hwnd);
+
+                if (!hwnd || !wnd)
+                    /* User switched to another application*/
+                    fgDeactivateMenu(menu->ParentWindow);
+                else if (!wnd->IsMenu && wnd!=menu->ParentWindow)   /* Make sure we don't kill the menu when trying to enter a submenu */
+                    /* User switched to another FreeGLUT window */
+                    fgDeactivateMenu(menu->ParentWindow);
+                else
+                {
+                    /* Check if focus lost because non-client area of
+                     * window was pressed (pressing on client area is
+                     * handled in fgCheckActiveMenu)
+                     */
+                    POINT mouse_pos;
+                    RECT clientArea = fghGetClientArea(menu->ParentWindow, GL_FALSE);
+                    GetCursorPos(&mouse_pos);
+                    if ( !PtInRect( &clientArea, mouse_pos ) )
+                        fgDeactivateMenu(menu->ParentWindow);
+                }
+            }
+        }
         break;
 
 #if 0