Visual Effects
Live window and layer opacity, optimized or true scene blur, and standard client-controlled surface alpha.
The opacity, blur, blur_mode, and nested popups properties of
sweets.window_rule({ ... }) apply compositor-side appearance to managed
Wayland and XWayland windows. They use the same retained initial identity and
ordered rule set as opening properties, but resolve live: a valid reload updates
windows that are already open without rerunning placement or focus.
sweets.layer_rule({ ... }) exposes the same
appearance fields for layer-shell roots, using exact namespace and current
layer identity instead of window metadata.
sweets.window_rule({
backend = "xdg",
app_id = "foot",
opacity = 0.88,
})
sweets.window_rule({
backend = "xwayland",
app_id = "XTerm",
opacity = 0.92,
})Matchers and appearance
Every appearance-only rule requires at least one matcher and one appearance property. A window rule may also combine these fields with opening properties.
| Field | Type | Meaning |
|---|---|---|
backend | string | Exactly "xdg" or "xwayland" |
app_id | string | XDG app ID, or X11 class for XWayland |
title | string | Initial window title |
dialog | boolean | Initial dialog fact |
transient | boolean | Initial parent or transient-for fact |
opacity | number | Finite whole-content opacity from 0.0 through 1.0 |
blur | boolean | Force or suppress blur for the matching managed window |
blur_mode | string | Per-window mode override: "optimized" or "scene" |
popups | table | Descendant XDG popup opacity, blur, and blur_mode |
Matching strings are exact and case-sensitive. When several rules match, a
later value replaces the earlier value for only the property it declares.
Unmatched windows use opacity 1.0 and do not request blur. Installed rules run
first and personal rules append afterward.
Opening-only, appearance-only, and combined declarations share one limit of 128 window rules and 32 KiB of retained matcher and opening-policy text.
Layer rules use an independent 128-rule and 32-KiB budget. Their opacity covers the layer root and ordinary subsurfaces, while independent XDG popups remain outside the multiplier. See Layer Rules for the live identity, ordering, and popup boundaries.
What becomes transparent
Opacity multiplies the managed root and all of its ordinary subsurfaces once. That means the complete application content—including text, images, and the application background—becomes translucent together.
The compositor border and independent role popups stay outside this multiplier.
Use the nested popups table to give descendant XDG popup trees their own
opacity and blur policy. Popup opacity does not multiply the root's opacity.
A value of 0.0 makes the selected content invisible but does not unmap it:
keyboard focus, pointer hit testing, popup grabs, and compositor operations
continue normally.
Client background alpha and Sweets whole-content opacity multiply. A Foot
background pixel at 0.70 client alpha with opacity = 0.75 produces
effective alpha 0.525. Fully opaque text from the same Foot window becomes
0.75 alpha.
Sweets does not alter client buffers. An opaque application becomes uniformly translucent when window-rule opacity matches; an application such as Foot that already draws a transparent background keeps that internal alpha distinction.
Backdrop blur
Blur is a separate opt-in from transparency. Enable the renderer globally, then enable it for matching windows:
sweets.blur({
enabled = true,
mode = "optimized",
strength = 8,
noise = 0.02,
})
sweets.window_rule({
app_id = "foot",
blur = true,
})| Global field | Type | Meaning |
|---|---|---|
enabled | boolean | Master switch; default false |
mode | string | Backdrop source: "optimized" or "scene"; default "optimized" |
strength | integer | Stable level from 1 through 15; default 8 |
noise | number | Finite premultiplied noise from 0.0 through 0.25; default 0.02 |
optimized prepares one shared blurred background per active output from its
clear color plus background and bottom layer surfaces. It intentionally ignores
ordinary windows and top/overlay content, so several blurred windows share one
low-cost source. scene samples the framebuffer immediately below each blurred
window. It therefore includes the wallpaper, bottom/background layers, and
ordinary windows below, in the same stacking order shown on screen. It never
samples the window that owns the effect or anything above it. Multiple
overlapping blurred windows consequently build on one another in deterministic
scene order. Sampling stops at the effect's physical bounds, so a neighboring
window across a gap cannot bleed into its blurred edge.
Forced window blur follows the presented content geometry and its effective
rounded corners. Forced layer blur follows the arranged layer-root geometry.
A layer rule can set blur_ignore_alpha from 0.0 through 1.0 to suppress
forced blur beneath client pixels at or below that alpha. The comparison uses
client alpha before whole-root rule opacity. Omitting it preserves the complete
arranged geometry.
A matching window or layer rule can set blur = false to suppress an
earlier matching rule. blur_mode overrides the global mode for only
that owner. An application that already draws transparent pixels, such as
Foot, remains merely transparent unless it requests blur or matching
window-rule appearance properties explicitly enable blur.
Client-requested blur regions
Sweets advertises ext_background_effect_manager_v1 version 1 with only its
blur capability. A native Wayland client can attach one background-effect
object to one of its surfaces and commit an exact blur region. Region add and
subtract operations, disjoint pieces, and an explicitly empty region are
preserved; destroying the source wl_region after the request is safe because
the request copies it. A change becomes visible only with the associated
wl_surface commit.
Requests work on ordinary managed XDG roots and subsurfaces, XDG popups, and layer-shell roots, subsurfaces, and popups that participate in the normal scene. Cursor surfaces, drag icons, input-method surfaces, unmanaged X11 surfaces, and secure lock surfaces do not receive backdrop effects. Sandboxed security-context clients do not see this global.
The global enabled switch still controls every effect. For a managed window,
blur = false vetoes requests in its subtree. Otherwise a non-empty committed
client region wins with its exact shape; blur = true supplies the rounded
managed-window shape only when no non-empty client request is present. The
window's blur_mode applies to both forms. A matching layer rule provides the
same force, veto, and mode policy for its root and ordinary subsurfaces. Role
popups remain independent and use their nested popup policy.
For popup trees, a non-empty client region also wins over forced geometry.
popups.blur = false vetoes the request. The global master gates every form.
Popup opacity affects client content, while the backdrop remains fully filtered.
popups.corner_radius clips the backdrop effect to an explicitly configured
popup shape; it does not clip the client's content or input region.
Disabling blur does not erase committed client requests, so re-enabling it on reload takes effect without client resubmission. Destroying the effect object queues removal for the next surface commit. Processing is bounded to 256 region operations and 256 resulting rectangles; a more complex request is ignored with one warning rather than disconnecting the client or creating unbounded render work.
Client-controlled surface opacity
Sweets advertises the standard staging alpha-modifier-v1 protocol as
wp_alpha_modifier_v1 version 1. A Wayland client can attach a constant alpha
multiplier to one of its own wl_surface objects and commit a new value without
reattaching or damaging its buffer.
The protocol value is surface-local. Changing a root surface does not change an independent subsurface or popup; each surface that wants a multiplier owns its own protocol object. By contrast, matching Sweets window-rule opacity is deliberate whole-window policy and supplies its opacity to the complete managed root and ordinary subsurface tree. The final alpha is:
client pixel alpha × client surface multiplier × Sweets window/layer opacityEvery factor is applied once. Destroying the modifier object restores its unspecified/unit value on the next surface commit. Invalid duplicate objects or requests after surface destruction are protocol errors for only the offending client.
The protocol remains available to security-context clients because it can modify only surfaces owned by that client; it provides no observation or cross-client control.
Reload and capture behavior
On every valid configuration reload, Sweets resolves all current managed windows and layer roots from their typed identities, compares the effective old and new appearance, then installs each complete new rule snapshot atomically. An opacity change cannot configure, move, resize, focus, restack, dismiss a popup, disturb its grab, or rerun opening rules. Title and app-ID updates after opening do not continuously restyle the window. A committed layer-shell layer change does re-resolve layer rules because current layer is part of that protocol identity; namespace remains fixed.
The appearance survives workspace hiding, minimize and restore, unmap and remap, output moves, and XWayland surface association. A changed visible value damages the complete affected region once. Blur strength, noise, mode, and the master switch are live too. The same effective values schedule no frame, and static translucent or blurred windows do not create a continuous redraw source.
When a resize, layout, fullscreen, workspace, or output move is waiting for client buffers, opacity, blur, rounded masks, stacking, and geometry all remain on the same last complete presentation. A valid appearance or blur reload updates an open held window once at that held geometry without restarting the move. Popups keep their held parent coordinates and their own opacity.
Closing a tiled transparent or blurred window replaces its live tree with one renderer-owned snapshot of the last displayed client and border pixels. The desktop backdrop is not baked into that snapshot: Sweets retains the forced rounded blur or exact client-requested regions as separate elements immediately below it. Snapshot and effects are released together, and the live surface is never composed in the same slot, avoiding a darker double-opacity frame.
Output capture observes the same composed blur and transparency shown on screen. Isolated window capture retains the selected window's effective alpha but intentionally excludes wallpaper, neighboring windows, and backdrop blur.
Opacity below 1.0 or an active blur effect makes the output ineligible for
direct primary-plane scanout because it must be composed with content behind
it. These restrictions do not by themselves disable the hardware cursor plane.
Removing the effects restores the existing primary-plane eligibility path when
all other gates pass.
Invalid types, non-finite numbers, values outside 0.0..=1.0, unknown fields,
or missing matchers/properties in either rule namespace reject the complete
reload and retain the last valid appearance.