fix #391: curated modern-only resolution list from the monitor's modes
User-directed (2026-08-13): "we should only support modern resolutions. Not any old format." New DisplayModeCatalog enumerates the window's monitor (Silk IMonitor.GetAllVideoModes) once at GameWindow load and curates via a pure, tested rule: modern widescreen families only (16:9/16:10/21:9/32:9 within 2.5%), at least 1280 wide, must fit the desktop (an impossible windowed pick is not offered - the measured 3840x2160-on-2560x1440 silent clamp class), desktop mode always included, refresh-rate duplicates collapsed, ascending order. The Config Resolution row consumes the catalog through two new optional Bind parameters; its Defaults value becomes the desktop's own mode. Fixture/headless callers keep the static preset ladder, which now drops 800x600 and is pinned by test to pass the same curation rule (the OP6 S4 "default must be re-selectable" invariant holds on both paths). Deliberate retail deviation, register row IA-22: retail listed the adapter's complete enumeration including 4:3 legacy modes and authored 800x600 as the Config default (gmConfigUI::InitOptions SetDefaultValue(0x03200258); gmClient::Init @0x004047af). The catalog is also the designated fullscreen mode-switch validation source for #376/#388 - an offered mode is supported by construction. Tests: DisplayModeCatalogTests (8 - filter/clamp/dedupe/sort/ultrawide/ desktop-inclusion/fallback-consistency); ConfigOptionsPageControllerTests row-12 default updated. App suite 4,961/3 skips; UI.Abstractions 916. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
7e0c130344
commit
13d388e5a9
9 changed files with 324 additions and 23 deletions
|
|
@ -362,6 +362,16 @@ public static class ConfigOptionsPageController
|
|||
/// <param name="debugFont">#378: fallback bitmap font when
|
||||
/// <paramref name="datFont"/> is unavailable — same convention
|
||||
/// <see cref="VendorUiController"/> uses.</param>
|
||||
/// <param name="availableResolutions">#391: the curated monitor-derived
|
||||
/// resolution list the Resolution dropdown offers. Null (fixture/
|
||||
/// conformance callers with no display) falls back to
|
||||
/// <see cref="DisplaySettings.AvailableResolutions"/>.</param>
|
||||
/// <param name="resolutionDefault">#391: the value the Defaults button
|
||||
/// restores for the Resolution row — production passes the desktop's own
|
||||
/// mode (see <c>DisplayModeCatalog</c>'s class doc for the deliberate,
|
||||
/// register-rowed deviation from retail's authored 800x600). Null falls
|
||||
/// back to <see cref="DisplaySettings.Default"/>.Resolution so the
|
||||
/// fallback default is always a member of the fallback list.</param>
|
||||
public static bool Bind(
|
||||
ImportedLayout layout,
|
||||
OptionPage page,
|
||||
|
|
@ -370,7 +380,9 @@ public static class ConfigOptionsPageController
|
|||
Bindings bindings,
|
||||
Func<uint, (uint tex, int w, int h)>? resolveSprite = null,
|
||||
UiDatFont? datFont = null,
|
||||
BitmapFont? debugFont = null)
|
||||
BitmapFont? debugFont = null,
|
||||
IReadOnlyList<string>? availableResolutions = null,
|
||||
string? resolutionDefault = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(layout);
|
||||
ArgumentNullException.ThrowIfNull(page);
|
||||
|
|
@ -425,7 +437,10 @@ public static class ConfigOptionsPageController
|
|||
BuildSeparatorRow(listBox);
|
||||
BindCameraSection(listBox, page, resolveString, bindings, ref cameraTurning);
|
||||
BuildSeparatorRow(listBox);
|
||||
BindGraphicsSection(listBox, page, resolveString, bindings, ref display, resolveSprite, datFont, debugFont);
|
||||
BindGraphicsSection(
|
||||
listBox, page, resolveString, bindings, ref display,
|
||||
resolveSprite, datFont, debugFont,
|
||||
availableResolutions, resolutionDefault);
|
||||
BuildSeparatorRow(listBox);
|
||||
BindRenderingQualitySection(listBox, page, resolveString, bindings, ref display, resolveSprite, datFont, debugFont);
|
||||
BuildSeparatorRow(listBox);
|
||||
|
|
@ -591,7 +606,9 @@ public static class ConfigOptionsPageController
|
|||
ref DisplaySettings display,
|
||||
Func<uint, (uint tex, int w, int h)>? resolveSprite,
|
||||
UiDatFont? datFont,
|
||||
BitmapFont? debugFont)
|
||||
BitmapFont? debugFont,
|
||||
IReadOnlyList<string>? availableResolutions,
|
||||
string? resolutionDefault)
|
||||
{
|
||||
BuildHeaderRow(listBox, "ID_Graphics_GraphicsSection", resolveString);
|
||||
|
||||
|
|
@ -613,12 +630,17 @@ public static class ConfigOptionsPageController
|
|||
// @gmClient::Init 0x004047af, not an invented preset), so clicking
|
||||
// Defaults both resizes the window AND leaves the dropdown showing
|
||||
// a highlighted, re-selectable row.
|
||||
// #391 (user-directed): the choices are the curated monitor-derived
|
||||
// list in production (see DisplayModeCatalog), and Defaults restores
|
||||
// the desktop's own mode rather than retail's authored 800x600 —
|
||||
// both halves of one register-rowed deviation. Fixture callers with
|
||||
// no display keep the static modern preset ladder + its default.
|
||||
BuildStringMenuRow(
|
||||
listBox, "ID_Rendering_DisplayResolution",
|
||||
DisplaySettings.AvailableResolutions, page, resolveString,
|
||||
availableResolutions ?? DisplaySettings.AvailableResolutions, page, resolveString,
|
||||
read: () => bindings.LoadDisplay().Resolution,
|
||||
apply: value => bindings.SaveDisplay(bindings.LoadDisplay() with { Resolution = value }),
|
||||
defaultValue: "800x600",
|
||||
defaultValue: resolutionDefault ?? DisplaySettings.Default.Resolution,
|
||||
storeOnly: false, // LIVE
|
||||
resolveSprite, datFont, debugFont);
|
||||
|
||||
|
|
|
|||
|
|
@ -2387,7 +2387,13 @@ public sealed class RetailUiRuntime : IDisposable
|
|||
// ConfigOptionsPageController.MenuChromeSprites' own doc.
|
||||
resolveSprite: _bindings.Assets.ResolveSprite,
|
||||
datFont: _bindings.Assets.DefaultFont,
|
||||
debugFont: _bindings.Assets.DebugFont);
|
||||
debugFont: _bindings.Assets.DebugFont,
|
||||
// #391: the monitor-derived curated list + desktop-mode
|
||||
// default, installed at startup by the graphical host;
|
||||
// fixture/headless mounts leave the catalog empty and the
|
||||
// controller falls back to the static preset ladder.
|
||||
availableResolutions: Rendering.DisplayModeCatalog.Resolutions,
|
||||
resolutionDefault: Rendering.DisplayModeCatalog.DesktopResolution);
|
||||
if (!configBound)
|
||||
Console.WriteLine("[UI] options panel: Config tab rows did not bind.");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue