srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/core
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2026-06-01 23:18:00 +0200
committersrdusr <[email protected]>2026-06-01 23:18:00 +0200
commit3ef784e09f6b81b767837e048d691c4e63528e55 (patch)
tree0f96600eff4028d93f12764a79c02dea69434bc8 /crates/core
parent27daed83230eaefd0f41461cad20bbed7d1ad575 (diff)
downloadsrdwm-3ef784e09f6b81b767837e048d691c4e63528e55.tar.gz
srdwm-3ef784e09f6b81b767837e048d691c4e63528e55.zip
Let negotiating clients be forced to server-side decoration, and document the GTK half
Asked to research how KDE and GNOME make decorations consistent, after being told too quickly that srdwm could only control its own titlebar. Measured against a nested srdwm, one client at a time: Qt/KDE creates a decoration object and asks for server-side; winit creates one and asks for CLIENT-side; GTK never creates one at all. The xdg-decoration spec says the compositor "can decide not to use the client's mode and enforce a different mode instead" and that the client "must obey" - so the first two are srdwm's to decide, and it had simply been deferring. The same spec closes the door on the third: a client that does not negotiate continues to self-decorate, and GTK is not having the conversation. New theme.decorations.force_server_side, default off, overrides the client's requested mode. Verified: with it off Alacritty draws its own content to the window's top edge, with it on the same window gets srdwm's titlebar -- (0,0,0) versus (46,52,64) sampled at three rows. Off by default because it cannot move a GTK button and can stack srdwm's titlebar on a client that draws its own regardless, which is the Firefox case already recorded here. The GTK half needs no compositor code, only the desktop setting GTK actually reads - xdg-desktop-portal's org.gnome.desktop.wm.preferences button-layout for GTK4, gtk-decoration-layout for GTK3. This machine was serving "close,minimize,maximize:" (left) while srdwm's own button_side was right, which is the entire mismatch. Documented in DEFAULTS.md with the mapping from button_side to layout string, and noted that this is exactly what kde-gtk-config does for KWin. 525 tests pass, clippy clean.
Diffstat (limited to 'crates/core')
-rw-r--r--crates/core/src/theme.rs23
1 files changed, 23 insertions, 0 deletions
diff --git a/crates/core/src/theme.rs b/crates/core/src/theme.rs
index 026688a..649ec64 100644
--- a/crates/core/src/theme.rs
+++ b/crates/core/src/theme.rs
@@ -175,6 +175,28 @@ pub struct ThemeConfig {
/// Asked for as titlebars able to use "decorations/buttons of the
/// program/dynamic".
pub dynamic_buttons: bool,
+ /// Enforce server-side decoration on every client that negotiates it,
+ /// instead of honouring what the client asked for.
+ ///
+ /// `xdg-decoration` explicitly allows this: "The compositor can decide
+ /// not to use the client's mode and enforce a different mode instead",
+ /// and "the specified mode must be obeyed by the client". So a toolkit
+ /// that asks for client-side - winit does, measured - can be given
+ /// srdwm's titlebar anyway, which is what makes every negotiating
+ /// window look the same.
+ ///
+ /// Off by default, because it cannot help the case it looks like it
+ /// should. A client that never creates a decoration object at all is
+ /// outside the protocol: "if compositor and client do not negotiate
+ /// the use of a server-side decoration ... clients continue to
+ /// self-decorate as they see fit". GTK is exactly that client - it
+ /// creates no decoration object, measured directly - so forcing this
+ /// on cannot move a single GTK button, while it *can* stack srdwm's
+ /// titlebar on top of a client that draws its own regardless (the
+ /// Firefox case this project already hit once). Turn it on to make
+ /// negotiating toolkits uniform; use `rules.lua`'s `decorated = false`
+ /// for the ones that draw their own anyway.
+ pub force_server_side: bool,
}
impl Default for ThemeConfig {
@@ -194,6 +216,7 @@ impl Default for ThemeConfig {
button_glyph_always: false,
traffic_light_buttons: true,
dynamic_buttons: true,
+ force_server_side: false,
}
}
}