diff --git a/src/Everything2Everything.App/Views/DiagnoseWindow.xaml b/src/Everything2Everything.App/Views/DiagnoseWindow.xaml
index 0ef9e94..3e10c7a 100644
--- a/src/Everything2Everything.App/Views/DiagnoseWindow.xaml
+++ b/src/Everything2Everything.App/Views/DiagnoseWindow.xaml
@@ -23,7 +23,7 @@
-
+
diff --git a/src/Everything2Everything.App/Views/FormatShiftTheme.xaml b/src/Everything2Everything.App/Views/FormatShiftTheme.xaml
index c903571..41ada10 100644
--- a/src/Everything2Everything.App/Views/FormatShiftTheme.xaml
+++ b/src/Everything2Everything.App/Views/FormatShiftTheme.xaml
@@ -1,6 +1,7 @@
@@ -577,16 +578,19 @@
+
+
-
+
+
+ VerticalAlignment="Stretch">
@@ -608,8 +612,12 @@
-
-
+
+
@@ -626,23 +634,18 @@
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
diff --git a/src/Everything2Everything.App/Views/QuickOptionsWindow.xaml b/src/Everything2Everything.App/Views/QuickOptionsWindow.xaml
index 8adf646..ba98883 100644
--- a/src/Everything2Everything.App/Views/QuickOptionsWindow.xaml
+++ b/src/Everything2Everything.App/Views/QuickOptionsWindow.xaml
@@ -20,7 +20,7 @@
-
+
diff --git a/src/Everything2Everything.App/Views/QuickProgressWindow.xaml b/src/Everything2Everything.App/Views/QuickProgressWindow.xaml
index f4d5a7a..637fd15 100644
--- a/src/Everything2Everything.App/Views/QuickProgressWindow.xaml
+++ b/src/Everything2Everything.App/Views/QuickProgressWindow.xaml
@@ -22,7 +22,7 @@
-
+
diff --git a/src/Everything2Everything.Tests/UnifiedTitleBarTests.cs b/src/Everything2Everything.Tests/UnifiedTitleBarTests.cs
index 2c8c2de..e195779 100644
--- a/src/Everything2Everything.Tests/UnifiedTitleBarTests.cs
+++ b/src/Everything2Everything.Tests/UnifiedTitleBarTests.cs
@@ -3,6 +3,7 @@ using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
+using System.Windows.Media;
using System.Xml.Linq;
using Everything2Everything.App.Views;
using Everything2Everything.Core;
@@ -276,6 +277,112 @@ public class UnifiedTitleBarTests
});
}
+ [Fact]
+ public void SettingsWindow_TitleBar_MustDisplayProperlyAlignedHeaderAndCloseButton()
+ {
+ RunOnSta(() =>
+ {
+ var store = new FakeSettingsStore();
+ var window = new SettingsWindow(store);
+
+ var content = (UIElement)window.Content;
+ content.Measure(new Size(560, 720));
+ content.Arrange(new Rect(0, 0, 560, 720));
+
+ var titleBar = FindLogicalChild(window);
+ Assert.NotNull(titleBar);
+ titleBar.ApplyTemplate();
+
+ // 1. TitleBar height must be 42px
+ Assert.Equal(42.0, titleBar.ActualHeight);
+
+ // 2. PART_MainGrid must stretch to 42px
+ var mainGrid = (FrameworkElement)titleBar.Template.FindName("PART_MainGrid", titleBar);
+ Assert.NotNull(mainGrid);
+ Assert.Equal(42.0, mainGrid.ActualHeight);
+
+ // 3. Find the rendered TextBlock with text "설정"
+ var textBlocks = FindVisualChildren(titleBar).Where(t => t.Text == "설정").ToList();
+ Assert.NotEmpty(textBlocks);
+ var titleTb = textBlocks.First();
+
+ // 4. TextBlock "설정" must not be at X=0 (must have left padding/margin >= 12px)
+ var textPt = titleTb.TransformToAncestor(titleBar).Transform(new Point(0, 0));
+ Assert.True(textPt.X >= 12.0, $"Title text X coordinate ({textPt.X}px) must be >= 12px to prevent touching window edge.");
+
+ var closeBtn = (FrameworkElement)titleBar.Template.FindName("PART_CloseButton", titleBar);
+ Assert.NotNull(closeBtn);
+ Assert.Equal(Visibility.Visible, closeBtn.Visibility);
+
+ // 5. Title text center Y and Close button center Y must match within 2.0px tolerance
+ var textCenterY = textPt.Y + titleTb.ActualHeight / 2.0;
+ var closeCenterY = closeBtn.TransformToAncestor(titleBar).Transform(new Point(0, closeBtn.ActualHeight / 2.0)).Y;
+ Assert.True(Math.Abs(textCenterY - closeCenterY) <= 2.0,
+ $"Title text CenterY ({textCenterY:F1}px) and CloseButton CenterY ({closeCenterY:F1}px) must match within 2px.");
+ });
+ }
+
+ [Fact]
+ public void DiagnoseWindow_TitleBar_MustHaveStandardHeightAndButtons()
+ {
+ RunOnSta(() =>
+ {
+ var engine = Everything2EverythingBootstrap.CreateDefault();
+ var window = new DiagnoseWindow(engine);
+
+ var content = (UIElement)window.Content;
+ content.Measure(new Size(680, 580));
+ content.Arrange(new Rect(0, 0, 680, 580));
+
+ var titleBar = FindLogicalChild(window);
+ Assert.NotNull(titleBar);
+ titleBar.ApplyTemplate();
+
+ // Height must be standard 42px (not hardcoded 32px)
+ Assert.Equal(42.0, titleBar.ActualHeight);
+ Assert.False(titleBar.ShowMaximize);
+ Assert.False(titleBar.ShowMinimize);
+ });
+ }
+
+ [Fact]
+ public void QuickOptionsWindow_TitleBar_MustHaveStandardHeightAndButtons()
+ {
+ RunOnSta(() =>
+ {
+ var store = new FakeSettingsStore();
+ var window = new QuickOptionsWindow(".mp4", 1, store);
+
+ var content = (UIElement)window.Content;
+ content.Measure(new Size(380, 500));
+ content.Arrange(new Rect(0, 0, 380, 500));
+
+ var titleBar = FindLogicalChild(window);
+ Assert.NotNull(titleBar);
+ titleBar.ApplyTemplate();
+
+ Assert.Equal(42.0, titleBar.ActualHeight);
+ Assert.False(titleBar.ShowMaximize);
+ Assert.False(titleBar.ShowMinimize);
+ });
+ }
+
+
+ private static IEnumerable FindVisualChildren(DependencyObject parent) where T : DependencyObject
+ {
+ int count = VisualTreeHelper.GetChildrenCount(parent);
+ for (int i = 0; i < count; i++)
+ {
+ var child = VisualTreeHelper.GetChild(parent, i);
+ if (child is T typed) yield return typed;
+ foreach (var descendant in FindVisualChildren(child))
+ {
+ yield return descendant;
+ }
+ }
+ }
+
+
private static bool IsDescendantOf(DependencyObject? node, DependencyObject targetAncestor)
{
while (node != null)