[KBM] Do not register low level hook if there're no remappings (#29708)

* [KBM] Do not register low level hook if there're no remappings

* f: typo

* f: address review comment
This commit is contained in:
Andrey Nekrasov 2024-01-03 16:49:29 +01:00 committed by GitHub
parent 46f5316858
commit 2a544583c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 5 deletions

View File

@ -6,9 +6,13 @@
#include <array>
#include <optional>
#include <functional>
#include <unordered_map>
// Initializes and runs windows message loop
inline int run_message_loop(const bool until_idle = false, const std::optional<uint32_t> timeout_ms = {})
inline int run_message_loop(const bool until_idle = false,
const std::optional<uint32_t> timeout_ms = {},
std::unordered_map<DWORD, std::function<void()>> wm_app_msg_callbacks = {})
{
MSG msg{};
bool stop = false;
@ -24,11 +28,16 @@ inline int run_message_loop(const bool until_idle = false, const std::optional<u
DispatchMessageW(&msg);
stop = until_idle && !PeekMessageW(&msg, nullptr, 0, 0, PM_NOREMOVE);
stop = stop || (msg.message == WM_TIMER && msg.wParam == timerId);
if (auto it = wm_app_msg_callbacks.find(msg.message); it != end(wm_app_msg_callbacks))
it->second();
}
if (timeout_ms.has_value())
{
KillTimer(nullptr, timerId);
}
return static_cast<int>(msg.wParam);
}

View File

@ -61,9 +61,14 @@ int WINAPI wWinMain(_In_ HINSTANCE /*hInstance*/,
}
auto kbm = KeyboardManager();
if (kbm.HasRegisteredRemappings())
kbm.StartLowlevelKeyboardHook();
run_message_loop();
auto StartHookFunc = [&kbm]() {
kbm.StartLowlevelKeyboardHook();
};
run_message_loop({}, {}, { { KeyboardManager::StartHookMessageID, StartHookFunc } });
kbm.StopLowlevelKeyboardHook();
Trace::UnregisterProvider();

View File

@ -21,8 +21,15 @@ HHOOK KeyboardManager::hookHandleCopy;
HHOOK KeyboardManager::hookHandle;
KeyboardManager* KeyboardManager::keyboardManagerObjectPtr;
namespace
{
DWORD mainThreadId = {};
}
KeyboardManager::KeyboardManager()
{
mainThreadId = GetCurrentThreadId();
// Load the initial settings.
LoadSettings();
@ -38,9 +45,11 @@ KeyboardManager::KeyboardManager()
}
loadingSettings = true;
bool loadedSuccessfully = false;
try
{
LoadSettings();
loadedSuccessfully = true;
}
catch (...)
{
@ -48,6 +57,18 @@ KeyboardManager::KeyboardManager()
}
loadingSettings = false;
if (!loadedSuccessfully)
return;
const bool newHasRemappings = HasRegisteredRemappingsUnchecked();
// We didn't have any bindings before and we have now
if (newHasRemappings && !hookHandle)
PostThreadMessageW(mainThreadId, StartHookMessageID, 0, 0);
// All bindings were removed
if (!newHasRemappings && hookHandle)
StopLowlevelKeyboardHook();
};
editorIsRunningEvent = CreateEvent(nullptr, true, false, KeyboardManagerConstants::EditorWindowEventName.c_str());
@ -121,6 +142,32 @@ void KeyboardManager::StopLowlevelKeyboardHook()
}
}
bool KeyboardManager::HasRegisteredRemappings() const
{
constexpr int MaxAttempts = 5;
if (loadingSettings)
{
for (int currentAttempt = 0; currentAttempt < MaxAttempts; ++currentAttempt)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
if (!loadingSettings)
break;
}
}
// Assume that we have registered remappings to be on the safe side if we couldn't check
if (loadingSettings)
return true;
return HasRegisteredRemappingsUnchecked();
}
bool KeyboardManager::HasRegisteredRemappingsUnchecked() const
{
return !(state.appSpecificShortcutReMap.empty() && state.appSpecificShortcutReMapSortedKeys.empty() && state.osLevelShortcutReMap.empty() && state.osLevelShortcutReMapSortedKeys.empty() && state.singleKeyReMap.empty() && state.singleKeyToTextReMap.empty());
}
intptr_t KeyboardManager::HandleKeyboardHookEvent(LowlevelKeyboardEvent* data) noexcept
{
if (loadingSettings)

View File

@ -7,6 +7,8 @@
class KeyboardManager
{
public:
static const inline DWORD StartHookMessageID = WM_APP + 1;
// Constructor
KeyboardManager();
@ -21,7 +23,12 @@ public:
void StartLowlevelKeyboardHook();
void StopLowlevelKeyboardHook();
bool HasRegisteredRemappings() const;
private:
// Returns whether there are any remappings available without waiting for settings to load
bool HasRegisteredRemappingsUnchecked() const;
// Contains the non localized module name
std::wstring moduleName = KeyboardManagerConstants::ModuleName;