CNA-BUG-177: The Headless and Terminal window constructors accept BorderlessFullscreen although their own SetFullscreenMode refuses it

CNA snapshot 009d40f5  ·  Known Issues › Current bugs  ·  source links pinned to 009d40f5

✓

Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.

Both capability-minimal windows store WindowDescription::fullscreenMode directly at construction instead of routing it through SetFullscreenMode, so a window created in BorderlessFullscreen reports that mode though the platform's capability is false.

Identifier
CNA-BUG-177
Category
Bug
Subsystem
Platforms
Status
Open
Verified against
CNA 009d40f5 (009d40f5dd085c4e674d3479675fac84b12b3e0a)
Severity
Low (a triage suggestion, not a project priority)
Evidence basis
Source-verified: read at TARGET, not executed
Tests touching this area
Yes: see Current tests
Affected contract
CNA::Platform::IPlatform::CreateWindow(const WindowDescription&) and IPlatformWindow::GetFullscreenMode()/SetFullscreenMode() on the Headless and Terminal platforms

Expected behaviour

platform-abstraction.md and IPlatformWindow::SetFullscreenMode state that “a window with no borderlessFullscreen capability must refuse that mode”, and the real backends enforce it uniformly: the Win32Window constructor and the CreateWindow functions of the X11, SDL2 and SDL3 platforms (X11Platform.cpp, Sdl2Platform.cpp, Sdl3Platform.cpp) funnel a non-Windowed WindowDescription::fullscreenMode through SetFullscreenMode right after construction, so the refusal path runs. Headless and Terminal report borderlessFullscreen = false and their SetFullscreenMode throws PlatformNotSupportedException(BorderlessFullscreen).

Actual behaviour at TARGET

HeadlessWindow and TerminalWindow initialise mode_(description.fullscreenMode) in their constructors and never call their own SetFullscreenMode. A window created with fullscreenMode = BorderlessFullscreen is therefore accepted, and GetFullscreenMode() returns BorderlessFullscreen, even though the platform's capability is false and a later SetFullscreenMode(BorderlessFullscreen) on the same window throws. The window is left in a mode the platform says it cannot provide.

Source locations

Evidence

Checked by reading the Headless and Terminal window classes, the SDL3/Win32/X11 constructors (which do route creation through SetFullscreenMode) and the conformance suite at 009d40f5. Not executed. The defect is that the two capability-minimal backends bypass their own refusal at construction; the real backends do not.

Independent re-verification: Checked by reading the Headless and Terminal window classes and CreateWindow functions, the Win32 window constructor, the X11, SDL2 and SDL3 CreateWindow functions and the conformance suite at 009d40f5. Not executed. The defect is that the two capability-minimal backends bypass their own refusal at construction; the real backends do not. The XNA-facing runtime cannot reach it: GraphicsDevice creates its window with the default Windowed mode and later calls SetFullscreenMode with ExclusiveFullscreen or Windowed only, so the path is reached only by code that calls IPlatform::CreateWindow directly with BorderlessFullscreen.

Focused reproduction

Illustrative (not compiled for this entry):

WindowDescription d;
d.fullscreenMode = WindowFullscreenMode::BorderlessFullscreen;
auto platform = PlatformFactory::Create("Headless");
auto window = platform->CreateWindow(d);                 // accepted
assert(!platform->GetCapabilities().borderlessFullscreen);
assert(window->GetFullscreenMode() == WindowFullscreenMode::BorderlessFullscreen);  // holds
window->SetFullscreenMode(WindowFullscreenMode::BorderlessFullscreen);              // now it throws

Current tests

PlatformConformanceTests.cpp's PlatformWindowConformance.BorderlessFullscreenFollowsItsCapability creates the window with the default (Windowed) mode and then calls SetFullscreenMode. No case creates a window with fullscreenMode = BorderlessFullscreen on a platform whose capability is false.

Regression test

Extend the window conformance suite: creating a window with a fullscreen mode the platform's capability forbids must either refuse (as the setter does) or clamp to Windowed, and GetFullscreenMode() must never report a mode the capability denies. The fix is to route the constructor's mode through the same SetFullscreenMode the other backends use.

Blast radius

Games that create a window in BorderlessFullscreen on the Headless or Terminal platform and read GetFullscreenMode(); the real backends (SDL3, SDL2, X11, Wayland, Win32) already refuse or apply the mode at creation and are unaffected.

Workaround

On Headless and Terminal, create windows with the default Windowed mode.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.

Known issues
Bug index