From 657b81c638eaba8cf6ade019b5ebb91b81640c4f Mon Sep 17 00:00:00 2001 From: Ruben Date: Tue, 1 Oct 2024 16:08:42 +0200 Subject: [PATCH] [Avalonia] Multi monitor DPI adjustments #26 --- .../Views/WinMainWindow.axaml.cs | 5 ++ .../Views/WinTitleBar.axaml.cs | 2 +- src/PicView.Avalonia/UI/ScreenHelper.cs | 25 +++----- src/PicView.Avalonia/UI/WindowHelper.cs | 59 ++++++++++++------- .../Views/StartUpMenu.axaml.cs | 2 +- .../ImageSizeCalculationHelper.cs | 8 +-- 6 files changed, 57 insertions(+), 44 deletions(-) diff --git a/src/PicView.Avalonia.Win32/Views/WinMainWindow.axaml.cs b/src/PicView.Avalonia.Win32/Views/WinMainWindow.axaml.cs index 48dff6a7c..2a73d706f 100644 --- a/src/PicView.Avalonia.Win32/Views/WinMainWindow.axaml.cs +++ b/src/PicView.Avalonia.Win32/Views/WinMainWindow.axaml.cs @@ -44,6 +44,11 @@ public WinMainWindow() break; } }); + ScalingChanged += (_, _) => + { + ScreenHelper.ScreenSize = ScreenHelper.GetScreenSize(this); + WindowHelper.SetSize(DataContext as MainViewModel); + }; PointerExited += (_, _) => { MainView.RemoveDragDropView(); diff --git a/src/PicView.Avalonia.Win32/Views/WinTitleBar.axaml.cs b/src/PicView.Avalonia.Win32/Views/WinTitleBar.axaml.cs index c9152832a..d4e8f88bd 100644 --- a/src/PicView.Avalonia.Win32/Views/WinTitleBar.axaml.cs +++ b/src/PicView.Avalonia.Win32/Views/WinTitleBar.axaml.cs @@ -29,6 +29,6 @@ private void MoveWindow(PointerPressedEventArgs e) { return; } - WindowHelper.WindowDragBehavior((Window)VisualRoot, e); + WindowHelper.WindowDragAndDoubleClickBehavior((Window)VisualRoot, e); } } \ No newline at end of file diff --git a/src/PicView.Avalonia/UI/ScreenHelper.cs b/src/PicView.Avalonia/UI/ScreenHelper.cs index 4c924e70f..9f6fc1d44 100644 --- a/src/PicView.Avalonia/UI/ScreenHelper.cs +++ b/src/PicView.Avalonia/UI/ScreenHelper.cs @@ -2,38 +2,29 @@ namespace PicView.Avalonia.UI; -public readonly struct ScreenSize(int width, int height, int workingAreaWidth, int workingAreaHeight, int x, int y, double scaling) +public class ScreenSize(double workingAreaWidth, double workingAreaHeight, double scaling) { - public int Width { get; init; } = width; - public int Height { get; init; } = height; public double WorkingAreaWidth { get; init; } = workingAreaWidth; public double WorkingAreaHeight { get; init; } = workingAreaHeight; public double Scaling { get; init; } = scaling; - - public int X { get; init; } - public int Y { get; init; } } public static class ScreenHelper { - public static ScreenSize ScreenSize { get; set; } - public static ScreenSize GetScreenSize(Window window) + public static ScreenSize? ScreenSize { get; set; } + public static ScreenSize? GetScreenSize(Window window) { - var screen = window.Screens.ScreenFromWindow(window); + var screen = window.Screens.ScreenFromVisual(window); - var monitorWidth = screen.WorkingArea.Width / screen.Scaling; - var monitorHeight = screen.WorkingArea.Height / screen.Scaling; + var monitorWidth = screen.Bounds.Width / screen.Scaling; + var monitorHeight = screen.Bounds.Height / screen.Scaling; - return new ScreenSize + return new ScreenSize(monitorWidth, monitorHeight, screen.Scaling) { - Width = screen.Bounds.Width, - Height = screen.Bounds.Height, WorkingAreaWidth = monitorWidth, WorkingAreaHeight = monitorHeight, - X = screen.Bounds.X, - Y = screen.Bounds.Y, - Scaling = screen.Scaling + Scaling = screen.Scaling, }; } } diff --git a/src/PicView.Avalonia/UI/WindowHelper.cs b/src/PicView.Avalonia/UI/WindowHelper.cs index 53592118b..42d42f00c 100644 --- a/src/PicView.Avalonia/UI/WindowHelper.cs +++ b/src/PicView.Avalonia/UI/WindowHelper.cs @@ -113,7 +113,7 @@ public static void CenterWindowOnScreen(bool horizontal = true) var scalingFactor = screen.Scaling; // Get the current screen's bounds (in physical pixels, not adjusted for scaling) - var screenBounds = screen.Bounds; + var screenBounds = screen.WorkingArea; // Calculate the actual bounds in logical units (adjusting for scaling) var screenWidth = screenBounds.Width / scalingFactor; @@ -135,8 +135,6 @@ public static void CenterWindowOnScreen(bool horizontal = true) { window.Position = new PixelPoint(window.Position.X, (int)centeredY); } - - }); } @@ -393,7 +391,38 @@ public static void Fullscreen(MainViewModel vm, IClassicDesktopStyleApplicationL vm.IsTopToolbarShown = false; // Hide interface in fullscreen. Remember to turn back when exiting fullscreen vm.IsBottomToolbarShown = false; vm.IsInterfaceShown = false; - Dispatcher.UIThread.Post(() => CenterWindowOnScreen()); + Dispatcher.UIThread.Post(() => + { + // Get the screen that the window is currently on + var window = desktop.MainWindow; + var screens = desktop.MainWindow.Screens; + var screen = screens.ScreenFromVisual(window); + + if (screen == null) + { + return; // No screen found (edge case) + } + + // Get the scaling factor of the screen (DPI scaling) + var scalingFactor = screen.Scaling; + + // Get the current screen's bounds (in physical pixels, not adjusted for scaling) + var screenBounds = screen.Bounds; + + // Calculate the actual bounds in logical units (adjusting for scaling) + var screenWidth = screenBounds.Width / scalingFactor; + var screenHeight = screenBounds.Height / scalingFactor; + + // Get the size of the window + var windowSize = window.ClientSize; + + // Calculate the position to center the window on the screen + var centeredX = screenBounds.X + (screenWidth - windowSize.Width) / 2; + var centeredY = screenBounds.Y + (screenHeight - windowSize.Height) / 2; + + // Set the window's new position + window.Position = new PixelPoint((int)centeredX, (int)centeredY); + }); // TODO: Add Fullscreen mode for Windows (and maybe for Linux?) // macOS fullscreen version already works nicely } @@ -515,25 +544,13 @@ public static void SetSize(double width, double height, double secondWidth, doub { return; } + var screenSize = ScreenHelper.ScreenSize; double desktopMinWidth = 0, desktopMinHeight = 0, containerWidth = 0, containerHeight = 0; - if (Dispatcher.UIThread.CheckAccess()) - { - desktopMinWidth = desktop.MainWindow.MinWidth; - desktopMinHeight = desktop.MainWindow.MinHeight; - containerWidth = mainView.Bounds.Width; - containerHeight = mainView.Bounds.Height; - } - else - { - Dispatcher.UIThread.Invoke(() => - { - desktopMinWidth = desktop.MainWindow.MinWidth; - desktopMinHeight = desktop.MainWindow.MinHeight; - containerWidth = mainView.Bounds.Width; - containerHeight = mainView.Bounds.Height; - }, DispatcherPriority.Send); - } + desktopMinWidth = desktop.MainWindow.MinWidth; + desktopMinHeight = desktop.MainWindow.MinHeight; + containerWidth = mainView.Bounds.Width; + containerHeight = mainView.Bounds.Height; if (double.IsNaN(containerWidth) || double.IsNaN(containerHeight) || double.IsNaN(width) || double.IsNaN(height)) { diff --git a/src/PicView.Avalonia/Views/StartUpMenu.axaml.cs b/src/PicView.Avalonia/Views/StartUpMenu.axaml.cs index 58691f118..5424a296f 100644 --- a/src/PicView.Avalonia/Views/StartUpMenu.axaml.cs +++ b/src/PicView.Avalonia/Views/StartUpMenu.axaml.cs @@ -135,7 +135,7 @@ public void ResponsiveSize(double width, double height) vm.TitleMaxWidth = ImageSizeCalculationHelper.GetTitleMaxWidth(vm.RotationAngle, width, height, desktop.MainWindow.MinWidth, desktop.MainWindow.MinHeight, ImageSizeCalculationHelper.GetInterfaceSize(), - desktop.MainWindow.Width); + desktop.MainWindow.Width, ScreenHelper.ScreenSize.Scaling); return; diff --git a/src/PicView.Core/Calculations/ImageSizeCalculationHelper.cs b/src/PicView.Core/Calculations/ImageSizeCalculationHelper.cs index 888955ee8..4116cc2b0 100644 --- a/src/PicView.Core/Calculations/ImageSizeCalculationHelper.cs +++ b/src/PicView.Core/Calculations/ImageSizeCalculationHelper.cs @@ -41,7 +41,7 @@ public static ImageSize GetImageSize(double width, var fullscreen = SettingsHelper.Settings.WindowProperties.Fullscreen || SettingsHelper.Settings.WindowProperties.Maximized; - + var borderSpaceHeight = fullscreen ? 0 : uiTopSize + uiBottomSize + galleryHeight; var borderSpaceWidth = fullscreen ? 0 : padding; @@ -151,7 +151,7 @@ public static ImageSize GetImageSize(double width, } var titleMaxWidth = GetTitleMaxWidth(rotationAngle, xWidth, xHeight, monitorMinWidth, monitorMinHeight, - interfaceSize, containerWidth); + interfaceSize, containerWidth, dpiScaling); return new ImageSize(xWidth, xHeight, 0, scrollWidth, scrollHeight, titleMaxWidth, margin, aspectRatio); } @@ -290,7 +290,7 @@ public static ImageSize GetImageSize(double width, } var titleMaxWidth = GetTitleMaxWidth(rotationAngle, combinedWidth, xHeight, monitorMinWidth, - monitorMinHeight, interfaceSize, containerWidth); + monitorMinHeight, interfaceSize, containerWidth, dpiScaling); var margin = firstSize.Height > secondSize.Height ? firstSize.Margin : secondSize.Margin; return new ImageSize(combinedWidth, xHeight, xWidth2, scrollWidth, scrollHeight, titleMaxWidth, margin, @@ -299,7 +299,7 @@ public static ImageSize GetImageSize(double width, public static double GetTitleMaxWidth(double rotationAngle, double width, double height, double monitorMinWidth, - double monitorMinHeight, double interfaceSize, double containerWidth) + double monitorMinHeight, double interfaceSize, double containerWidth, double dpiScaling) { double titleMaxWidth; var maximized = SettingsHelper.Settings.WindowProperties.Fullscreen ||