CNA-BUG-133: DIRECTX9 implements the window-to-logical transform but never registers for its window, so mouse and touch input ignore 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 3b43bd86; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
Input looks renderers up by window id through IGraphicsRenderer::GetForWindow; DIRECTX9 never calls RegisterForWindow, so Mouse::GetState, Mouse::SetPosition and touch pass raw window coordinates through under a virtual resolution, letterbox or display scale.
- Identifier
CNA-BUG-133- Category
- Bug
- Subsystem
- Input
- Status
- Open
- Verified against
- CNA
3b43bd86(3b43bd8687ed46523d873f9bec4b32bd8481dcb5) - Severity
- Medium (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(), Mouse::SetPosition(int, int) and TouchPanel positions on the DIRECTX9 renderer
Expected behaviour
IGraphicsRenderer.hpp states the registry rule: “Renderers that implement coordinate conversion register themselves here so input can map platform window-client coordinates”. EasyGL, SDL_GPU, WebGPU and FNA3D call RegisterForWindow.
Actual behaviour at TARGET
DirectX9Renderer.cpp implements TransformWindowToLogical and TransformLogicalToWindow (presentation geometry, letterbox, display scale; added by FULLSCREEN-002) but contains no RegisterForWindow call. window_to_logical and logical_to_window in Mouse.cpp and to_logical_position in SdlInputBridge.cpp find no renderer and return the window coordinate unchanged, so a game whose back buffer differs from the window size receives window pixels as game coordinates.
Source locations
modules/renderers/directx9/src/DirectX9Renderer.cpp— TransformWindowToLogical / TransformLogicalToWindow (added by FULLSCREEN-002); no RegisterForWindowmodules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp— RegisterForWindow / GetForWindow and the registry commentmodules/input/src/Xna/Mouse.cpp— window_to_logical and logical_to_window fall back to the raw coordinatemodules/input/src/Internal/SdlInputBridge.cpp— to_logical_position, used for mouse motion and touch
Evidence
Checked by reading and by grepping every renderer source for RegisterForWindow at 3b43bd86; not executed (DIRECTX9 is Windows-only).
Re-verified at c6dec91f: RegisterForWindow is called by EasyGLRenderer.cpp, Fna3dRenderer.cpp, SdlGpuRenderer.cpp and WebGPURenderer.cpp only; DirectX9Renderer.cpp still implements both transforms. Not executed.
Focused reproduction
// Illustrative; not compiled or run. CNA_GRAPHICS_RENDERER=DIRECTX9,
// PreferredBackBuffer 800x480, window resized to 1600x960.
MouseState s = Mouse::GetState();
// Pointer at the window centre: expected (400, 240); actual (800, 480).
Current tests
MouseInputTests.cpp (CoordinateTransformPreservesLetterboxOffsetAndInverse) registers a test renderer by hand; IGraphicsRendererWindowRegistryTests.cpp tests the registry. No test checks that each renderer registers itself.
Regression test
A per-renderer check that constructing the renderer on a window makes GetForWindow(window) return it (the SDL_GPU constructor test already does this); the fix is to register after initialisation and unregister on destruction, as the other renderers do.
Blast radius
Games on DIRECTX9 whose window is not exactly the back-buffer size, including resizable and fullscreen-letterboxed windows: mouse, SetPosition and touch positions are wrong. Other renderers are unaffected.
Workaround
Keep the window at the back-buffer size, or scale mouse coordinates 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