From 5ec320a0461437fb554c101ad63cc51a2f060a0d Mon Sep 17 00:00:00 2001 From: FileEX Date: Wed, 12 Nov 2025 19:44:43 +0100 Subject: [PATCH] Fix bugs --- Client/core/CMessageLoopHook.cpp | 37 +++++++++++++++++++ .../mods/deathmatch/logic/CPacketHandler.cpp | 6 +++ 2 files changed, 43 insertions(+) diff --git a/Client/core/CMessageLoopHook.cpp b/Client/core/CMessageLoopHook.cpp index 5935bdb8c2c..2b4606e82ea 100644 --- a/Client/core/CMessageLoopHook.cpp +++ b/Client/core/CMessageLoopHook.cpp @@ -22,6 +22,8 @@ UCHAR CMessageLoopHook::m_LastScanCode = NULL; BYTE* CMessageLoopHook::m_LastKeyboardState = new BYTE[256]; bool ms_bIgnoreNextEscapeCharacter = false; +#define WM_CUSTOMFOCUS_FIX WM_APP + 1 + CMessageLoopHook::CMessageLoopHook() { WriteDebugEvent("CMessageLoopHook::CMessageLoopHook"); @@ -132,6 +134,17 @@ LRESULT CALLBACK CMessageLoopHook::ProcessMessage(HWND hwnd, UINT uMsg, WPARAM w if (pModManager && pModManager->IsLoaded()) { bool bFocus = (wState == WA_CLICKACTIVE) || (wState == WA_ACTIVE); + + // Fix for the Windows behavior that removes focus from a window if it was minimized during startup + // (you have to double-click the icon or alt+tab to regain focus despite the window being visible). + // GitHub issue #4233 + static bool fixFirstTimeFocus = false; + if (!fixFirstTimeFocus && !bFocus && GetForegroundWindow() != hwnd && GetFocus() == hwnd && !IsIconic(hwnd)) + { + fixFirstTimeFocus = true; + PostMessage(hwnd, WM_CUSTOMFOCUS_FIX, 0, 0); + } + pModManager->GetClient()->OnWindowFocusChange(bFocus); } @@ -150,6 +163,30 @@ LRESULT CALLBACK CMessageLoopHook::ProcessMessage(HWND hwnd, UINT uMsg, WPARAM w } } + // When updating m_bFocused in CClientGame from CPacketHandler (to fix another bug — see the note there), + // the window might not actually have focus at that moment (even though Windows reports it as focused). + // In this case, isMTAWindowFocused returns false even though the window has focus. + // Therefore, we need to intercept the window return operation and manually set the focus in CClientGame. + if (uMsg == WM_WINDOWPOSCHANGING) + { + WINDOWPOS* wp = reinterpret_cast(lParam); + if (wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE && !(wp->flags & SWP_NOZORDER)) + { + if (GetForegroundWindow() == hwnd && !IsIconic(hwnd)) + { + CModManager* pModManager = CModManager::GetSingletonPtr(); + if (pModManager && pModManager->IsLoaded()) + pModManager->GetClient()->OnWindowFocusChange(true); + } + } + } + + if (uMsg == WM_CUSTOMFOCUS_FIX) + { + AllowSetForegroundWindow(ASFW_ANY); + SetForegroundWindow(hwnd); + } + if (uMsg == WM_PAINT) { GetVideoModeManager()->OnPaint(); diff --git a/Client/mods/deathmatch/logic/CPacketHandler.cpp b/Client/mods/deathmatch/logic/CPacketHandler.cpp index 339110ff311..72ecdc741a5 100644 --- a/Client/mods/deathmatch/logic/CPacketHandler.cpp +++ b/Client/mods/deathmatch/logic/CPacketHandler.cpp @@ -464,6 +464,12 @@ void CPacketHandler::Packet_ServerJoined(NetBitStreamInterface& bitStream) g_pCore->UpdateRecentlyPlayed(); + // Update focus state after joining + // m_bFocused is set in the CClientGame constructor - immediately after clicking "join." + // This means that if the window loses focus while joining the game, the game still believes it has focus, + // and isMTAWindowFocused returns true even when the user is doing anything outside the MTA window. + g_pClientGame->m_bFocused = g_pCore->IsFocused(); + auto discord = g_pCore->GetDiscord(); if (discord && discord->IsDiscordRPCEnabled()) {