shell: Populate focus_stack when unstacking

This commit is contained in:
Victoria Brekenfeld 2024-07-03 21:04:28 +02:00
parent dc882ffc36
commit b9a323c9ff
4 changed files with 61 additions and 18 deletions

View file

@ -18,7 +18,7 @@ use super::{Item, ResizeEdge};
fn toggle_stacking(state: &mut State, mapped: &CosmicMapped) { fn toggle_stacking(state: &mut State, mapped: &CosmicMapped) {
let mut shell = state.common.shell.write().unwrap(); let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone(); 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); std::mem::drop(shell);
Shell::set_focus(state, Some(&new_focus), &seat, None); Shell::set_focus(state, Some(&new_focus), &seat, None);
} }

View file

@ -882,7 +882,11 @@ impl FloatingLayout {
true true
} }
pub fn toggle_stacking(&mut self, mapped: &CosmicMapped) -> Option<KeyboardFocusTarget> { pub fn toggle_stacking(
&mut self,
mapped: &CosmicMapped,
mut focus_stack: FocusStackMut,
) -> Option<KeyboardFocusTarget> {
if !self.space.elements().any(|m| m == mapped) { if !self.space.elements().any(|m| m == mapped) {
return None; return None;
} }
@ -902,20 +906,24 @@ impl FloatingLayout {
Some(geo.size), Some(geo.size),
None, None,
); );
focus_stack.append(&mapped);
Some(KeyboardFocusTarget::Element(mapped)) Some(KeyboardFocusTarget::Element(mapped))
} else { } else {
// if we have a stack // if we have a stack
let mut surfaces = mapped.windows().map(|(s, _)| s).collect::<VecDeque<_>>(); let mut surfaces = mapped.windows().map(|(s, _)| s).collect::<VecDeque<_>>();
let first = surfaces.pop_front().expect("Stack without a window?"); let first = surfaces.pop_front().expect("Stack without a window?");
let focused = mapped.active_window();
self.space.unmap_elem(&mapped); self.space.unmap_elem(&mapped);
let handle = mapped.loop_handle(); let handle = mapped.loop_handle();
mapped.convert_to_surface(first, (&output, mapped.bbox()), self.theme.clone()); mapped.convert_to_surface(first, (&output, mapped.bbox()), self.theme.clone());
let mut new_elements = vec![mapped.clone()];
// map the rest // map the rest
for other in surfaces { for other in surfaces {
other.try_force_undecorated(false); other.try_force_undecorated(false);
other.set_tiled(false); other.set_tiled(false);
let focused = other == focused;
let window = CosmicMapped::from(CosmicWindow::new( let window = CosmicMapped::from(CosmicWindow::new(
other, other,
handle.clone(), handle.clone(),
@ -928,10 +936,19 @@ impl FloatingLayout {
window.set_bounds(layer_map.non_exclusive_zone().size); 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.map(window, None);
} }
self.space.map_element(mapped.clone(), location, false); self.space.map_element(mapped.clone(), location, false);
for elem in new_elements.into_iter().rev() {
focus_stack.append(&elem);
}
Some(KeyboardFocusTarget::Element(mapped)) Some(KeyboardFocusTarget::Element(mapped))
} }
} }
@ -939,16 +956,14 @@ impl FloatingLayout {
pub fn toggle_stacking_focused<'a>( pub fn toggle_stacking_focused<'a>(
&mut self, &mut self,
seat: &Seat<State>, seat: &Seat<State>,
mut focus_stack: FocusStackMut, focus_stack: FocusStackMut,
) -> Option<KeyboardFocusTarget> { ) -> Option<KeyboardFocusTarget> {
let Some(KeyboardFocusTarget::Element(elem)) = seat.get_keyboard().unwrap().current_focus() let Some(KeyboardFocusTarget::Element(elem)) = seat.get_keyboard().unwrap().current_focus()
else { else {
return None; return None;
}; };
let res = self.toggle_stacking(&elem); self.toggle_stacking(&elem, focus_stack)
focus_stack.append(&elem);
res
} }
pub fn move_element<'a>( pub fn move_element<'a>(

View file

@ -2108,7 +2108,11 @@ impl TilingLayout {
} }
} }
pub fn toggle_stacking(&mut self, mapped: &CosmicMapped) -> Option<KeyboardFocusTarget> { pub fn toggle_stacking(
&mut self,
mapped: &CosmicMapped,
mut focus_stack: FocusStackMut,
) -> Option<KeyboardFocusTarget> {
let gaps = self.gaps(); let gaps = self.gaps();
let Some(node_id) = mapped.tiling_node_id.lock().unwrap().clone() else { 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() { match tree.get_mut(&node_id).unwrap().data_mut() {
Data::Mapped { mapped, .. } => { Data::Mapped { mapped, .. } => {
mapped.convert_to_stack((&self.output, mapped.bbox()), self.theme.clone()); mapped.convert_to_stack((&self.output, mapped.bbox()), self.theme.clone());
focus_stack.append(&mapped);
KeyboardFocusTarget::Element(mapped.clone()) KeyboardFocusTarget::Element(mapped.clone())
} }
_ => unreachable!(), _ => unreachable!(),
@ -2133,6 +2138,9 @@ impl TilingLayout {
// if we have a stack // if we have a stack
let mut surfaces = mapped.windows().map(|(s, _)| s); let mut surfaces = mapped.windows().map(|(s, _)| s);
let first = surfaces.next().expect("Stack without a window?"); 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() { let handle = match tree.get_mut(&node_id).unwrap().data_mut() {
Data::Mapped { mapped, .. } => { Data::Mapped { mapped, .. } => {
@ -2142,6 +2150,7 @@ impl TilingLayout {
(&self.output, mapped.bbox()), (&self.output, mapped.bbox()),
self.theme.clone(), self.theme.clone(),
); );
new_elements.push(mapped.clone());
handle handle
} }
_ => unreachable!(), _ => unreachable!(),
@ -2152,6 +2161,7 @@ impl TilingLayout {
for other in surfaces { for other in surfaces {
other.try_force_undecorated(false); other.try_force_undecorated(false);
other.set_tiled(false); other.set_tiled(false);
let focused = other == focused;
let window = CosmicMapped::from(CosmicWindow::new( let window = CosmicMapped::from(CosmicWindow::new(
other, other,
handle.clone(), handle.clone(),
@ -2174,6 +2184,11 @@ impl TilingLayout {
); );
let node = window.tiling_node_id.lock().unwrap().clone().unwrap(); 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; current_node = node;
} }
@ -2184,15 +2199,20 @@ impl TilingLayout {
node_id node_id
}; };
for elem in new_elements.iter().rev() {
focus_stack.append(elem);
}
match tree.get(&node_id).unwrap().data() { match tree.get(&node_id).unwrap().data() {
Data::Group { alive, .. } => KeyboardFocusTarget::Group(WindowGroup { Data::Group { alive, .. } => KeyboardFocusTarget::Group(WindowGroup {
node: node_id.clone(), node: node_id.clone(),
alive: Arc::downgrade(alive), alive: Arc::downgrade(alive),
focus_stack: tree focus_stack: vec![new_elements[0]
.children_ids(&node_id) .tiling_node_id
.lock()
.unwrap() .unwrap()
.cloned() .clone()
.collect::<Vec<_>>(), .unwrap()],
}), }),
Data::Mapped { mapped, .. } => KeyboardFocusTarget::Element(mapped.clone()), Data::Mapped { mapped, .. } => KeyboardFocusTarget::Element(mapped.clone()),
_ => unreachable!(), _ => unreachable!(),
@ -2222,9 +2242,7 @@ impl TilingLayout {
{ {
match last_active_data { match last_active_data {
FocusedNodeData::Window(mapped) => { FocusedNodeData::Window(mapped) => {
let res = self.toggle_stacking(&mapped); return self.toggle_stacking(&mapped, focus_stack);
focus_stack.append(&mapped);
return res;
} }
FocusedNodeData::Group(_, _) => { FocusedNodeData::Group(_, _) => {
let mut handle = None; let mut handle = None;

View file

@ -3076,19 +3076,29 @@ impl Shell {
} }
#[must_use] #[must_use]
pub fn toggle_stacking(&mut self, window: &CosmicMapped) -> Option<KeyboardFocusTarget> { pub fn toggle_stacking(
&mut self,
seat: &Seat<State>,
window: &CosmicMapped,
) -> Option<KeyboardFocusTarget> {
if let Some(set) = self if let Some(set) = self
.workspaces .workspaces
.sets .sets
.values_mut() .values_mut()
.find(|set| set.sticky_layer.mapped().any(|m| m == window)) .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) { } else if let Some(workspace) = self.space_for_mut(window) {
if workspace.tiling_layer.mapped().any(|(m, _)| m == 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) { } 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 { } else {
None None
} }