[AOT] Low level keyboard hook (#18643)

* low level keyboard hook for always on top

* fix for message loop

* fix spellcheck

* refactoring and cleanup

* spellcheck
This commit is contained in:
Davide Giacometti
2022-06-23 16:29:53 +02:00
committed by GitHub
parent 2159e2722e
commit 301f26aca1
7 changed files with 221 additions and 6 deletions

View File

@@ -9,6 +9,7 @@
#include <common/utils/process_path.h>
#include <WinHookEventIDs.h>
#include <interop/shared_constants.h>
namespace NonLocalizable
{
@@ -23,9 +24,10 @@ bool isExcluded(HWND window)
return find_app_name_in_path(processPath, AlwaysOnTopSettings::settings().excludedApps);
}
AlwaysOnTop::AlwaysOnTop() :
AlwaysOnTop::AlwaysOnTop(bool useLLKH) :
SettingsObserver({SettingId::FrameEnabled, SettingId::Hotkey, SettingId::ExcludeApps}),
m_hinstance(reinterpret_cast<HINSTANCE>(&__ImageBase))
m_hinstance(reinterpret_cast<HINSTANCE>(&__ImageBase)),
m_useCentralizedLLKH(useLLKH)
{
s_instance = this;
DPIAware::EnableDPIAwarenessForThisProcess();
@@ -38,6 +40,8 @@ AlwaysOnTop::AlwaysOnTop() :
AlwaysOnTopSettings::instance().LoadSettings();
RegisterHotkey();
RegisterLLKH();
SubscribeToEvents();
StartTrackingTopmostWindows();
}
@@ -50,6 +54,13 @@ AlwaysOnTop::AlwaysOnTop() :
AlwaysOnTop::~AlwaysOnTop()
{
if (m_hPinEvent)
{
SetEvent(m_hPinEvent);
m_thread.join();
CloseHandle(m_hPinEvent);
}
CleanUp();
}
@@ -240,10 +251,57 @@ bool AlwaysOnTop::AssignBorder(HWND window)
void AlwaysOnTop::RegisterHotkey() const
{
if (m_useCentralizedLLKH)
{
return;
}
UnregisterHotKey(m_window, static_cast<int>(HotkeyId::Pin));
RegisterHotKey(m_window, static_cast<int>(HotkeyId::Pin), AlwaysOnTopSettings::settings().hotkey.get_modifiers(), AlwaysOnTopSettings::settings().hotkey.get_code());
}
void AlwaysOnTop::RegisterLLKH()
{
if (!m_useCentralizedLLKH)
{
return;
}
m_hPinEvent = CreateEventW(nullptr, false, false, CommonSharedConstants::ALWAYS_ON_TOP_PIN_EVENT);
if (!m_hPinEvent)
{
Logger::warn(L"Failed to create pinEvent. {}", get_last_error_or_default(GetLastError()));
return;
}
m_thread = std::thread([this]() {
MSG msg;
while (1)
{
DWORD dwEvt = MsgWaitForMultipleObjects(1, &m_hPinEvent, false, INFINITE, QS_ALLINPUT);
switch (dwEvt)
{
case WAIT_OBJECT_0:
if (HWND fw{ GetForegroundWindow() })
{
ProcessCommand(fw);
}
break;
case WAIT_OBJECT_0 + 1:
if (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
break;
default:
return false;
}
}
});
}
void AlwaysOnTop::SubscribeToEvents()
{
// subscribe to windows events

View File

@@ -13,7 +13,7 @@
class AlwaysOnTop : public SettingsObserver
{
public:
AlwaysOnTop();
AlwaysOnTop(bool useLLKH);
~AlwaysOnTop();
protected:
@@ -47,12 +47,16 @@ private:
HWND m_window{ nullptr };
HINSTANCE m_hinstance;
std::map<HWND, std::unique_ptr<WindowBorder>> m_topmostWindows{};
HANDLE m_hPinEvent;
std::thread m_thread;
const bool m_useCentralizedLLKH;
LRESULT WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
void HandleWinHookEvent(WinHookEvent* data) noexcept;
bool InitMainWindow();
void RegisterHotkey() const;
void RegisterLLKH();
void SubscribeToEvents();
void ProcessCommand(HWND window);

View File

@@ -52,7 +52,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
Trace::RegisterProvider();
AlwaysOnTop app;
AlwaysOnTop app(!pid.empty());
run_message_loop();