Layer::Window overlays: an OverlaySpec can now be an ordinary xdg toplevel, named through App::overlay_title; showcase persists the last pressed button too
Some checks failed
CI / build + test (push) Has been cancelled
CI / cargo audit (push) Has been cancelled

A shell built on ltk had no way to show something as a regular window: every overlay is a layer-shell surface, and layer-shell surfaces are either below all application windows or above all of them. crustace's "closing applications…" card ran into exactly that — on the overlay layer it covered the applications' own "save changes?" prompts, on the bottom layer it vanished behind their windows — and what that card wants is to be one window among the others: decorated by the compositor, stackable, listed in the switcher and the dock.
`Layer` gains a `Window` variant. An `OverlaySpec` carrying it is materialised by the reconciler as an `xdg_toplevel` (sctk `Window`, server-side decorations) instead of a layer surface: `size` is its fixed size, applied through min/max size (a zero component falls back to a default, since a toplevel cannot "fill"); anchor, exclusive zone and keyboard exclusivity are ignored. The window's app_id is `App::app_id()` and its title comes from the new, defaulted `App::overlay_title( id )`, so the compositor's window lists show something meaningful. `WindowHandler::configure` and `request_close` now resolve which surface a window belongs to: the main window keeps its behaviour, an overlay window is configured through its own `SurfaceState` (with the window geometry set to the configured size) and the compositor's close button delivers the spec's `on_dismiss` instead of exiting the app. Layer-shell applications now bind `xdg_wm_base` when the compositor offers it, so they can open such a window later. Adding a variant keeps every existing `OverlaySpec` literal compiling; the new trait method has a default.
The showcase example now also saves and restores `last_pressed`, bumping its private state format to version 2 with the note kept last so its line breaks survive.
This commit is contained in:
2026-08-15 17:56:06 +02:00
parent ccf07de593
commit 3046d86337
6 changed files with 71 additions and 6 deletions

View File

@@ -94,17 +94,19 @@ impl App for ShowcaseApp
fn app_id( &self ) -> &str { "net.liberux.ltk.example.showcase" }
// One field per line, the note last so its own line breaks survive.
fn save_state( &self ) -> Option<Vec<u8>>
{
Some( format!( "1\n{}\n{}\n{}", self.tab, self.slider_value, self.note ).into_bytes() )
Some( format!( "2\n{}\n{}\n{}\n{}", self.tab, self.last_pressed, self.slider_value, self.note ).into_bytes() )
}
fn restore_state( &mut self, state: Vec<u8> )
{
let Ok( text ) = String::from_utf8( state ) else { return };
let mut lines = text.splitn( 4, '\n' );
if lines.next() != Some( "1" ) { return; }
let mut lines = text.splitn( 5, '\n' );
if lines.next() != Some( "2" ) { return; }
if let Some( tab ) = lines.next().and_then( |l| l.parse().ok() ) { self.tab = tab; }
if let Some( pressed ) = lines.next() { self.last_pressed = pressed.to_string(); }
if let Some( v ) = lines.next().and_then( |l| l.parse().ok() ) { self.slider_value = v; }
if let Some( note ) = lines.next() { self.note = note.to_string(); }
}