Skip to content
36 changes: 29 additions & 7 deletions Client/core/CMessageLoopHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,37 @@ LRESULT CALLBACK CMessageLoopHook::ProcessMessage(HWND hwnd, UINT uMsg, WPARAM w
// Alternate alt-tab system
if (pThis && hwnd == pThis->GetHookedWindowHandle())
{
if (uMsg == WM_ACTIVATE && LOWORD(wParam) == WA_ACTIVE)
if (uMsg == WM_ACTIVATE)
{
GetVideoModeManager()->OnGainFocus();
}
if (uMsg == WM_ACTIVATE && LOWORD(wParam) == WA_INACTIVE)
{
GetVideoModeManager()->OnLoseFocus();
g_pCore->GetKeyBinds()->OnLoseFocus();
CModManager* pModManager = CModManager::GetSingletonPtr();
WORD wState = LOWORD(wParam);

if (pModManager && pModManager->IsLoaded())
{
CClientBase* pBase = pModManager->GetCurrentMod();

if (pBase)
{
bool bFocus = (wState == WA_CLICKACTIVE) || (wState == WA_ACTIVE);
pBase->OnWindowFocusChange(bFocus);
}
}

switch (wState)
{
case WA_ACTIVE:
GetVideoModeManager()->OnGainFocus();
break;

case WA_INACTIVE:
{
GetVideoModeManager()->OnLoseFocus();
g_pCore->GetKeyBinds()->OnLoseFocus();
break;
}
}
}

if (uMsg == WM_PAINT)
{
GetVideoModeManager()->OnPaint();
Expand Down
5 changes: 5 additions & 0 deletions Client/mods/deathmatch/CClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,11 @@ void CClient::GetPlayerNames(std::vector<SString>& vPlayerNames)
}
}

void CClient::OnWindowFocusChange(bool state)
{
g_pClientGame->OnWindowFocusChange(state);
}

CClient::InitializeArguments CClient::ExtractInitializeArguments(const char* arguments)
{
// Format: "nickname [password]"
Expand Down
2 changes: 2 additions & 0 deletions Client/mods/deathmatch/CClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class CClient : public CClientBase
bool HandleException(CExceptionInformation* pExceptionInformation);
void GetPlayerNames(std::vector<SString>& vPlayerNames);

void OnWindowFocusChange(bool state) override;

private:
struct InitializeArguments
{
Expand Down
15 changes: 15 additions & 0 deletions Client/mods/deathmatch/logic/CClientGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo())
m_lastWeaponSlot = WEAPONSLOT_MAX; // last stored weapon slot, for weapon slot syncing to server (sets to invalid value)
ResetAmmoInClip();

m_bFocused = g_pCore->IsFocused();

m_bCursorEventsEnabled = false;
m_bInitiallyFadedOut = true;

Expand Down Expand Up @@ -2565,6 +2567,7 @@ void CClientGame::AddBuiltInEvents()
m_Events.AddEvent("onClientRender", "", NULL, false);
m_Events.AddEvent("onClientMinimize", "", NULL, false);
m_Events.AddEvent("onClientRestore", "", NULL, false);
m_Events.AddEvent("onClientMTAFocusChange", "focused", NULL, false);

// Cursor events
m_Events.AddEvent("onClientClick", "button, state, screenX, screenY, worldX, worldY, worldZ, gui_clicked", NULL, false);
Expand Down Expand Up @@ -6548,6 +6551,18 @@ void CClientGame::RestreamWorld()
g_pGame->GetStreaming()->ReinitStreaming();
}

void CClientGame::OnWindowFocusChange(bool state)
{
if (state == m_bFocused)
return;

m_bFocused = state;

CLuaArguments Arguments;
Arguments.PushBoolean(state);
m_pRootEntity->CallEvent("onClientMTAFocusChange", Arguments, false);
}

void CClientGame::InsertIFPPointerToMap(const unsigned int u32BlockNameHash, const std::shared_ptr<CClientIFP>& pIFP)
{
m_mapOfIfpPointers[u32BlockNameHash] = pIFP;
Expand Down
5 changes: 5 additions & 0 deletions Client/mods/deathmatch/logic/CClientGame.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ class CClientGame
void EnablePacketRecorder(const char* szFilename);
void InitVoice(bool bEnabled, unsigned int uiServerSampleRate, unsigned char ucQuality, unsigned int uiBitrate);

bool IsWindowFocused() const { return m_bFocused; }

// Accessors

CVoiceRecorder* GetVoiceRecorder() { return m_pVoiceRecorder; };
Expand Down Expand Up @@ -439,6 +441,8 @@ class CClientGame
void RestreamModel(unsigned short usModel);
void RestreamWorld();

void OnWindowFocusChange(bool state);

private:
// CGUI Callbacks
bool OnKeyDown(CGUIKeyEventArgs Args);
Expand Down Expand Up @@ -773,6 +777,7 @@ class CClientGame
bool m_bBeingDeleted; // To enable speedy disconnect

bool m_bWasMinimized;
bool m_bFocused;

// Cache for speeding up collision processing
public:
Expand Down
6 changes: 6 additions & 0 deletions Client/mods/deathmatch/logic/luadefs/CLuaClientDefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void CLuaClientDefs::LoadFunctions()
{"isChatVisible", ArgumentParserWarn<false, IsChatVisible>},
{"isChatInputBlocked", ArgumentParser<IsChatInputBlocked>},
{"clearDebugBox", ArgumentParser<ClearDebug>},
{"isMTAWindowFocused", ArgumentParser<IsMTAWindowFocused>},
{"isCapsLockEnabled", ArgumentParser<IsCapsLockEnabled>}
};

Expand Down Expand Up @@ -72,6 +73,11 @@ bool CLuaClientDefs::ClearDebug()
return true;
}

bool CLuaClientDefs::IsMTAWindowFocused()
{
return m_pClientGame->IsWindowFocused();
}

bool CLuaClientDefs::IsCapsLockEnabled()
{
return ((::GetKeyState(VK_CAPITAL) & 0x0001) != 0);
Expand Down
1 change: 1 addition & 0 deletions Client/mods/deathmatch/logic/luadefs/CLuaClientDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ class CLuaClientDefs : public CLuaDefs
static bool IsChatVisible();
static bool IsChatInputBlocked();
static bool ClearDebug();
static bool IsMTAWindowFocused();
static bool IsCapsLockEnabled();
};
2 changes: 2 additions & 0 deletions Client/sdk/core/CClientBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ class CClientBase

virtual bool HandleException(CExceptionInformation* pExceptionInformation) = 0;
virtual void GetPlayerNames(std::vector<SString>& vPlayerNames) = 0;

virtual void OnWindowFocusChange(bool state) = 0;
};