diff --git a/Client/core/CMessageLoopHook.cpp b/Client/core/CMessageLoopHook.cpp index 564563e0df0..2351d98a160 100644 --- a/Client/core/CMessageLoopHook.cpp +++ b/Client/core/CMessageLoopHook.cpp @@ -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(); diff --git a/Client/mods/deathmatch/CClient.cpp b/Client/mods/deathmatch/CClient.cpp index cb0eeb4834f..ab4cb37e7d3 100644 --- a/Client/mods/deathmatch/CClient.cpp +++ b/Client/mods/deathmatch/CClient.cpp @@ -314,6 +314,11 @@ void CClient::GetPlayerNames(std::vector& vPlayerNames) } } +void CClient::OnWindowFocusChange(bool state) +{ + g_pClientGame->OnWindowFocusChange(state); +} + CClient::InitializeArguments CClient::ExtractInitializeArguments(const char* arguments) { // Format: "nickname [password]" diff --git a/Client/mods/deathmatch/CClient.h b/Client/mods/deathmatch/CClient.h index d8cdaa9668c..49c4a95c7d3 100644 --- a/Client/mods/deathmatch/CClient.h +++ b/Client/mods/deathmatch/CClient.h @@ -32,6 +32,8 @@ class CClient : public CClientBase bool HandleException(CExceptionInformation* pExceptionInformation); void GetPlayerNames(std::vector& vPlayerNames); + void OnWindowFocusChange(bool state) override; + private: struct InitializeArguments { diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 54c2dd8fe20..1e5a6e9fb37 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -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; @@ -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); @@ -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& pIFP) { m_mapOfIfpPointers[u32BlockNameHash] = pIFP; diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index 1d76e70f112..ef2468303d1 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -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; }; @@ -439,6 +441,8 @@ class CClientGame void RestreamModel(unsigned short usModel); void RestreamWorld(); + void OnWindowFocusChange(bool state); + private: // CGUI Callbacks bool OnKeyDown(CGUIKeyEventArgs Args); @@ -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: diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaClientDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaClientDefs.cpp index 044ab2e57b6..7df2d53e0ec 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaClientDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaClientDefs.cpp @@ -23,6 +23,7 @@ void CLuaClientDefs::LoadFunctions() {"isChatVisible", ArgumentParserWarn}, {"isChatInputBlocked", ArgumentParser}, {"clearDebugBox", ArgumentParser}, + {"isMTAWindowFocused", ArgumentParser}, {"isCapsLockEnabled", ArgumentParser} }; @@ -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); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaClientDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaClientDefs.h index 172cf53557a..7b3b276b83e 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaClientDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaClientDefs.h @@ -26,5 +26,6 @@ class CLuaClientDefs : public CLuaDefs static bool IsChatVisible(); static bool IsChatInputBlocked(); static bool ClearDebug(); + static bool IsMTAWindowFocused(); static bool IsCapsLockEnabled(); }; diff --git a/Client/sdk/core/CClientBase.h b/Client/sdk/core/CClientBase.h index acae1a75d18..17634dab811 100644 --- a/Client/sdk/core/CClientBase.h +++ b/Client/sdk/core/CClientBase.h @@ -32,4 +32,6 @@ class CClientBase virtual bool HandleException(CExceptionInformation* pExceptionInformation) = 0; virtual void GetPlayerNames(std::vector& vPlayerNames) = 0; + + virtual void OnWindowFocusChange(bool state) = 0; };