CNA-BUG-134: Inside a letterbox bar, Mouse::GetState reports the raw window coordinate on renderers whose transform declines the point
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.
EasyGL (every GL-family identity), OPENGL4, SDL_GPU, WEBGPU, SVG_DOM, HTML_DOM and GDI decline points outside the presented rectangle, and Mouse and the input bridge then report the untransformed window coordinate, which can look like a valid game position. The presented rectangle is smaller than the window only under CnaPresentationMode::Letterbox (the default mode) when the window aspect differs from the back buffer's; Overscan, Stretch, NativeBackBuffer and FixedHeightDynamicWidth present a rectangle that covers the whole window, so only a pointer outside the window itself is declined there.
- Identifier
CNA-BUG-134- Category
- Bug
- Subsystem
- Input
- 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
- Mouse::GetState() and touch positions under a letterboxed or overscanned presentation
Expected behaviour
A mouse position should always be in one coordinate space. Vulkan, Canvas and Direct2D return the logical coordinate even outside the presented rectangle (negative or beyond the back buffer), so a game can tell the pointer is in a bar.
Actual behaviour at TARGET
WindowToLogical in GlPresentationSurfaceState.hpp (EasyGL, OPENGL4) computes the logical coordinates and then returns windowX >= clientViewportX && ..., i.e. false inside a Letterbox bar; SDL_GPU, WebGPU, SVG_DOM, HTML_DOM and GDI (MapGdiWindowToLogical) do the same. On false, window_to_logical in Mouse.cpp leaves the output at the raw window coordinate, and to_logical_position in SdlInputBridge.cpp returns it too. With a 100-pixel left bar, a pointer at window x = 50 is reported as game x = 50, inside the playfield. Under Overscan the presented rectangle extends past every window edge, so in-window points always map.
Source locations
modules/graphics/include/CNA/Internal/Renderers/Common/GlPresentationSurfaceState.hpp— WindowToLogical: returns false outside the viewportmodules/input/src/Xna/Mouse.cpp— window_to_logical keeps the raw coordinate on falsemodules/input/src/Internal/SdlInputBridge.cpp— to_logical_position returns the raw coordinate on falsemodules/renderers/vulkan/src/VulkanRenderer.cpp— TransformWindowToLogical returns true with out-of-range logical coordinates, for contrast
Evidence
Checked by reading every renderer's TransformWindowToLogical at 009d40f5; not executed.
Independent re-verification: Read every TransformWindowToLogical override and every RegisterForWindow call at 009d40f5; not executed. DIRECTX11, DIRECTX12 and METAL also decline outside the rectangle but never register for their window (CNA-BUG-133), so input never consults them; VULKAN, Canvas, Direct2D, FNA3D, the SDL renderer and FREEDIRECT return true without a range check.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
MouseInputTests.cpp tests the transform inside the presented rectangle only (CoordinateTransformPreservesLetterboxOffsetAndInverse).
Regression test
A test renderer that declines points in a bar, asserting that Mouse::GetState reports an out-of-range logical coordinate (or a documented clamp), never the raw one.
Blast radius
Letterboxed or overscanned windows on the six renderers named; clicks in the bars land on game coordinates.
Workaround
Ignore mouse input while the window aspect differs from the back buffer, or compute the bars in the game.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- User guide
- Input: mouse
- Internals
- Input internals: mouse
- Deep dives
- Input model: logical coordinates
- Known issues
- Bug index