Repository navigation
Conversation
Taffy computes one tree at a time. The measure closure of `Window::request_measured_layout` runs inside that computation, so an element cannot lay a child out there, and `Window::layout_engine` is `None` for the duration anyway. An element that wants to size itself from content it has to measure has no way to do it. `IsolatedLayout` holds a second tree for that content. `enter` puts it in front of the window's tree for the duration of a closure and gives the window its own tree back afterwards. GPUIX needs this for a panel whose height animates to the height of its content. The width is what the parent gives it, which taffy hands to the measure closure, and the content has to be measured at that width for text to wrap the way it will on screen. Sent upstream as the same change on gpui/isolated-layout.
|
We require contributors to sign our Contributor License Agreement, and we don't have @mateo-m on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'. |
This was referenced Sep 4, 2026
Author
|
@cla-bot check |
|
The cla-bot has been summoned, and re-checked this pull request! |
mateo-m
force-pushed
the
zed/gpui-effect-layers
branch
from
September 4, 2026 18:27
be9fa96 to
7dd56fa
Compare
This was referenced Sep 4, 2026
This was referenced Sep 4, 2026
mateo-m
force-pushed
the
zed/gpui-effect-layers
branch
from
September 4, 2026 20:54
7dd56fa to
86aefea
Compare
mateo-m
force-pushed
the
zed/gpui-effect-layers
branch
from
September 4, 2026 21:57
86aefea to
7498262
Compare
mateo-m
force-pushed
the
zed/gpui-effect-layers
branch
from
September 4, 2026 22:47
7498262 to
d10f381
Compare
mateo-m
force-pushed
the
zed/gpui-effect-layers
branch
from
September 4, 2026 23:12
d10f381 to
08bbe47
Compare
mateo-m
force-pushed
the
zed/gpui-effect-layers
branch
from
September 4, 2026 23:52
08bbe47 to
59703a6
Compare
This was referenced Sep 5, 2026
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.
Objective
Let an element draw its subtree into its own texture, then paint that texture over the frame with a blur, a colour matrix, a mask and a blend mode. CSS
filter,backdrop-filter,mask-imageandmix-blend-modeall need this, and GPUI has no way to do it today.I need it for GPUIX, a React renderer for GPUI by @remorses. Same change as remorses#7.
I first opened this PR with the whole feature in one diff, then split it so each part gets its own review. This PR is the core: the scene, the style and the window. Stacked on #63793, so the diff GitHub shows includes #63771, #63792 and #63793. This PR alone: mateo-m/zed@zed/gpui-linear-gradients...zed/gpui-effect-layers.
The rest of the stack, in order:
gpui_web, which draws through wgpu.drop-shadow.Until a backend has its PR, its renderer draws a layer's content straight into the frame with no effect. That is why this PR alone changes nothing on screen.
Solution
LayerEffectsin style:blur,color_matrix,backdrop_blur,backdrop_matrix,mask,blend_mode,clips. Each field refines on its own, so a hover style that sets a blur keeps the mask.Styledgets a setter for each, plusbackground_imageandbackground_blend_mode, which paint through the same layer.EffectLayer,ColorMatrix,BlendMode,LayerRegionandBlurPlanin a neweffect_layer.rs. The scene getsLayerBeginandLayerEndbatches.EffectLayeris#[repr(C)]so the Metal build can export it through cbindgen.Window::paint_effect_layer(bounds, corner_radii, corner_shapes, effects, f).Style::paintcalls it when a style has any effect. A content blur grows the layer by three sigmas, the way a CSS filter bleeds past the border box.BlurPlan: two Gaussian passes, one per axis, on a texture shrunk by a scale, so a wide blur costs about the same as a narrow one. The renderers read it.LayerEffects::clipshas no writer until gpui: clip a rounded overflow box through an effect layer #63794. It is part of the struct the three renderers share, so it lands here and the struct layout stays fixed in the later PRs.Testing
crates/gpui/src/style.rs,a_hover_refinement_keeps_the_other_effects. It does not compile against the first version of this PR, whereeffectsrefined as one block.cargo test -p gpuiat this head: 314 passed, 1 doc test passed.cargo check -p gpui -p gpui_wgpu -p gpui_apple --testspasses.cargo fmt --all -- --checkis clean.cargo check -p gpui_windows --target x86_64-pc-windows-msvcpasses from macOS.EffectLayerends in apadfield, so its size stays a multiple of 8 bytes. The wgpu PR needs that, because WGSL rounds a struct that holds avec2<f32>up to 8 bytes and the field after the layer inLayerCompositemust land at the same offset on both sides.Self-Review Checklist:
Release Notes: