window_rules
A rule has two parts: match selects the windows, and the other fields change
their appearance. Add rules to ~/.config/gnoblin/init.lua after any
gnoblin.load(...) lines. Put rules for all windows before rules for specific ones.
Add a rule
This dims unfocused application windows without replacing imported rules:
gnoblin.window_rule {
match = {type = "window", focused = false},
opacity = 0.95,
}Save and run gnoblinctl config reload. Switch focus to check the result.
Choose what to match
Every condition in match must match. For example,
{type = "window", focused = false} selects unfocused application windows;
it does not select a bar or launcher. If focused is omitted, the rule can
match both focused and unfocused windows.
| Key | Matches |
|---|---|
type = "window" |
Application windows |
type = "layer" |
Layer-shell surfaces, such as bars and launchers |
focused = true or false |
Focus state |
app_id |
GTK application ID, or WM class when the GTK ID is empty |
title |
Current window title |
layer |
Layer-shell namespace supplied by the client |
workspace_id |
Stable ID of the current workspace |
workspace_number |
Current one-based workspace position, 1–1024 |
client_type |
"wayland", or "x11" for an Xwayland client |
Choose the match field based on what should identify the window:
- Use
app_idto match an application across its windows. - Use
titleto target a particular document or window. Titles often change as the document or page changes. - Use
layerto match the namespace chosen by the shell or client. It may not match the program's executable name.
Find the values
List open windows to see their current titles and IDs:
gnoblinctl window listThe APP ID shown by window list is a desktop-entry ID. It can differ from
the app_id used by window rules. To see the exact values for the focused
window, run:
gnoblinctl window matchUse rule_app_id for app_id and copy the reported title for a title rule.
Gnoblin uses the GTK application ID when present and falls back to the WM
class otherwise. Use --json for structured output or add a window ID to
inspect a specific window.
For a layer surface, run gnoblinctl layer list while it is running. Use the
reported namespace as the layer value. Layer surfaces do not appear in
window list.
Keep layer opacity scoped
Layer surfaces can include wallpaper clients. A rule matching only
{type = "layer"} with opacity can fade a wallpaper over the desktop
background, which looks like a color overlay. Match the layer namespace too:
gnoblin.window_rule {
match = {type = "layer", layer = "^my-panel$"},
opacity = 0.9,
}Get the exact namespace with gnoblinctl layer list. If your shell already
manages wallpaper, do not also start a separate wallpaper client through
Gnoblin's autostart. See the wallpaper guide for the
available setup options.
Write a matcher
The string fields app_id, title, and layer accept Lua 5.4 patterns.
They are case-sensitive and search anywhere by default. Use ^ and $ to
match the whole value.
A dot (.) matches any character; write %. to match a literal dot. See the
Lua pattern reference for
other pattern characters. JavaScript and PCRE regex syntax is not supported.
Use ^ at the start and $ at the end to match the whole value. For example,
if the console reports org.gnome.Nautilus as rule_app_id, match only that
app like this:
gnoblin.window_rule {
match = {type = "window", app_id = [[^org%.gnome%.Nautilus$]]},
opacity = 0.95,
}In Lua's [[...]] string, percent signs are kept as written. The % before
each dot makes it a literal dot in the pattern. Replace the example with the
value reported on your system.
To match a title containing Notes anywhere, omit the anchors:
gnoblin.window_rule {
match = {type = "window", title = "Notes"},
opacity = 0.9,
}This also matches titles such as Notes — Work. To match only the exact title
Notes, write title = "^Notes$".
For a layer client whose namespace is my-panel, match that surface like this:
gnoblin.window_rule {
match = {type = "layer", layer = "^my-panel$"},
opacity = 0.9,
}When a rule has more than one condition, all of them must match. This targets only unfocused windows from one app:
gnoblin.window_rule {
match = {
type = "window",
app_id = [[^org\.gnome\.Nautilus$]],
focused = false,
},
opacity = 0.9,
}You can combine app_id and title the same way when a rule should affect a
particular window title from one application.
Workspaces
Use a workspace ID when a rule should keep targeting the same workspace as
workspace positions change. Declare persistent workspaces as objects in the
top-level workspaces field of gnoblin.configure:
gnoblin.configure {
workspaces = {
{id = "code", name = "Code"},
{id = "web", name = "Web"},
{id = "chat", name = "Chat"},
},
}Each workspace needs a unique stable ID and a nonempty display name. IDs match
^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$. The list order determines each
workspace's current one-based position; the ID remains attached to that
workspace when positions change. Declared workspaces remain available when
empty. Runtime-created workspaces are temporary and can receive a session-only
ID; do not save a generated session ID in configuration.
Use declared IDs for persistent targets. A matcher can also use an ID assigned
to a runtime-created workspace. Generated @session-N IDs are temporary and
should not be saved in configuration. An {id = ...} placement target must
exist when the matching window opens; otherwise Gnoblin leaves the window in
place and logs a warning.
Match a window's current workspace by ID or by its current one-based position:
gnoblin.window_rule {
match = {type = "window", workspace_id = "code"},
opacity = 0.95,
}
gnoblin.window_rule {
match = {type = "window", workspace_number = 2},
opacity = 0.9,
}Workspace matches update when a window moves. Numbers can change as workspaces are created, removed, or reordered, so use IDs for rules that need a lasting target.
To place a newly created normal window, add a workspace effect to its rule:
gnoblin.window_rule {
match = {type = "window", app_id = "^org.example.Editor$"},
workspace = {id = "code"},
}Use workspace = {number = 2} to target a position instead; numbers range from
1 to 1024. Placement runs
once when the window is created; it is not repeated after title or focus
changes or a config reload. Transient and modal windows remain with their
parent.
Gnoblin leaves the window where it opened and logs a warning if its declared workspace ID is not present. It does the same when a numeric target position is unavailable when the window opens.
Rule order
Matching does not stop at the first rule. Later rules override only the fields they set. For example, an unfocused-window rule can change opacity while keeping a radius from an earlier all-window rule.
Use gnoblin.window_rule to add rules without removing earlier ones. Passing
a complete window_rules list to gnoblin.configure replaces the configured list;
see load order.
What can a rule change?
- Effects: blur, opacity, rounded corners and outlines, shadows and shaders.
- Titlebars: decoration policy and renderer.
- Layer animations: entry, exit and timing.
Prefer general rules when a behavior should apply to all clients. Use app-name exceptions only when you intend different behavior for that app.