fix(ui): keep the database Open dialog on screen on a second monitor

The saved-nest browser opened maximized with MaximizedBounds set from the
owner screen's working area in absolute coordinates. Windows reads that
position relative to the monitor, so on a secondary screen the offset was
applied twice and the modal dialog was placed off-screen, leaving the
disabled main window with no way back to it.

Open it instead as a normal window sized to 90% of the owner screen's
working area and centered there; it still clears the taskbar and moves
between monitors like any other window.
This commit is contained in:
aj committed 2026-10-06 14:40:41 -04:00
1 parent 89356371db
commit bb43118451
2 files changed
+46 -5

No files matched your search

@@ -121,6 +121,30 @@ public class SavedNestsFormTests
"The saved-nest dialog test did not complete.");
}
[Fact]
public void OpensAsALargeNormalWindowInsideTheOwnersScreen()
{
StaTestThread.Run(
() =>
{
using var owner = new Form { StartPosition = FormStartPosition.Manual, Bounds = new(40, 40, 400, 300) };
owner.Show();
using var form = new SavedNestsForm(new FakeRepository());
form.Show(owner);
var area = Screen.FromControl(owner).WorkingArea;
// A maximized dialog with fixed MaximizedBounds landed off-screen on a secondary
// monitor, hiding the modal dialog behind a disabled main window.
Assert.Equal(FormWindowState.Normal, form.WindowState);
Assert.True(area.Contains(form.Bounds), $"Dialog bounds {form.Bounds} are outside the working area {area}.");
Assert.True(
form.Width >= area.Width * 8 / 10 && form.Height >= area.Height * 8 / 10,
$"Dialog size {form.Size} is small for the working area {area}.");
},
TestTimeout,
"The saved-nest dialog test did not complete.");
}
private static NestRecord Record(string name) =>
new() { Id = Guid.NewGuid(), Name = name, SavedAt = DateTime.Now };
+22 -5
View File
@@ -69,10 +69,10 @@ public sealed class SavedNestsForm : Form
details = new NestDetailsSession(LoadDetailsAsync);
Text = WindowTitle;
StartPosition = FormStartPosition.CenterParent;
// Placed on the owner's screen in Load; see FitToScreen.
StartPosition = FormStartPosition.Manual;
ClientSize = new Size(1280, 800);
MinimumSize = new Size(800, 560);
WindowState = FormWindowState.Maximized;
MinimizeBox = false;
ShowInTaskbar = false;
@@ -278,9 +278,7 @@ public sealed class SavedNestsForm : Form
Load += (_, _) =>
{
// Keep a maximized dialog's bottom row clear of the taskbar.
var area = Screen.FromControl(Owner ?? this).WorkingArea;
MaximizedBounds = new Rectangle(area.Left, area.Top, area.Width, area.Height - 20);
FitToScreen();
// Minimum sizes are applied once the container has its real height; setting them
// on the default-sized container throws.
@@ -320,6 +318,25 @@ public sealed class SavedNestsForm : Form
return base.ProcessCmdKey(ref msg, keyData);
}
/// <summary>
/// Opens the dialog as a large normal window centered in the working area of the owner's
/// screen, so its bottom row stays clear of the taskbar. It is deliberately not maximized
/// with fixed <see cref="Form.MaximizedBounds"/>: Windows reads those relative to the
/// monitor, so bounds taken from a secondary screen moved the modal dialog off-screen there
/// and left the main window unusable.
/// </summary>
private void FitToScreen()
{
var area = Screen.FromControl(Owner ?? this).WorkingArea;
var width = System.Math.Max(MinimumSize.Width, area.Width * 9 / 10);
var height = System.Math.Max(MinimumSize.Height, area.Height * 9 / 10);
Bounds = new Rectangle(
System.Math.Max(area.Left, area.Left + (area.Width - width) / 2),
System.Math.Max(area.Top, area.Top + (area.Height - height) / 2),
width,
height);
}
private static DataGridView CreateGrid()
{
var grid = new DataGridView