Compose the DirectComposition tree behind child HWNDs on Windows - #5
Merged
ChrisUnityArto merged 1 commit intoOct 1, 2026
Merged
Conversation
`CreateTargetForHwnd(hwnd, true)` puts gpui's visual tree on top of every child window of the gpui window. gpui creates no child HWNDs of its own, so this only bites an embedder that parents a native child, such as a wry / WebView2 webview built with `build_as_child`: gpui's opaque frame covers the child completely, while the child still receives mouse input and keeps running. A video embed therefore plays audio with no picture. `topmost: false` composes gpui's tree behind its children, which matches macOS, where a child `NSView` draws above gpui's Metal layer. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
toddbeauchamp
approved these changes
Oct 1, 2026
toddbeauchamp
left a comment
There was a problem hiding this comment.
🤖 Taude: Approving. One flag, one Windows-only file, and it fixes the audio-but-no-picture video bug.
macOS: not affected. directx_renderer.rs only builds on Windows, and test-mac passed. The change makes Windows layer child windows the way macOS already does.
Checked:
- gpui never creates child windows itself, so normal gpui windows don't change.
- With DirectComposition on, gpui windows get
WS_EX_NOREDIRECTIONBITMAP, sofalsereally does put gpui's drawing behind children. - The
disable_direct_compositionpath doesn't use this code.
CI failures are unrelated to this PR (#4 fails the same jobs):
test-linux,test-windows,msrv:crates/gpui_media/build.rsusesbindgen, butCargo.tomlonly lists it as a build dependency on macOS. That bug is onunity/a11y-automation. Fix it there by listingbindgenon all platforms or skipping the bindgen code when the target isn't macOS.clippy: a newGOLDEN_RATIOlint atcrates/gpui/src/geometry.rs:3789.
Worth checking before GA (not blocking):
- Child windows now draw over all gpui UI on Windows. Check that a tooltip, dropdown or toast over a playing video still hides the webview, like the Hub does on macOS.
- Try closing and reopening the dialog, resizing the window, and dragging it to a screen with a different DPI. The webview shouldn't be left behind.
- Upstream Zed uses
true, so an upstream PR will probably need this to be opt-in.
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.
What
One argument in
gpui_windows/src/directx_renderer.rs:DirectComposition::newnow callsCreateTargetForHwnd(hwnd, false)instead oftrue.Why
The
topmostflag decides whether the composition target's visual tree is drawn above (true) or below (false) the window's child HWNDs. Withtrue, anything gpui paints covers every child window of the gpui window.gpui creates no child HWNDs of its own, so this only bites an embedder that parents a native child. The Unity Hub does exactly that: it embeds a wry / WebView2 webview with
build_as_childfor inline video. The result on Windows:falsecomposes gpui's tree behind its children, which matches macOS, where a childNSViewdraws above gpui's Metal layer. The Hub's embed code (clipping, hiding under modals and popovers, poster fallback) was already written for that model, and now behaves the same on both platforms.This change should also go upstream: gpui-ce#222's proposed webview crate, and any other
build_as_childuser on Windows, hits the same wall.Risk
disable_direct_compositionpath doesn't use this code and is unchanged.Testing
cargo build -p hub-gpui) against this commit through a local[patch]. In a manual run, the CLI-announcement dialog's inline video showed real frames in sync with audio, and play, pause and seek updated the picture. Before the change: audio only.🤖 Generated with Claude Code