srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/state/lifecycle.rs
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2025-05-30 01:12:00 +0200
committersrdusr <[email protected]>2025-05-30 01:12:00 +0200
commit3f2ac4d85c4e66c2f1ae6622bf3c2f302abe93b9 (patch)
treeba933aa00823a47a34715a09d15ffbf30a25b923 /crates/wayland/src/state/lifecycle.rs
parent49ded5541243408e50a391f95bdca037c370a709 (diff)
downloadsrdwm-3f2ac4d85c4e66c2f1ae6622bf3c2f302abe93b9.tar.gz
srdwm-3f2ac4d85c4e66c2f1ae6622bf3c2f302abe93b9.zip
Detect XWayland dialogs via WM_TRANSIENT_FOR, not just native xdg_toplevel parent
Window::is_dialog (close-button-only titlebar, no traffic lights) was only ever set from a native xdg_toplevel's own parent() - redraw_ decoration_buffer's is_dialog computation called dw.toplevel(), which is always None for an XWayland-backed DWindow (X11Surface's own accessor is x11_surface(), a different method), so the .unwrap_or(false) fallback made every XWayland dialog - a GTK "Save As", an app's own "About" box, anything setting the ICCCM transient-for hint - always draw with the full three-button titlebar and traffic-light colours, even though the feature this was built for explicitly wanted the opposite. Documented as a known gap at the time; now closed. redraw_decoration_buffer now also checks X11Surface::is_transient_for() for an XWayland window. property_notify gained a WmWindowProperty:: TransientFor arm that re-runs redraw_decoration_buffer, for a client that sets the hint slightly after its own initial map - the same "read fresh every call" pattern the existing xdg_toplevel::parent() check already relied on, extended to catch a late X11 property the way the Wayland equivalent (set_parent, any time) already was.
Diffstat (limited to 'crates/wayland/src/state/lifecycle.rs')
-rw-r--r--crates/wayland/src/state/lifecycle.rs23
1 files changed, 18 insertions, 5 deletions
diff --git a/crates/wayland/src/state/lifecycle.rs b/crates/wayland/src/state/lifecycle.rs
index b47cb23..53a5e86 100644
--- a/crates/wayland/src/state/lifecycle.rs
+++ b/crates/wayland/src/state/lifecycle.rs
@@ -81,11 +81,24 @@ impl CompState {
// change. Written back onto the real `Window` (not just used
// locally) so `ResizeEdge::hit_test`'s own `is_dialog` parameter
// - read from `core`, which has no protocol concept to derive
- // this from itself - agrees with whatever got drawn here. An
- // XWayland window's own `WM_TRANSIENT_FOR` isn't read yet, so this
- // stays `false` for those specifically - see `Window::is_dialog`'s
- // own doc comment.
- let is_dialog = self.id_to_window.get(&id).and_then(|dw| dw.toplevel()).map(|t| t.parent().is_some()).unwrap_or(false);
+ // this from itself - agrees with whatever got drawn here.
+ //
+ // Checks both real toplevel kinds a `DWindow` can wrap: a native
+ // `xdg_toplevel`'s own `parent()`, or an XWayland `X11Surface`'s
+ // `WM_TRANSIENT_FOR` via `is_transient_for()`. The X11 half used
+ // to be unchecked entirely (`.toplevel()` alone, which is always
+ // `None` for an X11-backed window - `X11Surface`'s own accessor
+ // is `.x11_surface()`, a different method), so every XWayland
+ // dialog - a GTK "Save As", an app's own "About" box, anything
+ // that sets the ICCCM transient-for hint - always drew with the
+ // full three-button titlebar and traffic-light colours, the
+ // native-Wayland-only case this whole feature was built for.
+ // Reported live: "dialog windows... should never have traffic
+ // light, should just be x" - true for native Wayland dialogs
+ // already, not for XWayland ones.
+ let is_dialog = self.id_to_window.get(&id).is_some_and(|dw| {
+ dw.toplevel().is_some_and(|t| t.parent().is_some()) || dw.x11_surface().is_some_and(|x| x.is_transient_for().is_some())
+ });
if let Some(win) = self.wm.borrow_mut().window_mut(id) {
win.is_dialog = is_dialog;
}