CNA-GAP-056: A foreign HWND adopted by handle is not subclassed and is absent from windows_, so the Win32 GL, Vulkan, relative-mouse and text-input services refuse 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.
AdoptWindowHandle wraps a foreign HWND without subclassing it or adding it to windows_, so it raises no CNA events and FindWindow cannot resolve its id; the WGL, Vulkan, relative-mouse and text-input services then reject it.
- Identifier
CNA-GAP-056- Category
- Functional gap
- Subsystem
- Platforms
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Evidence basis
- Source-verified: read at TARGET, not executed
- Tests touching this area
- Yes: see Current tests
- Affected contract
- CNA::Platform::Win32::Win32Platform::AdoptWindowHandle(std::uintptr_t) for a window CNA did not create
Expected behaviour
AdoptWindowHandle is documented to wrap a caller-owned window by its legacy handle token and return a non-owning wrapper. GraphicsDevice adopts a host-supplied DeviceWindowHandle through it, so a game that hands CNA a foreign HWND might reasonably expect to render to it.
Actual behaviour at TARGET
For an HWND not already in windows_, AdoptWindowHandle assigns a fresh id and constructs a Win32Window with the adopt tag; that constructor does not subclass the window (only the creating CreateWindowExW path installs StaticWindowProc), so no CNA events flow from it, and the wrapper is tracked in adopted_ but never added to windows_. Every id-based service resolves through FindWindow, which searches only windows_: Win32GlContext::CreateContext and Win32VulkanSurface::CreateSurface, relative-mouse targeting and Win32TextInput::Start all get nullptr and throw “the window id does not name a live window”. Handle-consuming renderers (which read the native handle through TryGetWin32) and the CPU presenter (which takes the Win32Window& directly) still work.
Source locations
modules/platform/src/Win32/Win32Platform.cpp— AdoptWindowHandle for a foreign HWND: fresh id, adopt-tag wrapper, not added to windows_; FindWindow searches windows_ onlymodules/platform/src/Win32/Win32Window.cpp— the adopt-tag constructor does not subclass the HWNDmodules/platform/src/Win32/Win32GraphicsServices.cpp— CreateContext/CreateSurface resolve through FindWindow and refuse an unknown id
Evidence
Checked by reading AdoptWindowHandle, the adopt-tag constructor, FindWindow and the GL/Vulkan/input service lookups at 009d40f5. Not executed (no Windows host). The refusals are clean exceptions, and no CNA contract promises these services on a foreign HWND, so this is a scoped functional gap rather than a broken promise. The Development Win32 page records it.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
Win32WindowTests.cpp's adoption cases (LegacyTokenRoundTripsThroughAdoption, AdoptedWindowDoesNotDestroy) adopt windows this platform created; none adopts a foreign HWND and then requests a GL context, Vulkan surface, relative mode or text input on it.
Regression test
Create an HWND outside CNA, adopt it by handle, and assert the intended behaviour for each service -- either they work (which requires registering the adopted window and subclassing it) or they refuse with a documented, specific message.
Blast radius
Applications that embed CNA in a foreign HWND and then ask for a GL context, a Vulkan surface, relative-mouse mode or text input on it. CNA-created windows, handle-consuming renderers and the CPU presenter are unaffected.
Workaround
Let CNA create the window (leave DeviceWindowHandle unset), or use a renderer that consumes the native handle directly.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- User guide
- Native platforms: Win32
- Maintainer workflow
- Modify a platform backend
- Known issues
- Functional gap index