Skip to content

Commit

Permalink
[FancyZones] Add setting always maximize for moved to the current act…
Browse files Browse the repository at this point in the history
…ive monitor
  • Loading branch information
quyenvsp committed Oct 3, 2023
1 parent a698eca commit 168983c
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 12 deletions.
27 changes: 17 additions & 10 deletions src/modules/fancyzones/FancyZonesLib/MonitorUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,19 +338,26 @@ namespace MonitorUtils

void OpenWindowOnActiveMonitor(HWND window, HMONITOR monitor) noexcept
{
// By default Windows opens new window on primary monitor.
// Try to preserve window width and height, adjust top-left corner if needed.
HMONITOR origin = MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY);
if (origin == monitor)
{
// Certain applications by design open in last known position, regardless of FancyZones.
// If that position is on currently active monitor, skip custom positioning.
return;
}

WINDOWPLACEMENT placement{};
if (GetWindowPlacement(window, &placement))
{
// By default Windows opens new window on primary monitor.
// Try to preserve window width and height, adjust top-left corner if needed.
HMONITOR origin = MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY);
if (FancyZonesWindowUtils::IsAlwaysMaximize(window))
{
// Skip if current window is always maximize by user setting
// and already SW_SHOWMAXIMIZED on currently active monitor
if (!FancyZonesWindowUtils::HasThickFrameAndMinimizeMaximizeButtons(window) || (placement.showCmd == SW_SHOWMAXIMIZED && origin == monitor))
{
return;
}
} else if (origin == monitor)
{
// Certain applications by design open in last known position, regardless of FancyZones.
// If that position is on currently active monitor, skip custom positioning.
return;
}
MONITORINFOEX originMi;
originMi.cbSize = sizeof(originMi);
if (GetMonitorInfo(origin, &originMi))
Expand Down
27 changes: 27 additions & 0 deletions src/modules/fancyzones/FancyZonesLib/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ namespace NonLocalizable
const wchar_t WindowSwitchingToggleID[] = L"fancyzones_windowSwitching";
const wchar_t NextTabHotkeyID[] = L"fancyzones_nextTab_hotkey";
const wchar_t PrevTabHotkeyID[] = L"fancyzones_prevTab_hotkey";
const wchar_t AlwaysMaximizeID[] = L"fancyzones_always_maximize";
const wchar_t ExcludedAppsID[] = L"fancyzones_excluded_apps";
const wchar_t ZoneHighlightOpacityID[] = L"fancyzones_highlight_opacity";
const wchar_t ShowZoneNumberID[] = L"fancyzones_showZoneNumber";
Expand Down Expand Up @@ -208,6 +209,32 @@ void FancyZonesSettings::LoadSettings()
}
}

// always maximize apps
if (auto val = values.get_string_value(NonLocalizable::AlwaysMaximizeID))
{
std::wstring apps = std::move(*val);
std::vector<std::wstring> alwaysMaximize;
auto alwaysMaximizeUppercase = apps;
CharUpperBuffW(alwaysMaximizeUppercase.data(), static_cast<DWORD>(alwaysMaximizeUppercase.length()));
std::wstring_view view(alwaysMaximizeUppercase);
view = left_trim<wchar_t>(trim<wchar_t>(view));

while (!view.empty())
{
auto pos = (std::min)(view.find_first_of(L"\r\n"), view.length());
alwaysMaximize.emplace_back(view.substr(0, pos));
view.remove_prefix(pos);
view = left_trim<wchar_t>(trim<wchar_t>(view));
}

if (m_settings.alwaysMaximizeArray != alwaysMaximize)
{
m_settings.alwaysMaximize = apps;
m_settings.alwaysMaximizeArray = alwaysMaximize;
NotifyObservers(SettingId::AlwaysMaximize);
}
}

// excluded apps
if (auto val = values.get_string_value(NonLocalizable::ExcludedAppsID))
{
Expand Down
2 changes: 2 additions & 0 deletions src/modules/fancyzones/FancyZonesLib/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ struct Settings
bool windowSwitching = true;
PowerToysSettings::HotkeyObject nextTabHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, false, VK_NEXT);
PowerToysSettings::HotkeyObject prevTabHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, false, VK_PRIOR);
std::wstring alwaysMaximize = L"";
std::vector<std::wstring> alwaysMaximizeArray;
std::wstring excludedApps = L"";
std::vector<std::wstring> excludedAppsArray;
};
Expand Down
1 change: 1 addition & 0 deletions src/modules/fancyzones/FancyZonesLib/SettingsConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ enum class SettingId
WindowSwitching,
NextTabHotkey,
PrevTabHotkey,
AlwaysMaximize,
ExcludedApps,
AllowSnapPopupWindows,
AllowSnapChildWindows,
Expand Down
23 changes: 21 additions & 2 deletions src/modules/fancyzones/FancyZonesLib/WindowUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,18 @@ bool FancyZonesWindowUtils::IsProcessOfWindowElevated(HWND window)
return false;
}

bool FancyZonesWindowUtils::IsAlwaysMaximize(HWND window)
{
std::wstring processPath = get_process_path_waiting_uwp(window);
CharUpperBuffW(const_cast<std::wstring&>(processPath).data(), static_cast<DWORD>(processPath.length()));
if (find_app_name_in_path(processPath, FancyZonesSettings::settings().alwaysMaximizeArray))
{
return true;
}

return false;
}

bool FancyZonesWindowUtils::IsExcluded(HWND window)
{
std::wstring processPath = get_process_path_waiting_uwp(window);
Expand Down Expand Up @@ -308,9 +320,16 @@ void FancyZonesWindowUtils::SizeWindowToRect(HWND window, RECT rect, BOOL snapZo
else
{
// If is not snap zone then need keep maximize state (move to active monitor)
if (!snapZone && placement.showCmd == SW_SHOWMAXIMIZED)
if (!snapZone)
{
maximizeLater = true;
if (IsAlwaysMaximize(window))
{
placement.showCmd = SW_SHOWMAXIMIZED;
}
if (placement.showCmd == SW_SHOWMAXIMIZED)
{
maximizeLater = true;
}
}

// Do not restore minimized windows. We change their placement though so they restore to the correct zone.
Expand Down
1 change: 1 addition & 0 deletions src/modules/fancyzones/FancyZonesLib/WindowUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace FancyZonesWindowUtils
bool HasThickFrameAndMinimizeMaximizeButtons(HWND window) noexcept;
bool IsProcessOfWindowElevated(HWND window); // If HWND is already dead, we assume it wasn't elevated

bool IsAlwaysMaximize(HWND window);
bool IsExcluded(HWND window);
bool IsExcludedByUser(const HWND& hwnd, std::wstring& processPath) noexcept;
bool IsExcludedByDefault(const HWND& hwnd, std::wstring& processPath) noexcept;
Expand Down
2 changes: 2 additions & 0 deletions src/modules/fancyzones/FancyZonesLib/trace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#define WindowSwitchingToggleKey "WindowSwitchingToggle"
#define NextTabHotkey "NextTabHotkey"
#define PrevTabHotkey "PrevTabHotkey"
#define AlwaysMaximizeCountKey "AlwaysMaximizeCount"
#define ExcludedAppsCountKey "ExcludedAppsCount"
#define KeyboardValueKey "KeyboardValue"
#define ActiveSetKey "ActiveSet"
Expand Down Expand Up @@ -334,6 +335,7 @@ void Trace::SettingsTelemetry(const Settings& settings) noexcept
TraceLoggingBoolean(settings.windowSwitching, WindowSwitchingToggleKey),
TraceLoggingWideString(nextTabHotkeyStr.c_str(), NextTabHotkey),
TraceLoggingWideString(prevTabHotkeyStr.c_str(), PrevTabHotkey),
TraceLoggingInt32(static_cast<int>(settings.excludedAppsArray.size()), AlwaysMaximizeCountKey),
TraceLoggingInt32(static_cast<int>(settings.excludedAppsArray.size()), ExcludedAppsCountKey));
}

Expand Down
4 changes: 4 additions & 0 deletions src/settings-ui/Settings.UI.Library/FZConfigProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public FZConfigProperties()
FancyzonesAllowPopupWindowSnap = new BoolProperty();
FancyzonesAllowChildWindowSnap = new BoolProperty();
FancyzonesDisableRoundCornersOnSnap = new BoolProperty();
FancyzonesALwaysMaximize = new StringProperty();
FancyzonesExcludedApps = new StringProperty();
FancyzonesInActiveColor = new StringProperty(ConfigDefaults.DefaultFancyZonesInActiveColor);
FancyzonesBorderColor = new StringProperty(ConfigDefaults.DefaultFancyzonesBorderColor);
Expand Down Expand Up @@ -136,6 +137,9 @@ public FZConfigProperties()
[JsonPropertyName("fancyzones_prevTab_hotkey")]
public KeyboardKeysProperty FancyzonesPrevTabHotkey { get; set; }

[JsonPropertyName("fancyzones_always_maximize")]
public StringProperty FancyzonesALwaysMaximize { get; set; }

[JsonPropertyName("fancyzones_excluded_apps")]
public StringProperty FancyzonesExcludedApps { get; set; }

Expand Down
19 changes: 19 additions & 0 deletions src/settings-ui/Settings.UI/SettingsXAML/Views/FancyZonesPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,25 @@
</controls:SettingsCard>
</controls:SettingsExpander.Items>
</controls:SettingsExpander>

<controls:SettingsExpander
x:Uid="FancyZones_AlwaysMaximize"
IsExpanded="True">
<controls:SettingsExpander.Items>
<controls:SettingsCard HorizontalContentAlignment="Stretch" ContentAlignment="Vertical">
<TextBox
x:Uid="FancyZones_AlwaysMaximize_TextBoxControl"
MinWidth="240"
MinHeight="160"
AcceptsReturn="True"
ScrollViewer.IsVerticalRailEnabled="True"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollMode="Enabled"
Text="{x:Bind Mode=TwoWay, Path=ViewModel.AlwaysMaximize, UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" />
</controls:SettingsCard>
</controls:SettingsExpander.Items>
</controls:SettingsExpander>
</custom:SettingsGroup>

<custom:SettingsGroup x:Uid="FancyZones_Layouts" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
Expand Down
10 changes: 10 additions & 0 deletions src/settings-ui/Settings.UI/Strings/en-us/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,16 @@
<data name="FancyZones_ExcludeApps.Description" xml:space="preserve">
<value>Excludes an application from snapping to zones and will only react to Windows Snap - add one application name per line</value>
</data>
<data name="FancyZones_AlwaysMaximize.Header" xml:space="preserve">
<value>Always maximize apps</value>
</data>
<data name="FancyZones_AlwaysMaximize.Description" xml:space="preserve">
<value>Always create new window application with maximize state - add one application name per line</value>
</data>
<data name="FancyZones_AlwaysMaximize_TextBoxControl.PlaceholderText" xml:space="preserve">
<value>Example: outlook.exe</value>
<comment>Don't translate outlook.exe</comment>
</data>
<data name="FancyZones_HighlightOpacity.Header" xml:space="preserve">
<value>Opacity (%)</value>
</data>
Expand Down
20 changes: 20 additions & 0 deletions src/settings-ui/Settings.UI/ViewModels/FancyZonesViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public FancyZonesViewModel(SettingsUtils settingsUtils, ISettingsRepository<Gene
_allowChildWindowSnap = Settings.Properties.FancyzonesAllowChildWindowSnap.Value;
_disableRoundCornersOnSnap = Settings.Properties.FancyzonesDisableRoundCornersOnSnap.Value;
_highlightOpacity = Settings.Properties.FancyzonesHighlightOpacity.Value;
_alwaysMaximize = Settings.Properties.FancyzonesALwaysMaximize.Value;
_excludedApps = Settings.Properties.FancyzonesExcludedApps.Value;
_systemTheme = Settings.Properties.FancyzonesSystemTheme.Value;
_showZoneNumber = Settings.Properties.FancyzonesShowZoneNumber.Value;
Expand Down Expand Up @@ -171,6 +172,7 @@ private void InitializeEnabledValue()
private bool _disableRoundCornersOnSnap;

private int _highlightOpacity;
private string _alwaysMaximize;
private string _excludedApps;
private HotkeySettings _editorHotkey;
private bool _windowSwitching;
Expand Down Expand Up @@ -877,6 +879,24 @@ public HotkeySettings PrevTabHotkey
}
}

public string AlwaysMaximize
{
get
{
return _alwaysMaximize;
}

set
{
if (value != _alwaysMaximize)
{
_alwaysMaximize = value;
Settings.Properties.FancyzonesALwaysMaximize.Value = value;
NotifyPropertyChanged();
}
}
}

public string ExcludedApps
{
get
Expand Down

0 comments on commit 168983c

Please sign in to comment.