Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions Client/core/CMessageLoopHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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);
}

Expand All @@ -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<WINDOWPOS*>(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();
Expand Down
6 changes: 6 additions & 0 deletions Client/mods/deathmatch/logic/CPacketHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
{
Expand Down
Loading