shell: Preserve snapped state through fullscreen/minimize round-trips

This commit is contained in:
Ilia Malanin 2026-02-13 23:36:27 +01:00 committed by Victoria Brekenfeld
parent 744e0da6f9
commit 4565514e76
3 changed files with 29 additions and 1 deletions

View file

@ -1641,6 +1641,14 @@ impl FloatingLayout {
elements elements
} }
pub fn snapped_geometry(&self, corners: &TiledCorners) -> Rectangle<i32, Local> {
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) { fn gaps(&self) -> (i32, i32) {
let g = self.theme.cosmic().gaps; let g = self.theme.cosmic().gaps;
(g.0 as i32, g.1 as i32) (g.0 as i32, g.1 as i32)

View file

@ -2571,6 +2571,7 @@ impl Shell {
state: state:
FloatingRestoreData { FloatingRestoreData {
was_maximized, was_maximized,
was_snapped,
geometry, geometry,
.. ..
}, },
@ -2594,6 +2595,12 @@ impl Shell {
fullscreen_geometry, fullscreen_geometry,
true, 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 { Some(FullscreenRestoreState::Tiling {
@ -4145,6 +4152,7 @@ impl Shell {
geometry: geo, geometry: geo,
output_size: set.output.geometry().size.as_logical(), output_size: set.output.geometry().size.as_logical(),
was_maximized: false, was_maximized: false,
was_snapped: None,
}, },
}); });
} else if let Some((workspace, window)) = } else if let Some((workspace, window)) =
@ -4691,6 +4699,7 @@ impl Shell {
geometry: from, geometry: from,
output_size: workspace.output.geometry().size.as_logical(), output_size: workspace.output.geometry().size.as_logical(),
was_maximized, was_maximized,
was_snapped: None,
}, },
}), }),
Some(from), Some(from),

View file

@ -8,7 +8,7 @@ use crate::{
}, },
shell::{ shell::{
ANIMATION_DURATION, OverviewMode, SeatMoveGrabState, ANIMATION_DURATION, OverviewMode, SeatMoveGrabState,
layout::{floating::FloatingLayout, tiling::TilingLayout}, layout::{floating::{FloatingLayout, TiledCorners}, tiling::TilingLayout},
}, },
state::State, state::State,
utils::{prelude::*, tween::EaseRectangle}, utils::{prelude::*, tween::EaseRectangle},
@ -286,6 +286,7 @@ pub struct FloatingRestoreData {
pub geometry: Rectangle<i32, Local>, pub geometry: Rectangle<i32, Local>,
pub output_size: Size<i32, Logical>, pub output_size: Size<i32, Logical>,
pub was_maximized: bool, pub was_maximized: bool,
pub was_snapped: Option<TiledCorners>,
} }
impl FloatingRestoreData { 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()`, // unmaximize_request might have triggered a `floating_layer.refresh()`,
// which may have already removed a non-alive surface. // which may have already removed a non-alive surface.
if let Some(floating_geometry) = self.floating_layer.unmap(mapped, None).or(was_maximized) { if let Some(floating_geometry) = self.floating_layer.unmap(mapped, None).or(was_maximized) {
@ -644,6 +646,7 @@ impl Workspace {
geometry: floating_geometry, geometry: floating_geometry,
output_size: self.output.geometry().size.as_logical(), output_size: self.output.geometry().size.as_logical(),
was_maximized: was_maximized.is_some(), was_maximized: was_maximized.is_some(),
was_snapped
}))); })));
}; };
@ -1066,6 +1069,7 @@ impl Workspace {
mapped.set_minimized(true); mapped.set_minimized(true);
mapped.configure(); mapped.configure();
let was_snapped = mapped.floating_tiled.lock().unwrap().clone();
if let Some(geometry) = self.floating_layer.unmap(&mapped, Some(to)) { if let Some(geometry) = self.floating_layer.unmap(&mapped, Some(to)) {
return Some(MinimizedWindow::Floating { return Some(MinimizedWindow::Floating {
window: mapped, window: mapped,
@ -1073,6 +1077,7 @@ impl Workspace {
geometry: was_maximized.unwrap_or(geometry), geometry: was_maximized.unwrap_or(geometry),
output_size: self.output.geometry().size.as_logical(), output_size: self.output.geometry().size.as_logical(),
was_maximized: was_maximized.is_some(), was_maximized: was_maximized.is_some(),
was_snapped,
}, },
}); });
} }
@ -1133,6 +1138,12 @@ impl Workspace {
}); });
std::mem::drop(state); std::mem::drop(state);
self.floating_layer.map_maximized(window, geometry, true); 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 None