#include <GL/freeglut.h>
#include "../fg_internal.h"
-extern RECT fghGetClientArea( const SFG_Window *window, BOOL wantPosOutside );
+
+extern void fgEnumMenus( FGCBMenuEnumerator enumCallback, SFG_Enumerator* enumerator );
+
GLvoid fgPlatformGetGameModeVMaxExtent( SFG_Window* window, int* x, int* y )
*y = glutGet ( GLUT_SCREEN_HEIGHT );
}
-void fgPlatformCheckMenuDeactivate()
+static void fghcbIsActiveMenu(SFG_Menu *menu,
+ SFG_Enumerator *enumerator)
+{
+ if (enumerator->found)
+ return;
+
+ /* Check the menu's active and the one we are searching for. */
+ if (menu->IsActive && menu->Window->Window.Handle==(HWND)enumerator->data)
+ {
+ enumerator->found = GL_TRUE;
+ enumerator->data = (void*) menu;
+ return;
+ }
+}
+
+void fgPlatformCheckMenuDeactivate(HWND newFocusWnd)
{
- /* 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.
+ /* User/system switched application focus.
+ * If we have an open menu, close it.
+ * If the window that got focus is an active
+ * menu window, don't do anything. This occurs
+ * as it is sadly necessary to do an activating
+ * ShowWindow() for the menu to pop up over the
+ * gamemode window.
+ * If the window that got focus is the gamemode
+ * window, the menus pop under it. Bring them
+ * back in view in this special case.
*/
SFG_Menu* menu = NULL;
+ SFG_Enumerator enumerator;
- if ( fgStructure.Menus.First )
- menu = fgGetActiveMenu();
-
- if ( menu )
+ if ( fgState.ActiveMenus )
{
- 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) /* Make sure we don't kill the menu when trying to enter a submenu */
+ /* see if there is an active menu whose window matches the one that got focus */
+ enumerator.found = GL_FALSE;
+ enumerator.data = (void*) newFocusWnd;
+ fgEnumMenus(fghcbIsActiveMenu, &enumerator);
+ if (enumerator.found)
+ menu = (SFG_Menu*) enumerator.data;
+
+ if ( !menu )
{
- if (wnd!=menu->ParentWindow)
- /* User switched to another FreeGLUT window */
- fgDeactivateMenu(menu->ParentWindow);
- else
+ /* window that got focus was not one of the active menus. That means we'll
+ * close the active menu's unless the window that got focus was their parent */
+ menu = fgGetActiveMenu();
+
+ if (newFocusWnd != menu->ParentWindow->Window.Handle)
{
- /* 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);
+ /* focus shifted to another window than the menu's parent, close menus */
+ fgDeactivateMenu(menu->ParentWindow);
+ return;
}
}
}