diff --git a/src/Files.App/Data/Items/WindowEx.cs b/src/Files.App/Data/Items/WindowEx.cs
deleted file mode 100644
index b19f3ba449f8..000000000000
--- a/src/Files.App/Data/Items/WindowEx.cs
+++ /dev/null
@@ -1,291 +0,0 @@
-// Copyright (c) Files Community
-// Licensed under the MIT License.
-
-using Microsoft.UI.Composition.SystemBackdrops;
-using Microsoft.UI.Windowing;
-using Microsoft.UI.Xaml;
-using System.Runtime.InteropServices;
-using Windows.Foundation;
-using Windows.Foundation.Collections;
-using Windows.Storage;
-using Windows.Win32;
-using Windows.Win32.Foundation;
-using Windows.Win32.Graphics.Gdi;
-using Windows.Win32.UI.WindowsAndMessaging;
-
-namespace Files.App.Data.Items
-{
- ///
- /// Represents base class to extend its features.
- ///
- public unsafe partial class WindowEx : Window, IDisposable
- {
- private bool _isInitialized;
- private readonly WNDPROC _oldWndProc;
- private readonly WNDPROC _newWndProc;
-
- private readonly ApplicationDataContainer _applicationDataContainer = ApplicationData.Current.LocalSettings;
-
- ///
- /// Gets hWnd of this .
- ///
- public nint WindowHandle { get; }
-
- ///
- /// Gets min width of this .
- ///
- public int MinWidth { get; }
-
- ///
- /// Gets min height of this .
- ///
- public int MinHeight { get; }
-
- private bool _IsMaximizable = true;
- ///
- /// Gets or sets a value that indicates whether this can be maximizable.
- ///
- public bool IsMaximizable
- {
- get => _IsMaximizable;
- set
- {
- _IsMaximizable = value;
-
- if (AppWindow.Presenter is OverlappedPresenter overlapped)
- overlapped.IsMaximizable = value;
- }
- }
-
- private bool _IsMinimizable = true;
- ///
- /// Gets or sets a value that indicates whether this can be minimizable.
- ///
- public bool IsMinimizable
- {
- get => _IsMinimizable;
- set
- {
- _IsMinimizable = value;
-
- if (AppWindow.Presenter is OverlappedPresenter overlapped)
- overlapped.IsMinimizable = value;
- }
- }
-
- ///
- /// Initializes class.
- ///
- /// Min width to set when initialized.
- /// Min height to set when initialized.
- public unsafe WindowEx(int minWidth = 400, int minHeight = 300)
- {
- WindowHandle = WinRT.Interop.WindowNative.GetWindowHandle(this);
- MinWidth = minWidth;
- MinHeight = minHeight;
- IsMaximizable = true;
- IsMinimizable = true;
-
- _newWndProc = new(NewWindowProc);
- var pNewWndProc = Marshal.GetFunctionPointerForDelegate(_newWndProc);
- var pOldWndProc = PInvoke.SetWindowLongPtr(new(WindowHandle), WINDOW_LONG_PTR_INDEX.GWL_WNDPROC, pNewWndProc);
- _oldWndProc = Marshal.GetDelegateForFunctionPointer(pOldWndProc);
-
- Closed += WindowEx_Closed;
- }
-
- private unsafe void StoreWindowPlacementData()
- {
- // Save window placement only for MainWindow
- if (!GetType().Name.Equals(nameof(MainWindow), StringComparison.OrdinalIgnoreCase))
- return;
-
- // Store monitor info
- using var data = new SystemIO.MemoryStream();
- using var sw = new SystemIO.BinaryWriter(data);
-
- var monitors = GetAllMonitorInfo();
- int nMonitors = PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CMONITORS);
- sw.Write(nMonitors);
-
- foreach (var monitor in monitors)
- {
- sw.Write(monitor.Item1);
- sw.Write(monitor.Item2.Left);
- sw.Write(monitor.Item2.Top);
- sw.Write(monitor.Item2.Right);
- sw.Write(monitor.Item2.Bottom);
- }
-
- WINDOWPLACEMENT placement = default;
- PInvoke.GetWindowPlacement(new(WindowHandle), ref placement);
-
- int structSize = Marshal.SizeOf(typeof(WINDOWPLACEMENT));
- IntPtr buffer = Marshal.AllocHGlobal(structSize);
- Marshal.StructureToPtr(placement, buffer, false);
- byte[] placementData = new byte[structSize];
- Marshal.Copy(buffer, placementData, 0, structSize);
- Marshal.FreeHGlobal(buffer);
-
- sw.Write(placementData);
- sw.Flush();
-
- var values = GetDataStore(out _, true);
-
- if (_applicationDataContainer.Containers.ContainsKey("WinUIEx"))
- _applicationDataContainer.Values.Remove("WinUIEx");
-
- values["MainWindowPlacementData"] = Convert.ToBase64String(data.ToArray());
- }
-
- private void RestoreWindowPlacementData()
- {
- // Save window placement only for MainWindow
- if (!GetType().Name.Equals(nameof(MainWindow), StringComparison.OrdinalIgnoreCase))
- return;
-
- var values = GetDataStore(out var oldDataExists, false);
-
- byte[]? data = null;
- if (values.TryGetValue(oldDataExists ? "WindowPersistance_FilesMainWindow" : "MainWindowPlacementData", out object? value))
- {
- if (value is string base64)
- data = Convert.FromBase64String(base64);
- }
-
- if (data is null)
- return;
-
- SystemIO.BinaryReader br = new(new SystemIO.MemoryStream(data));
-
- // Check if monitor layout changed since we stored position
- var monitors = GetAllMonitorInfo();
- int monitorCount = br.ReadInt32();
- int nMonitors = PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CMONITORS);
- if (monitorCount != nMonitors)
- return;
-
- for (int i = 0; i < monitorCount; i++)
- {
- var pMonitor = monitors[i];
- br.ReadString();
- if (pMonitor.Item2.Left != br.ReadDouble() ||
- pMonitor.Item2.Top != br.ReadDouble() ||
- pMonitor.Item2.Right != br.ReadDouble() ||
- pMonitor.Item2.Bottom != br.ReadDouble())
- return;
- }
-
- int structSize = Marshal.SizeOf(typeof(WINDOWPLACEMENT));
- byte[] placementData = br.ReadBytes(structSize);
- IntPtr buffer = Marshal.AllocHGlobal(structSize);
- Marshal.Copy(placementData, 0, buffer, structSize);
- var windowPlacementData = (WINDOWPLACEMENT)Marshal.PtrToStructure(buffer, typeof(WINDOWPLACEMENT))!;
-
- Marshal.FreeHGlobal(buffer);
-
- // Ignore anything by maximized or normal
- if (windowPlacementData.showCmd == (SHOW_WINDOW_CMD)0x0002 /*SW_INVALIDATE*/ &&
- windowPlacementData.flags == WINDOWPLACEMENT_FLAGS.WPF_RESTORETOMAXIMIZED)
- windowPlacementData.showCmd = SHOW_WINDOW_CMD.SW_MAXIMIZE;
- else if (windowPlacementData.showCmd != SHOW_WINDOW_CMD.SW_MAXIMIZE)
- windowPlacementData.showCmd = SHOW_WINDOW_CMD.SW_NORMAL;
-
- PInvoke.SetWindowPlacement(new(WindowHandle), in windowPlacementData);
-
- return;
- }
-
- private IPropertySet GetDataStore(out bool oldDataExists, bool useNewStore = true)
- {
- IPropertySet values;
- oldDataExists = false;
-
- if (_applicationDataContainer.Containers.TryGetValue("Files", out var dataContainer))
- {
- values = dataContainer.Values;
- }
- else if (!useNewStore && _applicationDataContainer.Containers.TryGetValue("WinUIEx", out var oldDataContainer))
- {
- values = oldDataContainer.Values;
- oldDataExists = true;
- }
- else
- {
- values = _applicationDataContainer.CreateContainer(
- "Files",
- ApplicationDataCreateDisposition.Always).Values;
- }
-
- return values;
- }
-
- private unsafe List> GetAllMonitorInfo()
- {
- List> monitors = [];
-
- MONITORENUMPROC monitorEnumProc = new((HMONITOR monitor, HDC deviceContext, RECT* rect, LPARAM data) =>
- {
- MONITORINFOEXW info = default;
- info.monitorInfo.cbSize = (uint)Marshal.SizeOf();
-
- PInvoke.GetMonitorInfo(monitor, (MONITORINFO*)&info);
-
- monitors.Add(new(
- info.szDevice.ToString(),
- new(new Point(rect->left, rect->top), new Point(rect->right, rect->bottom))));
-
- return true;
- });
-
- var pMonitorEnumProc = Marshal.GetFunctionPointerForDelegate(monitorEnumProc);
- var pfnMonitorEnumProc = (delegate* unmanaged[Stdcall])pMonitorEnumProc;
-
- LPARAM lParam = default;
- BOOL fRes = PInvoke.EnumDisplayMonitors(new(nint.Zero), (RECT*)null, pfnMonitorEnumProc, lParam);
- if (!fRes)
- Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
-
- return monitors;
- }
-
- private LRESULT NewWindowProc(HWND param0, uint param1, WPARAM param2, LPARAM param3)
- {
- switch (param1)
- {
- case 0x0018 /*WM_SHOWWINDOW*/ when param2 == (WPARAM)1 && !_isInitialized:
- {
- _isInitialized = true;
- RestoreWindowPlacementData();
- break;
- }
- case 0x0024: /*WM_GETMINMAXINFO*/
- {
- var dpi = PInvoke.GetDpiForWindow(param0);
- float scalingFactor = (float)dpi / 96;
-
- var minMaxInfo = Marshal.PtrToStructure(param3);
- minMaxInfo.ptMinTrackSize.X = (int)(MinWidth * scalingFactor);
- minMaxInfo.ptMinTrackSize.Y = (int)(MinHeight * scalingFactor);
- Marshal.StructureToPtr(minMaxInfo, param3, true);
- break;
- }
- }
-
- var pWindProc = Marshal.GetFunctionPointerForDelegate(_oldWndProc);
- var pfnWndProc = (delegate* unmanaged[Stdcall])pWindProc;
-
- return PInvoke.CallWindowProc(pfnWndProc, param0, param1, param2, param3);
- }
-
- private void WindowEx_Closed(object sender, WindowEventArgs args)
- {
- StoreWindowPlacementData();
- }
-
- public void Dispose()
- {
- Closed -= WindowEx_Closed;
- }
- }
-}
diff --git a/src/Files.App/MainWindow.xaml b/src/Files.App/MainWindow.xaml
index 101a403aba79..376ae4f1d5b7 100644
--- a/src/Files.App/MainWindow.xaml
+++ b/src/Files.App/MainWindow.xaml
@@ -1,10 +1,8 @@
-
diff --git a/src/Files.App/MainWindow.xaml.cs b/src/Files.App/MainWindow.xaml.cs
index 6dcfc8b56310..2abe332d706b 100644
--- a/src/Files.App/MainWindow.xaml.cs
+++ b/src/Files.App/MainWindow.xaml.cs
@@ -4,6 +4,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.UI;
using Microsoft.UI.Windowing;
+using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Animation;
using System.IO;
@@ -15,7 +16,7 @@
namespace Files.App
{
- public sealed partial class MainWindow : WinUIEx.WindowEx
+ public sealed partial class MainWindow : Window
{
private static MainWindow? _Instance;
public static MainWindow Instance => _Instance ??= new();
@@ -28,18 +29,21 @@ public MainWindow()
{
InitializeComponent();
- WindowHandle = WinUIEx.WindowExtensions.GetWindowHandle(this);
- MinHeight = 316;
- MinWidth = 416;
+ WindowHandle = WinRT.Interop.WindowNative.GetWindowHandle(this);
ExtendsContentIntoTitleBar = true;
Title = "Files";
- PersistenceId = "FilesMainWindow";
AppWindow.TitleBar.ButtonBackgroundColor = Colors.Transparent;
AppWindow.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
AppWindow.TitleBar.ButtonPressedBackgroundColor = Colors.Transparent;
AppWindow.TitleBar.ButtonHoverBackgroundColor = Colors.Transparent;
AppWindow.SetIcon(AppLifecycleHelper.AppIconPath);
+ if (AppWindow.Presenter.TryCast() is { } presenter)
+ {
+ presenter.PreferredMinimumHeight = 316;
+ presenter.PreferredMinimumWidth = 416;
+ }
+
WinUIEx.WindowManager.Get(this).WindowMessageReceived += WindowManager_WindowMessageReceived;
}
@@ -201,8 +205,9 @@ public async Task InitializeApplicationAsync(object activatedEventArgs)
Win32Helper.BringToForegroundEx(new(WindowHandle));
}
- if (Windows.Win32.PInvoke.IsIconic(new(WindowHandle)))
- WinUIEx.WindowExtensions.Restore(Instance); // Restore window if minimized
+ if (Windows.Win32.PInvoke.IsIconic(new(WindowHandle)) &&
+ AppWindow.Presenter.TryCast() is { } presenter)
+ presenter.Restore(); // Restore window if minimized
}
private Frame? EnsureWindowIsInitialized()
diff --git a/src/Files.App/Utils/Storage/Helpers/FilePropertiesHelpers.cs b/src/Files.App/Utils/Storage/Helpers/FilePropertiesHelpers.cs
index 5bfc5f15a7e2..0ca4d6535916 100644
--- a/src/Files.App/Utils/Storage/Helpers/FilePropertiesHelpers.cs
+++ b/src/Files.App/Utils/Storage/Helpers/FilePropertiesHelpers.cs
@@ -36,7 +36,7 @@ public static nint GetWindowHandle(Window w)
=> WinRT.Interop.WindowNative.GetWindowHandle(w);
private static TaskCompletionSource? PropertiesWindowsClosingTCS;
- private static readonly BlockingCollection WindowCache = [];
+ private static readonly BlockingCollection WindowCache = [];
///
/// Open properties window
@@ -103,7 +103,16 @@ public static void OpenPropertiesWindow(object item, IShellPage associatedInstan
if (!WindowCache.TryTake(out var propertiesWindow))
{
- propertiesWindow = new(460, 550);
+ propertiesWindow = new();
+
+ if (propertiesWindow.AppWindow.Presenter.TryCast() is { } presenter)
+ {
+ presenter.PreferredMinimumHeight = 460;
+ presenter.PreferredMinimumWidth = 550;
+ presenter.IsMinimizable = false;
+ presenter.IsMaximizable = false;
+ }
+
propertiesWindow.Closed += PropertiesWindow_Closed;
}
@@ -111,13 +120,11 @@ public static void OpenPropertiesWindow(object item, IShellPage associatedInstan
var height = Convert.ToInt32(500 * App.AppModel.AppWindowDPI);
propertiesWindow.AppWindow.Resize(new (width, height));
- propertiesWindow.IsMinimizable = false;
- propertiesWindow.IsMaximizable = false;
propertiesWindow.Content = frame;
propertiesWindow.SystemBackdrop = new AppSystemBackdrop(true);
var appWindow = propertiesWindow.AppWindow;
- appWindow.Title = "Properties".GetLocalizedResource();
+ appWindow.Title = Strings.Properties.GetLocalizedResource();
appWindow.TitleBar.ExtendsContentIntoTitleBar = true;
appWindow.TitleBar.ButtonBackgroundColor = Colors.Transparent;
appWindow.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
@@ -158,7 +165,7 @@ public static void OpenPropertiesWindow(object item, IShellPage associatedInstan
// So instead of destroying the Window object, cache it and reuse it as a workaround.
private static void PropertiesWindow_Closed(object sender, WindowEventArgs args)
{
- if (!App.AppModel.IsMainWindowClosed && sender is WindowEx window)
+ if (!App.AppModel.IsMainWindowClosed && sender is Window window)
{
args.Handled = true;