fix(win32): window-space UI HUDs clipped by the SetWindowRgn silhouette (#350) - #351
Merged
Merged
Conversation
…350) SetWindowRgn is a visual clip, not only a hit mask, so a window-space UI HUD off the avatar silhouette was cut away. Every region the transparent overlay builds (hit mask + surround union, and the AABB hit-rect path before the first mask) now unions the client-pixel rect of each live wsui slot, natively and with no app call, mirroring the Linux input region (#346). The fractions are of the whole window client, not zone 0. The runtime draws the layer into each per-view tile, and the tile spans the full window in both plain-projection and zones frames. The rect is widened by |disparity|/2 per side and scaled by the same client size the silhouette uses. A slot counts only while a texture is registered, so a disabled HUD drops out. HUD rects feed the region hash (and bypass the hit-rect hysteresis), so toggling re-applies the region and a static HUD costs no SetWindowRgn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…from the merged source Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #350.
Problem
SetWindowRgnis a visual clip, not only a hit mask. The transparent overlay's region is built around the avatar silhouette, so any window-space UI HUD (DisplayXRWindowSpaceUI→XrCompositionLayerWindowSpaceDXR) off the silhouette was cut away.Fix (
native~/displayxr_win32.c, Windows-only)A new helper,
wsui_region_rects, turns every live wsui slot into a client-pixel rect. That rect is unioned into every region the overlay builds:displayxr_set_overlay_hit_mask): appended after the silhouette and the surround rect/mask, before the Overlay hit mask clips PAINTING: port displayxr-common #27+#31 (fixed 256x144 raster, input-justified latency) — Lenovo field report #259 FNV hash. Showing, hiding or moving a HUD changes the hash and re-applies the region. A static HUD keeps the hash identical, so it adds no per-frameSetWindowRgn.displayxr_set_overlay_hit_rect, used before the first mask):CombineRgn(RGN_OR)onto the padded rect. A hash of the HUD rects bypasses the 4 px hysteresis when it changes, and leaves it alone when it doesn't.No app call is needed. This mirrors the Linux input region in #346 (
lin_rects_add_wsui) and the model viewer's "chrome" rects (displayxr-commonvk_clickthrough_region.h).Frame math (and why it differs from #346)
A slot's
x/y/w/h/disparityare fractions of the whole window client, not of zone 0. I checked this against displayxr-runtimeorigin/main@de3f621:tile_origin + (x ± disparity/2) · tile_w. Seecomp_d3d12_renderer.cpprender_window_space_layer/comp_d3d12_renderer_draw_window_space_pass,comp_d3d11_renderer.cpprender_window_space_layer(fraction → NDC of the view viewport), andvk_native/comp_vk_native_compositor.c~2660 (dx = tile_origin_x + (ws->x + eye_shift) * tile_w).d3d12_effective_canvas).comp_d3d12_renderer.cpp~3245,comp_d3d11_renderer.cpp~1897).So #346's zone-0 frame matches only when there is no sub-rect zone. With one (the avatar's bubble band sits beside its zone), it would misplace the HUD rects. #346 probably wants the same correction.
Each eye is shifted by ±disparity/2 (graded across views for more than 2, with the same extremes). The rect is therefore widened by
|disparity|/2on each side, rounded outward and clamped to the client.DPI space
The HUD rect is scaled by the same client size the silhouette uses. On the mask path that is
dst_w/dst_h. On the hit-rect path it isdisplayxr_get_overlay_size, the sameGetClientRectC# used for the AABB, called on the same thread that callsSetWindowRgn. It never uses managedScreen.*, so the HUD rects share a space with the rest of the region whatever DPI awareness that thread has.Hidden HUDs are excluded
displayxr_window_space_ui_get_pending_slotreturns 1 only while a texture is registered, andrelease_slot/clear_slotnull that texture. That is exactly when the provider submits the layer. A HUD that is disabled (OnDisable→ReleaseSlot), or that was never enabled (the app launches with HUDs off and toggles them with Shift+Tab), is not in the region. A HUD hidden only by blanking its canvas while the component stays enabled is still submitted, so it still counts.Threads and cost
The slot registry is written from managed on the main thread. Both region builders also run on the main thread (LateUpdate and the AsyncGPUReadback callback), so there is no cross-thread read. No provider state is read and no window query is added on the mask path. The work is at most
DXR_WSUI_MAX_SLOTS(4) volatile reads per rebuild.Clicks
Clicks inside a HUD reach the app as a result of the union: the borderless top-level overlay's
WM_NCHITTESTreturnsHTCLIENTfor every hit the OS delivers.s_hit_rectis consulted only on the opaqueWS_CHILDpath.Also
docs~/architecture/click-through-mask.md: new section "Window-space UI HUDs are part of the region (Windows transparent overlay: window-space UI HUDs clipped by the SetWindowRgn silhouette #350)".Runtime/Plugins/Windows/x64/displayxr_unity.dll(MSVC,build-win.bat). There are no compiler warnings; the only one is the existing CMake "CMAKE_BUILD_TYPE unused" configure warning. No shared headers were changed;displayxr_win32.cis compiled only on Windows.Verification
hit_masklog stays quiet apart from the 1 Hz line).🤖 Generated with Claude Code