From b5186ef21a74f9399714d2bac03ca016cd5820b2 Mon Sep 17 00:00:00 2001 From: Hojjat Date: Tue, 21 Apr 2026 15:52:26 -0600 Subject: [PATCH] fix: restore snapped windows as snapped after maximize/minimize --- src/shell/element/mod.rs | 3 ++- src/shell/layout/floating/mod.rs | 9 ++++++--- src/shell/mod.rs | 15 ++++++++++++++- src/shell/workspace.rs | 22 ++++++++++++++++++++-- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/shell/element/mod.rs b/src/shell/element/mod.rs index 7f3859ee..4696aa2e 100644 --- a/src/shell/element/mod.rs +++ b/src/shell/element/mod.rs @@ -82,10 +82,11 @@ space_elements! { Stack=CosmicStack, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub struct MaximizedState { pub original_geometry: Rectangle, pub original_layer: ManagedLayer, + pub original_snapped: Option, } #[derive(Clone)] diff --git a/src/shell/layout/floating/mod.rs b/src/shell/layout/floating/mod.rs index 3eee770b..e399f356 100644 --- a/src/shell/layout/floating/mod.rs +++ b/src/shell/layout/floating/mod.rs @@ -385,11 +385,13 @@ impl FloatingLayout { } else { self.animations.remove(&mapped); } - if mapped.floating_tiled.lock().unwrap().take().is_some() + // Restore to the corner this was snapped to if any + let snapped = mapped.floating_tiled.lock().unwrap().take(); + if let Some(snapped) = snapped && let Some(state) = mapped.maximized_state.lock().unwrap().as_mut() - && let Some(real_old_geo) = *mapped.last_geometry.lock().unwrap() + && state.original_snapped.is_none() { - state.original_geometry = real_old_geo; + state.original_snapped = Some(snapped); }; self.space .map_element(mapped, geometry.loc.as_logical(), true); @@ -1198,6 +1200,7 @@ impl FloatingLayout { *maximized_state = Some(MaximizedState { original_geometry: start_rectangle, original_layer: layer, + original_snapped: None, }); std::mem::drop(maximized_state); diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 9e11b18f..bdc093ec 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -2591,6 +2591,7 @@ impl Shell { *state = Some(MaximizedState { original_geometry: geometry, original_layer: ManagedLayer::Floating, + original_snapped: was_snapped, }); std::mem::drop(state); workspace.floating_layer.map_maximized( @@ -2625,6 +2626,7 @@ impl Shell { *state = Some(MaximizedState { original_geometry: previous_geometry, original_layer: ManagedLayer::Tiling, + original_snapped: None, }); std::mem::drop(state); workspace.floating_layer.map_maximized( @@ -2647,6 +2649,7 @@ impl Shell { *state = Some(MaximizedState { original_geometry: geometry, original_layer: ManagedLayer::Floating, + original_snapped: None, }); std::mem::drop(state); workspace.floating_layer.map_maximized( @@ -3372,6 +3375,7 @@ impl Shell { *mapped.maximized_state.lock().unwrap() = Some(MaximizedState { original_geometry: geometry, original_layer: ManagedLayer::Floating, + original_snapped: was_snapped, }); to_workspace .floating_layer @@ -4281,6 +4285,7 @@ impl Shell { *state = Some(MaximizedState { original_geometry, original_layer, + original_snapped: None, }); std::mem::drop(state); floating_layer.map_maximized(mapped.clone(), original_geometry, animate); @@ -4304,7 +4309,7 @@ impl Shell { .iter_mut() .find(|m| m.mapped().is_some_and(|m| m == mapped)) { - minimized.unmaximize(state.original_geometry); + minimized.unmaximize(state.original_geometry, state.original_snapped); } else { mapped.set_maximized(false); set.sticky_layer.map_internal( @@ -4313,6 +4318,10 @@ impl Shell { Some(state.original_geometry.size.as_logical()), None, ); + // Re-apply the snap if the window was snapped when it was maximized. + if let Some(corners) = state.original_snapped { + set.sticky_layer.snap_to_corner(mapped, &corners); + } } Some(state.original_geometry.size.as_logical()) } else { @@ -4589,11 +4598,13 @@ impl Shell { if let Some(MaximizedState { original_geometry, original_layer: _, + original_snapped, }) = *state { *state = Some(MaximizedState { original_geometry, original_layer: ManagedLayer::Sticky, + original_snapped, }); std::mem::drop(state); set.workspaces[set.active].floating_layer.map_maximized( @@ -4637,11 +4648,13 @@ impl Shell { if let Some(MaximizedState { original_geometry, original_layer: _, + original_snapped, }) = *state { *state = Some(MaximizedState { original_geometry, original_layer: previous_layer, + original_snapped, }); std::mem::drop(state); workspace diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index 1be2c2ae..a79b2acb 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -182,7 +182,11 @@ impl MinimizedWindow { } } - pub fn unmaximize(&mut self, original_geometry: Rectangle) { + pub fn unmaximize( + &mut self, + original_geometry: Rectangle, + original_snapped: Option, + ) { match self { MinimizedWindow::Fullscreen { .. } => {} MinimizedWindow::Tiling { @@ -196,6 +200,7 @@ impl MinimizedWindow { window, previous, .. } => { previous.geometry = original_geometry; + previous.was_snapped = original_snapped; window.set_maximized(false); window.configure(); } @@ -972,7 +977,7 @@ impl Workspace { let mut state = elem.maximized_state.lock().unwrap(); if let Some(state) = state.take() { if let Some(minimized) = self.minimized_windows.iter_mut().find(|m| *m == elem) { - minimized.unmaximize(state.original_geometry); + minimized.unmaximize(state.original_geometry, state.original_snapped); Some(state.original_geometry) } else { match state.original_layer { @@ -998,6 +1003,10 @@ impl Workspace { use_geometry.then_some(state.original_geometry.size.as_logical()), None, ); + // Re-apply the snap if the window was snapped before maximizing + if let Some(corners) = state.original_snapped { + self.floating_layer.snap_to_corner(elem, &corners); + } Some(state.original_geometry) } } @@ -1052,6 +1061,7 @@ impl Workspace { let was_maximized = if let Some(MaximizedState { original_geometry, original_layer, + original_snapped, }) = mapped.maximized_state.lock().unwrap().take() { // we need to do this manually instead of calling `self.unmaximize_request` @@ -1064,6 +1074,10 @@ impl Workspace { } mapped.set_geometry(original_geometry.to_global(&self.output)); mapped.set_maximized(false); + // Restore the snap marker to lett unminimize re-apply it. + if let Some(corners) = original_snapped { + *mapped.floating_tiled.lock().unwrap() = Some(corners); + } Some(original_geometry) } else { None @@ -1138,6 +1152,7 @@ impl Workspace { *state = Some(MaximizedState { original_geometry: geometry, original_layer: ManagedLayer::Floating, + original_snapped: previous.was_snapped, }); std::mem::drop(state); self.floating_layer.map_maximized(window, geometry, true); @@ -1171,6 +1186,7 @@ impl Workspace { *state = Some(MaximizedState { original_geometry: previous_geometry, original_layer: ManagedLayer::Tiling, + original_snapped: None, }); std::mem::drop(state); self.floating_layer.map_maximized(window, from, true); @@ -1187,6 +1203,7 @@ impl Workspace { *state = Some(MaximizedState { original_geometry: geometry, original_layer: ManagedLayer::Tiling, + original_snapped: None, }); std::mem::drop(state); self.floating_layer.map_maximized(window, from, true); @@ -1393,6 +1410,7 @@ impl Workspace { *state = Some(MaximizedState { original_geometry, original_layer, + original_snapped: None, }); std::mem::drop(state);