From 9ece3f933c7e6ef138ac0a1a160ad831dd41dba2 Mon Sep 17 00:00:00 2001 From: obesity40 <253336873+obesity40@users.noreply.github.com> Date: Thu, 1 Oct 2026 12:00:57 +0800 Subject: [PATCH 1/2] fix(ui): remove gaps at rounded window corners The root border was wrapped in a Border with Margin="1", which inset the content by one pixel and left a crescent of desktop visible at each rounded corner. Drop the wrapper and match the content radius to the window radius (7px). On Windows 11 DWM already rounds the window, so the extra region clip only fought it; keep the manual region for Windows 10 and recompute it when UiScale changes. --- src/OddSnap/UI/OcrResultWindow.xaml | 2 +- src/OddSnap/UI/OddSnapWindowChrome.cs | 32 +++++++++++++++++++------ src/OddSnap/UI/SettingsWindow.xaml | 10 +++++--- src/OddSnap/UI/UpscaleResultWindow.xaml | 2 +- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/OddSnap/UI/OcrResultWindow.xaml b/src/OddSnap/UI/OcrResultWindow.xaml index 3a9cc28a..ba1f3459 100644 --- a/src/OddSnap/UI/OcrResultWindow.xaml +++ b/src/OddSnap/UI/OcrResultWindow.xaml @@ -92,7 +92,7 @@ - + diff --git a/src/OddSnap/UI/OddSnapWindowChrome.cs b/src/OddSnap/UI/OddSnapWindowChrome.cs index 342c4111..71261d04 100644 --- a/src/OddSnap/UI/OddSnapWindowChrome.cs +++ b/src/OddSnap/UI/OddSnapWindowChrome.cs @@ -7,20 +7,20 @@ namespace OddSnap.UI; public static class OddSnapWindowChrome { - private const double DefaultCornerRadius = 12; + private const double DefaultCornerRadius = 7; - public static void Apply(Window window) + public static void Apply(Window window, double cornerRadius = DefaultCornerRadius) { WindowChrome.SetWindowChrome(window, new WindowChrome { CaptionHeight = 0, - CornerRadius = new CornerRadius(DefaultCornerRadius), + CornerRadius = new CornerRadius(cornerRadius), GlassFrameThickness = new Thickness(0), ResizeBorderThickness = new Thickness(8), UseAeroCaptionButtons = false }); - ApplyRoundedCorners(window, DefaultCornerRadius); + ApplyRoundedCorners(window, cornerRadius); } public static void ApplyRoundedCorners(Window window, double radius) @@ -35,6 +35,10 @@ void ApplyCurrentRegion() Dwm.TrySetWindowCornerPreference(hwnd, Dwm.DWMWCP_ROUND); Dwm.TrySetImmersiveDarkMode(hwnd, Theme.IsDark); + + // On Windows 11 DWM rounds layered windows themselves, so clipping + // a region on top of that would leave a crescent wherever the two + // roundings disagree. Only Windows 10 needs the manual region. if (OperatingSystem.IsWindowsVersionAtLeast(10, 0, 22000)) return; @@ -43,8 +47,15 @@ void ApplyCurrentRegion() window.SourceInitialized += (_, _) => ApplyCurrentRegion(); window.SizeChanged += (_, _) => ApplyCurrentRegion(); + + // On Windows 10 the region must be recomputed when the UI scale + // changes, because the content rounding scales with it. + void OnUiScaleChanged(double _) => ApplyCurrentRegion(); + UiScale.Changed += OnUiScaleChanged; + window.Closed += (_, _) => { + UiScale.Changed -= OnUiScaleChanged; var hwnd = new WindowInteropHelper(window).Handle; if (hwnd != IntPtr.Zero) User32.SetWindowRgn(hwnd, IntPtr.Zero, true); @@ -60,10 +71,17 @@ private static void SetRoundedWindowRegion(Window window, IntPtr hwnd, double ra var transform = source?.CompositionTarget?.TransformToDevice ?? System.Windows.Media.Matrix.Identity; int width = Math.Max(1, (int)Math.Ceiling(window.ActualWidth * transform.M11)); int height = Math.Max(1, (int)Math.Ceiling(window.ActualHeight * transform.M22)); - int diameterX = Math.Max(1, (int)Math.Round(radius * 2 * transform.M11)); - int diameterY = Math.Max(1, (int)Math.Round(radius * 2 * transform.M22)); - var region = Gdi32.CreateRoundRectRgn(0, 0, width + 1, height + 1, diameterX, diameterY); + // The root element is scaled by UiScale via a LayoutTransform, so the + // visible corner radius is radius * uiScale in layout units. + var effectiveRadius = radius * UiScale.Current; + + // GDI takes the ellipse *diameter*; WPF's CornerRadius is the radius. + int diameterX = Math.Max(2, (int)Math.Round(effectiveRadius * 2 * transform.M11)); + int diameterY = Math.Max(2, (int)Math.Round(effectiveRadius * 2 * transform.M22)); + + // Use the exact device bounds so the region lines up with the content. + var region = Gdi32.CreateRoundRectRgn(0, 0, width, height, diameterX, diameterY); if (region == IntPtr.Zero) return; diff --git a/src/OddSnap/UI/SettingsWindow.xaml b/src/OddSnap/UI/SettingsWindow.xaml index 4c3e11e5..39820019 100644 --- a/src/OddSnap/UI/SettingsWindow.xaml +++ b/src/OddSnap/UI/SettingsWindow.xaml @@ -643,8 +643,13 @@ - - + @@ -4491,5 +4496,4 @@ - diff --git a/src/OddSnap/UI/UpscaleResultWindow.xaml b/src/OddSnap/UI/UpscaleResultWindow.xaml index e3038267..8ca85e1e 100644 --- a/src/OddSnap/UI/UpscaleResultWindow.xaml +++ b/src/OddSnap/UI/UpscaleResultWindow.xaml @@ -22,7 +22,7 @@ - + From 3e02461b40e193e61c9c3b2fa1ae374b8fe6eee2 Mon Sep 17 00:00:00 2001 From: obesity40 <253336873+obesity40@users.noreply.github.com> Date: Thu, 8 Oct 2026 17:45:00 +0800 Subject: [PATCH 2/2] fix(ui): align title bar and close button corners with window radius --- src/OddSnap/App.xaml | 2 +- src/OddSnap/UI/Controls/OddSnapTitleBar.xaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OddSnap/App.xaml b/src/OddSnap/App.xaml index 71e62bb4..ce66b318 100644 --- a/src/OddSnap/App.xaml +++ b/src/OddSnap/App.xaml @@ -85,7 +85,7 @@