From da38e6a23d525fca3f8fb1f7d3821d6dd97bc797 Mon Sep 17 00:00:00 2001 From: Yevhenii Holovachov <55396981+yevhenii44@users.noreply.github.com> Date: Wed, 17 Jun 2020 16:06:16 +0300 Subject: [PATCH] [FancyZones] Changed Shift key capture method (#4274) * Used windows hook to capture shift key instead of getting state of key on window move --- src/modules/fancyzones/lib/FancyZones.cpp | 13 +++- .../fancyzones/lib/FancyZonesLib.vcxproj | 2 + .../lib/FancyZonesLib.vcxproj.filters | 6 ++ src/modules/fancyzones/lib/ShiftKeyHook.cpp | 60 +++++++++++++++++++ src/modules/fancyzones/lib/ShiftKeyHook.h | 16 +++++ .../fancyzones/lib/WindowMoveHandler.cpp | 37 +++++++++--- .../fancyzones/lib/WindowMoveHandler.h | 6 +- 7 files changed, 127 insertions(+), 13 deletions(-) create mode 100644 src/modules/fancyzones/lib/ShiftKeyHook.cpp create mode 100644 src/modules/fancyzones/lib/ShiftKeyHook.h diff --git a/src/modules/fancyzones/lib/FancyZones.cpp b/src/modules/fancyzones/lib/FancyZones.cpp index d66bb663a7..a33fba6e3d 100644 --- a/src/modules/fancyzones/lib/FancyZones.cpp +++ b/src/modules/fancyzones/lib/FancyZones.cpp @@ -18,6 +18,7 @@ #include #include +#include enum class DisplayChangeType { @@ -34,7 +35,8 @@ public: m_hinstance(hinstance), m_settings(settings), m_mouseHook(std::bind(&FancyZones::OnMouseDown, this)), - m_windowMoveHandler(settings, &m_mouseHook) + m_shiftHook(std::bind(&FancyZones::OnShiftChangeState, this, std::placeholders::_1)), + m_windowMoveHandler(settings, &m_mouseHook, &m_shiftHook) { m_settings->SetCallback(this); } @@ -47,12 +49,18 @@ public: void OnMouseDown() noexcept { - std::unique_lock writeLock(m_lock); m_windowMoveHandler.OnMouseDown(); PostMessageW(m_window, WM_PRIV_LOCATIONCHANGE, NULL, NULL); } + void OnShiftChangeState(bool state) noexcept + { + m_windowMoveHandler.OnShiftChangeState(state); + + PostMessageW(m_window, WM_PRIV_LOCATIONCHANGE, NULL, NULL); + } + void MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen) noexcept { std::unique_lock writeLock(m_lock); @@ -230,6 +238,7 @@ private: WindowMoveHandler m_windowMoveHandler; MonitorWorkAreaHandler m_workAreaHandler; SecondaryMouseButtonsHook m_mouseHook; + ShiftKeyHook m_shiftHook; winrt::com_ptr m_settings{}; GUID m_previousDesktopId{}; // UUID of previously active virtual desktop. diff --git a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj index c9a7781cbd..b1eb2ef5e4 100644 --- a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj +++ b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj @@ -106,6 +106,7 @@ + @@ -124,6 +125,7 @@ + diff --git a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters index 87f2f3954f..5c6c575dd3 100644 --- a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters +++ b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters @@ -60,6 +60,9 @@ Header Files + + Header Files + @@ -104,6 +107,9 @@ Source Files + + Source Files + diff --git a/src/modules/fancyzones/lib/ShiftKeyHook.cpp b/src/modules/fancyzones/lib/ShiftKeyHook.cpp new file mode 100644 index 0000000000..0778eaa1c8 --- /dev/null +++ b/src/modules/fancyzones/lib/ShiftKeyHook.cpp @@ -0,0 +1,60 @@ +#include "pch.h" +#include "ShiftKeyHook.h" + +#pragma region public + +HHOOK ShiftKeyHook::hHook = {}; +std::function ShiftKeyHook::callback = {}; + +ShiftKeyHook::ShiftKeyHook(std::function extCallback) +{ + callback = std::move(extCallback); + hHook = SetWindowsHookEx(WH_KEYBOARD_LL, ShiftKeyHookProc, GetModuleHandle(NULL), 0); +} + +void ShiftKeyHook::enable() +{ + if (!hHook) + { + hHook = SetWindowsHookEx(WH_KEYBOARD_LL, ShiftKeyHookProc, GetModuleHandle(NULL), 0); + } +} + +void ShiftKeyHook::disable() +{ + if (hHook) + { + UnhookWindowsHookEx(hHook); + hHook = NULL; + } +} + +#pragma endregion + +#pragma region private + +LRESULT CALLBACK ShiftKeyHook::ShiftKeyHookProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + if (nCode == HC_ACTION) + { + if (wParam == WM_KEYDOWN) + { + PKBDLLHOOKSTRUCT kbdHookStruct = (PKBDLLHOOKSTRUCT)lParam; + if (kbdHookStruct->vkCode == VK_LSHIFT || kbdHookStruct->vkCode == VK_RSHIFT) + { + callback(true); + } + } + else if (wParam == WM_KEYUP) + { + PKBDLLHOOKSTRUCT kbdHookStruct = (PKBDLLHOOKSTRUCT)lParam; + if (kbdHookStruct->vkCode == VK_LSHIFT || kbdHookStruct->vkCode == VK_RSHIFT) + { + callback(false); + } + } + } + return CallNextHookEx(hHook, nCode, wParam, lParam); +} + +#pragma endregion diff --git a/src/modules/fancyzones/lib/ShiftKeyHook.h b/src/modules/fancyzones/lib/ShiftKeyHook.h new file mode 100644 index 0000000000..8da6312231 --- /dev/null +++ b/src/modules/fancyzones/lib/ShiftKeyHook.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +class ShiftKeyHook +{ +public: + ShiftKeyHook(std::function); + void enable(); + void disable(); + +private: + static HHOOK hHook; + static std::function callback; + static LRESULT CALLBACK ShiftKeyHookProc(int, WPARAM, LPARAM); +}; diff --git a/src/modules/fancyzones/lib/WindowMoveHandler.cpp b/src/modules/fancyzones/lib/WindowMoveHandler.cpp index 5838116dd3..a4643012cc 100644 --- a/src/modules/fancyzones/lib/WindowMoveHandler.cpp +++ b/src/modules/fancyzones/lib/WindowMoveHandler.cpp @@ -10,6 +10,7 @@ #include "lib/util.h" #include "VirtualDesktopUtils.h" #include "lib/SecondaryMouseButtonsHook.h" +#include extern "C" IMAGE_DOS_HEADER __ImageBase; @@ -46,9 +47,10 @@ namespace WindowMoveHandlerUtils class WindowMoveHandlerPrivate { public: - WindowMoveHandlerPrivate(const winrt::com_ptr& settings, SecondaryMouseButtonsHook* mouseHook) : + WindowMoveHandlerPrivate(const winrt::com_ptr& settings, SecondaryMouseButtonsHook* mouseHook, ShiftKeyHook* shiftHook) : m_settings(settings), - m_mouseHook(mouseHook){}; + m_mouseHook(mouseHook), + m_shiftHook(shiftHook){}; bool IsDragEnabled() const noexcept { @@ -61,6 +63,7 @@ public: } void OnMouseDown() noexcept; + void OnShiftChangeState(bool state) noexcept; void MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map>& zoneWindowMap) noexcept; void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map>& zoneWindowMap) noexcept; @@ -75,16 +78,18 @@ private: private: winrt::com_ptr m_settings{}; SecondaryMouseButtonsHook* m_mouseHook{}; + ShiftKeyHook* m_shiftHook{}; HWND m_windowMoveSize{}; // The window that is being moved/sized bool m_inMoveSize{}; // Whether or not a move/size operation is currently active winrt::com_ptr m_zoneWindowMoveSize; // "Active" ZoneWindow, where the move/size is happening. Will update as drag moves between monitors. bool m_dragEnabled{}; // True if we should be showing zone hints while dragging - bool m_secondaryMouseButtonState{}; // True when secondary mouse button was clicked after windows was moved; + bool m_secondaryMouseButtonState{}; // True when secondary mouse button was clicked after window was moved + bool m_shiftKeyState{}; // True when shift key was pressed after window was moved }; -WindowMoveHandler::WindowMoveHandler(const winrt::com_ptr& settings, SecondaryMouseButtonsHook* mouseHook) : - pimpl(new WindowMoveHandlerPrivate(settings, mouseHook)) {} +WindowMoveHandler::WindowMoveHandler(const winrt::com_ptr& settings, SecondaryMouseButtonsHook* mouseHook, ShiftKeyHook* shiftHook) : + pimpl(new WindowMoveHandlerPrivate(settings, mouseHook, shiftHook)) {} WindowMoveHandler::~WindowMoveHandler() { @@ -106,6 +111,11 @@ void WindowMoveHandler::OnMouseDown() noexcept pimpl->OnMouseDown(); } +void WindowMoveHandler::OnShiftChangeState(bool state) noexcept +{ + pimpl->OnShiftChangeState(state); +} + void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map>& zoneWindowMap) noexcept { pimpl->MoveSizeStart(window, monitor, ptScreen, zoneWindowMap); @@ -136,6 +146,11 @@ void WindowMoveHandlerPrivate::OnMouseDown() noexcept m_secondaryMouseButtonState = !m_secondaryMouseButtonState; } +void WindowMoveHandlerPrivate::OnShiftChangeState(bool state) noexcept +{ + m_shiftKeyState = state; +} + void WindowMoveHandlerPrivate::MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map>& zoneWindowMap) noexcept { if (!IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray) || WindowMoveHandlerUtils::IsCursorTypeIndicatingSizeEvent()) @@ -158,6 +173,11 @@ void WindowMoveHandlerPrivate::MoveSizeStart(HWND window, HMONITOR monitor, POIN m_mouseHook->enable(); } + if (m_settings->GetSettings()->shiftDrag) + { + m_shiftHook->enable(); + } + // This updates m_dragEnabled depending on if the shift key is being held down. UpdateDragState(window); @@ -262,6 +282,7 @@ void WindowMoveHandlerPrivate::MoveSizeEnd(HWND window, POINT const& ptScreen, c } m_mouseHook->disable(); + m_shiftHook->disable(); m_inMoveSize = false; m_dragEnabled = false; @@ -321,15 +342,13 @@ bool WindowMoveHandlerPrivate::MoveWindowIntoZoneByDirection(HWND window, DWORD void WindowMoveHandlerPrivate::UpdateDragState(HWND window) noexcept { - const bool shift = GetAsyncKeyState(VK_SHIFT) & 0x8000; - if (m_settings->GetSettings()->shiftDrag) { - m_dragEnabled = (shift ^ m_secondaryMouseButtonState); + m_dragEnabled = (m_shiftKeyState ^ m_secondaryMouseButtonState); } else { - m_dragEnabled = !(shift ^ m_secondaryMouseButtonState); + m_dragEnabled = !(m_shiftKeyState ^ m_secondaryMouseButtonState); } static bool warning_shown = false; diff --git a/src/modules/fancyzones/lib/WindowMoveHandler.h b/src/modules/fancyzones/lib/WindowMoveHandler.h index 4e2a0a89be..3c5a64e846 100644 --- a/src/modules/fancyzones/lib/WindowMoveHandler.h +++ b/src/modules/fancyzones/lib/WindowMoveHandler.h @@ -2,18 +2,20 @@ interface IFancyZonesSettings; interface IZoneWindow; -interface SecondaryMouseButtonsHook; +class SecondaryMouseButtonsHook; +class ShiftKeyHook; class WindowMoveHandler { public: - WindowMoveHandler(const winrt::com_ptr& settings, SecondaryMouseButtonsHook* mouseHook); + WindowMoveHandler(const winrt::com_ptr& settings, SecondaryMouseButtonsHook* mouseHook, ShiftKeyHook* shiftHook); ~WindowMoveHandler(); bool InMoveSize() const noexcept; bool IsDragEnabled() const noexcept; void OnMouseDown() noexcept; + void OnShiftChangeState(bool state) noexcept; //True for shift down event false for shift up void MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map>& zoneWindowMap) noexcept; void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map>& zoneWindowMap) noexcept;