From 3b374c25da9e8b635e061aaf0e9525e147c70266 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Thu, 28 Mar 2024 18:46:50 -0400 Subject: [PATCH] Improve window focus tracking --- engine/source/platformWin32/platformWin32.h | 1 + engine/source/platformWin32/winInput.cpp | 2 +- engine/source/platformWin32/winWindow.cpp | 71 ++++++++++++++------- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/engine/source/platformWin32/platformWin32.h b/engine/source/platformWin32/platformWin32.h index cba4b8fe..bef1e8b3 100644 --- a/engine/source/platformWin32/platformWin32.h +++ b/engine/source/platformWin32/platformWin32.h @@ -71,6 +71,7 @@ struct Win32PlatState S32 desktopWidth; S32 desktopHeight; U32 currentTime; + bool focused; Win32WinMgr* windowManager; GFXVideoMode* videoMode; diff --git a/engine/source/platformWin32/winInput.cpp b/engine/source/platformWin32/winInput.cpp index b6bfb22d..bb85b437 100644 --- a/engine/source/platformWin32/winInput.cpp +++ b/engine/source/platformWin32/winInput.cpp @@ -448,7 +448,7 @@ bool Input::isActive() //------------------------------------------------------------------------------ void Input::process() { - if (smManager && smManager->isEnabled() && smActive) + if (smManager && smManager->isEnabled() && smActive && winState.focused) smManager->process(); } diff --git a/engine/source/platformWin32/winWindow.cpp b/engine/source/platformWin32/winWindow.cpp index 068d4206..99cd932d 100644 --- a/engine/source/platformWin32/winWindow.cpp +++ b/engine/source/platformWin32/winWindow.cpp @@ -49,7 +49,6 @@ static bool sgQueueEvents; extern U16 DIK_to_Key(U8 dikCode); // static helper variables -static bool windowActive = true; static bool windowLocked = false; static bool capsLockDown = false; @@ -90,6 +89,7 @@ Win32PlatState::Win32PlatState() desktopWidth = NULL; desktopHeight = NULL; currentTime = NULL; + focused = false; windowManager = NULL; @@ -211,7 +211,7 @@ static bool cursorInWindow() if (Win32Window == NULL) return false; - if (!windowActive) + if (!winState.focused) return false; if (Win32Window->mBorderless) @@ -279,7 +279,7 @@ static void updateCursorVisibility() static void setMouseClipping() { ClipCursor(NULL); - if (windowActive) + if (winState.focused) { setCursorVisible(false); @@ -485,7 +485,7 @@ static S32 mouseY = 0xFFFFFFFF; //-------------------------------------- static void CheckCursorPos() { - if (windowLocked && windowActive) + if (windowLocked && winState.focused) { POINT mousePos; GetCursorPos(&mousePos); @@ -592,6 +592,39 @@ static void mouseWheelEvent(S32 delta) } } +//-------------------------------------- +static void updateWindowFocus(HWND hWnd, bool newFocus, bool setMouseClip) +{ + // Ensure the window is actually focused right now + bool currentFocus = GetForegroundWindow() == hWnd; + if (winState.focused == newFocus || currentFocus != newFocus) + return; + + winState.focused = newFocus; + Con::printf("Window focused: %d", winState.focused); + + if (winState.focused) + { + Input::activate(); + } + else + { + DInputManager* mgr = dynamic_cast(Input::getManager()); + if (!mgr || !mgr->isMouseActive()) + { + // Deactivate all the mouse triggers: + for (U32 i = 0; i < 3; i++) + { + if (mouseButtonState[i]) + mouseButtonEvent(SI_BREAK, KEY_BUTTON0 + i); + } + } + Input::deactivate(); + } + + if (windowLocked && setMouseClip) + setMouseClipping(); +} struct WinMessage { @@ -635,11 +668,9 @@ static LRESULT PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM break; case WM_ACTIVATE: setCursorVisible(false); - windowActive = LOWORD(wParam) != WA_INACTIVE; - if (windowActive) + if (LOWORD(wParam) != WA_INACTIVE) { Game->refreshWindow(); - Input::activate(); if (Win32Window) { @@ -650,22 +681,16 @@ static LRESULT PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM } } } - else - { - DInputManager* mgr = dynamic_cast(Input::getManager()); - if (!mgr || !mgr->isMouseActive()) - { - // Deactivate all the mouse triggers: - for (U32 i = 0; i < 3; i++) - { - if (mouseButtonState[i]) - mouseButtonEvent(SI_BREAK, KEY_BUTTON0 + i); - } - } - Input::deactivate(); - } - if (windowLocked) - setMouseClipping(); + updateWindowFocus(hWnd, LOWORD(wParam) != WA_INACTIVE, true); + break; + case WM_SETFOCUS: + updateWindowFocus(hWnd, true, true); + break; + case WM_KILLFOCUS: + updateWindowFocus(hWnd, false, true); + break; + case WM_NCACTIVATE: + updateWindowFocus(hWnd, wParam, false); break; case WM_MOVE: