From 845bb466c67f7e3cfbd06b20683beaf849be26eb Mon Sep 17 00:00:00 2001 From: Seraphima Zykova Date: Mon, 24 Aug 2020 10:19:39 +0300 Subject: [PATCH] [FancyZones] Shift + StickyKeys behavior fix (#6039) --- src/modules/fancyzones/lib/FancyZones.cpp | 32 +------ .../fancyzones/lib/FancyZonesLib.vcxproj | 2 +- .../lib/FancyZonesLib.vcxproj.filters | 6 +- src/modules/fancyzones/lib/GenericKeyHook.cpp | 8 -- src/modules/fancyzones/lib/GenericKeyHook.h | 9 +- src/modules/fancyzones/lib/KeyState.h | 52 +++++++++++ .../fancyzones/lib/WindowMoveHandler.cpp | 87 +++++++------------ .../fancyzones/lib/WindowMoveHandler.h | 7 +- 8 files changed, 94 insertions(+), 109 deletions(-) delete mode 100644 src/modules/fancyzones/lib/GenericKeyHook.cpp create mode 100644 src/modules/fancyzones/lib/KeyState.h diff --git a/src/modules/fancyzones/lib/FancyZones.cpp b/src/modules/fancyzones/lib/FancyZones.cpp index 2d737aac23..a1ef11a82b 100644 --- a/src/modules/fancyzones/lib/FancyZones.cpp +++ b/src/modules/fancyzones/lib/FancyZones.cpp @@ -17,7 +17,6 @@ #include "MonitorWorkAreaHandler.h" #include -#include enum class DisplayChangeType { @@ -46,10 +45,9 @@ public: FancyZones(HINSTANCE hinstance, const winrt::com_ptr& settings) noexcept : m_hinstance(hinstance), m_settings(settings), - m_mouseHook(std::bind(&FancyZones::OnMouseDown, this)), - m_shiftHook(std::bind(&FancyZones::OnShiftChangeState, this, std::placeholders::_1)), - m_ctrlHook(std::bind(&FancyZones::OnCtrlChangeState, this, std::placeholders::_1)), - m_windowMoveHandler(settings, &m_mouseHook, &m_shiftHook, &m_ctrlHook) + m_windowMoveHandler(settings, [this]() { + PostMessageW(m_window, WM_PRIV_LOCATIONCHANGE, NULL, NULL); + }) { m_settings->SetCallback(this); } @@ -60,27 +58,6 @@ public: IFACEMETHODIMP_(void) Destroy() noexcept; - void OnMouseDown() noexcept - { - 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 OnCtrlChangeState(bool state) noexcept - { - m_windowMoveHandler.OnCtrlChangeState(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); @@ -267,9 +244,6 @@ private: HWND m_window{}; WindowMoveHandler m_windowMoveHandler; MonitorWorkAreaHandler m_workAreaHandler; - SecondaryMouseButtonsHook m_mouseHook; - ShiftKeyHook m_shiftHook; - CtrlKeyHook m_ctrlHook; 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 a1fd7225fc..8d40d85356 100644 --- a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj +++ b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj @@ -106,6 +106,7 @@ + @@ -123,7 +124,6 @@ - diff --git a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters index 219d8bc5d7..ceede79abc 100644 --- a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters +++ b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters @@ -69,6 +69,9 @@ Header Files + + Header Files + @@ -110,9 +113,6 @@ Source Files - - Source Files - Source Files diff --git a/src/modules/fancyzones/lib/GenericKeyHook.cpp b/src/modules/fancyzones/lib/GenericKeyHook.cpp deleted file mode 100644 index c79ddf6d09..0000000000 --- a/src/modules/fancyzones/lib/GenericKeyHook.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "pch.h" -#include "GenericKeyHook.h" - -HHOOK ShiftKeyHook::hHook{}; -std::function ShiftKeyHook::callback{}; - -HHOOK CtrlKeyHook::hHook{}; -std::function CtrlKeyHook::callback{}; diff --git a/src/modules/fancyzones/lib/GenericKeyHook.h b/src/modules/fancyzones/lib/GenericKeyHook.h index 4ba1ec9ce0..77d08c0b8c 100644 --- a/src/modules/fancyzones/lib/GenericKeyHook.h +++ b/src/modules/fancyzones/lib/GenericKeyHook.h @@ -1,7 +1,7 @@ #pragma once -#include #include "pch.h" +#include template class GenericKeyHook @@ -38,8 +38,8 @@ public: } private: - static HHOOK hHook; - static std::function callback; + inline static HHOOK hHook; + inline static std::function callback; static LRESULT CALLBACK GenericKeyHookProc(int nCode, WPARAM wParam, LPARAM lParam) { @@ -57,6 +57,3 @@ private: return CallNextHookEx(hHook, nCode, wParam, lParam); } }; - -typedef GenericKeyHook ShiftKeyHook; -typedef GenericKeyHook CtrlKeyHook; diff --git a/src/modules/fancyzones/lib/KeyState.h b/src/modules/fancyzones/lib/KeyState.h new file mode 100644 index 0000000000..6ec75c4635 --- /dev/null +++ b/src/modules/fancyzones/lib/KeyState.h @@ -0,0 +1,52 @@ +#pragma once + +#include "GenericKeyHook.h" + +template +class KeyState +{ +public: + KeyState(const std::function& callback) : + m_state(false), + m_hook(std::bind(&KeyState::onChangeState, this, std::placeholders::_1)), + m_updateCallback(callback) + { + + } + + inline bool state() const noexcept { return m_state; } + + inline void enable() + { + m_hook.enable(); + m_state = (((GetAsyncKeyState(keys) & 0x8000) || ...)); + } + + inline void disable() + { + m_hook.disable(); + } + + inline void setState(bool state) noexcept + { + if (m_state != state) + { + m_state = state; + if (m_updateCallback) + { + m_updateCallback(); + } + } + } + +private: + inline void onChangeState(bool state) noexcept + { + setState(state); + } + +private: + std::atomic m_state; + GenericKeyHook m_hook; + std::function m_updateCallback; +}; \ No newline at end of file diff --git a/src/modules/fancyzones/lib/WindowMoveHandler.cpp b/src/modules/fancyzones/lib/WindowMoveHandler.cpp index cc99dd8b69..2c733db786 100644 --- a/src/modules/fancyzones/lib/WindowMoveHandler.cpp +++ b/src/modules/fancyzones/lib/WindowMoveHandler.cpp @@ -13,6 +13,7 @@ #include "lib/SecondaryMouseButtonsHook.h" #include "lib/GenericKeyHook.h" #include "lib/FancyZonesData.h" +#include "lib/KeyState.h" extern "C" IMAGE_DOS_HEADER __ImageBase; @@ -56,11 +57,13 @@ namespace WindowMoveHandlerUtils class WindowMoveHandlerPrivate { public: - WindowMoveHandlerPrivate(const winrt::com_ptr& settings, SecondaryMouseButtonsHook* mouseHook, ShiftKeyHook* shiftHook, CtrlKeyHook* ctrlHook) : + WindowMoveHandlerPrivate(const winrt::com_ptr& settings, const std::function& keyUpdateCallback) : m_settings(settings), - m_mouseHook(mouseHook), - m_shiftHook(shiftHook), - m_ctrlHook(ctrlHook) + m_mouseState(false), + m_mouseHook(std::bind(&WindowMoveHandlerPrivate::OnMouseDown, this)), + m_shiftKeyState(keyUpdateCallback), + m_ctrlKeyState(keyUpdateCallback), + m_keyUpdateCallback(keyUpdateCallback) { } @@ -74,10 +77,6 @@ public: return m_inMoveSize; } - void OnMouseDown() noexcept; - void OnShiftChangeState(bool state) noexcept; - void OnCtrlChangeState(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; void MoveSizeEnd(HWND window, POINT const& ptScreen, const std::unordered_map>& zoneWindowMap) noexcept; @@ -93,19 +92,25 @@ private: void SetWindowTransparency(HWND window) noexcept; void ResetWindowTransparency() noexcept; + inline void OnMouseDown() noexcept + { + m_mouseState = !m_mouseState; + m_keyUpdateCallback(); + } + private: winrt::com_ptr m_settings{}; - SecondaryMouseButtonsHook* m_mouseHook{}; - ShiftKeyHook* m_shiftHook{}; - CtrlKeyHook* m_ctrlHook{}; 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 window was moved - bool m_shiftKeyState{}; // True when shift key was pressed after window was moved - bool m_ctrlKeyState{}; // True when ctrl key was pressed after window was moved + + std::atomic m_mouseState; + SecondaryMouseButtonsHook m_mouseHook; + KeyState m_shiftKeyState; + KeyState m_ctrlKeyState; + std::function m_keyUpdateCallback; struct WindowTransparencyProperties { @@ -117,8 +122,8 @@ private: } m_windowTransparencyProperties; }; -WindowMoveHandler::WindowMoveHandler(const winrt::com_ptr& settings, SecondaryMouseButtonsHook* mouseHook, ShiftKeyHook* shiftHook, CtrlKeyHook* ctrlHook) : - pimpl(new WindowMoveHandlerPrivate(settings, mouseHook, shiftHook, ctrlHook)) {} +WindowMoveHandler::WindowMoveHandler(const winrt::com_ptr& settings, const std::function& keyUpdateCallback) : + pimpl(new WindowMoveHandlerPrivate(settings, keyUpdateCallback)) {} WindowMoveHandler::~WindowMoveHandler() { @@ -135,21 +140,6 @@ bool WindowMoveHandler::IsDragEnabled() const noexcept return pimpl->IsDragEnabled(); } -void WindowMoveHandler::OnMouseDown() noexcept -{ - pimpl->OnMouseDown(); -} - -void WindowMoveHandler::OnShiftChangeState(bool state) noexcept -{ - pimpl->OnShiftChangeState(state); -} - -void WindowMoveHandler::OnCtrlChangeState(bool state) noexcept -{ - pimpl->OnCtrlChangeState(state); -} - void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map>& zoneWindowMap) noexcept { pimpl->MoveSizeStart(window, monitor, ptScreen, zoneWindowMap); @@ -180,21 +170,6 @@ bool WindowMoveHandler::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DW return pimpl->MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, cycle, zoneWindow); } -void WindowMoveHandlerPrivate::OnMouseDown() noexcept -{ - m_secondaryMouseButtonState = !m_secondaryMouseButtonState; -} - -void WindowMoveHandlerPrivate::OnShiftChangeState(bool state) noexcept -{ - m_shiftKeyState = state; -} - -void WindowMoveHandlerPrivate::OnCtrlChangeState(bool state) noexcept -{ - m_ctrlKeyState = 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()) @@ -214,11 +189,11 @@ void WindowMoveHandlerPrivate::MoveSizeStart(HWND window, HMONITOR monitor, POIN if (m_settings->GetSettings()->mouseSwitch) { - m_mouseHook->enable(); + m_mouseHook.enable(); } - m_shiftHook->enable(); - m_ctrlHook->enable(); + m_shiftKeyState.enable(); + m_ctrlKeyState.enable(); // This updates m_dragEnabled depending on if the shift key is being held down UpdateDragState(); @@ -306,7 +281,7 @@ void WindowMoveHandlerPrivate::MoveSizeUpdate(HMONITOR monitor, POINT const& ptS for (auto [keyMonitor, zoneWindow] : zoneWindowMap) { - zoneWindow->MoveSizeUpdate(ptScreen, m_dragEnabled, m_ctrlKeyState); + zoneWindow->MoveSizeUpdate(ptScreen, m_dragEnabled, m_ctrlKeyState.state()); } } } @@ -327,9 +302,9 @@ void WindowMoveHandlerPrivate::MoveSizeEnd(HWND window, POINT const& ptScreen, c return; } - m_mouseHook->disable(); - m_shiftHook->disable(); - m_ctrlHook->disable(); + m_mouseHook.disable(); + m_shiftKeyState.disable(); + m_ctrlKeyState.disable(); if (m_zoneWindowMoveSize) { @@ -374,7 +349,7 @@ void WindowMoveHandlerPrivate::MoveSizeEnd(HWND window, POINT const& ptScreen, c m_inMoveSize = false; m_dragEnabled = false; - m_secondaryMouseButtonState = false; + m_mouseState = false; m_windowMoveSize = nullptr; // Also, hide all windows (regardless of settings) @@ -430,11 +405,11 @@ void WindowMoveHandlerPrivate::UpdateDragState() noexcept { if (m_settings->GetSettings()->shiftDrag) { - m_dragEnabled = (m_shiftKeyState ^ m_secondaryMouseButtonState); + m_dragEnabled = (m_shiftKeyState.state() ^ m_mouseState); } else { - m_dragEnabled = !(m_shiftKeyState ^ m_secondaryMouseButtonState); + m_dragEnabled = !(m_shiftKeyState.state() ^ m_mouseState); } } diff --git a/src/modules/fancyzones/lib/WindowMoveHandler.h b/src/modules/fancyzones/lib/WindowMoveHandler.h index 74aeb0b8a9..aca793a5dd 100644 --- a/src/modules/fancyzones/lib/WindowMoveHandler.h +++ b/src/modules/fancyzones/lib/WindowMoveHandler.h @@ -1,7 +1,6 @@ #pragma once #include "SecondaryMouseButtonsHook.h" -#include "GenericKeyHook.h" interface IFancyZonesSettings; interface IZoneWindow; @@ -9,16 +8,12 @@ interface IZoneWindow; class WindowMoveHandler { public: - WindowMoveHandler(const winrt::com_ptr& settings, SecondaryMouseButtonsHook* mouseHook, ShiftKeyHook* shiftHook, CtrlKeyHook* ctrlHook); + WindowMoveHandler(const winrt::com_ptr& settings, const std::function& keyUpdateCallback); ~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 OnCtrlChangeState(bool state) noexcept; //True for ctrl down event false for ctrl 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; void MoveSizeEnd(HWND window, POINT const& ptScreen, const std::unordered_map>& zoneWindowMap) noexcept;