Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/OddSnap/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
</Style>

<Style x:Key="OddSnapTitleCloseButton" TargetType="Border" BasedOn="{StaticResource OddSnapTitleButton}">
<Setter Property="CornerRadius" Value="0,11,0,0"/>
<Setter Property="CornerRadius" Value="0,7,0,0"/>
</Style>

<Style x:Key="OddSnapTitleButtonIcon" TargetType="Image">
Expand Down
2 changes: 1 addition & 1 deletion src/OddSnap/UI/Controls/OddSnapTitleBar.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<Border x:Name="TitleBarBorder"
MinHeight="40"
Padding="14,0,0,0"
CornerRadius="11,11,0,0"
CornerRadius="7,7,0,0"
Background="Transparent"
MouseLeftButtonDown="TitleBar_MouseLeftButtonDown">
<Grid>
Expand Down
2 changes: 1 addition & 1 deletion src/OddSnap/UI/OcrResultWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
</Style>
</Window.Resources>

<Border x:Name="RootBorder" CornerRadius="12" ClipToBounds="True">
<Border x:Name="RootBorder" CornerRadius="7" ClipToBounds="True">
<Border.Effect>
<DropShadowEffect BlurRadius="24" ShadowDepth="2" Opacity="0.4" Color="Black"/>
</Border.Effect>
Expand Down
32 changes: 25 additions & 7 deletions src/OddSnap/UI/OddSnapWindowChrome.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;

Expand All @@ -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);
Expand All @@ -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;

Expand Down
10 changes: 7 additions & 3 deletions src/OddSnap/UI/SettingsWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -643,8 +643,13 @@

</Window.Resources>

<Border Margin="1" CornerRadius="12">
<Border x:Name="OuterBorder" CornerRadius="12" ClipToBounds="True"
<!--
The border must reach the window edge. The old wrapper had Margin="1",
which inset the content by 1px and left a crescent of desktop visible
at each rounded corner. The radius matches
OddSnapWindowChrome.DefaultCornerRadius.
-->
<Border x:Name="OuterBorder" CornerRadius="7" ClipToBounds="True"
BorderThickness="1">
<Grid>
<Grid.RowDefinitions>
Expand Down Expand Up @@ -4491,5 +4496,4 @@
</Grid>
</Grid>
</Border>
</Border>
</Window>
2 changes: 1 addition & 1 deletion src/OddSnap/UI/UpscaleResultWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<SolidColorBrush x:Key="LoadingTextBrush" Color="#FFFFFFFF"/>
</Window.Resources>

<Border x:Name="RootBorder" CornerRadius="12" ClipToBounds="True">
<Border x:Name="RootBorder" CornerRadius="7" ClipToBounds="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
Expand Down