Skip to content

Commit

Permalink
[Settings]restore window size and position (#13912)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidegiacometti authored Oct 25, 2021
1 parent 5910836 commit db90802
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 2 deletions.
21 changes: 21 additions & 0 deletions src/settings-ui/PowerToys.Settings/Helpers/NativeMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.InteropServices;

namespace PowerToys.Settings.Helpers
{
public static class NativeMethods
{
internal const int SW_SHOWNORMAL = 1;
internal const int SW_SHOWMAXIMIZED = 3;

[DllImport("user32.dll")]
internal static extern bool SetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);

[DllImport("user32.dll")]
internal static extern bool GetWindowPlacement(IntPtr hWnd, out WINDOWPLACEMENT lpwndpl);
}
}
25 changes: 25 additions & 0 deletions src/settings-ui/PowerToys.Settings/Helpers/POINT.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.InteropServices;

namespace PowerToys.Settings.Helpers
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1815:Override equals and operator equals on value types", Justification = "Interop")]
public struct POINT
{
public int X { get; set; }

public int Y { get; set; }

public POINT(int x, int y)
{
X = x;
Y = y;
}
}
}
31 changes: 31 additions & 0 deletions src/settings-ui/PowerToys.Settings/Helpers/RECT.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.InteropServices;

namespace PowerToys.Settings.Helpers
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1815:Override equals and operator equals on value types", Justification = "Interop")]
public struct RECT
{
public int Left { get; set; }

public int Top { get; set; }

public int Right { get; set; }

public int Bottom { get; set; }

public RECT(int left, int top, int right, int bottom)
{
Left = left;
Top = top;
Right = right;
Bottom = bottom;
}
}
}
27 changes: 27 additions & 0 deletions src/settings-ui/PowerToys.Settings/Helpers/WINDOWPLACEMENT.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.InteropServices;

namespace PowerToys.Settings.Helpers
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1815:Override equals and operator equals on value types", Justification = "Interop")]
public struct WINDOWPLACEMENT
{
public int Length { get; set; }

public int Flags { get; set; }

public int ShowCmd { get; set; }

public POINT MinPosition { get; set; }

public POINT MaxPosition { get; set; }

public RECT NormalPosition { get; set; }
}
}
36 changes: 34 additions & 2 deletions src/settings-ui/PowerToys.Settings/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
// See the LICENSE file in the project root for more information.

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows;
using System.Windows.Interop;
using Microsoft.PowerLauncher.Telemetry;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.PowerToys.Telemetry;
using Microsoft.Toolkit.Wpf.UI.XamlHost;
using PowerToys.Settings.Helpers;
using Windows.ApplicationModel.Resources;
using Windows.Data.Json;

Expand All @@ -28,8 +32,6 @@ public MainWindow()

this.InitializeComponent();

Utils.FitToScreen(this);

ResourceLoader loader = ResourceLoader.GetForViewIndependentUse();
Title = loader.GetString("SettingsWindow_Title");

Expand All @@ -55,6 +57,36 @@ public void NavigateToSection(Type type)
}
}

protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);

Utils.FitToScreen(this);

var handle = new WindowInteropHelper(this).Handle;
NativeMethods.GetWindowPlacement(handle, out var startupPlacement);
var placement = Utils.DeserializePlacementOrDefault(handle);
NativeMethods.SetWindowPlacement(handle, ref placement);

var windowRect = new Rectangle((int)Left, (int)Top, (int)Width, (int)Height);
var screenRect = new Rectangle((int)SystemParameters.VirtualScreenLeft, (int)SystemParameters.VirtualScreenTop, (int)SystemParameters.VirtualScreenWidth, (int)SystemParameters.VirtualScreenHeight);
var intersection = Rectangle.Intersect(windowRect, screenRect);

// Restore default position if 1/4 of width or height of the window is offscreen
if (intersection.Width < (Width * 0.75) || intersection.Height < (Height * 0.75))
{
NativeMethods.SetWindowPlacement(handle, ref startupPlacement);
}
}

protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
var handle = new WindowInteropHelper(this).Handle;

Utils.SerializePlacement(handle);
}

private void WindowsXamlHost_ChildChanged(object sender, EventArgs e)
{
// If sender is null, it could lead to a NullReferenceException. This might occur on restarting as admin (check https://github.com/microsoft/PowerToys/issues/7393 for details)
Expand Down
47 changes: 47 additions & 0 deletions src/settings-ui/PowerToys.Settings/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text.Json;
using System.Windows;
using PowerToys.Settings.Helpers;

namespace PowerToys.Settings
{
internal class Utils
{
private static string _placementPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Microsoft\PowerToys\settings-placement.json");

public static void FitToScreen(Window window)
{
if (SystemParameters.WorkArea.Width < window.Width)
Expand Down Expand Up @@ -66,5 +73,45 @@ public static void ShowHide(Window window)
window.MinWidth = originalMinWidth;
window.ShowInTaskbar = true;
}

public static WINDOWPLACEMENT DeserializePlacementOrDefault(IntPtr handle)
{
if (File.Exists(_placementPath))
{
try
{
var json = File.ReadAllText(_placementPath);
var placement = JsonSerializer.Deserialize<WINDOWPLACEMENT>(json);

placement.Length = Marshal.SizeOf(typeof(WINDOWPLACEMENT));
placement.Flags = 0;
placement.ShowCmd = placement.ShowCmd == NativeMethods.SW_SHOWMAXIMIZED ? NativeMethods.SW_SHOWMAXIMIZED : NativeMethods.SW_SHOWNORMAL;
return placement;
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception)
#pragma warning restore CA1031 // Do not catch general exception types
{
}
}

_ = NativeMethods.GetWindowPlacement(handle, out var defaultPlacement);
return defaultPlacement;
}

public static void SerializePlacement(IntPtr handle)
{
_ = NativeMethods.GetWindowPlacement(handle, out var placement);
try
{
var json = JsonSerializer.Serialize(placement);
File.WriteAllText(_placementPath, json);
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception)
#pragma warning restore CA1031 // Do not catch general exception types
{
}
}
}
}

0 comments on commit db90802

Please sign in to comment.