From 4565514e7699ceb71d6ffd1e47171498070dd983 Mon Sep 17 00:00:00 2001 From: Ilia Malanin Date: Fri, 13 Feb 2026 23:36:27 +0100 Subject: [PATCH] shell: Preserve snapped state through fullscreen/minimize round-trips --- src/shell/layout/floating/mod.rs | 8 ++++++++ src/shell/mod.rs | 9 +++++++++ src/shell/workspace.rs | 13 ++++++++++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/shell/layout/floating/mod.rs b/src/shell/layout/floating/mod.rs index 1f3a7334..dcb6d50f 100644 --- a/src/shell/layout/floating/mod.rs +++ b/src/shell/layout/floating/mod.rs @@ -1641,6 +1641,14 @@ impl FloatingLayout { elements } + pub fn snapped_geometry(&self, corners: &TiledCorners) -> Rectangle { + let output = self.space.outputs().next().unwrap().clone(); + let layers = layer_map_for_output(&output); + let non_exclusive = layers.non_exclusive_zone(); + std::mem::drop(layers); + corners.relative_geometry(non_exclusive, self.gaps()) + } + fn gaps(&self) -> (i32, i32) { let g = self.theme.cosmic().gaps; (g.0 as i32, g.1 as i32) diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 02f37475..a15f03c3 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -2571,6 +2571,7 @@ impl Shell { state: FloatingRestoreData { was_maximized, + was_snapped, geometry, .. }, @@ -2594,6 +2595,12 @@ impl Shell { fullscreen_geometry, true, ); + } else if let Some(corners) = was_snapped { + *window.floating_tiled.lock().unwrap() = Some(corners); + window.set_tiled(true); + let snapped_geo = workspace.floating_layer.snapped_geometry(&corners); + window.set_geometry(snapped_geo.to_global(&workspace.output)); + window.configure(); } } Some(FullscreenRestoreState::Tiling { @@ -4145,6 +4152,7 @@ impl Shell { geometry: geo, output_size: set.output.geometry().size.as_logical(), was_maximized: false, + was_snapped: None, }, }); } else if let Some((workspace, window)) = @@ -4691,6 +4699,7 @@ impl Shell { geometry: from, output_size: workspace.output.geometry().size.as_logical(), was_maximized, + was_snapped: None, }, }), Some(from), diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index 1c9da011..f57822d7 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -8,7 +8,7 @@ use crate::{ }, shell::{ ANIMATION_DURATION, OverviewMode, SeatMoveGrabState, - layout::{floating::FloatingLayout, tiling::TilingLayout}, + layout::{floating::{FloatingLayout, TiledCorners}, tiling::TilingLayout}, }, state::State, utils::{prelude::*, tween::EaseRectangle}, @@ -286,6 +286,7 @@ pub struct FloatingRestoreData { pub geometry: Rectangle, pub output_size: Size, pub was_maximized: bool, + pub was_snapped: Option, } impl FloatingRestoreData { @@ -637,6 +638,7 @@ impl Workspace { }))); } + let was_snapped = mapped.floating_tiled.lock().unwrap().clone(); // unmaximize_request might have triggered a `floating_layer.refresh()`, // which may have already removed a non-alive surface. if let Some(floating_geometry) = self.floating_layer.unmap(mapped, None).or(was_maximized) { @@ -644,6 +646,7 @@ impl Workspace { geometry: floating_geometry, output_size: self.output.geometry().size.as_logical(), was_maximized: was_maximized.is_some(), + was_snapped }))); }; @@ -1066,6 +1069,7 @@ impl Workspace { mapped.set_minimized(true); mapped.configure(); + let was_snapped = mapped.floating_tiled.lock().unwrap().clone(); if let Some(geometry) = self.floating_layer.unmap(&mapped, Some(to)) { return Some(MinimizedWindow::Floating { window: mapped, @@ -1073,6 +1077,7 @@ impl Workspace { geometry: was_maximized.unwrap_or(geometry), output_size: self.output.geometry().size.as_logical(), was_maximized: was_maximized.is_some(), + was_snapped, }, }); } @@ -1133,6 +1138,12 @@ impl Workspace { }); std::mem::drop(state); self.floating_layer.map_maximized(window, geometry, true); + } else if let Some(corners) = previous.was_snapped { + *window.floating_tiled.lock().unwrap() = Some(corners); + window.set_tiled(true); + let snapped_geo = self.floating_layer.snapped_geometry(&corners); + window.set_geometry(snapped_geo.to_global(&self.output)); + window.configure(); } None