[FancyZones] Changed Shift key capture method (#4274)

* Used windows hook to capture shift key instead of getting state of key on window move
This commit is contained in:
Yevhenii Holovachov 2020-06-17 16:06:16 +03:00 committed by GitHub
parent 698e5ec6ea
commit da38e6a23d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 127 additions and 13 deletions

View File

@ -18,6 +18,7 @@
#include <interface/win_hook_event_data.h> #include <interface/win_hook_event_data.h>
#include <lib/SecondaryMouseButtonsHook.h> #include <lib/SecondaryMouseButtonsHook.h>
#include <lib/ShiftKeyHook.h>
enum class DisplayChangeType enum class DisplayChangeType
{ {
@ -34,7 +35,8 @@ public:
m_hinstance(hinstance), m_hinstance(hinstance),
m_settings(settings), m_settings(settings),
m_mouseHook(std::bind(&FancyZones::OnMouseDown, this)), 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); m_settings->SetCallback(this);
} }
@ -47,12 +49,18 @@ public:
void OnMouseDown() noexcept void OnMouseDown() noexcept
{ {
std::unique_lock writeLock(m_lock);
m_windowMoveHandler.OnMouseDown(); m_windowMoveHandler.OnMouseDown();
PostMessageW(m_window, WM_PRIV_LOCATIONCHANGE, NULL, NULL); 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 void MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen) noexcept
{ {
std::unique_lock writeLock(m_lock); std::unique_lock writeLock(m_lock);
@ -230,6 +238,7 @@ private:
WindowMoveHandler m_windowMoveHandler; WindowMoveHandler m_windowMoveHandler;
MonitorWorkAreaHandler m_workAreaHandler; MonitorWorkAreaHandler m_workAreaHandler;
SecondaryMouseButtonsHook m_mouseHook; SecondaryMouseButtonsHook m_mouseHook;
ShiftKeyHook m_shiftHook;
winrt::com_ptr<IFancyZonesSettings> m_settings{}; winrt::com_ptr<IFancyZonesSettings> m_settings{};
GUID m_previousDesktopId{}; // UUID of previously active virtual desktop. GUID m_previousDesktopId{}; // UUID of previously active virtual desktop.

View File

@ -106,6 +106,7 @@
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />
<ClInclude Include="SecondaryMouseButtonsHook.h" /> <ClInclude Include="SecondaryMouseButtonsHook.h" />
<ClInclude Include="Settings.h" /> <ClInclude Include="Settings.h" />
<ClInclude Include="ShiftKeyHook.h" />
<ClInclude Include="trace.h" /> <ClInclude Include="trace.h" />
<ClInclude Include="util.h" /> <ClInclude Include="util.h" />
<ClInclude Include="VirtualDesktopUtils.h" /> <ClInclude Include="VirtualDesktopUtils.h" />
@ -124,6 +125,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="SecondaryMouseButtonsHook.cpp" /> <ClCompile Include="SecondaryMouseButtonsHook.cpp" />
<ClCompile Include="Settings.cpp" /> <ClCompile Include="Settings.cpp" />
<ClCompile Include="ShiftKeyHook.cpp" />
<ClCompile Include="trace.cpp" /> <ClCompile Include="trace.cpp" />
<ClCompile Include="util.cpp" /> <ClCompile Include="util.cpp" />
<ClCompile Include="VirtualDesktopUtils.cpp" /> <ClCompile Include="VirtualDesktopUtils.cpp" />

View File

@ -60,6 +60,9 @@
<ClInclude Include="MonitorWorkAreaHandler.h"> <ClInclude Include="MonitorWorkAreaHandler.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="ShiftKeyHook.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="pch.cpp"> <ClCompile Include="pch.cpp">
@ -104,6 +107,9 @@
<ClCompile Include="MonitorWorkAreaHandler.cpp"> <ClCompile Include="MonitorWorkAreaHandler.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="ShiftKeyHook.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="fancyzones.rc"> <ResourceCompile Include="fancyzones.rc">

View File

@ -0,0 +1,60 @@
#include "pch.h"
#include "ShiftKeyHook.h"
#pragma region public
HHOOK ShiftKeyHook::hHook = {};
std::function<void(bool)> ShiftKeyHook::callback = {};
ShiftKeyHook::ShiftKeyHook(std::function<void(bool)> 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

View File

@ -0,0 +1,16 @@
#pragma once
#include <functional>
class ShiftKeyHook
{
public:
ShiftKeyHook(std::function<void(bool)>);
void enable();
void disable();
private:
static HHOOK hHook;
static std::function<void(bool)> callback;
static LRESULT CALLBACK ShiftKeyHookProc(int, WPARAM, LPARAM);
};

View File

@ -10,6 +10,7 @@
#include "lib/util.h" #include "lib/util.h"
#include "VirtualDesktopUtils.h" #include "VirtualDesktopUtils.h"
#include "lib/SecondaryMouseButtonsHook.h" #include "lib/SecondaryMouseButtonsHook.h"
#include <lib/ShiftKeyHook.h>
extern "C" IMAGE_DOS_HEADER __ImageBase; extern "C" IMAGE_DOS_HEADER __ImageBase;
@ -46,9 +47,10 @@ namespace WindowMoveHandlerUtils
class WindowMoveHandlerPrivate class WindowMoveHandlerPrivate
{ {
public: public:
WindowMoveHandlerPrivate(const winrt::com_ptr<IFancyZonesSettings>& settings, SecondaryMouseButtonsHook* mouseHook) : WindowMoveHandlerPrivate(const winrt::com_ptr<IFancyZonesSettings>& settings, SecondaryMouseButtonsHook* mouseHook, ShiftKeyHook* shiftHook) :
m_settings(settings), m_settings(settings),
m_mouseHook(mouseHook){}; m_mouseHook(mouseHook),
m_shiftHook(shiftHook){};
bool IsDragEnabled() const noexcept bool IsDragEnabled() const noexcept
{ {
@ -61,6 +63,7 @@ public:
} }
void OnMouseDown() noexcept; void OnMouseDown() noexcept;
void OnShiftChangeState(bool state) noexcept;
void MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept; void MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept;
void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept; void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept;
@ -75,16 +78,18 @@ private:
private: private:
winrt::com_ptr<IFancyZonesSettings> m_settings{}; winrt::com_ptr<IFancyZonesSettings> m_settings{};
SecondaryMouseButtonsHook* m_mouseHook{}; SecondaryMouseButtonsHook* m_mouseHook{};
ShiftKeyHook* m_shiftHook{};
HWND m_windowMoveSize{}; // The window that is being moved/sized HWND m_windowMoveSize{}; // The window that is being moved/sized
bool m_inMoveSize{}; // Whether or not a move/size operation is currently active bool m_inMoveSize{}; // Whether or not a move/size operation is currently active
winrt::com_ptr<IZoneWindow> m_zoneWindowMoveSize; // "Active" ZoneWindow, where the move/size is happening. Will update as drag moves between monitors. winrt::com_ptr<IZoneWindow> 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_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<IFancyZonesSettings>& settings, SecondaryMouseButtonsHook* mouseHook) : WindowMoveHandler::WindowMoveHandler(const winrt::com_ptr<IFancyZonesSettings>& settings, SecondaryMouseButtonsHook* mouseHook, ShiftKeyHook* shiftHook) :
pimpl(new WindowMoveHandlerPrivate(settings, mouseHook)) {} pimpl(new WindowMoveHandlerPrivate(settings, mouseHook, shiftHook)) {}
WindowMoveHandler::~WindowMoveHandler() WindowMoveHandler::~WindowMoveHandler()
{ {
@ -106,6 +111,11 @@ void WindowMoveHandler::OnMouseDown() noexcept
pimpl->OnMouseDown(); 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<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept
{ {
pimpl->MoveSizeStart(window, monitor, ptScreen, zoneWindowMap); pimpl->MoveSizeStart(window, monitor, ptScreen, zoneWindowMap);
@ -136,6 +146,11 @@ void WindowMoveHandlerPrivate::OnMouseDown() noexcept
m_secondaryMouseButtonState = !m_secondaryMouseButtonState; 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<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept void WindowMoveHandlerPrivate::MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept
{ {
if (!IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray) || WindowMoveHandlerUtils::IsCursorTypeIndicatingSizeEvent()) if (!IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray) || WindowMoveHandlerUtils::IsCursorTypeIndicatingSizeEvent())
@ -158,6 +173,11 @@ void WindowMoveHandlerPrivate::MoveSizeStart(HWND window, HMONITOR monitor, POIN
m_mouseHook->enable(); 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. // This updates m_dragEnabled depending on if the shift key is being held down.
UpdateDragState(window); UpdateDragState(window);
@ -262,6 +282,7 @@ void WindowMoveHandlerPrivate::MoveSizeEnd(HWND window, POINT const& ptScreen, c
} }
m_mouseHook->disable(); m_mouseHook->disable();
m_shiftHook->disable();
m_inMoveSize = false; m_inMoveSize = false;
m_dragEnabled = false; m_dragEnabled = false;
@ -321,15 +342,13 @@ bool WindowMoveHandlerPrivate::MoveWindowIntoZoneByDirection(HWND window, DWORD
void WindowMoveHandlerPrivate::UpdateDragState(HWND window) noexcept void WindowMoveHandlerPrivate::UpdateDragState(HWND window) noexcept
{ {
const bool shift = GetAsyncKeyState(VK_SHIFT) & 0x8000;
if (m_settings->GetSettings()->shiftDrag) if (m_settings->GetSettings()->shiftDrag)
{ {
m_dragEnabled = (shift ^ m_secondaryMouseButtonState); m_dragEnabled = (m_shiftKeyState ^ m_secondaryMouseButtonState);
} }
else else
{ {
m_dragEnabled = !(shift ^ m_secondaryMouseButtonState); m_dragEnabled = !(m_shiftKeyState ^ m_secondaryMouseButtonState);
} }
static bool warning_shown = false; static bool warning_shown = false;

View File

@ -2,18 +2,20 @@
interface IFancyZonesSettings; interface IFancyZonesSettings;
interface IZoneWindow; interface IZoneWindow;
interface SecondaryMouseButtonsHook; class SecondaryMouseButtonsHook;
class ShiftKeyHook;
class WindowMoveHandler class WindowMoveHandler
{ {
public: public:
WindowMoveHandler(const winrt::com_ptr<IFancyZonesSettings>& settings, SecondaryMouseButtonsHook* mouseHook); WindowMoveHandler(const winrt::com_ptr<IFancyZonesSettings>& settings, SecondaryMouseButtonsHook* mouseHook, ShiftKeyHook* shiftHook);
~WindowMoveHandler(); ~WindowMoveHandler();
bool InMoveSize() const noexcept; bool InMoveSize() const noexcept;
bool IsDragEnabled() const noexcept; bool IsDragEnabled() const noexcept;
void OnMouseDown() 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<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept; void MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept;
void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept; void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept;