From 95a9a8a2b0e56d298849d527b505b2da23b4228c Mon Sep 17 00:00:00 2001 From: Samuel Chapleau Date: Fri, 26 May 2023 12:46:43 -0700 Subject: [PATCH] Use effective pixels for unsupported previewer (#26345) --- .../Peek.Common/Constants/WindowConstants.cs | 2 +- .../Peek.FilePreviewer/FilePreview.xaml.cs | 4 +- .../Peek.FilePreviewer/Models/PreviewSize.cs | 15 ++++++ .../Models/PreviewSizeChangedArgs.cs | 6 +-- .../Previewers/Interfaces/IPreviewer.cs | 3 +- .../MediaPreviewer/ImagePreviewer.cs | 5 +- .../MediaPreviewer/VideoPreviewer.cs | 6 ++- .../UnsupportedFilePreviewer.cs | 5 +- .../WebBrowserPreviewer.cs | 6 +-- .../peek/Peek.UI/Extensions/HWNDExtensions.cs | 7 +++ .../Peek.UI/Extensions/WindowExtensions.cs | 5 +- src/modules/peek/Peek.UI/MainWindow.xaml.cs | 49 +++++++++++-------- 12 files changed, 72 insertions(+), 41 deletions(-) create mode 100644 src/modules/peek/Peek.FilePreviewer/Models/PreviewSize.cs diff --git a/src/modules/peek/Peek.Common/Constants/WindowConstants.cs b/src/modules/peek/Peek.Common/Constants/WindowConstants.cs index f734912215..771b959433 100644 --- a/src/modules/peek/Peek.Common/Constants/WindowConstants.cs +++ b/src/modules/peek/Peek.Common/Constants/WindowConstants.cs @@ -8,7 +8,7 @@ namespace Peek.Common.Constants { public const double MaxWindowToMonitorRatio = 0.80; public const double MinWindowHeight = 500; - public const double MinWindowWidth = 680; + public const double MinWindowWidth = 500; public const double WindowWidthContentPadding = 7; public const double WindowHeightContentPadding = 16; } diff --git a/src/modules/peek/Peek.FilePreviewer/FilePreview.xaml.cs b/src/modules/peek/Peek.FilePreviewer/FilePreview.xaml.cs index 4a70b691ad..cac4830697 100644 --- a/src/modules/peek/Peek.FilePreviewer/FilePreview.xaml.cs +++ b/src/modules/peek/Peek.FilePreviewer/FilePreview.xaml.cs @@ -167,8 +167,8 @@ namespace Peek.FilePreviewer { if (Previewer != null) { - var size = await Previewer.GetPreviewSizeAsync(cancellationToken); - PreviewSizeChanged?.Invoke(this, new PreviewSizeChangedArgs(size)); + var previewSize = await Previewer.GetPreviewSizeAsync(cancellationToken); + PreviewSizeChanged?.Invoke(this, new PreviewSizeChangedArgs(previewSize)); } } diff --git a/src/modules/peek/Peek.FilePreviewer/Models/PreviewSize.cs b/src/modules/peek/Peek.FilePreviewer/Models/PreviewSize.cs new file mode 100644 index 0000000000..0fe4c2ffcb --- /dev/null +++ b/src/modules/peek/Peek.FilePreviewer/Models/PreviewSize.cs @@ -0,0 +1,15 @@ +// 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 Windows.Foundation; + +namespace Peek.FilePreviewer.Models +{ + public record PreviewSize + { + public Size? MonitorSize { get; init; } + + public bool UseEffectivePixels { get; init; } + } +} diff --git a/src/modules/peek/Peek.FilePreviewer/Models/PreviewSizeChangedArgs.cs b/src/modules/peek/Peek.FilePreviewer/Models/PreviewSizeChangedArgs.cs index 7a80e73dd8..bad9a4bff0 100644 --- a/src/modules/peek/Peek.FilePreviewer/Models/PreviewSizeChangedArgs.cs +++ b/src/modules/peek/Peek.FilePreviewer/Models/PreviewSizeChangedArgs.cs @@ -8,11 +8,11 @@ namespace Peek.FilePreviewer.Models { public class PreviewSizeChangedArgs { - public PreviewSizeChangedArgs(Size? windowSizeRequested) + public PreviewSizeChangedArgs(PreviewSize previewSize) { - WindowSizeRequested = windowSizeRequested; + PreviewSize = previewSize; } - public Size? WindowSizeRequested { get; init; } + public PreviewSize PreviewSize { get; init; } } } diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/IPreviewer.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/IPreviewer.cs index 61988e65c5..348c39d987 100644 --- a/src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/IPreviewer.cs +++ b/src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/IPreviewer.cs @@ -6,6 +6,7 @@ using System; using System.ComponentModel; using System.Threading; using System.Threading.Tasks; +using Peek.FilePreviewer.Models; using Windows.Foundation; namespace Peek.FilePreviewer.Previewers @@ -16,7 +17,7 @@ namespace Peek.FilePreviewer.Previewers public static bool IsFileTypeSupported(string fileExt) => throw new NotImplementedException(); - public Task GetPreviewSizeAsync(CancellationToken cancellationToken); + public Task GetPreviewSizeAsync(CancellationToken cancellationToken); Task LoadPreviewAsync(CancellationToken cancellationToken); diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/MediaPreviewer/ImagePreviewer.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/MediaPreviewer/ImagePreviewer.cs index 16ebee4c0b..8b9073031f 100644 --- a/src/modules/peek/Peek.FilePreviewer/Previewers/MediaPreviewer/ImagePreviewer.cs +++ b/src/modules/peek/Peek.FilePreviewer/Previewers/MediaPreviewer/ImagePreviewer.cs @@ -15,6 +15,7 @@ using Peek.Common.Extensions; using Peek.Common.Helpers; using Peek.Common.Models; using Peek.FilePreviewer.Exceptions; +using Peek.FilePreviewer.Models; using Peek.FilePreviewer.Previewers.Helpers; using Peek.FilePreviewer.Previewers.Interfaces; using Windows.Foundation; @@ -68,7 +69,7 @@ namespace Peek.FilePreviewer.Previewers GC.SuppressFinalize(this); } - public async Task GetPreviewSizeAsync(CancellationToken cancellationToken) + public async Task GetPreviewSizeAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (IsSvg(Item)) @@ -88,7 +89,7 @@ namespace Peek.FilePreviewer.Previewers } } - return ImageSize; + return new PreviewSize { MonitorSize = ImageSize }; } public async Task LoadPreviewAsync(CancellationToken cancellationToken) diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/MediaPreviewer/VideoPreviewer.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/MediaPreviewer/VideoPreviewer.cs index 7f5e6ae87f..196589df96 100644 --- a/src/modules/peek/Peek.FilePreviewer/Previewers/MediaPreviewer/VideoPreviewer.cs +++ b/src/modules/peek/Peek.FilePreviewer/Previewers/MediaPreviewer/VideoPreviewer.cs @@ -13,6 +13,7 @@ using Microsoft.UI.Dispatching; using Peek.Common.Extensions; using Peek.Common.Helpers; using Peek.Common.Models; +using Peek.FilePreviewer.Models; using Peek.FilePreviewer.Previewers.Interfaces; using Windows.Foundation; using Windows.Media.Core; @@ -74,10 +75,11 @@ namespace Peek.FilePreviewer.Previewers } } - public async Task GetPreviewSizeAsync(CancellationToken cancellationToken) + public async Task GetPreviewSizeAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - return await Task.Run(Item.GetVideoSize); + var videoSize = await Task.Run(Item.GetVideoSize); + return new PreviewSize { MonitorSize = videoSize }; } public async Task CopyAsync() diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/UnsupportedFilePreviewer/UnsupportedFilePreviewer.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/UnsupportedFilePreviewer/UnsupportedFilePreviewer.cs index 8fa67383a5..9a45b85351 100644 --- a/src/modules/peek/Peek.FilePreviewer/Previewers/UnsupportedFilePreviewer/UnsupportedFilePreviewer.cs +++ b/src/modules/peek/Peek.FilePreviewer/Previewers/UnsupportedFilePreviewer/UnsupportedFilePreviewer.cs @@ -51,10 +51,11 @@ namespace Peek.FilePreviewer.Previewers GC.SuppressFinalize(this); } - public Task GetPreviewSizeAsync(CancellationToken cancellationToken) + public Task GetPreviewSizeAsync(CancellationToken cancellationToken) { Size? size = new Size(680, 500); - return Task.FromResult(size); + var previewSize = new PreviewSize { MonitorSize = size, UseEffectivePixels = true }; + return Task.FromResult(previewSize); } public async Task LoadPreviewAsync(CancellationToken cancellationToken) diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/WebBrowserPreviewer.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/WebBrowserPreviewer.cs index a00e637742..c7eefdebcf 100644 --- a/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/WebBrowserPreviewer.cs +++ b/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/WebBrowserPreviewer.cs @@ -12,6 +12,7 @@ using Peek.Common.Constants; using Peek.Common.Extensions; using Peek.Common.Helpers; using Peek.Common.Models; +using Peek.FilePreviewer.Models; using Windows.Foundation; namespace Peek.FilePreviewer.Previewers @@ -76,10 +77,9 @@ namespace Peek.FilePreviewer.Previewers private Task? DisplayInfoTask { get; set; } - public Task GetPreviewSizeAsync(CancellationToken cancellationToken) + public Task GetPreviewSizeAsync(CancellationToken cancellationToken) { - Size? size = null; - return Task.FromResult(size); + return Task.FromResult(new PreviewSize { MonitorSize = null }); } public async Task LoadPreviewAsync(CancellationToken cancellationToken) diff --git a/src/modules/peek/Peek.UI/Extensions/HWNDExtensions.cs b/src/modules/peek/Peek.UI/Extensions/HWNDExtensions.cs index 8674e63303..315787327b 100644 --- a/src/modules/peek/Peek.UI/Extensions/HWNDExtensions.cs +++ b/src/modules/peek/Peek.UI/Extensions/HWNDExtensions.cs @@ -58,5 +58,12 @@ namespace Peek.UI.Extensions PInvoke.GetMonitorInfo(monitor, ref info); return new Size(info.rcMonitor.Size.Width, info.rcMonitor.Size.Height); } + + internal static double GetMonitorScale(this HWND hwnd) + { + var dpi = PInvoke.GetDpiForWindow(hwnd); + var scalingFactor = dpi / 96d; + return scalingFactor; + } } } diff --git a/src/modules/peek/Peek.UI/Extensions/WindowExtensions.cs b/src/modules/peek/Peek.UI/Extensions/WindowExtensions.cs index b113003c1f..71dbd6ca07 100644 --- a/src/modules/peek/Peek.UI/Extensions/WindowExtensions.cs +++ b/src/modules/peek/Peek.UI/Extensions/WindowExtensions.cs @@ -17,10 +17,7 @@ namespace Peek.UI.Extensions public static double GetMonitorScale(this Window window) { var hwnd = new HWND(window.GetWindowHandle()); - var dpi = PInvoke.GetDpiForWindow(new HWND(hwnd)); - double scalingFactor = dpi / 96d; - - return scalingFactor; + return hwnd.GetMonitorScale(); } public static void BringToForeground(this Window window) diff --git a/src/modules/peek/Peek.UI/MainWindow.xaml.cs b/src/modules/peek/Peek.UI/MainWindow.xaml.cs index 76ac8160fc..5376b41e52 100644 --- a/src/modules/peek/Peek.UI/MainWindow.xaml.cs +++ b/src/modules/peek/Peek.UI/MainWindow.xaml.cs @@ -2,6 +2,7 @@ // 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 interop; using Microsoft.PowerToys.Telemetry; using Microsoft.UI.Windowing; @@ -104,42 +105,48 @@ namespace Peek.UI private void FilePreviewer_PreviewSizeChanged(object sender, PreviewSizeChangedArgs e) { var foregroundWindowHandle = Windows.Win32.PInvoke.GetForegroundWindow(); - var monitorSize = foregroundWindowHandle.GetMonitorSize(); + var monitorScale = foregroundWindowHandle.GetMonitorScale(); // If no size is requested, try to fit to the monitor size. - Size requestedSize = e.WindowSizeRequested ?? monitorSize; + Size requestedSize = e.PreviewSize.MonitorSize ?? monitorSize; + var contentScale = e.PreviewSize.UseEffectivePixels ? 1 : monitorScale; + Size scaledRequestedSize = new Size(requestedSize.Width / contentScale, requestedSize.Height / contentScale); - double titleBarHeight = TitleBarControl.ActualHeight; - - double maxContentWidth = monitorSize.Width * WindowConstants.MaxWindowToMonitorRatio; - double maxContentHeight = (monitorSize.Height - titleBarHeight) * WindowConstants.MaxWindowToMonitorRatio; - Size maxContentSize = new(maxContentWidth, maxContentHeight); - - double minContentWidth = WindowConstants.MinWindowWidth; - double minContentHeight = WindowConstants.MinWindowHeight - titleBarHeight; - Size minContentSize = new(minContentWidth, minContentHeight); - - Size adjustedContentSize = requestedSize.Fit(maxContentSize, minContentSize); - - // TODO: Only re-center if window has not been resized by user (or use design-defined logic). // TODO: Investigate why portrait images do not perfectly fit edge-to-edge - double monitorScale = this.GetMonitorScale(); - double scaledWindowWidth = adjustedContentSize.Width / monitorScale; - double scaledWindowHeight = adjustedContentSize.Height / monitorScale; + Size monitorMinContentSize = GetMonitorMinContentSize(monitorScale); + Size monitorMaxContentSize = GetMonitorMaxContentSize(monitorSize, monitorScale); + Size adjustedContentSize = scaledRequestedSize.Fit(monitorMaxContentSize, monitorMinContentSize); - double desiredScaledHeight = scaledWindowHeight + titleBarHeight + WindowConstants.WindowWidthContentPadding; - double desiredScaledWidth = scaledWindowWidth + WindowConstants.WindowHeightContentPadding; + var titleBarHeight = TitleBarControl.ActualHeight; + var desiredWindowHeight = adjustedContentSize.Height + titleBarHeight + WindowConstants.WindowWidthContentPadding; + var desiredWindowWidth = adjustedContentSize.Width + WindowConstants.WindowHeightContentPadding; if (!TitleBarControl.Pinned) { - this.CenterOnMonitor(foregroundWindowHandle, desiredScaledWidth, desiredScaledHeight); // re-center if not pinned + this.CenterOnMonitor(foregroundWindowHandle, desiredWindowWidth, desiredWindowHeight); } this.Show(); this.BringToForeground(); } + private Size GetMonitorMaxContentSize(Size monitorSize, double scaling) + { + var titleBarHeight = TitleBarControl.ActualHeight; + var maxContentWidth = monitorSize.Width * WindowConstants.MaxWindowToMonitorRatio; + var maxContentHeight = (monitorSize.Height - titleBarHeight) * WindowConstants.MaxWindowToMonitorRatio; + return new Size(maxContentWidth / scaling, maxContentHeight / scaling); + } + + private Size GetMonitorMinContentSize(double scaling) + { + var titleBarHeight = TitleBarControl.ActualHeight; + var minContentWidth = WindowConstants.MinWindowWidth; + var minContentHeight = WindowConstants.MinWindowHeight - titleBarHeight; + return new Size(minContentWidth / scaling, minContentHeight / scaling); + } + /// /// Handle AppWindow closing to prevent app termination on close. ///