window_frames
Most apps draw their own titlebar and buttons. This is client-side decoration (CSD). Gnoblin can draw them instead: server-side decoration (SSD).
window_management.action_*_titlebar sets Mutter's titlebar action
preferences. GTK apps typically draw their own titlebars and read GNOME
settings directly, so this Lua setting does not change their client-side
decoration (CSD) behavior.
Gnoblin's built-in fallback server-side decoration (SSD) supports these actions:
toggle-maximizetoggle-maximize-horizontallytoggle-maximize-verticallyminimizelowermenunone
A custom SSD renderer implements its own titlebar click behavior.
Use frame.button_layout to choose the right-side buttons in Gnoblin's native
frame and its fallback. External renderers use their own settings.
window_management.button_layout does not change these titlebars. See
titlebar button placement.
The embedded default config enables Gnoblin's built-in native renderer with
mode = "auto" and extents {32, 1, 1, 1}. Apps keep their own titlebars;
apps requesting server decorations get a native frame. It needs no desktop shell
or external renderer. The default config disables animations.
Use mode to decide which windows get a frame and renderer to choose what
draws it. Setting a renderer alone does not enable frames. A config without a
frame rule retains the API default, "off".
Run gnoblinctl config restore-default to replace your config with the current
embedded defaults; Gnoblin backs up your previous config. To keep your other
settings, add the frame rule below instead.
Choose a mode
| Mode | Behavior |
|---|---|
off |
Let the app draw its titlebar; add no frame or cropping |
auto |
Add a frame only when the app explicitly asks for one |
prefer-server |
Prefer a Gnoblin frame for apps that support decoration negotiation |
replace |
Hide the configured app margins and draw a Gnoblin frame |
Apps negotiate decorations through Wayland decoration protocols. GTK on Wayland
uses KDE's server-decoration protocol; other clients commonly use
xdg-decoration. Gnoblin supports server decorations through both. GTK windows
that create the KDE decoration object use auto behavior by default, so
Gnoblin's native renderer supplies their frame. A matching Lua window rule can
select another mode. auto uses client requests instead of guessing from
appearance.
X11 apps count as asking for a server frame when they do not turn
decorations off with _MOTIF_WM_HINTS; with no rule they use auto. The
frame is drawn by the compositor around the client, so _NET_FRAME_EXTENTS
reports Gnoblin's border and client_type = "x11" in a rule match selects
only these windows.
GTK apps with a custom titlebar can still draw titlebar controls inside their
surface. Gnoblin applies its frame and clips declared client shadow margins,
but it cannot identify arbitrary pixels inside an app surface as a border
without risking removal of app content. corners.remove_csd reconstructs
detected client-rounded corners before applying Gnoblin's shape.
With prefer-server, Gnoblin uses the app's declared visible bounds when the
app keeps CSD. It clips buffer margins outside those bounds and draws Gnoblin's
configured border and shadow around them. Apps that omit visible bounds use the
full surface.
Let apps request a Gnoblin titlebar
Add this to ~/.config/gnoblin/init.lua after any gnoblin.load(...) lines:
gnoblin.window_rule {
match = {type = "window"},
frame = {
mode = "auto",
renderer = "native",
extents = {36, 0, 0, 0},
},
}This uses the built-in renderer with a 36-pixel titlebar and no side or bottom
border. extents lists top, right, bottom and left sizes in that order.
Save and run gnoblinctl config reload. The app must also update its Wayland
surface before a decoration change takes effect; if it does not change, reopen
the app. Apps that draw their own titlebars can look unchanged under auto.
Frame options
All fields below go inside frame. Later matching rules override individual
fields. Sizes are logical pixels.
| Field | Default | Values |
|---|---|---|
mode |
"off" |
Modes listed above |
extents |
{32, 1, 1, 1} |
Top/right/bottom/left frame size; integers 0–256 |
crop |
{0, 0, 0, 0} |
Removed client margins; same order and range |
renderer |
"native" |
Registered service name |
style |
"default" |
Style understood by that renderer |
background |
"#242424" |
Active background colour |
foreground |
"#eeeeee" |
Foreground colour |
inactive_background |
"#303030" |
Unfocused background colour |
button_layout |
{"minimize", "maximize", "close"} |
Native-frame buttons, without duplicates; {} hides them |
Colours accept #RRGGBB or #RRGGBBAA.
Renderer and style names accept 1–64 letters, digits, _ or -.
Cropping client decorations
The crop option hides a strip of the app and makes that strip unclickable. It
cannot distinguish a titlebar from tabs, search boxes or other controls. Use
it only when you know exactly which margins you want to hide.
With prefer-server, the declared visible bounds are cropped automatically
when an app keeps CSD; crop adds extra margins in that case. Negotiated SSD
clients use their own declared bounds and ignore crop. With replace, zero
extents give a crop-only window. Fullscreen temporarily removes explicit crop
and frame extents.
Custom renderers
Register the renderer command, then select its name in a rule:
gnoblin.configure {
frame_renderers = {
cairo = {"gnoblin-frame-cairo"},
},
}
gnoblin.window_rule {
match = {type = "window"},
frame = {mode = "auto", renderer = "cairo"},
}Use a command name resolved through the compositor's PATH, followed by
separate arguments. A full executable path is also accepted. native is
reserved.
Bingux supplies its own styled renderer.
Config reload restarts external renderers, including rebuilt executables at unchanged paths. The native frame keeps controls available during replacement or failure. A compositor upgrade still needs logout and login.
Limits
Frames work on normal Wayland application windows (xdg-toplevel) and on
X11 apps running through Xwayland, which have the same frame, rules, effects
and input as Wayland windows. They do not apply to popups, menus, bars or
launchers.
An X11 app can ask for its frame size (_NET_REQUEST_FRAME_EXTENTS) before
the window exists, when no rule can match its title or application. Gnoblin
answers with the rules that match only type = "window" and client_type;
the real size is set when the window is managed.
Text input, client-driven background blur and activation tokens come from Wayland protocols, so X11 apps do not use them. Moving framed windows between displays with different scales and cropping apps with many popups have limited test coverage.
Wayland window effects exclude transparent buffer margins outside the client's
declared window geometry. Borders and shadows include Gnoblin's server frame.
When an app uses Gnoblin's frame, corners.radius rounds the whole window,
frame and content, even in auto mode, so square app content never shows
outside the frame's corners.
States where rounding is off, such as maximised
with keep_maximized = false, make both the frame and the content square.
Popup positions use the parent window's client origin, excluding Gnoblin's frame extents and accounting for cropped margins. This also applies when a popup acknowledges its configuration or follows a moved parent.
For renderer implementation and tests, see renderer architecture and the author guide.