event_loop: drop the built-in titlebar when the compositor decorates
Some checks failed
CI / build + test (push) Has been cancelled
CI / cargo audit (push) Has been cancelled

ltk already asked for server-side decorations through SCTK (WindowDecorations::RequestServer on window creation) but painted its 36 px titlebar unconditionally, so under forge an xdg window carried two stacked bars: forge's SSD on top of ltk's own. The WindowHandler configure now honours the negotiated decoration_mode: Server zeroes titlebar_height, Client — which is also what SCTK reports when the compositor lacks xdg-decoration, e.g. GNOME — restores it from the new titlebar_base field. Every titlebar consumer (draw, close-button hit test, drag-move) already guards on the height being positive, so the suppressed bar costs nothing and the fallback path is unchanged.
This commit is contained in:
2026-07-24 23:20:16 +02:00
parent 3d7f3c53de
commit 142096827e
2 changed files with 13 additions and 1 deletions

View File

@@ -19,7 +19,7 @@ use smithay_client_toolkit::
wlr_layer::{ LayerShellHandler, LayerSurface, LayerSurfaceConfigure }, wlr_layer::{ LayerShellHandler, LayerSurface, LayerSurfaceConfigure },
xdg::XdgSurface, xdg::XdgSurface,
xdg::popup::{ Popup, PopupConfigure, PopupHandler }, xdg::popup::{ Popup, PopupConfigure, PopupHandler },
xdg::window::{ Window, WindowConfigure, WindowHandler }, xdg::window::{ DecorationMode, Window, WindowConfigure, WindowHandler },
}, },
shm::{ Shm, ShmHandler }, shm::{ Shm, ShmHandler },
session_lock::{ SessionLock, SessionLockHandler, SessionLockSurface, SessionLockSurfaceConfigure }, session_lock::{ SessionLock, SessionLockHandler, SessionLockSurface, SessionLockSurfaceConfigure },
@@ -222,6 +222,14 @@ impl<A: App> WindowHandler for AppData<A>
window.set_max_size( None ); window.set_max_size( None );
self.pending_size_hint_unpin = false; self.pending_size_hint_unpin = false;
} }
let tb = if configure.decoration_mode == DecorationMode::Server { 0.0 }
else { self.main.titlebar_base };
if self.main.titlebar_height != tb
{
self.main.titlebar_height = tb;
self.main.content_dirty = true;
self.view_dirty = true;
}
let ( hint_w, hint_h ) = self.app.window_size_hint().unwrap_or( ( 800, 600 ) ); let ( hint_w, hint_h ) = self.app.window_size_hint().unwrap_or( ( 800, 600 ) );
let w = configure.new_size.0.map( |v| v.get() ).unwrap_or( hint_w ); let w = configure.new_size.0.map( |v| v.get() ).unwrap_or( hint_w );
let h = configure.new_size.1.map( |v| v.get() ).unwrap_or( hint_h ); let h = configure.new_size.1.map( |v| v.get() ).unwrap_or( hint_h );

View File

@@ -260,6 +260,9 @@ pub( crate ) struct SurfaceState<Msg: Clone>
pub touch_slots: HashMap<i32, crate::types::Point>, pub touch_slots: HashMap<i32, crate::types::Point>,
/// Height of the client-side title bar (0 for layer-shell surfaces). /// Height of the client-side title bar (0 for layer-shell surfaces).
pub titlebar_height: f32, pub titlebar_height: f32,
/// Title bar height before decoration negotiation; restored when the
/// compositor hands decorations back to the client.
pub titlebar_base: f32,
/// Title text shown in the client-side title bar. /// Title text shown in the client-side title bar.
pub titlebar_title: String, pub titlebar_title: String,
/// Rect of the close button in the title bar (for hit testing). /// Rect of the close button in the title bar (for hit testing).
@@ -313,6 +316,7 @@ impl<Msg: Clone> SurfaceState<Msg>
context_menu: None, context_menu: None,
gesture: GestureState::new(), gesture: GestureState::new(),
titlebar_height, titlebar_height,
titlebar_base: titlebar_height,
titlebar_title, titlebar_title,
titlebar_close_rect: Rect::default(), titlebar_close_rect: Rect::default(),
scale_factor: 1, scale_factor: 1,