CNA-BUG-177: The Headless and Terminal window constructors accept BorderlessFullscreen although their own SetFullscreenMode refuses it
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
modules/platform/src/Headless/HeadlessPlatform.cpp— HeadlessWindow constructor (mode_(description.fullscreenMode)) vs SetFullscreenMode (throws for BorderlessFullscreen)modules/platform/src/Terminal/TerminalPlatform.cpp— TerminalWindow constructor and SetFullscreenMode, the same shapemodules/platform/tests/CNA/Platform/PlatformConformanceTests.cpp— BorderlessFullscreenFollowsItsCapability tests only the setter, not creation
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.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- User guide
- Platform Support: capability matrix
- Architecture
- Platform architecture: windows
- Known issues
- Bug index