From 0a4c4b5941fe982ccb3d3175e26d9d83f0025ffd Mon Sep 17 00:00:00 2001 From: srdusr <99972264+srdusr@users.noreply.github.com> Date: Sat, 15 Feb 2025 14:56:00 +0200 Subject: Checkpoint: preserve all uncommitted rust-rewrite worktree work Safety commit before reconciling this worktree with main, which has diverged with its own separate fixes today. Nothing here is reviewed or curated yet - this exists purely so none of this work can be lost to a git operation, disk issue, or worktree cleanup while that reconciliation happens. --- crates/wayland/src/protocols/xdg_decoration.rs | 63 ++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 crates/wayland/src/protocols/xdg_decoration.rs (limited to 'crates/wayland/src/protocols/xdg_decoration.rs') diff --git a/crates/wayland/src/protocols/xdg_decoration.rs b/crates/wayland/src/protocols/xdg_decoration.rs new file mode 100644 index 0000000..25973c0 --- /dev/null +++ b/crates/wayland/src/protocols/xdg_decoration.rs @@ -0,0 +1,63 @@ +//! `zxdg_decoration_manager_v1`: negotiates whether a toplevel draws its own +//! (client-side) chrome or lets us draw it (server-side). + +use smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode as DecorationMode; +use smithay::wayland::shell::xdg::decoration::XdgDecorationHandler; +use smithay::wayland::shell::xdg::ToplevelSurface; + +use crate::state::CompState; + +impl XdgDecorationHandler for CompState { + /// Offers whichever mode `theme.decorations.default_mode`/`srd set + /// decoration_mode` currently prefers - a client with a real opinion + /// of its own still overrides this via `request_mode` below regardless + /// of what's offered here; this only decides what a client with *no* + /// preference ends up with. See `srdwm_core::ThemeConfig:: + /// default_decorated`'s own doc comment for why this is configurable + /// rather than hardcoded to one mode. + fn new_decoration(&mut self, toplevel: ToplevelSurface) { + let offer = if self.wm.borrow().theme.default_decorated { DecorationMode::ServerSide } else { DecorationMode::ClientSide }; + toplevel.with_pending_state(|state| { + state.decoration_mode = Some(offer); + }); + } + + /// Honors whichever mode the client actually asked for, rather than + /// always forcing server-side - and mirrors the result into our own + /// `Window.decorated`, so a client drawing its own titlebar doesn't + /// *also* get one drawn on top of it by us. + /// + /// Always forcing `ServerSide` (what this used to do) is why some + /// clients ended up with two sets of window buttons: Firefox requests + /// client-side decoration when its own "use system titlebar" setting + /// is off, and draws its own close/minimize/maximize row regardless of + /// what the compositor grants - so forcing server-side just added + /// srdwm's row on top of the one Firefox was drawing anyway, instead + /// of preventing it. Respecting the request means srdwm steps out of + /// the way for exactly those clients, while everything that accepts + /// (or has no preference and gets offered) server-side still gets our + /// titlebar as before. + fn request_mode(&mut self, toplevel: ToplevelSurface, mode: DecorationMode) { + toplevel.with_pending_state(|state| { + state.decoration_mode = Some(mode); + }); + toplevel.send_configure(); + self.set_decorated_from_mode(toplevel.wl_surface(), mode == DecorationMode::ServerSide); + } + + /// The client dropped its decoration-mode preference. `new_decoration` + /// already offers the configured default as the mode the next + /// configure will carry, so mirror that same default here rather than + /// leaving whatever mode was negotiated before this - otherwise a + /// client that requests one mode, then later unsets it expecting the + /// default back, would stay stuck in that mode forever. + fn unset_mode(&mut self, toplevel: ToplevelSurface) { + let default_decorated = self.wm.borrow().theme.default_decorated; + let mode = if default_decorated { DecorationMode::ServerSide } else { DecorationMode::ClientSide }; + toplevel.with_pending_state(|state| { + state.decoration_mode = Some(mode); + }); + toplevel.send_configure(); + self.set_decorated_from_mode(toplevel.wl_surface(), default_decorated); + } +} -- cgit v1.2.3