From 2effbd0baf5650d2cbda68bcf02735b2ff655fed Mon Sep 17 00:00:00 2001 From: yuyoyuppe Date: Thu, 18 Jun 2020 14:27:20 +0300 Subject: [PATCH] Runner: improve debugging experience with hooks --- src/common/common.vcxproj | 1 + src/common/common.vcxproj.filters | 3 ++ src/common/debug_control.h | 4 +++ src/common/interop/KeyboardHook.cpp | 29 ++++++++++++------- src/modules/fancyzones/dll/dllmain.cpp | 16 +++++++--- .../lib/SecondaryMouseButtonsHook.cpp | 13 +++++++++ src/modules/fancyzones/lib/ShiftKeyHook.cpp | 14 +++++++++ src/modules/keyboardmanager/dll/dllmain.cpp | 5 ++-- src/modules/shortcut_guide/shortcut_guide.cpp | 17 ++++++++--- src/runner/lowlevel_keyboard_event.cpp | 6 ++-- 10 files changed, 83 insertions(+), 25 deletions(-) create mode 100644 src/common/debug_control.h diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index 5e41a1ffce..fe2fc94f0b 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj @@ -120,6 +120,7 @@ + diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters index 69899feaa3..bd0e986dce 100644 --- a/src/common/common.vcxproj.filters +++ b/src/common/common.vcxproj.filters @@ -117,6 +117,9 @@ Header Files + + Header Files + diff --git a/src/common/debug_control.h b/src/common/debug_control.h new file mode 100644 index 0000000000..0f7995b67d --- /dev/null +++ b/src/common/debug_control.h @@ -0,0 +1,4 @@ +#pragma once + +// Prevent system-wide input lagging while paused in the debugger +//#define DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED diff --git a/src/common/interop/KeyboardHook.cpp b/src/common/interop/KeyboardHook.cpp index df734b2022..b5d3f8c202 100644 --- a/src/common/interop/KeyboardHook.cpp +++ b/src/common/interop/KeyboardHook.cpp @@ -3,6 +3,7 @@ #include #include #include +#include using namespace interop; using namespace System::Runtime::InteropServices; @@ -45,9 +46,9 @@ void KeyboardHook::DispatchProc() // Release lock while callback is being invoked Monitor::Exit(queue); - + keyboardEventCallback->Invoke(nextEv); - + // Re-aquire lock Monitor::Enter(queue); } @@ -60,15 +61,23 @@ void KeyboardHook::Start() hookProc = gcnew HookProcDelegate(this, &KeyboardHook::HookProc); Process ^ curProcess = Process::GetCurrentProcess(); ProcessModule ^ curModule = curProcess->MainModule; - // register low level hook procedure - hookHandle = SetWindowsHookEx( - WH_KEYBOARD_LL, - (HOOKPROC)(void*)Marshal::GetFunctionPointerForDelegate(hookProc), - 0, - 0); - if (hookHandle == nullptr) +#if defined(DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED) + const bool hookDisabled = IsDebuggerPresent(); +#else + const bool hookDisabled = false; +#endif + if (!hookDisabled) { - throw std::exception("SetWindowsHookEx failed."); + // register low level hook procedure + hookHandle = SetWindowsHookEx( + WH_KEYBOARD_LL, + (HOOKPROC)(void*)Marshal::GetFunctionPointerForDelegate(hookProc), + 0, + 0); + if (hookHandle == nullptr) + { + throw std::exception("SetWindowsHookEx failed."); + } } kbEventDispatch->Start(); diff --git a/src/modules/fancyzones/dll/dllmain.cpp b/src/modules/fancyzones/dll/dllmain.cpp index 6d06f04911..3eec6ec8c4 100644 --- a/src/modules/fancyzones/dll/dllmain.cpp +++ b/src/modules/fancyzones/dll/dllmain.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include #include +#include #include #include #include @@ -78,11 +79,18 @@ public: InitializeWinhookEventIds(); Trace::FancyZones::EnableFancyZones(true); m_app = MakeFancyZones(reinterpret_cast(&__ImageBase), m_settings); - - s_llKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), NULL); - if (!s_llKeyboardHook) +#if defined(DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED) + const bool hook_disabled = IsDebuggerPresent(); +#else + const bool hook_disabled = false; +#endif + if (!hook_disabled) { - MessageBoxW(NULL, L"Cannot install keyboard listener.", L"PowerToys - FancyZones", MB_OK | MB_ICONERROR); + s_llKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), NULL); + if (!s_llKeyboardHook) + { + MessageBoxW(NULL, L"Cannot install keyboard listener.", L"PowerToys - FancyZones", MB_OK | MB_ICONERROR); + } } std::array events_to_subscribe = { diff --git a/src/modules/fancyzones/lib/SecondaryMouseButtonsHook.cpp b/src/modules/fancyzones/lib/SecondaryMouseButtonsHook.cpp index ecb763eb9c..a19c85e4c9 100644 --- a/src/modules/fancyzones/lib/SecondaryMouseButtonsHook.cpp +++ b/src/modules/fancyzones/lib/SecondaryMouseButtonsHook.cpp @@ -1,5 +1,6 @@ #include "pch.h" #include "SecondaryMouseButtonsHook.h" +#include #pragma region public @@ -9,11 +10,23 @@ std::function SecondaryMouseButtonsHook::callback = {}; SecondaryMouseButtonsHook::SecondaryMouseButtonsHook(std::function extCallback) { callback = std::move(extCallback); +#if defined(DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED) + if (IsDebuggerPresent()) + { + return; + } +#endif hHook = SetWindowsHookEx(WH_MOUSE_LL, SecondaryMouseButtonsProc, GetModuleHandle(NULL), 0); } void SecondaryMouseButtonsHook::enable() { +#if defined(DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED) + if (IsDebuggerPresent()) + { + return; + } +#endif if (!hHook) { hHook = SetWindowsHookEx(WH_MOUSE_LL, SecondaryMouseButtonsProc, GetModuleHandle(NULL), 0); diff --git a/src/modules/fancyzones/lib/ShiftKeyHook.cpp b/src/modules/fancyzones/lib/ShiftKeyHook.cpp index 0778eaa1c8..0b1d470e24 100644 --- a/src/modules/fancyzones/lib/ShiftKeyHook.cpp +++ b/src/modules/fancyzones/lib/ShiftKeyHook.cpp @@ -1,6 +1,8 @@ #include "pch.h" #include "ShiftKeyHook.h" +#include + #pragma region public HHOOK ShiftKeyHook::hHook = {}; @@ -9,11 +11,23 @@ std::function ShiftKeyHook::callback = {}; ShiftKeyHook::ShiftKeyHook(std::function extCallback) { callback = std::move(extCallback); +#if defined(DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED) + if (IsDebuggerPresent()) + { + return; + } +#endif hHook = SetWindowsHookEx(WH_KEYBOARD_LL, ShiftKeyHookProc, GetModuleHandle(NULL), 0); } void ShiftKeyHook::enable() { +#if defined(DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED) + if (IsDebuggerPresent()) + { + return; + } +#endif if (!hHook) { hHook = SetWindowsHookEx(WH_KEYBOARD_LL, ShiftKeyHookProc, GetModuleHandle(NULL), 0); diff --git a/src/modules/keyboardmanager/dll/dllmain.cpp b/src/modules/keyboardmanager/dll/dllmain.cpp index cc8c3a3b69..1bdfd1069a 100644 --- a/src/modules/keyboardmanager/dll/dllmain.cpp +++ b/src/modules/keyboardmanager/dll/dllmain.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "KeyboardEventHandlers.h" #include "Input.h" @@ -298,11 +299,9 @@ public: return CallNextHookEx(hook_handle_copy, nCode, wParam, lParam); } - // Prevent system-wide input lagging while paused in the debugger - //#define DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED void start_lowlevel_keyboard_hook() { -#if defined(_DEBUG) && defined(DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED) +#if defined(DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED) if (IsDebuggerPresent()) { return; diff --git a/src/modules/shortcut_guide/shortcut_guide.cpp b/src/modules/shortcut_guide/shortcut_guide.cpp index ef14f91082..eaea8cc1be 100644 --- a/src/modules/shortcut_guide/shortcut_guide.cpp +++ b/src/modules/shortcut_guide/shortcut_guide.cpp @@ -6,6 +6,7 @@ #include #include +#include extern "C" IMAGE_DOS_HEADER __ImageBase; @@ -134,10 +135,18 @@ void OverlayWindow::enable() winkey_popup->set_theme(theme.value); target_state = std::make_unique(pressTime.value); winkey_popup->initialize(); - hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), NULL); - if (!hook_handle) +#if defined(DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED) + const bool hook_disabled = IsDebuggerPresent(); +#else + const bool hook_disabled = false; +#endif + if (!hook_disabled) { - MessageBoxW(NULL, L"Cannot install keyboard listener.", L"PowerToys - Shortcut Guide", MB_OK | MB_ICONERROR); + hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), NULL); + if (!hook_handle) + { + MessageBoxW(NULL, L"Cannot install keyboard listener.", L"PowerToys - Shortcut Guide", MB_OK | MB_ICONERROR); + } } } _enabled = true; @@ -195,7 +204,7 @@ intptr_t OverlayWindow::signal_event(LowlevelKeyboardEvent* event) event->wParam == WM_SYSKEYUP) { bool suppress = target_state->signal_event(event->lParam->vkCode, - event->wParam == WM_KEYDOWN || event->wParam == WM_SYSKEYDOWN); + event->wParam == WM_KEYDOWN || event->wParam == WM_SYSKEYDOWN); return suppress ? 1 : 0; } else diff --git a/src/runner/lowlevel_keyboard_event.cpp b/src/runner/lowlevel_keyboard_event.cpp index ace61df544..e4c5924a71 100644 --- a/src/runner/lowlevel_keyboard_event.cpp +++ b/src/runner/lowlevel_keyboard_event.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "lowlevel_keyboard_event.h" #include "powertoys_events.h" +#include namespace { @@ -22,12 +23,9 @@ namespace } } -// Prevent system-wide input lagging while paused in the debugger -//#define DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED - void start_lowlevel_keyboard_hook() { -#if defined(_DEBUG) && defined(DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED) +#if defined(DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED) if (IsDebuggerPresent()) { return;