From b9a323c9ff001f81dfafffb3f40b4122660da27c Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Wed, 3 Jul 2024 21:04:28 +0200 Subject: [PATCH] shell: Populate focus_stack when unstacking --- src/shell/grabs/menu/default.rs | 2 +- src/shell/layout/floating/mod.rs | 25 ++++++++++++++++++----- src/shell/layout/tiling/mod.rs | 34 ++++++++++++++++++++++++-------- src/shell/mod.rs | 18 +++++++++++++---- 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/shell/grabs/menu/default.rs b/src/shell/grabs/menu/default.rs index 68e7b64f..72c6c967 100644 --- a/src/shell/grabs/menu/default.rs +++ b/src/shell/grabs/menu/default.rs @@ -18,7 +18,7 @@ use super::{Item, ResizeEdge}; fn toggle_stacking(state: &mut State, mapped: &CosmicMapped) { let mut shell = state.common.shell.write().unwrap(); let seat = shell.seats.last_active().clone(); - if let Some(new_focus) = shell.toggle_stacking(mapped) { + if let Some(new_focus) = shell.toggle_stacking(&seat, mapped) { std::mem::drop(shell); Shell::set_focus(state, Some(&new_focus), &seat, None); } diff --git a/src/shell/layout/floating/mod.rs b/src/shell/layout/floating/mod.rs index f7cad190..1c184a30 100644 --- a/src/shell/layout/floating/mod.rs +++ b/src/shell/layout/floating/mod.rs @@ -882,7 +882,11 @@ impl FloatingLayout { true } - pub fn toggle_stacking(&mut self, mapped: &CosmicMapped) -> Option { + pub fn toggle_stacking( + &mut self, + mapped: &CosmicMapped, + mut focus_stack: FocusStackMut, + ) -> Option { if !self.space.elements().any(|m| m == mapped) { return None; } @@ -902,20 +906,24 @@ impl FloatingLayout { Some(geo.size), None, ); + focus_stack.append(&mapped); Some(KeyboardFocusTarget::Element(mapped)) } else { // if we have a stack let mut surfaces = mapped.windows().map(|(s, _)| s).collect::>(); let first = surfaces.pop_front().expect("Stack without a window?"); + let focused = mapped.active_window(); self.space.unmap_elem(&mapped); let handle = mapped.loop_handle(); mapped.convert_to_surface(first, (&output, mapped.bbox()), self.theme.clone()); + let mut new_elements = vec![mapped.clone()]; // map the rest for other in surfaces { other.try_force_undecorated(false); other.set_tiled(false); + let focused = other == focused; let window = CosmicMapped::from(CosmicWindow::new( other, handle.clone(), @@ -928,10 +936,19 @@ impl FloatingLayout { window.set_bounds(layer_map.non_exclusive_zone().size); } + if focused { + new_elements.insert(0, window.clone()); + } else { + new_elements.push(window.clone()); + } self.map(window, None); } self.space.map_element(mapped.clone(), location, false); + for elem in new_elements.into_iter().rev() { + focus_stack.append(&elem); + } + Some(KeyboardFocusTarget::Element(mapped)) } } @@ -939,16 +956,14 @@ impl FloatingLayout { pub fn toggle_stacking_focused<'a>( &mut self, seat: &Seat, - mut focus_stack: FocusStackMut, + focus_stack: FocusStackMut, ) -> Option { let Some(KeyboardFocusTarget::Element(elem)) = seat.get_keyboard().unwrap().current_focus() else { return None; }; - let res = self.toggle_stacking(&elem); - focus_stack.append(&elem); - res + self.toggle_stacking(&elem, focus_stack) } pub fn move_element<'a>( diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index 6e77b3f1..0f717f8d 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -2108,7 +2108,11 @@ impl TilingLayout { } } - pub fn toggle_stacking(&mut self, mapped: &CosmicMapped) -> Option { + pub fn toggle_stacking( + &mut self, + mapped: &CosmicMapped, + mut focus_stack: FocusStackMut, + ) -> Option { let gaps = self.gaps(); let Some(node_id) = mapped.tiling_node_id.lock().unwrap().clone() else { @@ -2125,6 +2129,7 @@ impl TilingLayout { match tree.get_mut(&node_id).unwrap().data_mut() { Data::Mapped { mapped, .. } => { mapped.convert_to_stack((&self.output, mapped.bbox()), self.theme.clone()); + focus_stack.append(&mapped); KeyboardFocusTarget::Element(mapped.clone()) } _ => unreachable!(), @@ -2133,6 +2138,9 @@ impl TilingLayout { // if we have a stack let mut surfaces = mapped.windows().map(|(s, _)| s); let first = surfaces.next().expect("Stack without a window?"); + let focused = mapped.active_window(); + + let mut new_elements = Vec::new(); let handle = match tree.get_mut(&node_id).unwrap().data_mut() { Data::Mapped { mapped, .. } => { @@ -2142,6 +2150,7 @@ impl TilingLayout { (&self.output, mapped.bbox()), self.theme.clone(), ); + new_elements.push(mapped.clone()); handle } _ => unreachable!(), @@ -2152,6 +2161,7 @@ impl TilingLayout { for other in surfaces { other.try_force_undecorated(false); other.set_tiled(false); + let focused = other == focused; let window = CosmicMapped::from(CosmicWindow::new( other, handle.clone(), @@ -2174,6 +2184,11 @@ impl TilingLayout { ); let node = window.tiling_node_id.lock().unwrap().clone().unwrap(); + if focused { + new_elements.insert(0, window); + } else { + new_elements.push(window); + } current_node = node; } @@ -2184,15 +2199,20 @@ impl TilingLayout { node_id }; + for elem in new_elements.iter().rev() { + focus_stack.append(elem); + } + match tree.get(&node_id).unwrap().data() { Data::Group { alive, .. } => KeyboardFocusTarget::Group(WindowGroup { node: node_id.clone(), alive: Arc::downgrade(alive), - focus_stack: tree - .children_ids(&node_id) + focus_stack: vec![new_elements[0] + .tiling_node_id + .lock() .unwrap() - .cloned() - .collect::>(), + .clone() + .unwrap()], }), Data::Mapped { mapped, .. } => KeyboardFocusTarget::Element(mapped.clone()), _ => unreachable!(), @@ -2222,9 +2242,7 @@ impl TilingLayout { { match last_active_data { FocusedNodeData::Window(mapped) => { - let res = self.toggle_stacking(&mapped); - focus_stack.append(&mapped); - return res; + return self.toggle_stacking(&mapped, focus_stack); } FocusedNodeData::Group(_, _) => { let mut handle = None; diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 37550fcc..012379d5 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -3076,19 +3076,29 @@ impl Shell { } #[must_use] - pub fn toggle_stacking(&mut self, window: &CosmicMapped) -> Option { + pub fn toggle_stacking( + &mut self, + seat: &Seat, + window: &CosmicMapped, + ) -> Option { if let Some(set) = self .workspaces .sets .values_mut() .find(|set| set.sticky_layer.mapped().any(|m| m == window)) { - set.sticky_layer.toggle_stacking(window) + let workspace = &mut set.workspaces[set.active]; + set.sticky_layer + .toggle_stacking(window, workspace.focus_stack.get_mut(seat)) } else if let Some(workspace) = self.space_for_mut(window) { if workspace.tiling_layer.mapped().any(|(m, _)| m == window) { - workspace.tiling_layer.toggle_stacking(window) + workspace + .tiling_layer + .toggle_stacking(window, workspace.focus_stack.get_mut(seat)) } else if workspace.floating_layer.mapped().any(|w| w == window) { - workspace.floating_layer.toggle_stacking(window) + workspace + .floating_layer + .toggle_stacking(window, workspace.focus_stack.get_mut(seat)) } else { None }