Skip to content

Commit

Permalink
[FancyZones] Shift + StickyKeys behavior fix (#6039)
Browse files Browse the repository at this point in the history
  • Loading branch information
SeraphimaZykova committed Aug 24, 2020
1 parent f64df97 commit 845bb46
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 109 deletions.
32 changes: 3 additions & 29 deletions src/modules/fancyzones/lib/FancyZones.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include "MonitorWorkAreaHandler.h"

#include <lib/SecondaryMouseButtonsHook.h>
#include <lib/GenericKeyHook.h>

enum class DisplayChangeType
{
Expand Down Expand Up @@ -46,10 +45,9 @@ struct FancyZones : public winrt::implements<FancyZones, IFancyZones, IFancyZone
FancyZones(HINSTANCE hinstance, const winrt::com_ptr<IFancyZonesSettings>& 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);
}
Expand All @@ -60,27 +58,6 @@ struct FancyZones : public winrt::implements<FancyZones, IFancyZones, IFancyZone
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);
Expand Down Expand Up @@ -267,9 +244,6 @@ struct FancyZones : public winrt::implements<FancyZones, IFancyZones, IFancyZone
HWND m_window{};
WindowMoveHandler m_windowMoveHandler;
MonitorWorkAreaHandler m_workAreaHandler;
SecondaryMouseButtonsHook m_mouseHook;
ShiftKeyHook m_shiftHook;
CtrlKeyHook m_ctrlHook;

winrt::com_ptr<IFancyZonesSettings> m_settings{};
GUID m_previousDesktopId{}; // UUID of previously active virtual desktop.
Expand Down
2 changes: 1 addition & 1 deletion src/modules/fancyzones/lib/FancyZonesLib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
<ClInclude Include="GenericKeyHook.h" />
<ClInclude Include="FancyZonesData.h" />
<ClInclude Include="JsonHelpers.h" />
<ClInclude Include="KeyState.h" />
<ClInclude Include="MonitorWorkAreaHandler.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="resource.h" />
Expand All @@ -123,7 +124,6 @@
<ClCompile Include="FancyZones.cpp" />
<ClCompile Include="FancyZonesDataTypes.cpp" />
<ClCompile Include="FancyZonesWinHookEventIDs.cpp" />
<ClCompile Include="GenericKeyHook.cpp" />
<ClCompile Include="FancyZonesData.cpp" />
<ClCompile Include="JsonHelpers.cpp" />
<ClCompile Include="MonitorWorkAreaHandler.cpp" />
Expand Down
6 changes: 3 additions & 3 deletions src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@
<ClInclude Include="FancyZonesDataTypes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="KeyState.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
Expand Down Expand Up @@ -110,9 +113,6 @@
<ClCompile Include="MonitorWorkAreaHandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GenericKeyHook.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FancyZonesData.cpp">
<Filter>Source Files</Filter>
</ClCompile>
Expand Down
8 changes: 0 additions & 8 deletions src/modules/fancyzones/lib/GenericKeyHook.cpp

This file was deleted.

9 changes: 3 additions & 6 deletions src/modules/fancyzones/lib/GenericKeyHook.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

#include <functional>
#include "pch.h"
#include <functional>

template<int... keys>
class GenericKeyHook
Expand Down Expand Up @@ -38,8 +38,8 @@ class GenericKeyHook
}

private:
static HHOOK hHook;
static std::function<void(bool)> callback;
inline static HHOOK hHook;
inline static std::function<void(bool)> callback;

static LRESULT CALLBACK GenericKeyHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
Expand All @@ -57,6 +57,3 @@ class GenericKeyHook
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
};

typedef GenericKeyHook<VK_LSHIFT, VK_RSHIFT> ShiftKeyHook;
typedef GenericKeyHook<VK_LCONTROL, VK_RCONTROL> CtrlKeyHook;
52 changes: 52 additions & 0 deletions src/modules/fancyzones/lib/KeyState.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#pragma once

#include "GenericKeyHook.h"

template<int... keys>
class KeyState
{
public:
KeyState(const std::function<void()>& 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<bool> m_state;
GenericKeyHook<keys...> m_hook;
std::function<void()> m_updateCallback;
};
87 changes: 31 additions & 56 deletions src/modules/fancyzones/lib/WindowMoveHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -56,11 +57,13 @@ namespace WindowMoveHandlerUtils
class WindowMoveHandlerPrivate
{
public:
WindowMoveHandlerPrivate(const winrt::com_ptr<IFancyZonesSettings>& settings, SecondaryMouseButtonsHook* mouseHook, ShiftKeyHook* shiftHook, CtrlKeyHook* ctrlHook) :
WindowMoveHandlerPrivate(const winrt::com_ptr<IFancyZonesSettings>& settings, const std::function<void()>& 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)
{
}

Expand All @@ -74,10 +77,6 @@ class WindowMoveHandlerPrivate
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<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 MoveSizeEnd(HWND window, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept;
Expand All @@ -93,19 +92,25 @@ class WindowMoveHandlerPrivate
void SetWindowTransparency(HWND window) noexcept;
void ResetWindowTransparency() noexcept;

inline void OnMouseDown() noexcept
{
m_mouseState = !m_mouseState;
m_keyUpdateCallback();
}

private:
winrt::com_ptr<IFancyZonesSettings> 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<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_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<bool> m_mouseState;
SecondaryMouseButtonsHook m_mouseHook;
KeyState<VK_LSHIFT, VK_RSHIFT> m_shiftKeyState;
KeyState<VK_LCONTROL, VK_RCONTROL> m_ctrlKeyState;
std::function<void()> m_keyUpdateCallback;

struct WindowTransparencyProperties
{
Expand All @@ -117,8 +122,8 @@ class WindowMoveHandlerPrivate
} m_windowTransparencyProperties;
};

WindowMoveHandler::WindowMoveHandler(const winrt::com_ptr<IFancyZonesSettings>& settings, SecondaryMouseButtonsHook* mouseHook, ShiftKeyHook* shiftHook, CtrlKeyHook* ctrlHook) :
pimpl(new WindowMoveHandlerPrivate(settings, mouseHook, shiftHook, ctrlHook)) {}
WindowMoveHandler::WindowMoveHandler(const winrt::com_ptr<IFancyZonesSettings>& settings, const std::function<void()>& keyUpdateCallback) :
pimpl(new WindowMoveHandlerPrivate(settings, keyUpdateCallback)) {}

WindowMoveHandler::~WindowMoveHandler()
{
Expand All @@ -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<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept
{
pimpl->MoveSizeStart(window, monitor, ptScreen, zoneWindowMap);
Expand Down Expand Up @@ -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<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept
{
if (!IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray) || WindowMoveHandlerUtils::IsCursorTypeIndicatingSizeEvent())
Expand All @@ -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();
Expand Down Expand Up @@ -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());
}
}
}
Expand All @@ -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)
{
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
}

Expand Down
7 changes: 1 addition & 6 deletions src/modules/fancyzones/lib/WindowMoveHandler.h
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
#pragma once

#include "SecondaryMouseButtonsHook.h"
#include "GenericKeyHook.h"

interface IFancyZonesSettings;
interface IZoneWindow;

class WindowMoveHandler
{
public:
WindowMoveHandler(const winrt::com_ptr<IFancyZonesSettings>& settings, SecondaryMouseButtonsHook* mouseHook, ShiftKeyHook* shiftHook, CtrlKeyHook* ctrlHook);
WindowMoveHandler(const winrt::com_ptr<IFancyZonesSettings>& settings, const std::function<void()>& 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<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 MoveSizeEnd(HWND window, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IZoneWindow>>& zoneWindowMap) noexcept;
Expand Down

0 comments on commit 845bb46

Please sign in to comment.