diff --git a/src/modules/fancyzones/FancyZonesLib/Settings.cpp b/src/modules/fancyzones/FancyZonesLib/Settings.cpp index 9cc886fe5cd4..dc4e927ff794 100644 --- a/src/modules/fancyzones/FancyZonesLib/Settings.cpp +++ b/src/modules/fancyzones/FancyZonesLib/Settings.cpp @@ -20,6 +20,7 @@ namespace NonLocalizable const wchar_t MouseMiddleClickSpanningMultipleZonesID[] = L"fancyzones_mouseMiddleClickSpanningMultipleZones"; const wchar_t OverrideSnapHotKeysID[] = L"fancyzones_overrideSnapHotkeys"; const wchar_t MoveWindowAcrossMonitorsID[] = L"fancyzones_moveWindowAcrossMonitors"; + const wchar_t CycleThroughAllZonesID[] = L"fancyzones_cycleThroughAllZones"; const wchar_t MoveWindowsBasedOnPositionID[] = L"fancyzones_moveWindowsBasedOnPosition"; const wchar_t OverlappingZonesAlgorithmID[] = L"fancyzones_overlappingZonesAlgorithm"; const wchar_t DisplayOrWorkAreaChangeMoveWindowsID[] = L"fancyzones_displayOrWorkAreaChange_moveWindows"; @@ -111,6 +112,7 @@ void FancyZonesSettings::LoadSettings() SetBoolFlag(values, NonLocalizable::MouseMiddleClickSpanningMultipleZonesID, SettingId::MouseMiddleClickSpanningMultipleZones, m_settings.mouseMiddleClickSpanningMultipleZones); SetBoolFlag(values, NonLocalizable::OverrideSnapHotKeysID, SettingId::OverrideSnapHotkeys, m_settings.overrideSnapHotkeys); SetBoolFlag(values, NonLocalizable::MoveWindowAcrossMonitorsID, SettingId::MoveWindowAcrossMonitors, m_settings.moveWindowAcrossMonitors); + SetBoolFlag(values, NonLocalizable::CycleThroughAllZonesID, SettingId::CycleThroughAllZones, m_settings.cycleThroughAllZones); SetBoolFlag(values, NonLocalizable::MoveWindowsBasedOnPositionID, SettingId::MoveWindowsBasedOnPosition, m_settings.moveWindowsBasedOnPosition); SetBoolFlag(values, NonLocalizable::DisplayOrWorkAreaChangeMoveWindowsID, SettingId::DisplayOrWorkAreaChangeMoveWindows, m_settings.displayOrWorkAreaChange_moveWindows); SetBoolFlag(values, NonLocalizable::ZoneSetChangeMoveWindowsID, SettingId::ZoneSetChangeMoveWindows, m_settings.zoneSetChange_moveWindows); diff --git a/src/modules/fancyzones/FancyZonesLib/Settings.h b/src/modules/fancyzones/FancyZonesLib/Settings.h index a9bcbeaa172f..1c8df1ce34a3 100644 --- a/src/modules/fancyzones/FancyZonesLib/Settings.h +++ b/src/modules/fancyzones/FancyZonesLib/Settings.h @@ -32,6 +32,7 @@ struct Settings bool zoneSetChange_moveWindows = false; bool overrideSnapHotkeys = false; bool moveWindowAcrossMonitors = false; + bool cycleThroughAllZones = true; bool moveWindowsBasedOnPosition = false; bool appLastZone_moveWindows = false; bool openWindowOnActiveMonitor = false; diff --git a/src/modules/fancyzones/FancyZonesLib/SettingsConstants.h b/src/modules/fancyzones/FancyZonesLib/SettingsConstants.h index a789d864848d..c32114942f49 100644 --- a/src/modules/fancyzones/FancyZonesLib/SettingsConstants.h +++ b/src/modules/fancyzones/FancyZonesLib/SettingsConstants.h @@ -7,6 +7,7 @@ enum class SettingId MouseMiddleClickSpanningMultipleZones, OverrideSnapHotkeys, MoveWindowAcrossMonitors, + CycleThroughAllZones, MoveWindowsBasedOnPosition, OverlappingZonesAlgorithm, DisplayOrWorkAreaChangeMoveWindows, diff --git a/src/modules/fancyzones/FancyZonesLib/WindowKeyboardSnap.cpp b/src/modules/fancyzones/FancyZonesLib/WindowKeyboardSnap.cpp index f982d5deeaeb..cc8f666a4010 100644 --- a/src/modules/fancyzones/FancyZonesLib/WindowKeyboardSnap.cpp +++ b/src/modules/fancyzones/FancyZonesLib/WindowKeyboardSnap.cpp @@ -25,32 +25,46 @@ bool WindowKeyboardSnap::Snap(HWND window, RECT windowRect, HMONITOR monitor, DW // clean previous extension data m_extendData.Reset(); + bool success = false; + bool cycle = FancyZonesSettings::settings().cycleThroughAllZones; + const auto& currentWorkArea = activeWorkAreas.at(monitor); if (monitors.size() > 1 && FancyZonesSettings::settings().moveWindowAcrossMonitors) { // Multi monitor environment. // First, try to stay on the same monitor - bool success = MoveByDirectionAndPosition(window, windowRect, vkCode, false, currentWorkArea.get()); + success = MoveByDirectionAndPosition(window, windowRect, vkCode, false, currentWorkArea.get()); if (success) { return true; } // Try to snap on another monitor - success = SnapBasedOnPositionOnAnotherMonitor(window, windowRect, vkCode, monitor, activeWorkAreas, monitors); + success = SnapBasedOnPositionOnAnotherMonitor(window, windowRect, vkCode, cycle, monitor, activeWorkAreas, monitors); if (success) { // Unsnap from previous work area currentWorkArea->Unsnap(window); } - - return success; } else { // Single monitor environment, or combined multi-monitor environment. - return MoveByDirectionAndPosition(window, windowRect, vkCode, true, currentWorkArea.get()); + success = MoveByDirectionAndPosition(window, windowRect, vkCode, cycle, currentWorkArea.get()); + } + + if (!success && (vkCode == VK_UP || vkCode == VK_DOWN)) + { + WINDOWPLACEMENT placement{}; + GetWindowPlacement(window, &placement); + if (vkCode == VK_UP) + placement.showCmd = SW_SHOWMAXIMIZED; + else if (vkCode == VK_DOWN) + placement.showCmd = SW_SHOWMINIMIZED; + success = SetWindowPlacement(window, &placement); } + + return success; } bool WindowKeyboardSnap::Extend(HWND window, RECT windowRect, HMONITOR monitor, DWORD vkCode, const std::unordered_map>& activeWorkAreas) @@ -133,7 +147,7 @@ bool WindowKeyboardSnap::SnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode, return false; } -bool WindowKeyboardSnap::SnapBasedOnPositionOnAnotherMonitor(HWND window, RECT windowRect, DWORD vkCode, HMONITOR current, const std::unordered_map>& activeWorkAreas, const std::vector>& monitors) +bool WindowKeyboardSnap::SnapBasedOnPositionOnAnotherMonitor(HWND window, RECT windowRect, DWORD vkCode, bool cycle, HMONITOR current, const std::unordered_map>& activeWorkAreas, const std::vector>& monitors) { // Extract zones from all other monitors and target one of them std::vector zoneRects; @@ -192,6 +206,9 @@ bool WindowKeyboardSnap::SnapBasedOnPositionOnAnotherMonitor(HWND window, RECT w return snapped; } + if (!cycle) + return false; + // We reached the end of all monitors. // Try again, cycling on all monitors. // First, add zones from the origin monitor to zoneRects diff --git a/src/modules/fancyzones/FancyZonesLib/WindowKeyboardSnap.h b/src/modules/fancyzones/FancyZonesLib/WindowKeyboardSnap.h index 086b4047bac1..58aeeba2807e 100644 --- a/src/modules/fancyzones/FancyZonesLib/WindowKeyboardSnap.h +++ b/src/modules/fancyzones/FancyZonesLib/WindowKeyboardSnap.h @@ -46,7 +46,7 @@ class WindowKeyboardSnap private: bool SnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode, HMONITOR monitor, const std::unordered_map>& activeWorkAreas, const std::vector& monitors); - bool SnapBasedOnPositionOnAnotherMonitor(HWND window, RECT windowRect, DWORD vkCode, HMONITOR monitor, const std::unordered_map>& activeWorkAreas, const std::vector>& monitors); + bool SnapBasedOnPositionOnAnotherMonitor(HWND window, RECT windowRect, DWORD vkCode, bool cycle, HMONITOR monitor, const std::unordered_map>& activeWorkAreas, const std::vector>& monitors); bool MoveByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, WorkArea* const workArea); bool MoveByDirectionAndPosition(HWND window, RECT windowRect, DWORD vkCode, bool cycle, WorkArea* const workArea); diff --git a/src/modules/fancyzones/FancyZonesLib/trace.cpp b/src/modules/fancyzones/FancyZonesLib/trace.cpp index 69e341197a26..512a82bc6fbe 100644 --- a/src/modules/fancyzones/FancyZonesLib/trace.cpp +++ b/src/modules/fancyzones/FancyZonesLib/trace.cpp @@ -48,6 +48,7 @@ #define MoveWindowsOnZoneSetChangeKey "MoveWindowsOnZoneSetChange" #define OverrideSnapHotKeysKey "OverrideSnapHotKeys" #define MoveWindowAcrossMonitorsKey "MoveWindowAcrossMonitors" +#define CycleThroughAllZonesKey "CycleThroughAllZones" #define MoveWindowsBasedOnPositionKey "MoveWindowsBasedOnPosition" #define MoveWindowsToLastZoneOnAppOpeningKey "MoveWindowsToLastZoneOnAppOpening" #define OpenWindowOnActiveMonitorKey "OpenWindowOnActiveMonitor" @@ -303,6 +304,7 @@ void Trace::SettingsTelemetry(const Settings& settings) noexcept TraceLoggingBoolean(settings.zoneSetChange_moveWindows, MoveWindowsOnZoneSetChangeKey), TraceLoggingBoolean(settings.overrideSnapHotkeys, OverrideSnapHotKeysKey), TraceLoggingBoolean(settings.moveWindowAcrossMonitors, MoveWindowAcrossMonitorsKey), + TraceLoggingBoolean(settings.cycleThroughAllZones, CycleThroughAllZonesKey), TraceLoggingBoolean(settings.moveWindowsBasedOnPosition, MoveWindowsBasedOnPositionKey), TraceLoggingBoolean(settings.appLastZone_moveWindows, MoveWindowsToLastZoneOnAppOpeningKey), TraceLoggingBoolean(settings.openWindowOnActiveMonitor, OpenWindowOnActiveMonitorKey), diff --git a/src/modules/fancyzones/FancyZonesTests/UnitTests/FancyZonesSettings.Spec.cpp b/src/modules/fancyzones/FancyZonesTests/UnitTests/FancyZonesSettings.Spec.cpp index 8c93e5a05cee..d4a97034bfac 100644 --- a/src/modules/fancyzones/FancyZonesTests/UnitTests/FancyZonesSettings.Spec.cpp +++ b/src/modules/fancyzones/FancyZonesTests/UnitTests/FancyZonesSettings.Spec.cpp @@ -34,6 +34,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.cycleThroughAllZones, actual.cycleThroughAllZones); Assert::AreEqual(expected.moveWindowsBasedOnPosition, actual.moveWindowsBasedOnPosition); Assert::AreEqual(expected.appLastZone_moveWindows, actual.appLastZone_moveWindows); Assert::AreEqual(expected.openWindowOnActiveMonitor, actual.openWindowOnActiveMonitor); @@ -74,6 +75,7 @@ namespace FancyZonesUnitTests values.add_property(L"fancyzones_zoneSetChange_moveWindows", m_defaultSettings.zoneSetChange_moveWindows); values.add_property(L"fancyzones_overrideSnapHotkeys", m_defaultSettings.overrideSnapHotkeys); values.add_property(L"fancyzones_moveWindowAcrossMonitors", m_defaultSettings.moveWindowAcrossMonitors); + values.add_property(L"fancyzones_cycleThroughAllZones", m_defaultSettings.cycleThroughAllZones); values.add_property(L"fancyzones_moveWindowsBasedOnPosition", m_defaultSettings.moveWindowsBasedOnPosition); values.add_property(L"fancyzones_appLastZone_moveWindows", m_defaultSettings.appLastZone_moveWindows); values.add_property(L"fancyzones_openWindowOnActiveMonitor", m_defaultSettings.openWindowOnActiveMonitor); @@ -117,6 +119,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_cycleThroughAllZones", expected.cycleThroughAllZones); 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); diff --git a/src/settings-ui/Settings.UI.Library/FZConfigProperties.cs b/src/settings-ui/Settings.UI.Library/FZConfigProperties.cs index 9150cdbe90b5..ad9806a770eb 100644 --- a/src/settings-ui/Settings.UI.Library/FZConfigProperties.cs +++ b/src/settings-ui/Settings.UI.Library/FZConfigProperties.cs @@ -27,6 +27,7 @@ public FZConfigProperties() FancyzonesMouseSwitch = new BoolProperty(); FancyzonesMouseMiddleClickSpanningMultipleZones = new BoolProperty(); FancyzonesMoveWindowsAcrossMonitors = new BoolProperty(); + FancyzonesCycleThroughAllZones = new BoolProperty(); FancyzonesMoveWindowsBasedOnPosition = new BoolProperty(); FancyzonesOverlappingZonesAlgorithm = new IntProperty(); FancyzonesDisplayOrWorkAreaChangeMoveWindows = new BoolProperty(ConfigDefaults.DefaultFancyzonesDisplayOrWorkAreaChangeMoveWindows); @@ -72,6 +73,9 @@ public FZConfigProperties() [JsonPropertyName("fancyzones_moveWindowAcrossMonitors")] public BoolProperty FancyzonesMoveWindowsAcrossMonitors { get; set; } + [JsonPropertyName("fancyzones_cycleThroughAllZones")] + public BoolProperty FancyzonesCycleThroughAllZones { get; set; } + [JsonPropertyName("fancyzones_moveWindowsBasedOnPosition")] public BoolProperty FancyzonesMoveWindowsBasedOnPosition { get; set; } diff --git a/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/FancyZones.cs b/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/FancyZones.cs index e557f08bdf51..6a866b121fd3 100644 --- a/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/FancyZones.cs +++ b/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/FancyZones.cs @@ -63,6 +63,7 @@ public void OriginalFilesModificationTest(string version, string fileName) Assert.AreEqual(originalSettings.Properties.FancyzonesMakeDraggedWindowTransparent.Value, viewModel.MakeDraggedWindowsTransparent); Assert.AreEqual(originalSettings.Properties.FancyzonesMouseSwitch.Value, viewModel.MouseSwitch); Assert.AreEqual(originalSettings.Properties.FancyzonesMoveWindowsAcrossMonitors.Value, viewModel.MoveWindowsAcrossMonitors); + Assert.AreEqual(originalSettings.Properties.FancyzonesCycleThroughAllZones.Value, viewModel.CycleThroughAllZones); Assert.AreEqual(originalSettings.Properties.FancyzonesMoveWindowsBasedOnPosition.Value, viewModel.MoveWindowsBasedOnPosition); Assert.AreEqual(originalSettings.Properties.FancyzonesOpenWindowOnActiveMonitor.Value, viewModel.OpenWindowOnActiveMonitor); Assert.AreEqual(originalSettings.Properties.FancyzonesOverrideSnapHotkeys.Value, viewModel.OverrideSnapHotkeys); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/FancyZonesPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/FancyZonesPage.xaml index 2b9053142b7f..b9d9e2ed901b 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/FancyZonesPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/FancyZonesPage.xaml @@ -254,6 +254,12 @@ IsEnabled="{x:Bind ViewModel.SnapHotkeysCategoryEnabled, Mode=OneWay}"> + + + diff --git a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw index f2efe864b4ce..ffdc2bcf1285 100644 --- a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw +++ b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw @@ -864,6 +864,9 @@ opera.exe Move windows between zones across all monitors + + Cycle through all zones + Override Windows Snap diff --git a/src/settings-ui/Settings.UI/ViewModels/FancyZonesViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/FancyZonesViewModel.cs index 3fa21824e6ff..f5049a3875ec 100644 --- a/src/settings-ui/Settings.UI/ViewModels/FancyZonesViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/FancyZonesViewModel.cs @@ -70,6 +70,7 @@ public FancyZonesViewModel(SettingsUtils settingsUtils, ISettingsRepository GetAllHotkeySettings() private bool _mouseMiddleButtonSpanningMultipleZones; private bool _overrideSnapHotkeys; private bool _moveWindowsAcrossMonitors; + private bool _cycleThroughAllZones; private MoveWindowBehaviour _moveWindowBehaviour; private OverlappingZonesAlgorithm _overlappingZonesAlgorithm; private bool _displayOrWorkAreaChangeMoveWindows; @@ -342,6 +344,24 @@ public bool MoveWindowsAcrossMonitors } } + public bool CycleThroughAllZones + { + get + { + return _cycleThroughAllZones; + } + + set + { + if (value != _cycleThroughAllZones) + { + _cycleThroughAllZones = value; + Settings.Properties.FancyzonesCycleThroughAllZones.Value = value; + NotifyPropertyChanged(); + } + } + } + public bool MoveWindowsBasedOnPosition { get