fix #376/#388 review round: post-condition truth, idempotence, one
position memory, unified monitor, maximized restore; AD-92
Dual-lens Opus review of e56aa511 (reports committed under
docs/research/). The consolidated corrections:
- Mechanism M1 (load-bearing): on Windows, Silk's GLFW error callback
QUEUES exceptions on a static list instead of throwing - they detonate
later at window close, which is exactly #388's original two-stage
crash shape. catch(GlfwException) was dead code here and a failed
SetWindowMonitor "succeeded". Success is now judged by the NATIVE
POST-CONDITION (GetWindowMonitor after the call) on both enter and
exit; the catches remain only for the throwing platforms.
- M2 (both lenses): same-mode fullscreen re-apply is a no-op BEFORE any
native work (new IDisplayModeSwitcher.CurrentFullscreenMode). Every
Display-backed Config row applies per change - sliders per DRAG TICK -
so without this every tick while fullscreen re-issued a real
display-mode change.
- M3/M5 (both): the remembered windowed placement is process state (two
target instances exist - startup and live-save); a fullscreen boot now
exits through either instance to the real placement, not the (60,60)
literal.
- M4 (both): the switcher resolves the WINDOW'S monitor (attached
monitor when fullscreen, else IWindow.Monitor's index into the GLFW
array - the same monitor DisplayModeCatalog enumerated), primary only
as a last resort; the offered-list/switch-target mismatch is gone.
- Blast M2b: the offered-mode validator falls back to the SAME static
ladder the dropdown falls back to - Full Screen is no longer a
permanent silent no-op on catalog-less hosts (the switcher's own
monitor-mode-list check remains the hard guard).
- Blast M3: a windowed pick on a MAXIMIZED window restores it first
(Size writes are silently ignored while maximized; the deleted
WindowState=Normal write used to do this incidentally). New
IWindowedSizeSurface.IsMaximized/Restore.
- Mechanism M5: no silent bail-outs - the unparseable-resolution
fullscreen path logs, and the failure line no longer claims "staying
windowed" when the state is unchanged (#392 noted inline).
- Q1 nit: one cached Glfw wrapper (per-call GetApi allocated + took a
native refcount); IsFullscreen/CurrentFullscreenMode guarded.
- AD-92: highest-refresh-for-WxH + refuse-and-log versus retail's
pass-through-and-error ForceDisplayResolution.
Known-open tail, filed not hidden: #392 (persisted-flag divergence on a
refused enter - needs an apply-result seam); the mechanism report's
pacing-refresh WATCH rides the same seam.
Tests: +3 (same-mode no-op, unparseable-while-fullscreen refusal,
maximized restore-before-write). App suite 4,975/3 skips.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
229242e1fe
commit
ec2a7b0cce
6 changed files with 1257 additions and 28 deletions
|
|
@ -160,16 +160,26 @@ public sealed class RuntimeSettingsControllerTests
|
|||
{
|
||||
public Silk.NET.Maths.Vector2D<int> Size { get; set; } = new(1280, 720);
|
||||
public int Writes { get; private set; }
|
||||
public bool IsMaximized { get; set; }
|
||||
public int Restores { get; private set; }
|
||||
|
||||
Silk.NET.Maths.Vector2D<int> IWindowedSizeSurface.Size
|
||||
{
|
||||
get => Size;
|
||||
set { Size = value; Writes++; }
|
||||
}
|
||||
|
||||
public void Restore()
|
||||
{
|
||||
IsMaximized = false;
|
||||
Restores++;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class FakeModeSwitcher : IDisplayModeSwitcher
|
||||
{
|
||||
public bool IsFullscreen { get; set; }
|
||||
public (int Width, int Height)? CurrentFullscreenMode { get; set; }
|
||||
public bool EnterSucceeds { get; set; } = true;
|
||||
public List<string> Calls { get; } = [];
|
||||
|
||||
|
|
@ -177,7 +187,11 @@ public sealed class RuntimeSettingsControllerTests
|
|||
{
|
||||
Calls.Add($"enter:{width}x{height}");
|
||||
error = EnterSucceeds ? null : "injected failure";
|
||||
if (EnterSucceeds) IsFullscreen = true;
|
||||
if (EnterSucceeds)
|
||||
{
|
||||
IsFullscreen = true;
|
||||
CurrentFullscreenMode = (width, height);
|
||||
}
|
||||
return EnterSucceeds;
|
||||
}
|
||||
|
||||
|
|
@ -186,10 +200,74 @@ public sealed class RuntimeSettingsControllerTests
|
|||
Calls.Add($"leave:{width}x{height}");
|
||||
error = null;
|
||||
IsFullscreen = false;
|
||||
CurrentFullscreenMode = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DisplayApply_SameFullscreenMode_IsANoOp_BeforeAnyNativeWork()
|
||||
{
|
||||
// Review M2: sliders apply per drag tick; without this guard every
|
||||
// tick while fullscreen re-issued a real display-mode change.
|
||||
var surface = new FakeSizeSurface();
|
||||
var switcher = new FakeModeSwitcher
|
||||
{
|
||||
IsFullscreen = true,
|
||||
CurrentFullscreenMode = (1920, 1080),
|
||||
};
|
||||
var target = new SilkRuntimeDisplayWindowTarget(
|
||||
surface, switcher, _ => true);
|
||||
|
||||
target.Apply(DisplaySettings.Default with
|
||||
{
|
||||
Fullscreen = true,
|
||||
Resolution = "1920x1080",
|
||||
});
|
||||
|
||||
Assert.Empty(switcher.Calls);
|
||||
Assert.Equal(0, surface.Writes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DisplayApply_UnparseableResolutionWhileFullscreen_RefusesWithoutCalls()
|
||||
{
|
||||
var surface = new FakeSizeSurface();
|
||||
var switcher = new FakeModeSwitcher();
|
||||
var target = new SilkRuntimeDisplayWindowTarget(
|
||||
surface, switcher, _ => true);
|
||||
|
||||
target.Apply(DisplaySettings.Default with
|
||||
{
|
||||
Fullscreen = true,
|
||||
Resolution = "garbage",
|
||||
});
|
||||
|
||||
Assert.Empty(switcher.Calls);
|
||||
Assert.Equal(0, surface.Writes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DisplayApply_MaximizedWindowedPick_RestoresBeforeTheSizeWrite()
|
||||
{
|
||||
// Blast M3: a maximized window silently ignores Size writes; the
|
||||
// deleted WindowState=Normal write used to un-maximize incidentally.
|
||||
var surface = new FakeSizeSurface { IsMaximized = true };
|
||||
var switcher = new FakeModeSwitcher();
|
||||
var target = new SilkRuntimeDisplayWindowTarget(
|
||||
surface, switcher, _ => true);
|
||||
|
||||
target.Apply(DisplaySettings.Default with
|
||||
{
|
||||
Fullscreen = false,
|
||||
Resolution = "1600x900",
|
||||
});
|
||||
|
||||
Assert.Equal(1, surface.Restores);
|
||||
Assert.Equal(1, surface.Writes);
|
||||
Assert.False(surface.IsMaximized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DisplayApply_FullscreenPick_IsAValidatedModeSwitch_NeverASizeWrite()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue