Skip to content

The Blur Pull Request#3483

Open
YaLTeR wants to merge 14 commits intomainfrom
wip/branch
Open

The Blur Pull Request#3483
YaLTeR wants to merge 14 commits intomainfrom
wip/branch

Conversation

@YaLTeR
Copy link
Member

@YaLTeR YaLTeR commented Feb 21, 2026

Well, looks like I'm ready to promote this branch to a pull request. All planned features are implemented, all bugs that I knew about and wanted to fix should be fixed.

Please test and report any problems and suggestions. See the docs at https://github.com/niri-wm/niri/blob/wip/branch/docs/wiki/Window-Effects.md.

image

There's no "alpha threshold" setting for blur, instead clients are encouraged to implement the ext-background-effect protocol which lets them shape their background blur. It's already implemented, or in progress, in:

Note

Currently, this PR doesn't implement ext-background-effect for popups and subsurfaces. This is mainly because I don't have any clients that do this to test with. If some client can do it I'll look into it.

This PR also implements the KDE blur protocol which makes a bunch of other clients work (Alacritty, kitty, etc.) but I'll remove it before merging because even KDE has dropped it in favor of ext-background-effect.

Background blur turned out to be a massive undertaking. Not because of blur itself, but because window background effects in general required a lot of thinking and additions to the code, especially to make them as efficient as possible. Xray and non-xray background effects, both of which this PR implements, are also pretty much two entirely separate and very different beasts, both of which I had to get working with all other niri features (like block-out-from).

What's left is some code cleanups, and maybe splitting the commits a bit further.

Non-xray might land a bit later than xray because it depends on a WIP Smithay PR.

Implements #54, supersedes #1634. Thanks @visualglitch91 for rebasing and maintaining the previous blur PR all this time!

This was referenced Feb 21, 2026
use smithay::utils::{Logical, Rectangle};
use smithay::wayland::compositor::{RectangleKind, RegionAttributes};

pub fn region_to_non_overlapping_rects(
Copy link

Choose a reason for hiding this comment

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

Heya, I also implemented the kde blur and ext-background-effect protcols in my fork.

While doing that, I noticed that a lot of clients just define a single rectangle as their region, which encompasses the entire window / layer. This led to me developing this helper utility:

https://github.com/Naxdy/niri/blob/7b713f75d6340eea4a8bf9bf97e4bad8fdc0f21f/src/utils/region.rs

The helper exists mainly to avoid having to allocate an extra Vec for clients that only define one rectangle. There are other optimizations as well that help for checking whether a region changed (and then not re-render blur if that's the case), but those may not be applicable in your case.

Feel free to take a look and see if it's useful for you.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hey, guess this is more of a Smithay question because it already gives us a pre-allocated Vec: https://smithay.github.io/smithay/smithay/wayland/background_effect/struct.BackgroundEffectSurfaceCachedState.html

As for KDE-blur, I probably won't keep the impl in niri so it doesn't matter.

Other than that, in this PR I already made the computations as lazy as possible, so the non-overlapping region is only computed when the window-submitted wl_region actually changes, and only when it's first needed. And changes to the region don't cause blur re-renders.

Will likely drop this commit as even KDE removed this protocol in favor of ext-background-effect:
https://invent.kde.org/plasma/kwin/-/merge_requests/8798
@nishiiko
Copy link

setting xray false for all windows makes the blur only apply when the opening animation fully finishes
it can be sort of worked around by only setting xray false for floating windows only instead, but it ends up feeling a little clunky as everything behind a floating window disappears immediately during the anmiation of floating -> tiled mode

2026-02-21.14-22-33.mp4
2026-02-21.14-25-18.mp4

@YaLTeR
Copy link
Member Author

YaLTeR commented Feb 21, 2026

Yes, that's one of the known limitations of non-xray:

They disappear during window open/close animations and while dragging a tiled window. Fixing this requries subframe support in the Smithay rendering code.

@YaLTeR
Copy link
Member Author

YaLTeR commented Feb 21, 2026

everything behind a floating window disappears immediately during the anmiation of floating -> tiled mode

I'll have to think if there's a non-cursed way of delaying the xray change until the end of the animation, but probably there isn't any non-cursed way

@ryzendew
Copy link

image after doing some testing not finding any issues yet just noise looks really bad sadly. nice work!

@YaLTeR
Copy link
Member Author

YaLTeR commented Feb 21, 2026

just noise looks really bad sadly

hm?

@Suya1671
Copy link
Contributor

just noise looks really bad sadly

hm?

Compared to hyprlands or naxdy's fork, the noise looks rather... uniform? at higher values the pattern is very noticable/distracting.

image (0.2)

maybe either increase the transparency of the noise or it's distribution? idk

@YaLTeR
Copy link
Member Author

YaLTeR commented Feb 21, 2026

Yeah but the default value is 0.02, ofc if you make it higher it will be more visible. Is it noticeable at lower values or do you need higher values for some reason?

@BBaoVanC
Copy link

Might be good to add foot to the list of programs with ext-background-effect-v1 support in progress: https://codeberg.org/dnkl/foot/pulls/2198

@s3bba
Copy link

s3bba commented Feb 21, 2026

Is it noticeable at lower values or do you need higher values for some reason?

For me, the 0.02 setting at 4k and 2.4K screen resolutions is not noticeable, even when looking closely for it. I had to take a screenshot and zoom in really far to be able to see any noise patterns.

@seadx6-neo
Copy link

Dude! I hope this gets pulled and gets released soon! Using Noctalia, it would make everything look amazing

@yuxqiu
Copy link
Contributor

yuxqiu commented Feb 22, 2026

I was experimenting with blurring Firefox using this customChrome.css together with the following window rule in niri (Firefox 147 with vertical sidebar enabled):

window-rule {
    match app-id="firefox"
    background-effect {
        blur true
    }
}

Everything works fine at first. However, whenever I expand the vertical sidebar (either by making it to show full tab titles or by clicking the settings/bookmarks icons on the sidebar), strange glitchy black pixels appear in the background of the expanded sidebar. Sometimes black pixels also show up when I move the mouse over that area.

Interestingly, switching to another window and then back to Firefox resolves the glitch: the blur is applied correctly again with no visible artifacts. However, this fix is only temporary: as soon as I hide the sidebar again, switch to another window and back, and then re-expand the sidebar, the glitchy black pixels reappear.

One additional clue that might help narrow it down: whenever I take a screenshot or record a video of the glitched area, the captured image/video correctly shows the blur with no black pixel artifacts at all.

I'm not sure whether this is a firefox quirk or something on niri's side. I figured it could be worth bringing it up here first in case these are indeed artifacts that shouldn't be happening.

@YaLTeR
Copy link
Member Author

YaLTeR commented Feb 22, 2026

Everything works fine at first. However, whenever I expand the vertical sidebar (either by making it to show full tab titles or by clicking the settings/bookmarks icons on the sidebar), strange glitchy black pixels appear in the background of the expanded sidebar. Sometimes black pixels also show up when I move the mouse over that area.

This is usually a clientside bug when the client tells niri that some part of a Wayland surface is fully opaque when it isn't. GTK 3 tends to do this with rounded surfaces and the usual fix is to make them have background opacity 0.99 instead of 1. Firefox does custom Wayland handling, so not sure how you can fix it there.

You can check that this is the issue by binding https://niri-wm.github.io/niri/Configuration%3A-Debug-Options.html#debug-toggle-opaque-regions then seeing if the surface in question is blue (which is opaque) instead of red (semitransparent).

@yuxqiu
Copy link
Contributor

yuxqiu commented Feb 22, 2026

You can check that this is the issue by binding niri-wm.github.io/niri/Configuration%3A-Debug-Options.html#debug-toggle-opaque-regions then seeing if the surface in question is blue (which is opaque) instead of red (semitransparent).

Thanks! Yeah, indeed I noticed that the expanded region isn't fully red. It's a bit bluish compared to the titlebar and the unchanged sidebar region. Also, can confirm that setting background opacity to 0.99 fixes the problem.

@YaLTeR
Copy link
Member Author

YaLTeR commented Feb 24, 2026

What are the implications of changing your wallpaper? Is it 1 time CPU usage or extra memory usage? I'm not proficient enough to evaluate the code, but are there checks in place to de-allocate memory of old blurred wallpapers not in use? Only asking because there was that 1 memory leak that recently got fixed which affected all windows.

1 time extra CPU/GPU usage. The same textures are reused. If there's any leak then it's a bug.

@travis-aaron
Copy link

travis-aaron commented Feb 24, 2026

Kitty added support for ext-background-effect a few days ago: kovidgoyal/kitty@bcba8fc

@b0o
Copy link

b0o commented Feb 24, 2026

Love it! One request: It would be nice to be able to configure passes and offset inside of window-rule/layer-rule - I'd like my bar to use a smaller blur radius than my terminal.

@YaLTeR
Copy link
Member Author

YaLTeR commented Feb 25, 2026

Love it! One request: It would be nice to be able to configure passes and offset inside of window-rule/layer-rule - I'd like my bar to use a smaller blur radius than my terminal.

The reason it's not in window rules is because it's not doable for xray where blur happens once globally.

@b0o
Copy link

b0o commented Feb 25, 2026

Makes sense. But, since xray can be set in window/layer rules, do you think it could be allowable to set passes/offset only if xray is false, and either error or just ignore it and use the global value if xray is true?

For bars, it seems disabling xray should have minimal performance impact, since there will rarely be motion behind them, and they should be stationary, right?

@YaLTeR
Copy link
Member Author

YaLTeR commented Feb 25, 2026

For bars, it seems disabling xray should have minimal performance impact, since there will rarely be motion behind them, and they should be stationary, right?

CSD shadows extend under them, overview open/close will cause nonxray reblur, any workspace switch also.

Makes sense. But, since xray can be set in window/layer rules, do you think it could be allowable to set passes/offset only if xray is false, and either error or just ignore it and use the global value if xray is true?

I'm not sure if it's a good design because it's a weird limitation if you're not familiar with the inner workings.

@ffs-akl
Copy link

ffs-akl commented Feb 25, 2026

Currently, Niri applies the blur effect to the entire surface geometry of a window. For many Wayland native tools, the surface is often much larger than the actual visible UI elements (to accommodate animations or input handling).
In the case of SwayNC, the surface occupies a full-height pillar on the right side of the screen. Because Niri blurs the entire rectangle, it creates a massive "blurry wall" that obscures the windows underneath, even when no notifications are present or when the cards only take up a small portion of that space.
grim-2026-02-25-235538

@HigherOrderLogic
Copy link
Contributor

Sounds like SwayNC needs to implement ext-background-effect.

@psi4j
Copy link

psi4j commented Feb 25, 2026

With regard to the non-xray blur:

It appears that the blur is only activated until after the window-open animation finishes. That is, if I have it set to 150 ms, that is when it starts. Setting the duration-sm to 0 makes the non-xray blur virtually instant, which is ideal.

animations {
    window-open {
        duration-ms 0
        curve "ease-out-expo"
    }
}

window-rule {
    match app-id="^kitty$"
    background-effect {
        blur true
        xray false
    }
}

Maybe these should both trigger in parallel instead of sequentially.

Edit:

I see non-xray requires some upstream work in Smithay.

@psi4j
Copy link

psi4j commented Feb 25, 2026

Currently, Niri applies the blur effect to the entire surface geometry of a window.

If you read what YaLTeR said in his post, you'll notice he definitely did address this. I understand Hyprland lets you set an alpha threshold for their blur effect, but I agree with YaLTeR, we should be incentivizing clients to implement ext-background-effect since it exists. Somebody earlier also said "why not both?" and that was answered as well.

nficca added a commit to nficca/nixos-config that referenced this pull request Feb 26, 2026
@nishiiko
Copy link

Because Niri blurs the entire rectangle, it creates a massive "blurry wall" that obscures the windows underneath, even when no notifications are present or when the cards only take up a small portion of that space.

There is an open issue by Erik for implementing ext-background-effect which would fix the problem, this is an issue on SwayNC's end
@ffs-akl

@ffs-akl
Copy link

ffs-akl commented Feb 27, 2026

@nishiiko Thank you for figuring this out. I’ll keep an eye on the SwayNC feature request you linked."

@yayuuu
Copy link

yayuuu commented Mar 1, 2026

I really wanted to test it earlier, but I got sick and just feeling good enough to try it.
Overall it works really smooth, I didn't notice any breaking bugs or performance issues so far, but there is one feature that I like in the Naxdy's implementation, that this one doesn't have - ignore alpha. Without this, anything that has a different shape than a rectangle is going to spill blur outside of the desired area, for example dank bar with goth corners covers much more than it should. With ignore-alpha I can set transparent parts to not have any background effects.

This version:
official_small

Naxdy's version:
naxdy_small

It's not a deal breaker for me, I would probably switch to a solid color bar and not use any layer blur, but it would be nice to have.

@HigherOrderLogic
Copy link
Contributor

ignore alpha

See the original post:

There's no "alpha threshold" setting for blur, instead clients are encouraged to implement the ext-background-effect protocol which lets them shape their background blur. It's already implemented, or in progress, in:

@YaLTeR
Copy link
Member Author

YaLTeR commented Mar 1, 2026

for example dank bar

DMS also already has ext-bg-effect in the works (both PR into Quickshell and a wip DMS branch).

@Abijspy
Copy link

Abijspy commented Mar 1, 2026

for example dank bar

DMS also already has ext-bg-effect in the works (both PR into Quickshell and a wip DMS branch).

Also Noctalia merged their niri-blur branch into main with dependency changed from quickshell to their own custom quick shell with ext-bg-effect named noctalia-qs

@yayuuu
Copy link

yayuuu commented Mar 1, 2026

for example dank bar

DMS also already has ext-bg-effect in the works (both PR into Quickshell and a wip DMS branch).

Ok, that's nice. Then I think that solves this issue.

@zetaPRIME
Copy link

meanwhile my setup is on AGS, and I'm not sure if that's ever getting an easy way to do floating blur regions for elements because gtk4 doesn't allow access to know the css of anything

@levkush
Copy link

levkush commented Mar 2, 2026

Hey, is there any variable to not blur fully transparent (alpha 0) surfaces? Thanks in advance!

@LuckShiba
Copy link
Contributor

Hey, is there any variable to not blur fully transparent (alpha 0) surfaces? Thanks in advance!

From the PR description:

There's no "alpha threshold" setting for blur, instead clients are encouraged to implement the ext-background-effect protocol which lets them shape their background blur.

@levkush
Copy link

levkush commented Mar 2, 2026

Hey, is there any variable to not blur fully transparent (alpha 0) surfaces? Thanks in advance!

From the PR description:

There's no "alpha threshold" setting for blur, instead clients are encouraged to implement the ext-background-effect protocol which lets them shape their background blur.

Thank you for letting me know! I didnt see that, sorry.

@ItsLemmy
Copy link

ItsLemmy commented Mar 2, 2026

Blur settings not properly applied to layer-shell surfaces on initial startup

Description:
I'm encountering an issue where custom blur settings are ignored on layer-shell surfaces during niri's initial startup, falling back to the default values. Regular windows apply the custom blur correctly from the start.

Steps to Reproduce:

  1. Set an exaggerated blur setting in config.kdl (e.g., saturation 15.5).
  2. Start niri.
  3. Observe that the blur behind a normal window (like a terminal) applies the custom settings, while the blur behind a layer-shell surface (like noctalia) uses the default settings.
  4. Trigger a config hot-reload (e.g., by making an edit to one of the blur variable in config.kdl and saving).
  5. The layer-shell blur will now correctly update to the custom settings.

Additional Context:

  • This issue affects all blur variables (passes, offset, noise, and saturation).
  • In the screenshot below, notice the highly saturated blur behind the terminal compared to the default blur behind the top bar.

Config Snippet:

blur {
   passes 2        // more passes = stronger blur (default: 3)
   offset 3.0      // sample distance per pass (default: 3.0)
   noise 0.02      // grain overlay (default: 0.02)
   saturation 15.5 // color saturation boost (default: 1.5)
}
image

@YaLTeR
Copy link
Member Author

YaLTeR commented Mar 2, 2026

I think I know why this happens, and it's probably xray vs. nonxray rather than normal vs. layer-shell

@ItsLemmy
Copy link

ItsLemmy commented Mar 2, 2026

Yeah I forgot to mention I use xray false on the layer.

@ItsLemmy
Copy link

ItsLemmy commented Mar 3, 2026

Working great thx!

@flyingbucket
Copy link

By the way, WezTerm is also implementing support for ext-background-effect in their PR #7615.
wezterm/wezterm#7615

@pancakesmeow
Copy link

foot has merged and released support for ext-background-effect https://codeberg.org/dnkl/foot/releases/tag/1.26.0

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.