[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:
Родитель
46f5316858
Коммит
2a544583c0
|
@ -6,9 +6,13 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <functional>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
// Initializes and runs windows message loop
|
// 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{};
|
MSG msg{};
|
||||||
bool stop = false;
|
bool stop = false;
|
||||||
|
@ -24,11 +28,16 @@ inline int run_message_loop(const bool until_idle = false, const std::optional<u
|
||||||
DispatchMessageW(&msg);
|
DispatchMessageW(&msg);
|
||||||
stop = until_idle && !PeekMessageW(&msg, nullptr, 0, 0, PM_NOREMOVE);
|
stop = until_idle && !PeekMessageW(&msg, nullptr, 0, 0, PM_NOREMOVE);
|
||||||
stop = stop || (msg.message == WM_TIMER && msg.wParam == timerId);
|
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())
|
if (timeout_ms.has_value())
|
||||||
{
|
{
|
||||||
KillTimer(nullptr, timerId);
|
KillTimer(nullptr, timerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<int>(msg.wParam);
|
return static_cast<int>(msg.wParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +69,7 @@ template<typename T>
|
||||||
inline T GetWindowCreateParam(LPARAM lparam)
|
inline T GetWindowCreateParam(LPARAM lparam)
|
||||||
{
|
{
|
||||||
static_assert(sizeof(T) <= sizeof(void*));
|
static_assert(sizeof(T) <= sizeof(void*));
|
||||||
T data{ static_cast <T>(reinterpret_cast<CREATESTRUCT*>(lparam)->lpCreateParams) };
|
T data{ static_cast<T>(reinterpret_cast<CREATESTRUCT*>(lparam)->lpCreateParams) };
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,5 +83,5 @@ inline void StoreWindowParam(HWND window, T data)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T GetWindowParam(HWND window)
|
inline T GetWindowParam(HWND window)
|
||||||
{
|
{
|
||||||
return reinterpret_cast <T>(GetWindowLongPtrW(window, GWLP_USERDATA));
|
return reinterpret_cast<T>(GetWindowLongPtrW(window, GWLP_USERDATA));
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,9 +61,14 @@ int WINAPI wWinMain(_In_ HINSTANCE /*hInstance*/,
|
||||||
}
|
}
|
||||||
|
|
||||||
auto kbm = KeyboardManager();
|
auto kbm = KeyboardManager();
|
||||||
kbm.StartLowlevelKeyboardHook();
|
if (kbm.HasRegisteredRemappings())
|
||||||
|
kbm.StartLowlevelKeyboardHook();
|
||||||
|
|
||||||
run_message_loop();
|
auto StartHookFunc = [&kbm]() {
|
||||||
|
kbm.StartLowlevelKeyboardHook();
|
||||||
|
};
|
||||||
|
|
||||||
|
run_message_loop({}, {}, { { KeyboardManager::StartHookMessageID, StartHookFunc } });
|
||||||
|
|
||||||
kbm.StopLowlevelKeyboardHook();
|
kbm.StopLowlevelKeyboardHook();
|
||||||
Trace::UnregisterProvider();
|
Trace::UnregisterProvider();
|
||||||
|
|
|
@ -21,8 +21,15 @@ HHOOK KeyboardManager::hookHandleCopy;
|
||||||
HHOOK KeyboardManager::hookHandle;
|
HHOOK KeyboardManager::hookHandle;
|
||||||
KeyboardManager* KeyboardManager::keyboardManagerObjectPtr;
|
KeyboardManager* KeyboardManager::keyboardManagerObjectPtr;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
DWORD mainThreadId = {};
|
||||||
|
}
|
||||||
|
|
||||||
KeyboardManager::KeyboardManager()
|
KeyboardManager::KeyboardManager()
|
||||||
{
|
{
|
||||||
|
mainThreadId = GetCurrentThreadId();
|
||||||
|
|
||||||
// Load the initial settings.
|
// Load the initial settings.
|
||||||
LoadSettings();
|
LoadSettings();
|
||||||
|
|
||||||
|
@ -38,9 +45,11 @@ KeyboardManager::KeyboardManager()
|
||||||
}
|
}
|
||||||
|
|
||||||
loadingSettings = true;
|
loadingSettings = true;
|
||||||
|
bool loadedSuccessfully = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
LoadSettings();
|
LoadSettings();
|
||||||
|
loadedSuccessfully = true;
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
@ -48,6 +57,18 @@ KeyboardManager::KeyboardManager()
|
||||||
}
|
}
|
||||||
|
|
||||||
loadingSettings = false;
|
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());
|
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
|
intptr_t KeyboardManager::HandleKeyboardHookEvent(LowlevelKeyboardEvent* data) noexcept
|
||||||
{
|
{
|
||||||
if (loadingSettings)
|
if (loadingSettings)
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
class KeyboardManager
|
class KeyboardManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static const inline DWORD StartHookMessageID = WM_APP + 1;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
KeyboardManager();
|
KeyboardManager();
|
||||||
|
|
||||||
|
@ -21,7 +23,12 @@ public:
|
||||||
void StartLowlevelKeyboardHook();
|
void StartLowlevelKeyboardHook();
|
||||||
void StopLowlevelKeyboardHook();
|
void StopLowlevelKeyboardHook();
|
||||||
|
|
||||||
|
bool HasRegisteredRemappings() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Returns whether there are any remappings available without waiting for settings to load
|
||||||
|
bool HasRegisteredRemappingsUnchecked() const;
|
||||||
|
|
||||||
// Contains the non localized module name
|
// Contains the non localized module name
|
||||||
std::wstring moduleName = KeyboardManagerConstants::ModuleName;
|
std::wstring moduleName = KeyboardManagerConstants::ModuleName;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче