Skip to content

fix: blur the translucent window on KDE Plasma 6.8 and newer KWin - #745

Open
itsmunzir wants to merge 3 commits into
penso:mainfrom
itsmunzir:fix/685-ext-background-effect
Open

itsmunzir wants to merge 3 commits into
penso:mainfrom
itsmunzir:fix/685-ext-background-effect

Conversation

@itsmunzir

Copy link
Copy Markdown
Contributor

Fixes #685.

Problem

With [backdrop] blur = true, the window is translucent on KDE Plasma 6.8 (Wayland) but the desktop behind it is not blurred. GPUI's Wayland backend (gpui-pre-linux 0.3.6, wayland/window.rs update_window) only binds org_kde_kwin_blur_manager. KWin 6.8 no longer advertises that global and offers the standard ext_background_effect_manager_v1 instead, so the blur request had nothing to bind to. Upstream Zed's gpui_linux has no ext_background_effect_v1 support yet either.

Approach

GPUI is pinned to an exact version, so this patches it in the repo:

  1. build: vendor gpui-pre-linux 0.3.6 unmodified: a byte-for-byte copy of the published crate under vendor/gpui-pre-linux (without the registry's Cargo.toml.orig/.cargo-ok), wired in through [patch.crates-io] like crates/embed-resource and excluded from the workspace, so fmt/clippy keep their scope. vendor/README.md records the source revision (zed@bcf6582). Reviewers can check it with diff -r ~/.cargo/registry/src/*/gpui-pre-linux-0.3.6/src vendor/gpui-pre-linux/src.
  2. build: skip vendored crates in the file-size check: GPUI's client.rs (3,223 lines) and window.rs (2,332) exceed the 1,000-line limit. Splitting them would make re-syncing with upstream impractical, so check-file-size.sh now skips vendor/. Code this project owns is checked as before. This relaxes a deliberate policy, so it needs your call. If you'd rather not vendor GPUI, I'll send the fix upstream only and close this.
  3. fix: blur the translucent window on KDE Plasma 6.8 and newer KWin: the actual change (+34 lines in two files):
    • binds ext_background_effect_manager_v1 (from wayland-protocols 0.32.13, already in the lockfile with the staging feature, so no new dependency) and prefers it, with org_kde_kwin_blur as the fallback;
    • its blur region starts empty (KDE's covers the whole surface by default), so it is set to the same window-area region GPUI already computes for the opaque region; the region is double-buffered and applies with the next surface commit;
    • clearing blur or closing the window destroys the effect object, which removes the region on the next commit, and re-enabling creates a fresh one, so background_effect_exists cannot be raised.

The compositor's capabilities event is ignored, as GPUI already does for the KDE manager: if blur isn't offered, setting a region has no effect.

I'll send the same change upstream to zed-industries/zed. Once a gpui-pre release includes it, vendor/ and the patch entry can be dropped.

Screenshots

None. The change only affects KWin 6.8+ sessions and I'm on Hyprland, which blurs translucent surfaces without any protocol request. I have no KDE 6.8 desktop to capture before/after.

QA

  • just ci on ca33d9c (Linux x86_64, Omarchy/Hyprland): fmt check, file-size, keep-sorted, and clippy -D warnings (all features and no default features) pass. Tests: 4,630 passed, 3 failed, 9 ignored in herdr-gpui, and every other crate passed. The 3 failures are host-dependent and fail identically on unmodified main (0ca50aa) on this machine, so they are unrelated to this change:

    • config::tests::loading::managed_headers_accept_lf_and_crlf_without_migrating_defaults and …local_overrides_merge_tables_replace_arrays_and_refresh_defaults read the desktop's real Omarchy theme state ("Omarchy" vs the expected "Default")
    • cloud::install::tests::the_probe_finds_herdr_where_the_bridge_looks finds the distro's /usr/bin/herdr, which isn't in the test's list of system roots that skip the assertion

    So this is not a fully green local run. I can send a separate fix that isolates those tests from the host if you want.

  • cargo check --locked -p gpui-pre-linux builds the patched crate with no warnings

  • Vendored copy is byte-identical to the published crate (diff -r against the cargo registry source)

  • On KDE Plasma 6.8 Wayland with the blur effect enabled: set backdrop.opacity 0.85 and blur = true, put a detailed window behind Herdr UI, and confirm it shows through blurred

  • Toggle Settings > Theme > Window between Translucent + blur and opaque a few times: blur turns off and on again, with no protocol error in the log

  • On an older KWin that still offers org_kde_kwin_blur only: blur still works (fallback path)

  • On Hyprland: no visible change (no protocol request is needed there)

Replace the registry crate through [patch.crates-io] with a byte-for-byte
copy so Linux platform fixes can ship before a gpui-pre release carries
them. The crate is excluded from the workspace and keeps its upstream
layout.
Vendored third-party crates keep their upstream layout so they can be
diffed and re-synced against the published crate; splitting them to fit
the 1,000-line limit would defeat that. Code this project owns is still
checked as before.
KWin 6.8 no longer advertises org_kde_kwin_blur_manager and offers the
standard ext_background_effect_manager_v1 instead, so `backdrop.blur`
had nothing to bind to and the desktop showed through unblurred.

Bind ext_background_effect_manager_v1 in the vendored gpui-pre-linux and
prefer it, keeping org_kde_kwin_blur as the fallback. Its blur region
starts empty, unlike KDE's whole-surface default, so it is given the
window area GPUI already computes for the opaque region. Clearing the
blur or closing the window destroys the effect object, which removes the
region on the next commit.

Fixes penso#685
@itsmunzir
itsmunzir requested a review from penso as a code owner October 20, 2026 15:46
@greptile-apps

greptile-apps Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The change reaches a specific Linux window-blur workflow.

Fix the missing vendored source in the Nix build before merging; the blur rectangle also needs a resize follow-up.

Findings

  1. P1 Nix builds lose required source ▶
  2. P2 Blur stops at old edges ▶

Summary

Vendors gpui-pre-linux 0.3.6 and adds standard Wayland background-effect requests, while retaining the older KDE blur fallback.

  • Wayland windows blur the desktop through KWin's standard effect or its older KDE protocol.

Acknowledged choices: itsmunzir explicitly identifies the vendored file-size exemption as intentional and says compositor capabilities are intentionally ignored.

Review checks were static. No build, desktop session, or visual verification was run.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Window appearance changes] --> B{Standard manager available?}
  B -->|Yes| C{Blur requested?}
  C -->|Yes| D[Create effect if needed and set blur rectangle]
  C -->|No| E[Destroy existing effect]
  B -->|No| F[Use older KDE manager if available]
  D --> G[Next surface commit applies blur]
  E --> G
  F --> G
Loading

Reviews (1) · Last reviewed commit: "fix: blur the translucent window on KDE ..." · Reviewed by Greptile

Comment thread Cargo.toml
embed-resource = { path = "crates/embed-resource" }
# Unmodified gpui-pre-linux 0.3.6 (zed@bcf6582), vendored so Linux platform
# fixes can ship before a gpui-pre release carries them. See vendor/README.md.
gpui-pre-linux = { path = "vendor/gpui-pre-linux" }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Nix builds lose required source

The new path patch requires vendor/gpui-pre-linux, but flake.nix copies an explicit list of source directories that leaves out vendor. Cargo cannot find vendor/gpui-pre-linux/Cargo.toml, so the Nix package fails before compilation. Add the vendored crate to the Nix source list alongside this patch.

Comment on lines +2253 to +2257
// Unlike org_kde_kwin_blur, whose default covers the whole surface,
// the blur region starts empty, so the window area is set explicitly.
// It is double-buffered and applies with the next surface commit.
if let Some(effect) = &state.background_effect {
effect.set_blur_region(Some(&region));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Blur stops at old edges

The new blur rectangle does not follow window size changes. Resizing updates the bounds without calling update_window, and rendering skips unchanged appearance and inset calls. Enlarging or maximizing a blurred window therefore leaves the added area unblurred.

Refresh the region when the size changes. Calculate it from the current surface bounds rather than window_bounds, which keeps the size used to restore a maximized window.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Backdrop blur does nothing on KDE Plasma 6.8 (KWin offers ext_background_effect_v1, not org_kde_kwin_blur)

1 participant