Window Rules
Place and shape matching XDG and XWayland windows when they first map.
sweets.rule({ ... }) matches a window by exact app_id, title, and an
optional backend, then applies placement and behavior when the window first
maps. Rules are optional. A window with no matching rule opens on the current
workspace as usual.
sweets.rule({ app_id = "org.wezfurlong.wezterm", workspace = 2 })
sweets.rule({ title = "Picture-in-Picture", floating = true, focus = false })
sweets.rule({ backend = "xwayland", app_id = "steam", monitor = "DP-1" })
sweets.rule({ app_id = "org.gnome.Nautilus", floating = true, size = { 900, 700 } })
sweets.rule({ title = "Picture-in-Picture", floating = true, size = { 480, 270 }, position = "top-right" })Options
| Key | Type | Default | Description |
|---|---|---|---|
app_id | string | — | Exact app_id (Wayland) or X11 class to match |
title | string | — | Exact window title to match |
backend | string | any | Restrict to xdg or xwayland windows |
workspace | num | current | Workspace 1–10 to open the window on |
monitor | string | current | Output name to open the window on |
floating | bool | layout | true floats the window, false forces tiling |
focus | bool | auto | false opens the window without taking focus |
size | table | natural | Open size { width, height }; each value is pixels when > 1 or a fraction of the output when <= 1. Floating windows only |
position | string | table | center | An anchor name (center, top-left, top, top-right, left, right, bottom-left, bottom, bottom-right) or { x, y } coordinates for the window's top-left. Floating windows only |
maximized | bool | false | true opens the window maximized |
fullscreen | bool | false | true opens the window fullscreen (cannot combine with maximized) |
A rule must set at least one matcher (app_id, title, or backend);
otherwise configuration is rejected. app_id, title, and monitor cannot be
empty strings.
Matching
Matching is exact, not substring or pattern. All present matchers must hold:
a rule with both app_id and title only fires when both match exactly. When
several rules match the same window they apply in config order, and a later
rule's fields override an earlier rule's — so you can layer a broad rule and a
specific one.
Run sweetctl views to read each window's real app_id and quoted title.
Titles often contain dynamic text (for example Page — Firefox), so an exact
title rule is best reserved for stable titles like Picture-in-Picture.
Placement and focus
When workspace or monitor sends a window somewhere that is not currently
visible, Sweets follows the window: it switches to that workspace or output
so the window is shown rather than mapped off-screen. If the target is already
visible on another output, that output simply becomes active.
focus only suppresses auto-focus — focus = false opens a window without
giving it keyboard focus. It cannot grant focus to a window that would not
normally take it (a focus value of true is the same as omitting the field).
size applies to floating windows only — the tiler owns the size of tiled
windows. Pair it with floating = true (or a window that already floats); on a
tiled window the size is ignored. The window opens centered at the requested
size, clamped to its output, and you can resize it freely afterward.
Each size value is read as pixels when it is greater than 1, or as a
fraction of the output when it is 1 or less. So { 900, 700 } is 900×700
pixels, while { 0.5, 0.5 } is half the monitor's width and height — handy when
a rule should scale across monitors of different resolutions.
position (floating windows only) places the window in one of two ways:
- An anchor name snaps it to one of nine spots on its output. Edge and
corner anchors inset by the configured outer gap;
centeris the default and matches a rule with noposition. Combine it withsizeto open, say, a small player pinned to thetop-right. { x, y }coordinates set the window's top-left precisely. Each value is pixels when> 1or a fraction of the output when between0and1— so{ 100, 0.25 }is 100px from the left and a quarter of the way down. The window is clamped to stay on its output.
maximized = true opens the window maximized (covering the usable area), and
fullscreen = true opens it fullscreen (covering the whole output, no border or
gaps). Both work for tiled or floating windows, and any size/position
becomes the geometry the window restores to when it leaves the mode. The two are
mutually exclusive — setting both in one rule is rejected. A client that does
not honor the state keeps its own size.
If a rule names a monitor that is currently disconnected, Sweets ignores that
field and falls back to the current output, so the window stays reachable.
Applying changes
Rules are evaluated once, when a window first maps. For XWayland windows the
title and app_id may be set slightly after the window appears, which can make
title-based rules unreliable for those clients. After editing rules, reload the
configuration and reopen the window to apply the change.