Window rules#
Rules match windows and apply effects. Each window-rule { } node needs at least one match; matchers are regexes in KDL raw strings.
window-rule {
match title=#"^Minecraft"# is-xwayland=#false
exclude title=#"launcher"#
open-on-workspace 6
opacity 0.98
allow-tearing #true
}
window-rule {
match app-id=#"^foot$"# title=#"^scratch"#
open-floating #true
default-size 800 600
open-centered
animation "slide" dir="top"
}
Matching#
Selectors AND together within a match node and OR across multiple match nodes, and any matching exclude node vetoes the rule:
| Selector | Matches |
|---|---|
app-id | regex against the app id (X11 class for XWayland windows) |
title | regex against the window title |
is-xwayland | X11 windows (#true) or native Wayland (#false) |
is-floating | current floating state |
is-fullscreen | current fullscreen state |
Regexes use the lightweight regex-lite dialect and are validated when the config parses; a bad pattern is a config error. Rules apply in file order: scalar effects (workspace, size, opacity) let the later match win, boolean effects accumulate.
The classic no-capture use is keeping your Discord DMs off stream:
window-rule {
match app-id=#"^discord$"#
no-capture
}
On your screen the window is normal; every screenshot, recording, and cast sees an opaque black box in its place (rounded to match), and even the close-animation replay stays blacked out. Pixels never leave the compositor.
Effects#
All thirteen effects work today. The open-* family positions the window once, when it maps, and stays as mapped; every other effect is re-resolved on running windows by burrow reload, so a rule edit lands on the apps you already have open. no-anim and animation cover both the open and the close.
| Effect | Type | Does |
|---|---|---|
open-floating | bool | start floating (or #false to force tiling) |
open-on-workspace | number | map on that workspace (1-based; creates it if needed) |
default-size | two ints | initial floating size |
open-centered | flag | center a floating window |
opacity | 0..1 | per-window opacity |
allow-tearing | bool | let this window tear when fullscreen, same as the surface requesting it |
no-anim | flag | skip this window's open and close animations |
animation | style | override the open/close style, same grammar as animation styles |
rounding | px 0..200 | override the decoration corner radius for this window |
shadow | bool | opt this window out of (or back into) the drop shadow |
dim | bool | opt this window out of (or back into) dim-inactive |
blur | bool | give this window the blurred backdrop; blur is opt-in per window |
no-capture | flag | black the window out of every capture path: screenshots, recordings, and casts |
Layer rules#
Layer rules target layer surfaces (bars, launchers, wallpaper tools) by namespace, and their effect today is the blurred backdrop:
layer-rule {
match namespace=#"^quickshell:bar"#
blur
ignore-alpha 0.2
}
match namespace is a regex, same dialect as window rules, and multiple match nodes OR together. Three effects:
blurhands the surface the cached backdrop blur (it needsdecoration { blur { } }switched on).ignore-alphamasks the blur to the pixels where the surface's own alpha is at or above the threshold (0..1), so a pill-shaped bar blurs only under its pills; unset blurs the whole rect. The mask needs an ARGB buffer, since XRGB surfaces pin alpha to one.no-animskips the surface's open and close animations. Shells that remap their layer surfaces on every state change flicker through the popin otherwise; this rule keeps them still.