mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-09 04:37:30 +02:00
[FancyZones] Use Ctrl+Win+Alt+arrows to Expand/shrink windows to adjacent zones (#6446)
* Added an Alt key hook * Refactor a block of code into a method * Again refactored existing code * Apparently Win+Alt does not reach FancyZones * Using Ctrl+alt instead of Win+alt for now * It works * Fixed VD change * Remove unused member * Fix compilation error * Enable shrinking * Fixed comments in .h files * Remove newline * Refactored a function into two The next task is to simplify their code. * Updated a comment * Update a variable name * Reverted to the old implementation of directional move * More refactoring * Remove space * Fixed windows getting stuck * Changed function name
This commit is contained in:
@@ -207,6 +207,7 @@ private:
|
|||||||
bool OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexcept;
|
bool OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexcept;
|
||||||
bool OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept;
|
bool OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept;
|
||||||
bool OnSnapHotkey(DWORD vkCode) noexcept;
|
bool OnSnapHotkey(DWORD vkCode) noexcept;
|
||||||
|
bool ProcessDirectedSnapHotkey(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept;
|
||||||
|
|
||||||
void RegisterVirtualDesktopUpdates(std::vector<GUID>& ids) noexcept;
|
void RegisterVirtualDesktopUpdates(std::vector<GUID>& ids) noexcept;
|
||||||
|
|
||||||
@@ -524,21 +525,23 @@ FancyZones::OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept
|
|||||||
// Return true to swallow the keyboard event
|
// Return true to swallow the keyboard event
|
||||||
bool const shift = GetAsyncKeyState(VK_SHIFT) & 0x8000;
|
bool const shift = GetAsyncKeyState(VK_SHIFT) & 0x8000;
|
||||||
bool const win = GetAsyncKeyState(VK_LWIN) & 0x8000 || GetAsyncKeyState(VK_RWIN) & 0x8000;
|
bool const win = GetAsyncKeyState(VK_LWIN) & 0x8000 || GetAsyncKeyState(VK_RWIN) & 0x8000;
|
||||||
if (win && !shift)
|
bool const alt = GetAsyncKeyState(VK_MENU) & 0x8000;
|
||||||
|
bool const ctrl = GetAsyncKeyState(VK_CONTROL) & 0x8000;
|
||||||
|
if ((win && !shift && !ctrl) || (win && ctrl && alt))
|
||||||
{
|
{
|
||||||
bool const ctrl = GetAsyncKeyState(VK_CONTROL) & 0x8000;
|
// Temporarily disable Win+Ctrl+Number functionality
|
||||||
if (ctrl)
|
// if (ctrl)
|
||||||
{
|
// {
|
||||||
// Temporarily disable Win+Ctrl+Number functionality
|
// if ((info->vkCode >= '0') && (info->vkCode <= '9'))
|
||||||
//if ((info->vkCode >= '0') && (info->vkCode <= '9'))
|
// {
|
||||||
//{
|
// // Win+Ctrl+Number will cycle through ZoneSets
|
||||||
// // Win+Ctrl+Number will cycle through ZoneSets
|
// Trace::FancyZones::OnKeyDown(info->vkCode, win, ctrl, false /*inMoveSize*/);
|
||||||
// Trace::FancyZones::OnKeyDown(info->vkCode, win, ctrl, false /*inMoveSize*/);
|
// CycleActiveZoneSet(info->vkCode);
|
||||||
// CycleActiveZoneSet(info->vkCode);
|
// return true;
|
||||||
// return true;
|
// }
|
||||||
//}
|
// }
|
||||||
}
|
// else
|
||||||
else if ((info->vkCode == VK_RIGHT) || (info->vkCode == VK_LEFT) || (info->vkCode == VK_UP) || (info->vkCode == VK_DOWN))
|
if ((info->vkCode == VK_RIGHT) || (info->vkCode == VK_LEFT) || (info->vkCode == VK_UP) || (info->vkCode == VK_DOWN))
|
||||||
{
|
{
|
||||||
if (ShouldProcessSnapHotkey(info->vkCode))
|
if (ShouldProcessSnapHotkey(info->vkCode))
|
||||||
{
|
{
|
||||||
@@ -1142,7 +1145,7 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
|
|||||||
{
|
{
|
||||||
// Multi monitor environment.
|
// Multi monitor environment.
|
||||||
// First, try to stay on the same monitor
|
// First, try to stay on the same monitor
|
||||||
bool success = m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, false, m_workAreaHandler.GetWorkArea(m_currentDesktopId, current));
|
bool success = ProcessDirectedSnapHotkey(window, vkCode, false, m_workAreaHandler.GetWorkArea(m_currentDesktopId, current));
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@@ -1250,7 +1253,7 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Single monitor environment, or combined multi-monitor environment.
|
// Single monitor environment, or combined multi-monitor environment.
|
||||||
return m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, true, m_workAreaHandler.GetWorkArea(m_currentDesktopId, current));
|
return ProcessDirectedSnapHotkey(window, vkCode, true, m_workAreaHandler.GetWorkArea(m_currentDesktopId, current));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1271,6 +1274,19 @@ bool FancyZones::OnSnapHotkey(DWORD vkCode) noexcept
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FancyZones::ProcessDirectedSnapHotkey(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept
|
||||||
|
{
|
||||||
|
// Check whether Alt is used in the shortcut key combination
|
||||||
|
if (GetAsyncKeyState(VK_MENU) & 0x8000)
|
||||||
|
{
|
||||||
|
return m_windowMoveHandler.ExtendWindowByDirectionAndPosition(window, vkCode, zoneWindow);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, cycle, zoneWindow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FancyZones::RegisterVirtualDesktopUpdates(std::vector<GUID>& ids) noexcept
|
void FancyZones::RegisterVirtualDesktopUpdates(std::vector<GUID>& ids) noexcept
|
||||||
{
|
{
|
||||||
std::unique_lock writeLock(m_lock);
|
std::unique_lock writeLock(m_lock);
|
||||||
|
|||||||
@@ -82,8 +82,9 @@ public:
|
|||||||
void MoveSizeEnd(HWND window, 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;
|
||||||
|
|
||||||
void MoveWindowIntoZoneByIndexSet(HWND window, const std::vector<size_t>& indexSet, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept;
|
void MoveWindowIntoZoneByIndexSet(HWND window, const std::vector<size_t>& indexSet, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept;
|
||||||
bool MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow);
|
bool MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept;
|
||||||
bool MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow);
|
bool MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept;
|
||||||
|
bool ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void WarnIfElevationIsRequired(HWND window) noexcept;
|
void WarnIfElevationIsRequired(HWND window) noexcept;
|
||||||
@@ -160,16 +161,21 @@ void WindowMoveHandler::MoveWindowIntoZoneByIndexSet(HWND window, const std::vec
|
|||||||
pimpl->MoveWindowIntoZoneByIndexSet(window, indexSet, zoneWindow);
|
pimpl->MoveWindowIntoZoneByIndexSet(window, indexSet, zoneWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowMoveHandler::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow)
|
bool WindowMoveHandler::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept
|
||||||
{
|
{
|
||||||
return pimpl->MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, cycle, zoneWindow);
|
return pimpl->MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, cycle, zoneWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowMoveHandler::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow)
|
bool WindowMoveHandler::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept
|
||||||
{
|
{
|
||||||
return pimpl->MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, cycle, zoneWindow);
|
return pimpl->MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, cycle, zoneWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WindowMoveHandler::ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept
|
||||||
|
{
|
||||||
|
return pimpl->ExtendWindowByDirectionAndPosition(window, vkCode, zoneWindow);
|
||||||
|
}
|
||||||
|
|
||||||
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 (!FancyZonesUtils::IsCandidateForZoning(window, m_settings->GetSettings()->excludedAppsArray) || WindowMoveHandlerUtils::IsCursorTypeIndicatingSizeEvent())
|
if (!FancyZonesUtils::IsCandidateForZoning(window, m_settings->GetSettings()->excludedAppsArray) || WindowMoveHandlerUtils::IsCursorTypeIndicatingSizeEvent())
|
||||||
@@ -376,16 +382,21 @@ void WindowMoveHandlerPrivate::MoveWindowIntoZoneByIndexSet(HWND window, const s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowMoveHandlerPrivate::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow)
|
bool WindowMoveHandlerPrivate::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept
|
||||||
{
|
{
|
||||||
return zoneWindow && zoneWindow->MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, cycle);
|
return zoneWindow && zoneWindow->MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, cycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowMoveHandlerPrivate::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow)
|
bool WindowMoveHandlerPrivate::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept
|
||||||
{
|
{
|
||||||
return zoneWindow && zoneWindow->MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, cycle);
|
return zoneWindow && zoneWindow->MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, cycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WindowMoveHandlerPrivate::ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept
|
||||||
|
{
|
||||||
|
return zoneWindow && zoneWindow->ExtendWindowByDirectionAndPosition(window, vkCode);
|
||||||
|
}
|
||||||
|
|
||||||
void WindowMoveHandlerPrivate::WarnIfElevationIsRequired(HWND window) noexcept
|
void WindowMoveHandlerPrivate::WarnIfElevationIsRequired(HWND window) noexcept
|
||||||
{
|
{
|
||||||
static bool warning_shown = false;
|
static bool warning_shown = false;
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ public:
|
|||||||
void MoveSizeEnd(HWND window, 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;
|
||||||
|
|
||||||
void MoveWindowIntoZoneByIndexSet(HWND window, const std::vector<size_t>& indexSet, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept;
|
void MoveWindowIntoZoneByIndexSet(HWND window, const std::vector<size_t>& indexSet, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept;
|
||||||
bool MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow);
|
bool MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept;
|
||||||
bool MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow);
|
bool MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept;
|
||||||
|
bool ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class WindowMoveHandlerPrivate* pimpl;
|
class WindowMoveHandlerPrivate* pimpl;
|
||||||
|
|||||||
@@ -143,12 +143,16 @@ public:
|
|||||||
MoveWindowIntoZoneByDirectionAndIndex(HWND window, HWND zoneWindow, DWORD vkCode, bool cycle) noexcept;
|
MoveWindowIntoZoneByDirectionAndIndex(HWND window, HWND zoneWindow, DWORD vkCode, bool cycle) noexcept;
|
||||||
IFACEMETHODIMP_(bool)
|
IFACEMETHODIMP_(bool)
|
||||||
MoveWindowIntoZoneByDirectionAndPosition(HWND window, HWND zoneWindow, DWORD vkCode, bool cycle) noexcept;
|
MoveWindowIntoZoneByDirectionAndPosition(HWND window, HWND zoneWindow, DWORD vkCode, bool cycle) noexcept;
|
||||||
|
IFACEMETHODIMP_(bool)
|
||||||
|
ExtendWindowByDirectionAndPosition(HWND window, HWND windowZone, DWORD vkCode) noexcept;
|
||||||
IFACEMETHODIMP_(void)
|
IFACEMETHODIMP_(void)
|
||||||
MoveWindowIntoZoneByPoint(HWND window, HWND zoneWindow, POINT ptClient) noexcept;
|
MoveWindowIntoZoneByPoint(HWND window, HWND zoneWindow, POINT ptClient) noexcept;
|
||||||
IFACEMETHODIMP_(bool)
|
IFACEMETHODIMP_(bool)
|
||||||
CalculateZones(RECT workArea, int zoneCount, int spacing) noexcept;
|
CalculateZones(RECT workArea, int zoneCount, int spacing) noexcept;
|
||||||
IFACEMETHODIMP_(bool)
|
IFACEMETHODIMP_(bool)
|
||||||
IsZoneEmpty(int zoneIndex) noexcept;
|
IsZoneEmpty(int zoneIndex) noexcept;
|
||||||
|
IFACEMETHODIMP_(std::vector<size_t>)
|
||||||
|
GetCombinedZoneRange(const std::vector<size_t>& initialZones, const std::vector<size_t>& finalZones) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool CalculateFocusLayout(Rect workArea, int zoneCount) noexcept;
|
bool CalculateFocusLayout(Rect workArea, int zoneCount) noexcept;
|
||||||
@@ -161,6 +165,12 @@ private:
|
|||||||
|
|
||||||
std::vector<winrt::com_ptr<IZone>> m_zones;
|
std::vector<winrt::com_ptr<IZone>> m_zones;
|
||||||
std::map<HWND, std::vector<size_t>> m_windowIndexSet;
|
std::map<HWND, std::vector<size_t>> m_windowIndexSet;
|
||||||
|
|
||||||
|
// Needed for ExtendWindowByDirectionAndPosition
|
||||||
|
std::map<HWND, std::vector<size_t>> m_windowInitialIndexSet;
|
||||||
|
std::map<HWND, size_t> m_windowFinalIndex;
|
||||||
|
bool m_inExtendWindow = false;
|
||||||
|
|
||||||
ZoneSetConfig m_config;
|
ZoneSetConfig m_config;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -276,6 +286,13 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND windowZone, const std::v
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always clear the info related to SelectManyZones if it's not being used
|
||||||
|
if (!m_inExtendWindow)
|
||||||
|
{
|
||||||
|
m_windowFinalIndex.erase(window);
|
||||||
|
m_windowInitialIndexSet.erase(window);
|
||||||
|
}
|
||||||
|
|
||||||
RECT size;
|
RECT size;
|
||||||
bool sizeEmpty = true;
|
bool sizeEmpty = true;
|
||||||
size_t bitmask = 0;
|
size_t bitmask = 0;
|
||||||
@@ -410,12 +427,15 @@ ZoneSet::MoveWindowIntoZoneByDirectionAndPosition(HWND window, HWND windowZone,
|
|||||||
else if (cycle)
|
else if (cycle)
|
||||||
{
|
{
|
||||||
// Try again from the position off the screen in the opposite direction to vkCode
|
// Try again from the position off the screen in the opposite direction to vkCode
|
||||||
|
// Consider all zones as available
|
||||||
|
zoneRects.resize(zoneObjects.size());
|
||||||
|
std::transform(zoneObjects.begin(), zoneObjects.end(), zoneRects.begin(), [](auto zone) { return zone->GetZoneRect(); });
|
||||||
windowRect = FancyZonesUtils::PrepareRectForCycling(windowRect, windowZoneRect, vkCode);
|
windowRect = FancyZonesUtils::PrepareRectForCycling(windowRect, windowZoneRect, vkCode);
|
||||||
result = FancyZonesUtils::ChooseNextZoneByPosition(vkCode, windowRect, zoneRects);
|
result = FancyZonesUtils::ChooseNextZoneByPosition(vkCode, windowRect, zoneRects);
|
||||||
|
|
||||||
if (result < zoneRects.size())
|
if (result < zoneRects.size())
|
||||||
{
|
{
|
||||||
MoveWindowIntoZoneByIndex(window, windowZone, freeZoneIndices[result]);
|
MoveWindowIntoZoneByIndex(window, windowZone, result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -424,6 +444,93 @@ ZoneSet::MoveWindowIntoZoneByDirectionAndPosition(HWND window, HWND windowZone,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IFACEMETHODIMP_(bool)
|
||||||
|
ZoneSet::ExtendWindowByDirectionAndPosition(HWND window, HWND windowZone, DWORD vkCode) noexcept
|
||||||
|
{
|
||||||
|
if (m_zones.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RECT windowRect, windowZoneRect;
|
||||||
|
if (GetWindowRect(window, &windowRect) && GetWindowRect(windowZone, &windowZoneRect))
|
||||||
|
{
|
||||||
|
auto zoneObjects = GetZones();
|
||||||
|
auto oldZones = GetZoneIndexSetFromWindow(window);
|
||||||
|
std::vector<bool> usedZoneIndices(zoneObjects.size(), false);
|
||||||
|
std::vector<RECT> zoneRects;
|
||||||
|
std::vector<size_t> freeZoneIndices;
|
||||||
|
|
||||||
|
// If selectManyZones = true for the second time, use the last zone into which we moved
|
||||||
|
// instead of the window rect and enable moving to all zones except the old one
|
||||||
|
auto finalIndexIt = m_windowFinalIndex.find(window);
|
||||||
|
if (finalIndexIt != m_windowFinalIndex.end())
|
||||||
|
{
|
||||||
|
usedZoneIndices[finalIndexIt->second] = true;
|
||||||
|
windowRect = zoneObjects[finalIndexIt->second]->GetZoneRect();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (size_t idx : oldZones)
|
||||||
|
{
|
||||||
|
usedZoneIndices[idx] = true;
|
||||||
|
}
|
||||||
|
// Move to coordinates relative to windowZone
|
||||||
|
windowRect.top -= windowZoneRect.top;
|
||||||
|
windowRect.bottom -= windowZoneRect.top;
|
||||||
|
windowRect.left -= windowZoneRect.left;
|
||||||
|
windowRect.right -= windowZoneRect.left;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < zoneObjects.size(); i++)
|
||||||
|
{
|
||||||
|
if (!usedZoneIndices[i])
|
||||||
|
{
|
||||||
|
zoneRects.emplace_back(zoneObjects[i]->GetZoneRect());
|
||||||
|
freeZoneIndices.emplace_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t result = FancyZonesUtils::ChooseNextZoneByPosition(vkCode, windowRect, zoneRects);
|
||||||
|
if (result < zoneRects.size())
|
||||||
|
{
|
||||||
|
size_t targetZone = freeZoneIndices[result];
|
||||||
|
std::vector<size_t> resultIndexSet;
|
||||||
|
|
||||||
|
// First time with selectManyZones = true for this window?
|
||||||
|
if (finalIndexIt == m_windowFinalIndex.end())
|
||||||
|
{
|
||||||
|
// Already zoned?
|
||||||
|
if (oldZones.size())
|
||||||
|
{
|
||||||
|
m_windowInitialIndexSet[window] = oldZones;
|
||||||
|
m_windowFinalIndex[window] = targetZone;
|
||||||
|
resultIndexSet = GetCombinedZoneRange(oldZones, { targetZone });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_windowInitialIndexSet[window] = { targetZone };
|
||||||
|
m_windowFinalIndex[window] = targetZone;
|
||||||
|
resultIndexSet = { targetZone };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto deletethis = m_windowInitialIndexSet[window];
|
||||||
|
m_windowFinalIndex[window] = targetZone;
|
||||||
|
resultIndexSet = GetCombinedZoneRange(m_windowInitialIndexSet[window], { targetZone });
|
||||||
|
}
|
||||||
|
|
||||||
|
m_inExtendWindow = true;
|
||||||
|
MoveWindowIntoZoneByIndexSet(window, windowZone, resultIndexSet);
|
||||||
|
m_inExtendWindow = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
IFACEMETHODIMP_(void)
|
IFACEMETHODIMP_(void)
|
||||||
ZoneSet::MoveWindowIntoZoneByPoint(HWND window, HWND zoneWindow, POINT ptClient) noexcept
|
ZoneSet::MoveWindowIntoZoneByPoint(HWND window, HWND zoneWindow, POINT ptClient) noexcept
|
||||||
{
|
{
|
||||||
@@ -779,6 +886,48 @@ void ZoneSet::StampWindow(HWND window, size_t bitmask) noexcept
|
|||||||
SetProp(window, ZonedWindowProperties::PropertyMultipleZoneID, reinterpret_cast<HANDLE>(bitmask));
|
SetProp(window, ZonedWindowProperties::PropertyMultipleZoneID, reinterpret_cast<HANDLE>(bitmask));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> ZoneSet::GetCombinedZoneRange(const std::vector<size_t>& initialZones, const std::vector<size_t>& finalZones) noexcept
|
||||||
|
{
|
||||||
|
std::vector<size_t> combinedZones, result;
|
||||||
|
std::set_union(begin(initialZones), end(initialZones), begin(finalZones), end(finalZones), std::back_inserter(combinedZones));
|
||||||
|
|
||||||
|
RECT boundingRect;
|
||||||
|
bool boundingRectEmpty = true;
|
||||||
|
auto zones = GetZones();
|
||||||
|
|
||||||
|
for (size_t zoneId : combinedZones)
|
||||||
|
{
|
||||||
|
RECT rect = zones[zoneId]->GetZoneRect();
|
||||||
|
if (boundingRectEmpty)
|
||||||
|
{
|
||||||
|
boundingRect = rect;
|
||||||
|
boundingRectEmpty = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boundingRect.left = min(boundingRect.left, rect.left);
|
||||||
|
boundingRect.top = min(boundingRect.top, rect.top);
|
||||||
|
boundingRect.right = max(boundingRect.right, rect.right);
|
||||||
|
boundingRect.bottom = max(boundingRect.bottom, rect.bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!boundingRectEmpty)
|
||||||
|
{
|
||||||
|
for (size_t zoneId = 0; zoneId < zones.size(); zoneId++)
|
||||||
|
{
|
||||||
|
RECT rect = zones[zoneId]->GetZoneRect();
|
||||||
|
if (boundingRect.left <= rect.left && rect.right <= boundingRect.right &&
|
||||||
|
boundingRect.top <= rect.top && rect.bottom <= boundingRect.bottom)
|
||||||
|
{
|
||||||
|
result.push_back(zoneId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
winrt::com_ptr<IZoneSet> MakeZoneSet(ZoneSetConfig const& config) noexcept
|
winrt::com_ptr<IZoneSet> MakeZoneSet(ZoneSetConfig const& config) noexcept
|
||||||
{
|
{
|
||||||
return winrt::make_self<ZoneSet>(config);
|
return winrt::make_self<ZoneSet>(config);
|
||||||
|
|||||||
@@ -91,6 +91,19 @@ interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet :
|
|||||||
* zones left in the zone layout in which window can move.
|
* zones left in the zone layout in which window can move.
|
||||||
*/
|
*/
|
||||||
IFACEMETHOD_(bool, MoveWindowIntoZoneByDirectionAndPosition)(HWND window, HWND zoneWindow, DWORD vkCode, bool cycle) = 0;
|
IFACEMETHOD_(bool, MoveWindowIntoZoneByDirectionAndPosition)(HWND window, HWND zoneWindow, DWORD vkCode, bool cycle) = 0;
|
||||||
|
/**
|
||||||
|
* Extend or shrink the window to an adjacent zone based on direction (using CTRL+WIN+ALT + LEFT/RIGHT/UP/DOWN arrow), based on
|
||||||
|
* their on-screen position.
|
||||||
|
*
|
||||||
|
* @param window Handle of window which should be assigned to zone.
|
||||||
|
* @param zoneWindow The m_window of a ZoneWindow, it's a hidden window representing the
|
||||||
|
* current monitor desktop work area.
|
||||||
|
* @param vkCode Pressed arrow key.
|
||||||
|
*
|
||||||
|
* @returns Boolean indicating whether the window was rezoned. False could be returned when there are no more
|
||||||
|
* zones available in the given direction.
|
||||||
|
*/
|
||||||
|
IFACEMETHOD_(bool, ExtendWindowByDirectionAndPosition)(HWND window, HWND zoneWindow, DWORD vkCode) = 0;
|
||||||
/**
|
/**
|
||||||
* Assign window to the zone based on cursor coordinates.
|
* Assign window to the zone based on cursor coordinates.
|
||||||
*
|
*
|
||||||
@@ -119,6 +132,15 @@ interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet :
|
|||||||
* @returns Boolean indicating whether the zone is empty.
|
* @returns Boolean indicating whether the zone is empty.
|
||||||
*/
|
*/
|
||||||
IFACEMETHOD_(bool, IsZoneEmpty)(int zoneIndex) = 0;
|
IFACEMETHOD_(bool, IsZoneEmpty)(int zoneIndex) = 0;
|
||||||
|
/**
|
||||||
|
* Returns all zones spanned by the minimum bounding rectangle containing the two given zone index sets.
|
||||||
|
*
|
||||||
|
* @param initialZones The indices of the first chosen zone (the anchor).
|
||||||
|
* @param finalZones The indices of the last chosen zone (the current window position).
|
||||||
|
*
|
||||||
|
* @returns A vector indicating describing the chosen zone index set.
|
||||||
|
*/
|
||||||
|
IFACEMETHOD_(std::vector<size_t>, GetCombinedZoneRange)(const std::vector<size_t>& initialZones, const std::vector<size_t>& finalZones) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ZoneSetConfig
|
struct ZoneSetConfig
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ public:
|
|||||||
MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle) noexcept;
|
MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle) noexcept;
|
||||||
IFACEMETHODIMP_(bool)
|
IFACEMETHODIMP_(bool)
|
||||||
MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle) noexcept;
|
MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle) noexcept;
|
||||||
|
IFACEMETHODIMP_(bool)
|
||||||
|
ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode) noexcept;
|
||||||
IFACEMETHODIMP_(void)
|
IFACEMETHODIMP_(void)
|
||||||
CycleActiveZoneSet(DWORD vkCode) noexcept;
|
CycleActiveZoneSet(DWORD vkCode) noexcept;
|
||||||
IFACEMETHODIMP_(std::wstring)
|
IFACEMETHODIMP_(std::wstring)
|
||||||
@@ -233,44 +235,7 @@ IFACEMETHODIMP ZoneWindow::MoveSizeUpdate(POINT const& ptScreen, bool dragEnable
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<size_t> newHighlightZone;
|
highlightZone = m_activeZoneSet->GetCombinedZoneRange(m_initialHighlightZone, highlightZone);
|
||||||
std::set_union(begin(highlightZone), end(highlightZone), begin(m_initialHighlightZone), end(m_initialHighlightZone), std::back_inserter(newHighlightZone));
|
|
||||||
|
|
||||||
RECT boundingRect;
|
|
||||||
bool boundingRectEmpty = true;
|
|
||||||
auto zones = m_activeZoneSet->GetZones();
|
|
||||||
|
|
||||||
for (size_t zoneId : newHighlightZone)
|
|
||||||
{
|
|
||||||
RECT rect = zones[zoneId]->GetZoneRect();
|
|
||||||
if (boundingRectEmpty)
|
|
||||||
{
|
|
||||||
boundingRect = rect;
|
|
||||||
boundingRectEmpty = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
boundingRect.left = min(boundingRect.left, rect.left);
|
|
||||||
boundingRect.top = min(boundingRect.top, rect.top);
|
|
||||||
boundingRect.right = max(boundingRect.right, rect.right);
|
|
||||||
boundingRect.bottom = max(boundingRect.bottom, rect.bottom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
highlightZone.clear();
|
|
||||||
|
|
||||||
if (!boundingRectEmpty)
|
|
||||||
{
|
|
||||||
for (size_t zoneId = 0; zoneId < zones.size(); zoneId++)
|
|
||||||
{
|
|
||||||
RECT rect = zones[zoneId]->GetZoneRect();
|
|
||||||
if (boundingRect.left <= rect.left && rect.right <= boundingRect.right &&
|
|
||||||
boundingRect.top <= rect.top && rect.bottom <= boundingRect.bottom)
|
|
||||||
{
|
|
||||||
highlightZone.push_back(zoneId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -367,6 +332,20 @@ ZoneWindow::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IFACEMETHODIMP_(bool)
|
||||||
|
ZoneWindow::ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode) noexcept
|
||||||
|
{
|
||||||
|
if (m_activeZoneSet)
|
||||||
|
{
|
||||||
|
if (m_activeZoneSet->ExtendWindowByDirectionAndPosition(window, m_window.get(), vkCode))
|
||||||
|
{
|
||||||
|
SaveWindowProcessToZoneIndex(window);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
IFACEMETHODIMP_(void)
|
IFACEMETHODIMP_(void)
|
||||||
ZoneWindow::CycleActiveZoneSet(DWORD wparam) noexcept
|
ZoneWindow::CycleActiveZoneSet(DWORD wparam) noexcept
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IZoneWindow
|
|||||||
* @param dragEnabled Boolean indicating is giving hints about active zone layout enabled.
|
* @param dragEnabled Boolean indicating is giving hints about active zone layout enabled.
|
||||||
* Hints are given while dragging window while holding SHIFT key.
|
* Hints are given while dragging window while holding SHIFT key.
|
||||||
* @param selectManyZones When this parameter is true, the set of highlighted zones is computed
|
* @param selectManyZones When this parameter is true, the set of highlighted zones is computed
|
||||||
by finding the minimum bounding rectangle of the zone(s) from which the
|
* by finding the minimum bounding rectangle of the zone(s) from which the
|
||||||
user started dragging and the zone(s) above which the user is hovering
|
* user started dragging and the zone(s) above which the user is hovering
|
||||||
at the moment this function is called. Otherwise, highlight only the zone(s)
|
* at the moment this function is called. Otherwise, highlight only the zone(s)
|
||||||
above which the user is currently hovering.
|
* above which the user is currently hovering.
|
||||||
*/
|
*/
|
||||||
IFACEMETHOD(MoveSizeUpdate)(POINT const& ptScreen, bool dragEnabled, bool selectManyZones) = 0;
|
IFACEMETHOD(MoveSizeUpdate)(POINT const& ptScreen, bool dragEnabled, bool selectManyZones) = 0;
|
||||||
/**
|
/**
|
||||||
@@ -81,6 +81,17 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IZoneWindow
|
|||||||
* zones left in the zone layout in which window can move.
|
* zones left in the zone layout in which window can move.
|
||||||
*/
|
*/
|
||||||
IFACEMETHOD_(bool, MoveWindowIntoZoneByDirectionAndPosition)(HWND window, DWORD vkCode, bool cycle) = 0;
|
IFACEMETHOD_(bool, MoveWindowIntoZoneByDirectionAndPosition)(HWND window, DWORD vkCode, bool cycle) = 0;
|
||||||
|
/**
|
||||||
|
* Extend or shrink the window to an adjacent zone based on direction (using CTRL+WIN+ALT + LEFT/RIGHT/UP/DOWN arrow), based on
|
||||||
|
* their on-screen position.
|
||||||
|
*
|
||||||
|
* @param window Handle of window which should be assigned to zone.
|
||||||
|
* @param vkCode Pressed arrow key.
|
||||||
|
*
|
||||||
|
* @returns Boolean indicating whether the window was rezoned. False could be returned when there are no more
|
||||||
|
* zones available in the given direction.
|
||||||
|
*/
|
||||||
|
IFACEMETHOD_(bool, ExtendWindowByDirectionAndPosition)(HWND window, DWORD vkCode) = 0;
|
||||||
/**
|
/**
|
||||||
* Cycle through active zone layouts (giving hints about each layout).
|
* Cycle through active zone layouts (giving hints about each layout).
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user