Win arrows revisited (#5932)

* Added the setting

* Refactored existing code, the main feature isn't implemented yet

* Renamed a method

* Updated a comment in IZoneWindow

* Added the zone selection algorithm, didn't test it

* Basic features work

* Single monitor cycling works

* Seems that the feature works well

* Polished the settings page

* Rebase fix

* Fixed a null pointer dereference

* Use classic if syntax

* Fixed bad indentation

How did these lines unindent themselves?

* Removed TODO comment

* Rebase fix

* Another rebase fix
This commit is contained in:
Ivan Stošić
2020-08-21 12:53:03 +02:00
committed by GitHub
parent 64c51a49a0
commit 976116a012
24 changed files with 657 additions and 173 deletions

View File

@@ -17,6 +17,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
FancyzonesOverrideSnapHotkeys = new BoolProperty();
FancyzonesMouseSwitch = new BoolProperty();
FancyzonesMoveWindowsAcrossMonitors = new BoolProperty();
FancyzonesMoveWindowsBasedOnPosition = new BoolProperty();
FancyzonesDisplayChangeMoveWindows = new BoolProperty();
FancyzonesZoneSetChangeMoveWindows = new BoolProperty();
FancyzonesAppLastZoneMoveWindows = new BoolProperty();
@@ -46,6 +47,9 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
[JsonPropertyName("fancyzones_moveWindowAcrossMonitors")]
public BoolProperty FancyzonesMoveWindowsAcrossMonitors { get; set; }
[JsonPropertyName("fancyzones_moveWindowsBasedOnPosition")]
public BoolProperty FancyzonesMoveWindowsBasedOnPosition { get; set; }
[JsonPropertyName("fancyzones_displayChange_moveWindows")]
public BoolProperty FancyzonesDisplayChangeMoveWindows { get; set; }

View File

@@ -41,6 +41,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels
_mouseSwitch = Settings.Properties.FancyzonesMouseSwitch.Value;
_overrideSnapHotkeys = Settings.Properties.FancyzonesOverrideSnapHotkeys.Value;
_moveWindowsAcrossMonitors = Settings.Properties.FancyzonesMoveWindowsAcrossMonitors.Value;
_moveWindowsBasedOnPosition = Settings.Properties.FancyzonesMoveWindowsBasedOnPosition.Value;
_displayChangemoveWindows = Settings.Properties.FancyzonesDisplayChangeMoveWindows.Value;
_zoneSetChangeMoveWindows = Settings.Properties.FancyzonesZoneSetChangeMoveWindows.Value;
_appLastZoneMoveWindows = Settings.Properties.FancyzonesAppLastZoneMoveWindows.Value;
@@ -84,6 +85,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels
private bool _mouseSwitch;
private bool _overrideSnapHotkeys;
private bool _moveWindowsAcrossMonitors;
private bool _moveWindowsBasedOnPosition;
private bool _displayChangemoveWindows;
private bool _zoneSetChangeMoveWindows;
private bool _appLastZoneMoveWindows;
@@ -119,10 +121,19 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels
SendConfigMSG(snd.ToString());
OnPropertyChanged("IsEnabled");
OnPropertyChanged("SnapHotkeysCategoryEnabled");
}
}
}
public bool SnapHotkeysCategoryEnabled
{
get
{
return _isEnabled && _overrideSnapHotkeys;
}
}
public bool ShiftDrag
{
get
@@ -178,6 +189,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels
_overrideSnapHotkeys = value;
Settings.Properties.FancyzonesOverrideSnapHotkeys.Value = value;
RaisePropertyChanged();
OnPropertyChanged("SnapHotkeysCategoryEnabled");
}
}
}
@@ -200,6 +212,24 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels
}
}
public bool MoveWindowsBasedOnPosition
{
get
{
return _moveWindowsBasedOnPosition;
}
set
{
if (value != _moveWindowsBasedOnPosition)
{
_moveWindowsBasedOnPosition = value;
Settings.Properties.FancyzonesMoveWindowsBasedOnPosition.Value = value;
RaisePropertyChanged();
}
}
}
public bool DisplayChangeMoveWindows
{
get

View File

@@ -107,6 +107,25 @@ namespace ViewModelTests
viewModel.OverrideSnapHotkeys = true;
}
[TestMethod]
public void MoveWindowsBasedOnPosition_ShouldSetValue2True_WhenSuccessful()
{
// Assert
Func<string, int> SendMockIPCConfigMSG = msg =>
{
FancyZonesSettingsIPCMessage snd = JsonSerializer.Deserialize<FancyZonesSettingsIPCMessage>(msg);
Assert.IsTrue(snd.Powertoys.FancyZones.Properties.FancyzonesMoveWindowsBasedOnPosition.Value);
return 0;
};
// arrange
FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName);
Assert.IsFalse(viewModel.MoveWindowsBasedOnPosition); // check if value was initialized to false.
// act
viewModel.MoveWindowsBasedOnPosition = true;
}
[TestMethod]
public void ZoneSetChangeFlashZones_ShouldSetValue2False_WhenSuccessful()
{

View File

@@ -319,7 +319,7 @@
<value>Use a non-primary mouse button to toggle zone activation</value>
</data>
<data name="FancyZones_MoveWindowsAcrossAllMonitorsCheckBoxControl.Content" xml:space="preserve">
<value>Move windows between zones across all monitors when snapping with (Win + Arrow)</value>
<value>Move windows between zones across all monitors</value>
</data>
<data name="FancyZones_OverrideSnapHotkeysCheckBoxControl.Content" xml:space="preserve">
<value>Override Windows Snap shortcut (Win + Arrow) to move windows between zones</value>
@@ -666,4 +666,7 @@
<data name="ImageResizer_Formatting_Sizename.Text" xml:space="preserve">
<value>Size name</value>
</data>
<data name="FancyZones_MoveWindowsBasedOnPositionCheckBoxControl.Content" xml:space="preserve">
<value>Move windows based on their position</value>
</data>
</root>

View File

@@ -100,10 +100,15 @@
Margin="{StaticResource SmallTopMargin}"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"/>
<CheckBox x:Uid="FancyZones_MoveWindowsBasedOnPositionCheckBoxControl"
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.MoveWindowsBasedOnPosition}"
Margin="24,12,0,0"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.SnapHotkeysCategoryEnabled}"/>
<CheckBox x:Uid="FancyZones_MoveWindowsAcrossAllMonitorsCheckBoxControl"
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.MoveWindowsAcrossMonitors}"
Margin="{StaticResource SmallTopMargin}"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"/>
Margin="24,12,0,0"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.SnapHotkeysCategoryEnabled}"/>
<CheckBox x:Uid="FancyZones_DisplayChangeMoveWindowsCheckBoxControl"
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.DisplayChangeMoveWindows}"

View File

@@ -242,6 +242,8 @@ private:
void UpdateZoneWindows() noexcept;
void UpdateWindowsPositions() noexcept;
void CycleActiveZoneSet(DWORD vkCode) noexcept;
bool OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexcept;
bool OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept;
bool OnSnapHotkey(DWORD vkCode) noexcept;
void RegisterVirtualDesktopUpdates(std::vector<GUID>& ids) noexcept;
@@ -254,7 +256,7 @@ private:
void MoveWindowIntoZone(HWND window, winrt::com_ptr<IZoneWindow> zoneWindow, const std::vector<int>& zoneIndexSet) noexcept;
void OnEditorExitEvent() noexcept;
bool ShouldProcessSnapHotkey() noexcept;
bool ShouldProcessSnapHotkey(DWORD vkCode) noexcept;
std::vector<std::pair<HMONITOR, RECT>> GetRawMonitorData() noexcept;
std::vector<HMONITOR> GetMonitorsSorted() noexcept;
@@ -576,9 +578,9 @@ FancyZones::OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept
// return true;
//}
}
else if ((info->vkCode == VK_RIGHT) || (info->vkCode == VK_LEFT))
else if ((info->vkCode == VK_RIGHT) || (info->vkCode == VK_LEFT) || (info->vkCode == VK_UP) || (info->vkCode == VK_DOWN))
{
if (ShouldProcessSnapHotkey())
if (ShouldProcessSnapHotkey(info->vkCode))
{
Trace::FancyZones::OnKeyDown(info->vkCode, win, ctrl, false /*inMoveSize*/);
// Win+Left, Win+Right will cycle through Zones in the active ZoneSet when WM_PRIV_LOWLEVELKB's handled
@@ -1071,71 +1073,214 @@ void FancyZones::CycleActiveZoneSet(DWORD vkCode) noexcept
}
}
bool FancyZones::OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexcept
{
HMONITOR current;
if (m_settings->GetSettings()->spanZonesAcrossMonitors)
{
current = NULL;
}
else
{
current = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
}
std::vector<HMONITOR> monitorInfo = GetMonitorsSorted();
if (current && monitorInfo.size() > 1 && m_settings->GetSettings()->moveWindowAcrossMonitors)
{
// Multi monitor environment.
auto currMonitorInfo = std::find(std::begin(monitorInfo), std::end(monitorInfo), current);
do
{
std::unique_lock writeLock(m_lock);
if (m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, false /* cycle through zones */, m_workAreaHandler.GetWorkArea(m_currentDesktopId, *currMonitorInfo)))
{
return true;
}
// We iterated through all zones in current monitor zone layout, move on to next one (or previous depending on direction).
if (vkCode == VK_RIGHT)
{
currMonitorInfo = std::next(currMonitorInfo);
if (currMonitorInfo == std::end(monitorInfo))
{
currMonitorInfo = std::begin(monitorInfo);
}
}
else if (vkCode == VK_LEFT)
{
if (currMonitorInfo == std::begin(monitorInfo))
{
currMonitorInfo = std::end(monitorInfo);
}
currMonitorInfo = std::prev(currMonitorInfo);
}
} while (*currMonitorInfo != current);
}
else
{
// Single monitor environment, or combined multi-monitor environment.
std::unique_lock writeLock(m_lock);
if (m_settings->GetSettings()->restoreSize)
{
bool moved = m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, false /* cycle through zones */, m_workAreaHandler.GetWorkArea(m_currentDesktopId, current));
if (!moved)
{
RestoreWindowOrigin(window);
RestoreWindowSize(window);
}
return true;
}
else
{
return m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, true /* cycle through zones */, m_workAreaHandler.GetWorkArea(m_currentDesktopId, current));
}
}
}
bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
{
HMONITOR current;
if (m_settings->GetSettings()->spanZonesAcrossMonitors)
{
current = NULL;
}
else
{
current = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
}
auto allMonitors = GetAllMonitorRects<&MONITORINFOEX::rcWork>();
if (current && allMonitors.size() > 1 && m_settings->GetSettings()->moveWindowAcrossMonitors)
{
// Multi monitor environment.
// First, try to stay on the same monitor
bool success = m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, false, m_workAreaHandler.GetWorkArea(m_currentDesktopId, current));
if (success)
{
return true;
}
// If that didn't work, extract zones from all other monitors and target one of them
std::vector<RECT> zoneRects;
std::vector<std::pair<size_t, winrt::com_ptr<IZoneWindow>>> zoneRectsInfo;
RECT currentMonitorRect{ .top = 0, .bottom = -1 };
for (const auto& [monitor, monitorRect] : allMonitors)
{
if (monitor == current)
{
currentMonitorRect = monitorRect;
}
else
{
auto workArea = m_workAreaHandler.GetWorkArea(m_currentDesktopId, monitor);
auto zoneSet = workArea->ActiveZoneSet();
if (zoneSet)
{
auto zones = zoneSet->GetZones();
for (size_t i = 0; i < zones.size(); i++)
{
const auto& zone = zones[i];
RECT zoneRect = zone->GetZoneRect();
zoneRect.left += monitorRect.left;
zoneRect.right += monitorRect.left;
zoneRect.top += monitorRect.top;
zoneRect.bottom += monitorRect.top;
zoneRects.emplace_back(zoneRect);
zoneRectsInfo.emplace_back(i, workArea);
}
}
}
}
// Ensure we can get the windowRect, if not, just quit
RECT windowRect;
if (!GetWindowRect(window, &windowRect))
{
return false;
}
size_t chosenIdx = ChooseNextZoneByPosition(vkCode, windowRect, zoneRects);
if (chosenIdx < zoneRects.size())
{
// Moving to another monitor succeeded
const auto& [trueZoneIdx, zoneWindow] = zoneRectsInfo[chosenIdx];
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, { static_cast<int>(trueZoneIdx) }, zoneWindow);
return true;
}
// We reached the end of all monitors.
// Try again, cycling on all monitors.
// First, add zones from the origin monitor to zoneRects
// Sanity check: the current monitor is valid
if (currentMonitorRect.top <= currentMonitorRect.bottom)
{
auto workArea = m_workAreaHandler.GetWorkArea(m_currentDesktopId, current);
auto zoneSet = workArea->ActiveZoneSet();
if (zoneSet)
{
auto zones = zoneSet->GetZones();
for (size_t i = 0; i < zones.size(); i++)
{
const auto& zone = zones[i];
RECT zoneRect = zone->GetZoneRect();
zoneRect.left += currentMonitorRect.left;
zoneRect.right += currentMonitorRect.left;
zoneRect.top += currentMonitorRect.top;
zoneRect.bottom += currentMonitorRect.top;
zoneRects.emplace_back(zoneRect);
zoneRectsInfo.emplace_back(i, workArea);
}
}
}
else
{
return false;
}
RECT combinedRect = GetAllMonitorsCombinedRect<&MONITORINFOEX::rcWork>();
windowRect = PrepareRectForCycling(windowRect, combinedRect, vkCode);
chosenIdx = ChooseNextZoneByPosition(vkCode, windowRect, zoneRects);
if (chosenIdx < zoneRects.size())
{
// Moving to another monitor succeeded
const auto& [trueZoneIdx, zoneWindow] = zoneRectsInfo[chosenIdx];
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, { static_cast<int>(trueZoneIdx) }, zoneWindow);
return true;
}
else
{
// Giving up
return false;
}
}
else
{
// Single monitor environment, or combined multi-monitor environment.
return m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, true, m_workAreaHandler.GetWorkArea(m_currentDesktopId, current));
}
}
bool FancyZones::OnSnapHotkey(DWORD vkCode) noexcept
{
auto window = GetForegroundWindow();
if (IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray))
{
HMONITOR current;
if (m_settings->GetSettings()->spanZonesAcrossMonitors)
if (m_settings->GetSettings()->moveWindowsBasedOnPosition)
{
current = NULL;
return OnSnapHotkeyBasedOnPosition(window, vkCode);
}
else
{
current = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
}
std::vector<HMONITOR> monitorInfo = GetMonitorsSorted();
if (current && monitorInfo.size() > 1 && m_settings->GetSettings()->moveWindowAcrossMonitors)
{
// Multi monitor environment.
auto currMonitorInfo = std::find(std::begin(monitorInfo), std::end(monitorInfo), current);
do
{
std::unique_lock writeLock(m_lock);
if (m_windowMoveHandler.MoveWindowIntoZoneByDirection(window, vkCode, false /* cycle through zones */, m_workAreaHandler.GetWorkArea(m_currentDesktopId, *currMonitorInfo)))
{
return true;
}
// We iterated through all zones in current monitor zone layout, move on to next one (or previous depending on direction).
if (vkCode == VK_RIGHT)
{
currMonitorInfo = std::next(currMonitorInfo);
if (currMonitorInfo == std::end(monitorInfo))
{
currMonitorInfo = std::begin(monitorInfo);
}
}
else if (vkCode == VK_LEFT)
{
if (currMonitorInfo == std::begin(monitorInfo))
{
currMonitorInfo = std::end(monitorInfo);
}
currMonitorInfo = std::prev(currMonitorInfo);
}
} while (*currMonitorInfo != current);
}
else
{
// Single monitor environment, or combined multi-monitor environment.
std::unique_lock writeLock(m_lock);
if (m_settings->GetSettings()->restoreSize)
{
bool moved = m_windowMoveHandler.MoveWindowIntoZoneByDirection(window, vkCode, false /* cycle through zones */, m_workAreaHandler.GetWorkArea(m_currentDesktopId, current));
if (!moved)
{
RestoreWindowOrigin(window);
RestoreWindowSize(window);
}
return true;
}
else
{
return m_windowMoveHandler.MoveWindowIntoZoneByDirection(window, vkCode, true /* cycle through zones */, m_workAreaHandler.GetWorkArea(m_currentDesktopId, current));
}
return (vkCode == VK_LEFT || vkCode == VK_RIGHT) && OnSnapHotkeyBasedOnZoneNumber(window, vkCode);
}
}
return false;
@@ -1179,7 +1324,7 @@ void FancyZones::OnEditorExitEvent() noexcept
}
}
bool FancyZones::ShouldProcessSnapHotkey() noexcept
bool FancyZones::ShouldProcessSnapHotkey(DWORD vkCode) noexcept
{
if (m_settings->GetSettings()->overrideSnapHotkeys)
{
@@ -1196,7 +1341,14 @@ bool FancyZones::ShouldProcessSnapHotkey() noexcept
auto zoneWindow = m_workAreaHandler.GetWorkArea(m_currentDesktopId, monitor);
if (zoneWindow->ActiveZoneSet() != nullptr)
{
return true;
if (vkCode == VK_UP || vkCode == VK_DOWN)
{
return m_settings->GetSettings()->moveWindowsBasedOnPosition;
}
else
{
return true;
}
}
}
return false;

View File

@@ -12,6 +12,7 @@ namespace NonLocalizable
const wchar_t MouseSwitchID[] = L"fancyzones_mouseSwitch";
const wchar_t OverrideSnapHotKeysID[] = L"fancyzones_overrideSnapHotkeys";
const wchar_t MoveWindowAcrossMonitorsID[] = L"fancyzones_moveWindowAcrossMonitors";
const wchar_t MoveWindowsBasedOnPositionID[] = L"fancyzones_moveWindowsBasedOnPosition";
const wchar_t DisplayChangeMoveWindowsID[] = L"fancyzones_displayChange_moveWindows";
const wchar_t ZoneSetChangeMoveWindowsID[] = L"fancyzones_zoneSetChange_moveWindows";
const wchar_t AppLastZoneMoveWindowsID[] = L"fancyzones_appLastZone_moveWindows";
@@ -44,7 +45,7 @@ public:
{
LoadSettings(name, true);
}
IFACEMETHODIMP_(void) SetCallback(IFancyZonesCallback* callback) { m_callback = callback; }
IFACEMETHODIMP_(void) ResetCallback() { m_callback = nullptr; }
IFACEMETHODIMP_(bool) GetConfig(_Out_ PWSTR buffer, _Out_ int *buffer_sizeg) noexcept;
@@ -67,11 +68,13 @@ private:
PCWSTR name;
bool* value;
int resourceId;
} m_configBools[13 /* 14 */] = { // "Turning FLASHING_ZONE option off"
} m_configBools[14 /* 15 */] = { // "Turning FLASHING_ZONE option off"
{ NonLocalizable::ShiftDragID, &m_settings.shiftDrag, IDS_SETTING_DESCRIPTION_SHIFTDRAG },
{ NonLocalizable::MouseSwitchID, &m_settings.mouseSwitch, IDS_SETTING_DESCRIPTION_MOUSESWITCH },
{ NonLocalizable::OverrideSnapHotKeysID, &m_settings.overrideSnapHotkeys, IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS },
{ NonLocalizable::MoveWindowAcrossMonitorsID, &m_settings.moveWindowAcrossMonitors, IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS },
{ NonLocalizable::MoveWindowsBasedOnPositionID, &m_settings.moveWindowsBasedOnPosition, IDS_SETTING_DESCRIPTION_MOVE_WINDOWS_BASED_ON_POSITION },
// "Turning FLASHING_ZONE option off"
//{ L"fancyzones_zoneSetChange_flashZones", &m_settings.zoneSetChange_flashZones, IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES },
{ NonLocalizable::DisplayChangeMoveWindowsID, &m_settings.displayChange_moveWindows, IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS },
@@ -81,7 +84,7 @@ private:
{ NonLocalizable::RestoreSizeID, &m_settings.restoreSize, IDS_SETTING_DESCRIPTION_RESTORESIZE },
{ NonLocalizable::UseCursorPosEditorStartupScreenID, &m_settings.use_cursorpos_editor_startupscreen, IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN },
{ NonLocalizable::ShowOnAllMonitorsID, &m_settings.showZonesOnAllMonitors, IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS},
{ NonLocalizable::SpanZonesAcrossMonitorsID, &m_settings.spanZonesAcrossMonitors, IDS_SETTING_DESCRIPTION_SPAN_ZONES_ACROSS_MONITORS },
{ NonLocalizable::SpanZonesAcrossMonitorsID, &m_settings.spanZonesAcrossMonitors, IDS_SETTING_DESCRIPTION_SPAN_ZONES_ACROSS_MONITORS },
{ NonLocalizable::MakeDraggedWindowTransparentID, &m_settings.makeDraggedWindowTransparent, IDS_SETTING_DESCRIPTION_MAKE_DRAGGED_WINDOW_TRANSPARENT},
};
@@ -115,9 +118,9 @@ IFACEMETHODIMP_(bool) FancyZonesSettings::GetConfig(_Out_ PWSTR buffer, _Out_ in
settings.add_color_picker(NonLocalizable::ZoneHighlightColorID, IDS_SETTING_DESCRIPTION_ZONEHIGHLIGHTCOLOR, m_settings.zoneHighlightColor);
settings.add_color_picker(NonLocalizable::ZoneColorID, IDS_SETTING_DESCRIPTION_ZONECOLOR, m_settings.zoneColor);
settings.add_color_picker(NonLocalizable::ZoneBorderColorID, IDS_SETTING_DESCRIPTION_ZONE_BORDER_COLOR, m_settings.zoneBorderColor);
settings.add_int_spinner(NonLocalizable::ZoneHighlightOpacityID, IDS_SETTINGS_HIGHLIGHT_OPACITY, m_settings.zoneHighlightOpacity, 0, 100, 1);
settings.add_multiline_string(NonLocalizable::ExcludedAppsID, IDS_SETTING_EXCLUDED_APPS_DESCRIPTION, m_settings.excludedApps);
return settings.serialize_to_buffer(buffer, buffer_size);
@@ -235,4 +238,4 @@ CATCH_LOG();
winrt::com_ptr<IFancyZonesSettings> MakeFancyZonesSettings(HINSTANCE hinstance, PCWSTR name) noexcept
{
return winrt::make_self<FancyZonesSettings>(hinstance, name);
}
}

View File

@@ -22,6 +22,7 @@ struct Settings
bool zoneSetChange_moveWindows = false;
bool overrideSnapHotkeys = false;
bool moveWindowAcrossMonitors = false;
bool moveWindowsBasedOnPosition = false;
bool appLastZone_moveWindows = false;
bool openWindowOnActiveMonitor = false;
bool restoreSize = false;

View File

@@ -83,7 +83,8 @@ public:
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<int>& indexSet, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept;
bool MoveWindowIntoZoneByDirection(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow);
bool MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow);
bool MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow);
private:
void WarnIfElevationIsRequired(HWND window) noexcept;
@@ -169,9 +170,14 @@ void WindowMoveHandler::MoveWindowIntoZoneByIndexSet(HWND window, const std::vec
pimpl->MoveWindowIntoZoneByIndexSet(window, indexSet, zoneWindow);
}
bool WindowMoveHandler::MoveWindowIntoZoneByDirection(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)
{
return pimpl->MoveWindowIntoZoneByDirection(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)
{
return pimpl->MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, cycle, zoneWindow);
}
void WindowMoveHandlerPrivate::OnMouseDown() noexcept
@@ -389,9 +395,14 @@ void WindowMoveHandlerPrivate::MoveWindowIntoZoneByIndexSet(HWND window, const s
}
}
bool WindowMoveHandlerPrivate::MoveWindowIntoZoneByDirection(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)
{
return zoneWindow && zoneWindow->MoveWindowIntoZoneByDirection(window, vkCode, cycle);
return zoneWindow && zoneWindow->MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, cycle);
}
bool WindowMoveHandlerPrivate::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow)
{
return zoneWindow && zoneWindow->MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, cycle);
}
void WindowMoveHandlerPrivate::WarnIfElevationIsRequired(HWND window) noexcept

View File

@@ -24,7 +24,8 @@ public:
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<int>& indexSet, winrt::com_ptr<IZoneWindow> zoneWindow) noexcept;
bool MoveWindowIntoZoneByDirection(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow);
bool MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow);
bool MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow);
private:
class WindowMoveHandlerPrivate* pimpl;

View File

@@ -138,7 +138,9 @@ public:
IFACEMETHODIMP_(void)
MoveWindowIntoZoneByIndexSet(HWND window, HWND windowZone, const std::vector<int>& indexSet) noexcept;
IFACEMETHODIMP_(bool)
MoveWindowIntoZoneByDirection(HWND window, HWND zoneWindow, DWORD vkCode, bool cycle) noexcept;
MoveWindowIntoZoneByDirectionAndIndex(HWND window, HWND zoneWindow, DWORD vkCode, bool cycle) noexcept;
IFACEMETHODIMP_(bool)
MoveWindowIntoZoneByDirectionAndPosition(HWND window, HWND zoneWindow, DWORD vkCode, bool cycle) noexcept;
IFACEMETHODIMP_(void)
MoveWindowIntoZoneByPoint(HWND window, HWND zoneWindow, POINT ptClient) noexcept;
IFACEMETHODIMP_(bool)
@@ -315,7 +317,7 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND windowZone, const std::v
}
IFACEMETHODIMP_(bool)
ZoneSet::MoveWindowIntoZoneByDirection(HWND window, HWND windowZone, DWORD vkCode, bool cycle) noexcept
ZoneSet::MoveWindowIntoZoneByDirectionAndIndex(HWND window, HWND windowZone, DWORD vkCode, bool cycle) noexcept
{
if (m_zones.empty())
{
@@ -361,6 +363,65 @@ ZoneSet::MoveWindowIntoZoneByDirection(HWND window, HWND windowZone, DWORD vkCod
return true;
}
IFACEMETHODIMP_(bool)
ZoneSet::MoveWindowIntoZoneByDirectionAndPosition(HWND window, HWND windowZone, DWORD vkCode, bool cycle) noexcept
{
if (m_zones.empty())
{
return false;
}
auto zoneObjects = GetZones();
std::vector<bool> usedZoneIndices(zoneObjects.size(), false);
for (size_t idx : GetZoneIndexSetFromWindow(window))
{
usedZoneIndices[idx] = true;
}
std::vector<RECT> zoneRects;
std::vector<size_t> freeZoneIndices;
for (size_t i = 0; i < zoneObjects.size(); i++)
{
if (!usedZoneIndices[i])
{
zoneRects.emplace_back(zoneObjects[i]->GetZoneRect());
freeZoneIndices.emplace_back(i);
}
}
RECT windowRect, windowZoneRect;
if (GetWindowRect(window, &windowRect) && GetWindowRect(windowZone, &windowZoneRect))
{
// Move to coordinates relative to windowZone
windowRect.top -= windowZoneRect.top;
windowRect.bottom -= windowZoneRect.top;
windowRect.left -= windowZoneRect.left;
windowRect.right -= windowZoneRect.left;
size_t result = ChooseNextZoneByPosition(vkCode, windowRect, zoneRects);
if (result < zoneRects.size())
{
MoveWindowIntoZoneByIndex(window, windowZone, freeZoneIndices[result]);
return true;
}
else if (cycle)
{
// Try again from the position off the screen in the opposite direction to vkCode
windowRect = PrepareRectForCycling(windowRect, windowZoneRect, vkCode);
result = ChooseNextZoneByPosition(vkCode, windowRect, zoneRects);
if (result < zoneRects.size())
{
MoveWindowIntoZoneByIndex(window, windowZone, freeZoneIndices[result]);
return true;
}
}
}
return false;
}
IFACEMETHODIMP_(void)
ZoneSet::MoveWindowIntoZoneByPoint(HWND window, HWND zoneWindow, POINT ptClient) noexcept
{

View File

@@ -64,7 +64,8 @@ interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet :
*/
IFACEMETHOD_(void, MoveWindowIntoZoneByIndexSet)(HWND window, HWND zoneWindow, const std::vector<int>& indexSet) = 0;
/**
* Assign window to the zone based on direction (using WIN + LEFT/RIGHT arrow).
* Assign window to the zone based on direction (using WIN + LEFT/RIGHT arrow), based on zone index numbers,
* not 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
@@ -75,7 +76,21 @@ interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet :
* @returns Boolean which is always true if cycle argument is set, otherwise indicating if there is more
* zones left in the zone layout in which window can move.
*/
IFACEMETHOD_(bool, MoveWindowIntoZoneByDirection)(HWND window, HWND zoneWindow, DWORD vkCode, bool cycle) = 0;
IFACEMETHOD_(bool, MoveWindowIntoZoneByDirectionAndIndex)(HWND window, HWND zoneWindow, DWORD vkCode, bool cycle) = 0;
/**
* Assign window to the zone based on direction (using WIN + 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.
* @param cycle Whether we should move window to the first zone if we reached last zone in layout.
*
* @returns Boolean which is always true if cycle argument is set, otherwise indicating if there is more
* zones left in the zone layout in which window can move.
*/
IFACEMETHOD_(bool, MoveWindowIntoZoneByDirectionAndPosition)(HWND window, HWND zoneWindow, DWORD vkCode, bool cycle) = 0;
/**
* Assign window to the zone based on cursor coordinates.
*

View File

@@ -203,7 +203,9 @@ public:
IFACEMETHODIMP_(void)
MoveWindowIntoZoneByIndexSet(HWND window, const std::vector<int>& indexSet) noexcept;
IFACEMETHODIMP_(bool)
MoveWindowIntoZoneByDirection(HWND window, DWORD vkCode, bool cycle) noexcept;
MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle) noexcept;
IFACEMETHODIMP_(bool)
MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle) noexcept;
IFACEMETHODIMP_(void)
CycleActiveZoneSet(DWORD vkCode) noexcept;
IFACEMETHODIMP_(std::wstring)
@@ -457,11 +459,25 @@ ZoneWindow::MoveWindowIntoZoneByIndexSet(HWND window, const std::vector<int>& in
}
IFACEMETHODIMP_(bool)
ZoneWindow::MoveWindowIntoZoneByDirection(HWND window, DWORD vkCode, bool cycle) noexcept
ZoneWindow::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle) noexcept
{
if (m_activeZoneSet)
{
if (m_activeZoneSet->MoveWindowIntoZoneByDirection(window, m_window.get(), vkCode, cycle))
if (m_activeZoneSet->MoveWindowIntoZoneByDirectionAndIndex(window, m_window.get(), vkCode, cycle))
{
SaveWindowProcessToZoneIndex(window);
return true;
}
}
return false;
}
IFACEMETHODIMP_(bool)
ZoneWindow::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle) noexcept
{
if (m_activeZoneSet)
{
if (m_activeZoneSet->MoveWindowIntoZoneByDirectionAndPosition(window, m_window.get(), vkCode, cycle))
{
SaveWindowProcessToZoneIndex(window);
return true;

View File

@@ -58,7 +58,8 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IZoneWindow
*/
IFACEMETHOD_(void, MoveWindowIntoZoneByIndexSet)(HWND window, const std::vector<int>& indexSet) = 0;
/**
* Assign window to the zone based on direction (using WIN + LEFT/RIGHT arrow).
* Assign window to the zone based on direction (using WIN + LEFT/RIGHT arrow), based on zone index numbers,
* not their on-screen position.
*
* @param window Handle of window which should be assigned to zone.
* @param vkCode Pressed arrow key.
@@ -67,7 +68,19 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IZoneWindow
* @returns Boolean which is always true if cycle argument is set, otherwise indicating if there is more
* zones left in the zone layout in which window can move.
*/
IFACEMETHOD_(bool, MoveWindowIntoZoneByDirection)(HWND window, DWORD vkCode, bool cycle) = 0;
IFACEMETHOD_(bool, MoveWindowIntoZoneByDirectionAndIndex)(HWND window, DWORD vkCode, bool cycle) = 0;
/**
* Assign window to the zone based on direction (using WIN + 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.
* @param cycle Whether we should move window to the first zone if we reached last zone in layout.
*
* @returns Boolean which is always true if cycle argument is set, otherwise indicating if there is more
* zones left in the zone layout in which window can move.
*/
IFACEMETHOD_(bool, MoveWindowIntoZoneByDirectionAndPosition)(HWND window, DWORD vkCode, bool cycle) = 0;
/**
* Cycle through active zone layouts (giving hints about each layout).
*

View File

@@ -9,6 +9,7 @@ BEGIN
IDS_SETTING_DESCRIPTION_MOUSESWITCH "Use a non-primary mouse button to toggle zone activation"
IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS "Override Windows Snap hotkeys (Win + Arrow) to move windows between zones"
IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS "Move windows between zones across all monitors when snapping with (Win + Arrow)"
IDS_SETTING_DESCRIPTION_MOVE_WINDOWS_BASED_ON_POSITION "Move windows based on their position when snapping with (Win + Arrow)"
IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS "Keep windows in their zones when the screen resolution changes"
IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS "During zone layout changes, windows assigned to a zone will match new size/positions"
IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES "Flash zones when the active FancyZones layout changes"

View File

@@ -16,30 +16,31 @@
#define IDS_SETTING_DESCRIPTION_MOUSESWITCH 102
#define IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS 103
#define IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS 104
#define IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS 105
#define IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS 106
#define IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES 107
#define IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS 108
#define IDS_SETTING_DESCRIPTION_SPAN_ZONES_ACROSS_MONITORS 109
#define IDS_SETTING_DESCRIPTION_MAKE_DRAGGED_WINDOW_TRANSPARENT 110
#define IDS_SETTING_DESCRIPTION_ZONECOLOR 111
#define IDS_SETTING_DESCRIPTION_ZONE_BORDER_COLOR 112
#define IDS_SETTING_DESCRIPTION_ZONEHIGHLIGHTCOLOR 113
#define IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS 114
#define IDS_SETTING_DESCRIPTION_OPEN_WINDOW_ON_ACTIVE_MONITOR 115
#define IDS_SETTING_DESCRIPTION_RESTORESIZE 116
#define IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN 117
#define IDS_SETTING_DESCRIPTION 118
#define IDS_SETTING_LAUNCH_EDITOR_LABEL 119
#define IDS_SETTING_LAUNCH_EDITOR_BUTTON 120
#define IDS_SETTING_LAUNCH_EDITOR_DESCRIPTION 121
#define IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL 122
#define IDS_SETTING_EXCLUDED_APPS_DESCRIPTION 123
#define IDS_SETTINGS_HIGHLIGHT_OPACITY 124
#define IDS_FANCYZONES 125
#define IDS_CANT_DRAG_ELEVATED 126
#define IDS_CANT_DRAG_ELEVATED_LEARN_MORE 127
#define IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN 128
#define IDS_KEYBOARD_LISTENER_ERROR 129
#define IDS_WINDOW_EVENT_LISTENER_ERROR 130
#define IDS_POWERTOYS_FANCYZONES 131
#define IDS_SETTING_DESCRIPTION_MOVE_WINDOWS_BASED_ON_POSITION 105
#define IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS 106
#define IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS 107
#define IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES 108
#define IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS 109
#define IDS_SETTING_DESCRIPTION_SPAN_ZONES_ACROSS_MONITORS 110
#define IDS_SETTING_DESCRIPTION_MAKE_DRAGGED_WINDOW_TRANSPARENT 111
#define IDS_SETTING_DESCRIPTION_ZONECOLOR 112
#define IDS_SETTING_DESCRIPTION_ZONE_BORDER_COLOR 113
#define IDS_SETTING_DESCRIPTION_ZONEHIGHLIGHTCOLOR 114
#define IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS 115
#define IDS_SETTING_DESCRIPTION_OPEN_WINDOW_ON_ACTIVE_MONITOR 116
#define IDS_SETTING_DESCRIPTION_RESTORESIZE 117
#define IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN 118
#define IDS_SETTING_DESCRIPTION 119
#define IDS_SETTING_LAUNCH_EDITOR_LABEL 120
#define IDS_SETTING_LAUNCH_EDITOR_BUTTON 121
#define IDS_SETTING_LAUNCH_EDITOR_DESCRIPTION 122
#define IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL 123
#define IDS_SETTING_EXCLUDED_APPS_DESCRIPTION 124
#define IDS_SETTINGS_HIGHLIGHT_OPACITY 125
#define IDS_FANCYZONES 126
#define IDS_CANT_DRAG_ELEVATED 127
#define IDS_CANT_DRAG_ELEVATED_LEARN_MORE 128
#define IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN 129
#define IDS_KEYBOARD_LISTENER_ERROR 130
#define IDS_WINDOW_EVENT_LISTENER_ERROR 131
#define IDS_POWERTOYS_FANCYZONES 132

View File

@@ -36,6 +36,7 @@
#define MoveWindowsOnZoneSetChangeKey "MoveWindowsOnZoneSetChange"
#define OverrideSnapHotKeysKey "OverrideSnapHotKeys"
#define MoveWindowAcrossMonitorsKey "MoveWindowAcrossMonitors"
#define MoveWindowsBasedOnPositionKey "MoveWindowsBasedOnPosition"
#define MoveWindowsToLastZoneOnAppOpeningKey "MoveWindowsToLastZoneOnAppOpening"
#define OpenWindowOnActiveMonitorKey "OpenWindowOnActiveMonitor"
#define RestoreSizeKey "RestoreSize"
@@ -215,13 +216,13 @@ void Trace::FancyZones::EditorLaunched(int value) noexcept
void Trace::SettingsChanged(const Settings& settings) noexcept
{
const auto& editorHotkey = settings.editorHotkey;
std::wstring hotkeyStr = L"alt:" + std::to_wstring(editorHotkey.alt_pressed())
+ L", ctrl:" + std::to_wstring(editorHotkey.ctrl_pressed())
+ L", shift:" + std::to_wstring(editorHotkey.shift_pressed())
+ L", win:" + std::to_wstring(editorHotkey.win_pressed())
+ L", code:" + std::to_wstring(editorHotkey.get_code())
std::wstring hotkeyStr = L"alt:" + std::to_wstring(editorHotkey.alt_pressed())
+ L", ctrl:" + std::to_wstring(editorHotkey.ctrl_pressed())
+ L", shift:" + std::to_wstring(editorHotkey.shift_pressed())
+ L", win:" + std::to_wstring(editorHotkey.win_pressed())
+ L", code:" + std::to_wstring(editorHotkey.get_code())
+ L", keyFromCode:" + editorHotkey.get_key();
TraceLoggingWrite(
g_hProvider,
EventSettingsChangedKey,
@@ -234,6 +235,7 @@ void Trace::SettingsChanged(const Settings& settings) noexcept
TraceLoggingBoolean(settings.zoneSetChange_moveWindows, MoveWindowsOnZoneSetChangeKey),
TraceLoggingBoolean(settings.overrideSnapHotkeys, OverrideSnapHotKeysKey),
TraceLoggingBoolean(settings.moveWindowAcrossMonitors, MoveWindowAcrossMonitorsKey),
TraceLoggingBoolean(settings.moveWindowsBasedOnPosition, MoveWindowsBasedOnPositionKey),
TraceLoggingBoolean(settings.appLastZone_moveWindows, MoveWindowsToLastZoneOnAppOpeningKey),
TraceLoggingBoolean(settings.openWindowOnActiveMonitor, OpenWindowOnActiveMonitorKey),
TraceLoggingBoolean(settings.restoreSize, RestoreSizeKey),

View File

@@ -6,6 +6,7 @@
#include <common/dpi_aware.h>
#include <sstream>
#include <complex>
// Non-Localizable strings
namespace NonLocalizable
@@ -348,3 +349,126 @@ bool IsValidDeviceId(const std::wstring& str)
return true;
}
size_t ChooseNextZoneByPosition(DWORD vkCode, RECT windowRect, const std::vector<RECT>& zoneRects) noexcept
{
using complex = std::complex<double>;
const size_t invalidResult = zoneRects.size();
const double inf = 1e100;
const double eccentricity = 2.0;
auto rectCenter = [](RECT rect) {
return complex {
0.5 * rect.left + 0.5 * rect.right,
0.5 * rect.top + 0.5 * rect.bottom
};
};
auto distance = [&](complex arrowDirection, complex zoneDirection) {
double result = inf;
try
{
double scalarProduct = (arrowDirection * conj(zoneDirection)).real();
if (scalarProduct <= 0.0)
{
return inf;
}
// no need to divide by abs(arrowDirection) because it's = 1
double cosAngle = scalarProduct / abs(zoneDirection);
double tanAngle = abs(tan(acos(cosAngle)));
if (tanAngle > 10)
{
// The angle is too wide
return inf;
}
// find the intersection with the ellipse with given eccentricity and major axis along arrowDirection
double intersectY = 2 * eccentricity / (1.0 + eccentricity * eccentricity * tanAngle * tanAngle);
double distanceEstimate = scalarProduct / intersectY;
if (std::isfinite(distanceEstimate))
{
result = distanceEstimate;
}
}
catch (...)
{
}
return result;
};
std::vector<std::pair<size_t, complex>> candidateCenters;
for (size_t i = 0; i < zoneRects.size(); i++)
{
auto center = rectCenter(zoneRects[i]);
// Offset the zone slightly, to differentiate in case there are overlapping zones
center += 0.001 * (i + 1);
candidateCenters.emplace_back(i, center);
}
complex directionVector, windowCenter = rectCenter(windowRect);
switch (vkCode)
{
case VK_UP:
directionVector = { 0.0, -1.0 };
break;
case VK_DOWN:
directionVector = { 0.0, 1.0 };
break;
case VK_LEFT:
directionVector = { -1.0, 0.0 };
break;
case VK_RIGHT:
directionVector = { 1.0, 0.0 };
break;
default:
return invalidResult;
}
size_t closestIdx = invalidResult;
double smallestDistance = inf;
for (auto [zoneIdx, zoneCenter] : candidateCenters)
{
double dist = distance(directionVector, zoneCenter - windowCenter);
if (dist < smallestDistance)
{
smallestDistance = dist;
closestIdx = zoneIdx;
}
}
return closestIdx;
}
RECT PrepareRectForCycling(RECT windowRect, RECT zoneWindowRect, DWORD vkCode) noexcept
{
LONG deltaX = 0, deltaY = 0;
switch (vkCode)
{
case VK_UP:
deltaY = zoneWindowRect.bottom - zoneWindowRect.top;
break;
case VK_DOWN:
deltaY = zoneWindowRect.top - zoneWindowRect.bottom;
break;
case VK_LEFT:
deltaX = zoneWindowRect.right - zoneWindowRect.left;
break;
case VK_RIGHT:
deltaX = zoneWindowRect.left - zoneWindowRect.right;
}
windowRect.left += deltaX;
windowRect.right += deltaX;
windowRect.top += deltaY;
windowRect.bottom += deltaY;
return windowRect;
}

View File

@@ -177,3 +177,5 @@ void RestoreWindowOrigin(HWND window) noexcept;
bool IsValidGuid(const std::wstring& str);
bool IsValidDeviceId(const std::wstring& str);
size_t ChooseNextZoneByPosition(DWORD vkCode, RECT windowRect, const std::vector<RECT>& zoneRects) noexcept;
RECT PrepareRectForCycling(RECT windowRect, RECT zoneWindowRect, DWORD vkCode) noexcept;

View File

@@ -70,6 +70,7 @@ namespace FancyZonesUnitTests
ptSettings.add_bool_toggle(L"fancyzones_mouseSwitch", IDS_SETTING_DESCRIPTION_MOUSESWITCH, settings.mouseSwitch);
ptSettings.add_bool_toggle(L"fancyzones_overrideSnapHotkeys", IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS, settings.overrideSnapHotkeys);
ptSettings.add_bool_toggle(L"fancyzones_moveWindowAcrossMonitors", IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS, settings.moveWindowAcrossMonitors);
ptSettings.add_bool_toggle(L"fancyzones_moveWindowsBasedOnPosition", IDS_SETTING_DESCRIPTION_MOVE_WINDOWS_BASED_ON_POSITION, settings.moveWindowsBasedOnPosition);
ptSettings.add_bool_toggle(L"fancyzones_zoneSetChange_flashZones", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES, settings.zoneSetChange_flashZones);
ptSettings.add_bool_toggle(L"fancyzones_displayChange_moveWindows", IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS, settings.displayChange_moveWindows);
ptSettings.add_bool_toggle(L"fancyzones_zoneSetChange_moveWindows", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS, settings.zoneSetChange_moveWindows);
@@ -120,6 +121,7 @@ namespace FancyZonesUnitTests
.zoneSetChange_moveWindows = true,
.overrideSnapHotkeys = false,
.moveWindowAcrossMonitors = false,
.moveWindowsBasedOnPosition = false,
.appLastZone_moveWindows = true,
.restoreSize = false,
.use_cursorpos_editor_startupscreen = true,
@@ -151,6 +153,7 @@ namespace FancyZonesUnitTests
.zoneSetChange_moveWindows = true,
.overrideSnapHotkeys = false,
.moveWindowAcrossMonitors = false,
.moveWindowsBasedOnPosition = false,
.appLastZone_moveWindows = true,
.restoreSize = false,
.use_cursorpos_editor_startupscreen = true,
@@ -182,6 +185,7 @@ namespace FancyZonesUnitTests
.zoneSetChange_moveWindows = true,
.overrideSnapHotkeys = false,
.moveWindowAcrossMonitors = false,
.moveWindowsBasedOnPosition = false,
.appLastZone_moveWindows = true,
.restoreSize = false,
.use_cursorpos_editor_startupscreen = true,
@@ -215,6 +219,7 @@ namespace FancyZonesUnitTests
.zoneSetChange_moveWindows = true,
.overrideSnapHotkeys = false,
.moveWindowAcrossMonitors = false,
.moveWindowsBasedOnPosition = false,
.appLastZone_moveWindows = true,
.restoreSize = false,
.use_cursorpos_editor_startupscreen = true,
@@ -248,6 +253,7 @@ namespace FancyZonesUnitTests
.zoneSetChange_moveWindows = true,
.overrideSnapHotkeys = false,
.moveWindowAcrossMonitors = false,
.moveWindowsBasedOnPosition = false,
.appLastZone_moveWindows = true,
.restoreSize = false,
.use_cursorpos_editor_startupscreen = true,
@@ -288,6 +294,7 @@ namespace FancyZonesUnitTests
ptSettings.add_bool_toggle(L"fancyzones_mouseSwitch", IDS_SETTING_DESCRIPTION_MOUSESWITCH, settings.mouseSwitch);
ptSettings.add_bool_toggle(L"fancyzones_overrideSnapHotkeys", IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS, settings.overrideSnapHotkeys);
ptSettings.add_bool_toggle(L"fancyzones_moveWindowAcrossMonitors", IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS, settings.moveWindowAcrossMonitors);
ptSettings.add_bool_toggle(L"fancyzones_moveWindowsBasedOnPosition", IDS_SETTING_DESCRIPTION_MOVE_WINDOWS_BASED_ON_POSITION, settings.moveWindowsBasedOnPosition);
ptSettings.add_bool_toggle(L"fancyzones_zoneSetChange_flashZones", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES, settings.zoneSetChange_flashZones);
ptSettings.add_bool_toggle(L"fancyzones_displayChange_moveWindows", IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS, settings.displayChange_moveWindows);
ptSettings.add_bool_toggle(L"fancyzones_zoneSetChange_moveWindows", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS, settings.zoneSetChange_moveWindows);

View File

@@ -33,6 +33,7 @@ namespace FancyZonesUnitTests
Assert::AreEqual(expected.zoneSetChange_moveWindows, actual.zoneSetChange_moveWindows);
Assert::AreEqual(expected.overrideSnapHotkeys, actual.overrideSnapHotkeys);
Assert::AreEqual(expected.moveWindowAcrossMonitors, actual.moveWindowAcrossMonitors);
Assert::AreEqual(expected.moveWindowsBasedOnPosition, actual.moveWindowsBasedOnPosition);
Assert::AreEqual(expected.appLastZone_moveWindows, actual.appLastZone_moveWindows);
Assert::AreEqual(expected.openWindowOnActiveMonitor, actual.openWindowOnActiveMonitor);
Assert::AreEqual(expected.restoreSize, actual.restoreSize);
@@ -113,6 +114,7 @@ namespace FancyZonesUnitTests
values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows);
values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys);
values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors);
values.add_property(L"fancyzones_moveWindowsBasedOnPosition", expected.moveWindowsBasedOnPosition);
values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows);
values.add_property(L"fancyzones_openWindowOnActiveMonitor", expected.openWindowOnActiveMonitor);
values.add_property(L"fancyzones_restoreSize", expected.restoreSize);
@@ -152,6 +154,7 @@ namespace FancyZonesUnitTests
values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows);
values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys);
values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors);
values.add_property(L"fancyzones_moveWindowsBasedOnPosition", expected.moveWindowsBasedOnPosition);
values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows);
values.add_property(L"fancyzones_openWindowOnActiveMonitor", expected.openWindowOnActiveMonitor);
values.add_property(L"fancyzones_restoreSize", expected.restoreSize);
@@ -185,6 +188,7 @@ namespace FancyZonesUnitTests
.zoneSetChange_moveWindows = m_defaultSettings.zoneSetChange_moveWindows,
.overrideSnapHotkeys = m_defaultSettings.overrideSnapHotkeys,
.moveWindowAcrossMonitors = m_defaultSettings.moveWindowAcrossMonitors,
.moveWindowsBasedOnPosition = m_defaultSettings.moveWindowsBasedOnPosition,
.appLastZone_moveWindows = m_defaultSettings.appLastZone_moveWindows,
.openWindowOnActiveMonitor = m_defaultSettings.openWindowOnActiveMonitor,
.restoreSize = m_defaultSettings.restoreSize,
@@ -231,6 +235,7 @@ namespace FancyZonesUnitTests
values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows);
values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys);
values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors);
values.add_property(L"fancyzones_moveWindowsBasedOnPosition", expected.moveWindowsBasedOnPosition);
values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows);
values.add_property(L"fancyzones_openWindowOnActiveMonitor", expected.openWindowOnActiveMonitor);
values.add_property(L"fancyzones_restoreSize", expected.restoreSize);
@@ -264,6 +269,7 @@ namespace FancyZonesUnitTests
values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows);
values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys);
values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors);
values.add_property(L"fancyzones_moveWindowsBasedOnPosition", expected.moveWindowsBasedOnPosition);
values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows);
values.add_property(L"fancyzones_openWindowOnActiveMonitor", expected.openWindowOnActiveMonitor);
values.add_property(L"fancyzones_restoreSize", expected.restoreSize);
@@ -298,6 +304,7 @@ namespace FancyZonesUnitTests
values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows);
values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys);
values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors);
values.add_property(L"fancyzones_moveWindowsBasedOnPosition", expected.moveWindowsBasedOnPosition);
values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows);
values.add_property(L"fancyzones_openWindowOnActiveMonitor", expected.openWindowOnActiveMonitor);
values.add_property(L"fancyzones_restoreSize", expected.restoreSize);
@@ -333,6 +340,7 @@ namespace FancyZonesUnitTests
values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows);
values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys);
values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors);
values.add_property(L"fancyzones_moveWindowsBasedOnPosition", expected.moveWindowsBasedOnPosition);
values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows);
values.add_property(L"fancyzones_openWindowOnActiveMonitor", expected.openWindowOnActiveMonitor);
values.add_property(L"fancyzones_restoreSize", expected.restoreSize);
@@ -449,6 +457,7 @@ namespace FancyZonesUnitTests
.zoneSetChange_moveWindows = true,
.overrideSnapHotkeys = false,
.moveWindowAcrossMonitors = false,
.moveWindowsBasedOnPosition = false,
.appLastZone_moveWindows = false,
.openWindowOnActiveMonitor = false,
.restoreSize = false,
@@ -473,6 +482,7 @@ namespace FancyZonesUnitTests
values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows);
values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys);
values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors);
values.add_property(L"fancyzones_moveWindowsBasedOnPosition", expected.moveWindowsBasedOnPosition);
values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows);
values.add_property(L"fancyzones_openWindowOnActiveMonitor", expected.openWindowOnActiveMonitor);
values.add_property(L"fancyzones_restoreSize", expected.restoreSize);
@@ -588,6 +598,7 @@ namespace FancyZonesUnitTests
ptSettings.add_bool_toggle(L"fancyzones_mouseSwitch", IDS_SETTING_DESCRIPTION_MOUSESWITCH, settings.mouseSwitch);
ptSettings.add_bool_toggle(L"fancyzones_overrideSnapHotkeys", IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS, settings.overrideSnapHotkeys);
ptSettings.add_bool_toggle(L"fancyzones_moveWindowAcrossMonitors", IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS, settings.moveWindowAcrossMonitors);
ptSettings.add_bool_toggle(L"fancyzones_moveWindowsBasedOnPosition", IDS_SETTING_DESCRIPTION_MOVE_WINDOWS_BASED_ON_POSITION, settings.moveWindowsBasedOnPosition);
ptSettings.add_bool_toggle(L"fancyzones_zoneSetChange_flashZones", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES, settings.zoneSetChange_flashZones);
ptSettings.add_bool_toggle(L"fancyzones_displayChange_moveWindows", IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS, settings.displayChange_moveWindows);
ptSettings.add_bool_toggle(L"fancyzones_zoneSetChange_moveWindows", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS, settings.zoneSetChange_moveWindows);
@@ -625,7 +636,7 @@ namespace FancyZonesUnitTests
int expectedSize = 0;
m_settings->GetConfig(nullptr, &expectedSize);
Assert::AreNotEqual(0, expectedSize);
int actualBufferSize = expectedSize;
PWSTR actualBuffer = new wchar_t[actualBufferSize];
@@ -641,7 +652,7 @@ namespace FancyZonesUnitTests
int actualBufferSize = size - 1;
PWSTR actualBuffer = new wchar_t[actualBufferSize];
Assert::IsFalse(m_settings->GetConfig(actualBuffer, &actualBufferSize));
Assert::AreEqual(size, actualBufferSize);
}

View File

@@ -481,7 +481,7 @@ namespace FancyZonesUnitTests
}
};
// MoveWindowIntoZoneByDirection is complicated enough to warrant it's own test class
// MoveWindowIntoZoneByDirectionAndIndex is complicated enough to warrant it's own test class
TEST_CLASS (ZoneSetsMoveWindowIntoZoneByDirectionUnitTests)
{
winrt::com_ptr<IZoneSet> m_set;
@@ -508,7 +508,7 @@ namespace FancyZonesUnitTests
ZoneSetConfig config({}, ZoneSetLayoutType::Custom, Mocks::Monitor());
auto set = MakeZoneSet(config);
set->MoveWindowIntoZoneByDirection(Mocks::Window(), Mocks::Window(), VK_LEFT, true);
set->MoveWindowIntoZoneByDirectionAndIndex(Mocks::Window(), Mocks::Window(), VK_LEFT, true);
}
TEST_METHOD (EmptyZonesRight)
@@ -516,36 +516,36 @@ namespace FancyZonesUnitTests
ZoneSetConfig config({}, ZoneSetLayoutType::Custom, Mocks::Monitor());
auto set = MakeZoneSet(config);
set->MoveWindowIntoZoneByDirection(Mocks::Window(), Mocks::Window(), VK_RIGHT, true);
set->MoveWindowIntoZoneByDirectionAndIndex(Mocks::Window(), Mocks::Window(), VK_RIGHT, true);
}
TEST_METHOD (MoveRightNoZones)
{
HWND window = Mocks::Window();
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_RIGHT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_RIGHT, true);
Assert::AreEqual({ 0 }, m_set->GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (MoveLeftNoZones)
{
HWND window = Mocks::Window();
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_LEFT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_LEFT, true);
Assert::AreEqual({ 2 }, m_set->GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (MoveRightTwice)
{
HWND window = Mocks::Window();
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_RIGHT, true);
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_RIGHT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_RIGHT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_RIGHT, true);
Assert::AreEqual({ 1 }, m_set->GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (MoveLeftTwice)
{
HWND window = Mocks::Window();
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_LEFT, true);
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_LEFT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_LEFT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_LEFT, true);
Assert::AreEqual({ 1 }, m_set->GetZoneIndexSetFromWindow(window));
}
@@ -554,7 +554,7 @@ namespace FancyZonesUnitTests
HWND window = Mocks::Window();
for (int i = 0; i <= m_set->GetZones().size(); i++)
{
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_RIGHT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_RIGHT, true);
}
Assert::AreEqual({ 0 }, m_set->GetZoneIndexSetFromWindow(window));
@@ -565,7 +565,7 @@ namespace FancyZonesUnitTests
HWND window = Mocks::Window();
for (int i = 0; i <= m_set->GetZones().size(); i++)
{
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_LEFT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_LEFT, true);
}
Assert::AreEqual({ 2 }, m_set->GetZoneIndexSetFromWindow(window));
@@ -575,10 +575,10 @@ namespace FancyZonesUnitTests
{
HWND window = Mocks::Window();
m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 0);
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_RIGHT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_RIGHT, true);
Assert::AreEqual({ 1 }, m_set->GetZoneIndexSetFromWindow(window));
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_RIGHT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_RIGHT, true);
Assert::AreEqual({ 2 }, m_set->GetZoneIndexSetFromWindow(window));
}
@@ -589,10 +589,10 @@ namespace FancyZonesUnitTests
Assert::AreEqual({ 0, 1 }, m_set->GetZoneIndexSetFromWindow(window));
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_RIGHT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_RIGHT, true);
Assert::AreEqual({ 1 }, m_set->GetZoneIndexSetFromWindow(window));
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_RIGHT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_RIGHT, true);
Assert::AreEqual({ 2 }, m_set->GetZoneIndexSetFromWindow(window));
}
@@ -606,12 +606,12 @@ namespace FancyZonesUnitTests
Assert::AreEqual({ 0 }, m_set->GetZoneIndexSetFromWindow(window1));
Assert::AreEqual({ 1 }, m_set->GetZoneIndexSetFromWindow(window2));
m_set->MoveWindowIntoZoneByDirection(window1, Mocks::Window(), VK_RIGHT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window1, Mocks::Window(), VK_RIGHT, true);
Assert::AreEqual({ 1 }, m_set->GetZoneIndexSetFromWindow(window1));
Assert::AreEqual({ 1 }, m_set->GetZoneIndexSetFromWindow(window2));
m_set->MoveWindowIntoZoneByDirection(window1, Mocks::Window(), VK_RIGHT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window1, Mocks::Window(), VK_RIGHT, true);
Assert::AreEqual({ 2 }, m_set->GetZoneIndexSetFromWindow(window1));
Assert::AreEqual({ 1 }, m_set->GetZoneIndexSetFromWindow(window2));
@@ -621,10 +621,10 @@ namespace FancyZonesUnitTests
{
HWND window = Mocks::Window();
m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 2);
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_LEFT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_LEFT, true);
Assert::AreEqual({ 1 }, m_set->GetZoneIndexSetFromWindow(window));
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_LEFT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_LEFT, true);
Assert::AreEqual({ 0 }, m_set->GetZoneIndexSetFromWindow(window));
}
@@ -635,10 +635,10 @@ namespace FancyZonesUnitTests
Assert::AreEqual({ 1, 2 }, m_set->GetZoneIndexSetFromWindow(window));
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_LEFT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_LEFT, true);
Assert::AreEqual({ 0 }, m_set->GetZoneIndexSetFromWindow(window));
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_LEFT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_LEFT, true);
Assert::AreEqual({ 2 }, m_set->GetZoneIndexSetFromWindow(window));
}
@@ -652,11 +652,11 @@ namespace FancyZonesUnitTests
Assert::AreEqual({ 1 }, m_set->GetZoneIndexSetFromWindow(window1));
Assert::AreEqual({ 2 }, m_set->GetZoneIndexSetFromWindow(window2));
m_set->MoveWindowIntoZoneByDirection(window2, Mocks::Window(), VK_LEFT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window2, Mocks::Window(), VK_LEFT, true);
Assert::AreEqual({ 1 }, m_set->GetZoneIndexSetFromWindow(window1));
Assert::AreEqual({ 1 }, m_set->GetZoneIndexSetFromWindow(window2));
m_set->MoveWindowIntoZoneByDirection(window2, Mocks::Window(), VK_LEFT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window2, Mocks::Window(), VK_LEFT, true);
Assert::AreEqual({ 1 }, m_set->GetZoneIndexSetFromWindow(window1));
Assert::AreEqual({ 0 }, m_set->GetZoneIndexSetFromWindow(window2));
}
@@ -665,7 +665,7 @@ namespace FancyZonesUnitTests
{
HWND window = Mocks::Window();
m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 2);
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_RIGHT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_RIGHT, true);
Assert::AreEqual({ 0 }, m_set->GetZoneIndexSetFromWindow(window));
}
@@ -673,7 +673,7 @@ namespace FancyZonesUnitTests
{
HWND window = Mocks::Window();
m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 0);
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_LEFT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_LEFT, true);
Assert::AreEqual({ 2 }, m_set->GetZoneIndexSetFromWindow(window));
}
@@ -683,7 +683,7 @@ namespace FancyZonesUnitTests
m_set->MoveWindowIntoZoneByIndex(window1, Mocks::Window(), 0);
HWND window2 = Mocks::Window();
m_set->MoveWindowIntoZoneByDirection(window2, Mocks::Window(), VK_RIGHT, true);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window2, Mocks::Window(), VK_RIGHT, true);
Assert::AreEqual({ 0 }, m_set->GetZoneIndexSetFromWindow(window1));
Assert::AreEqual({ 0 }, m_set->GetZoneIndexSetFromWindow(window2));
@@ -695,9 +695,9 @@ namespace FancyZonesUnitTests
m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 0);
for (size_t i = 0; i < m_set->GetZones().size() - 1; ++i)
{
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_RIGHT, false);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_RIGHT, false);
}
bool moreZonesInLayout = m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_RIGHT, false);
bool moreZonesInLayout = m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_RIGHT, false);
Assert::IsFalse(moreZonesInLayout);
}
@@ -707,9 +707,9 @@ namespace FancyZonesUnitTests
m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 2);
for (size_t i = 0; i < m_set->GetZones().size() - 1; ++i)
{
m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_LEFT, false);
m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_LEFT, false);
}
bool moreZonesInLayout = m_set->MoveWindowIntoZoneByDirection(window, Mocks::Window(), VK_LEFT, false);
bool moreZonesInLayout = m_set->MoveWindowIntoZoneByDirectionAndIndex(window, Mocks::Window(), VK_LEFT, false);
Assert::IsFalse(moreZonesInLayout);
}
};

View File

@@ -527,7 +527,7 @@ namespace FancyZonesUnitTests
{
PrepareFZData();
auto zoneWindow = MakeZoneWindow(winrt::make_self<MockZoneWindowHost>().get(), m_hInst, m_monitor, m_uniqueId.str(), {}, false);
const auto window = Mocks::Window();
zoneWindow->MoveSizeEnter(window);
@@ -626,14 +626,14 @@ namespace FancyZonesUnitTests
zoneWindow->MoveWindowIntoZoneByIndex(Mocks::Window(), 0);
}
TEST_METHOD(MoveWindowIntoZoneByDirection)
TEST_METHOD(MoveWindowIntoZoneByDirectionAndIndex)
{
PrepareFZData();
auto zoneWindow = MakeZoneWindow(winrt::make_self<MockZoneWindowHost>().get(), m_hInst, m_monitor, m_uniqueId.str(), {}, false);
Assert::IsNotNull(zoneWindow->ActiveZoneSet());
const auto window = Mocks::WindowCreate(m_hInst);
zoneWindow->MoveWindowIntoZoneByDirection(window, VK_RIGHT, true);
zoneWindow->MoveWindowIntoZoneByDirectionAndIndex(window, VK_RIGHT, true);
const auto& actualAppZoneHistory = m_fancyZonesData.GetAppZoneHistoryMap();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
@@ -649,9 +649,9 @@ namespace FancyZonesUnitTests
Assert::IsNotNull(zoneWindow->ActiveZoneSet());
const auto window = Mocks::WindowCreate(m_hInst);
zoneWindow->MoveWindowIntoZoneByDirection(window, VK_RIGHT, true);
zoneWindow->MoveWindowIntoZoneByDirection(window, VK_RIGHT, true);
zoneWindow->MoveWindowIntoZoneByDirection(window, VK_RIGHT, true);
zoneWindow->MoveWindowIntoZoneByDirectionAndIndex(window, VK_RIGHT, true);
zoneWindow->MoveWindowIntoZoneByDirectionAndIndex(window, VK_RIGHT, true);
zoneWindow->MoveWindowIntoZoneByDirectionAndIndex(window, VK_RIGHT, true);
const auto& actualAppZoneHistory = m_fancyZonesData.GetAppZoneHistoryMap();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
@@ -776,7 +776,7 @@ namespace FancyZonesUnitTests
auto zone = MakeZone(RECT{ 50, 50, 300, 300 });
zoneWindow->ActiveZoneSet()->AddZone(zone);
zoneWindow->MoveWindowIntoZoneByDirection(window, VK_LEFT, true);
zoneWindow->MoveWindowIntoZoneByDirectionAndIndex(window, VK_LEFT, true);
RECT inZoneRect;
GetWindowRect(window, &inZoneRect);

View File

@@ -308,14 +308,15 @@ namespace PowerToysTests
Assert.AreNotEqual(toggleValues[1], GetPropertyValue<bool>(savedProps, "fancyzones_mouseSwitch"));
Assert.AreNotEqual(toggleValues[2], GetPropertyValue<bool>(savedProps, "fancyzones_overrideSnapHotkeys"));
Assert.AreNotEqual(toggleValues[3], GetPropertyValue<bool>(savedProps, "fancyzones_moveWindowAcrossMonitors"));
Assert.AreNotEqual(toggleValues[4], GetPropertyValue<bool>(savedProps, "fancyzones_displayChange_moveWindows"));
Assert.AreNotEqual(toggleValues[5], GetPropertyValue<bool>(savedProps, "fancyzones_zoneSetChange_moveWindows"));
Assert.AreNotEqual(toggleValues[6], GetPropertyValue<bool>(savedProps, "fancyzones_appLastZone_moveWindows"));
Assert.AreNotEqual(toggleValues[7], GetPropertyValue<bool>(savedProps, "fancyzones_restoreSize"));
Assert.AreNotEqual(toggleValues[8], GetPropertyValue<bool>(savedProps, "use_cursorpos_editor_startupscreen"));
Assert.AreNotEqual(toggleValues[9], GetPropertyValue<bool>(savedProps, "fancyzones_show_on_all_monitors"));
Assert.AreNotEqual(toggleValues[10], GetPropertyValue<bool>(savedProps, "fancyzones_multi_monitor_mode"));
Assert.AreNotEqual(toggleValues[11], GetPropertyValue<bool>(savedProps, "fancyzones_makeDraggedWindowTransparent"));
Assert.AreNotEqual(toggleValues[4], GetPropertyValue<bool>(savedProps, "fancyzones_moveWindowsBasedOnPosition"));
Assert.AreNotEqual(toggleValues[5], GetPropertyValue<bool>(savedProps, "fancyzones_displayChange_moveWindows"));
Assert.AreNotEqual(toggleValues[6], GetPropertyValue<bool>(savedProps, "fancyzones_zoneSetChange_moveWindows"));
Assert.AreNotEqual(toggleValues[7], GetPropertyValue<bool>(savedProps, "fancyzones_appLastZone_moveWindows"));
Assert.AreNotEqual(toggleValues[8], GetPropertyValue<bool>(savedProps, "fancyzones_restoreSize"));
Assert.AreNotEqual(toggleValues[9], GetPropertyValue<bool>(savedProps, "use_cursorpos_editor_startupscreen"));
Assert.AreNotEqual(toggleValues[10], GetPropertyValue<bool>(savedProps, "fancyzones_show_on_all_monitors"));
Assert.AreNotEqual(toggleValues[11], GetPropertyValue<bool>(savedProps, "fancyzones_multi_monitor_mode"));
Assert.AreNotEqual(toggleValues[12], GetPropertyValue<bool>(savedProps, "fancyzones_makeDraggedWindowTransparent"));
}
/*
@@ -349,14 +350,15 @@ namespace PowerToysTests
Assert.AreEqual(toggleValues[1], GetPropertyValue<bool>(savedProps, "fancyzones_mouseSwitch"));
Assert.AreEqual(toggleValues[2], GetPropertyValue<bool>(savedProps, "fancyzones_overrideSnapHotkeys"));
Assert.AreEqual(toggleValues[3], GetPropertyValue<bool>(savedProps, "fancyzones_moveWindowAcrossMonitors"));
Assert.AreEqual(toggleValues[4], GetPropertyValue<bool>(savedProps, "fancyzones_displayChange_moveWindows"));
Assert.AreEqual(toggleValues[5], GetPropertyValue<bool>(savedProps, "fancyzones_zoneSetChange_moveWindows"));
Assert.AreEqual(toggleValues[6], GetPropertyValue<bool>(savedProps, "fancyzones_appLastZone_moveWindows"));
Assert.AreEqual(toggleValues[7], GetPropertyValue<bool>(savedProps, "fancyzones_restoreSize"));
Assert.AreEqual(toggleValues[8], GetPropertyValue<bool>(savedProps, "use_cursorpos_editor_startupscreen"));
Assert.AreEqual(toggleValues[9], GetPropertyValue<bool>(savedProps, "fancyzones_show_on_all_monitors"));
Assert.AreEqual(toggleValues[10], GetPropertyValue<bool>(savedProps, "fancyzones_span_zones_across_monitors"));
Assert.AreEqual(toggleValues[11], GetPropertyValue<bool>(savedProps, "fancyzones_makeDraggedWindowTransparent"));
Assert.AreEqual(toggleValues[4], GetPropertyValue<bool>(savedProps, "fancyzones_moveWindowsBasedOnPosition"));
Assert.AreEqual(toggleValues[5], GetPropertyValue<bool>(savedProps, "fancyzones_displayChange_moveWindows"));
Assert.AreEqual(toggleValues[6], GetPropertyValue<bool>(savedProps, "fancyzones_zoneSetChange_moveWindows"));
Assert.AreEqual(toggleValues[7], GetPropertyValue<bool>(savedProps, "fancyzones_appLastZone_moveWindows"));
Assert.AreEqual(toggleValues[8], GetPropertyValue<bool>(savedProps, "fancyzones_restoreSize"));
Assert.AreEqual(toggleValues[9], GetPropertyValue<bool>(savedProps, "use_cursorpos_editor_startupscreen"));
Assert.AreEqual(toggleValues[10], GetPropertyValue<bool>(savedProps, "fancyzones_show_on_all_monitors"));
Assert.AreEqual(toggleValues[11], GetPropertyValue<bool>(savedProps, "fancyzones_span_zones_across_monitors"));
Assert.AreEqual(toggleValues[12], GetPropertyValue<bool>(savedProps, "fancyzones_makeDraggedWindowTransparent"));
}
[TestMethod]