diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index 6312325e..4f4a3755 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -291,6 +291,7 @@ impl TilingLayout { focus_stack: impl Iterator + 'a, ) { let output = seat.active_output(); + window.output_enter(&output, window.bbox()); self.map_internal(window, &output, Some(focus_stack)); self.refresh(); } @@ -345,17 +346,27 @@ impl TilingLayout { *window.tiling_node_id.lock().unwrap() = Some(window_id); } - pub fn unmap(&mut self, window: &CosmicMapped) -> bool { - if self.unmap_window_internal(window) { - window.set_tiled(false); - self.refresh(); - true - } else { - false - } + pub fn unmap(&mut self, window: &CosmicMapped) -> Option { + let output = { + let node_id = window.tiling_node_id.lock().unwrap().clone()?; + self.trees + .iter() + .find(|(_, tree)| { + tree.get(&node_id) + .map(|node| node.data().is_mapped(Some(window))) + .unwrap_or(false) + }) + .map(|(o, _)| o.output.clone())? + }; + + self.unmap_window_internal(window); + window.output_leave(&output); + window.set_tiled(false); + self.refresh(); + Some(output) } - fn unmap_window_internal(&mut self, mapped: &CosmicMapped) -> bool { + fn unmap_window_internal(&mut self, mapped: &CosmicMapped) { if let Some(node_id) = mapped.tiling_node_id.lock().unwrap().as_ref() { if let Some(tree) = self.trees.values_mut().find(|tree| { tree.get(node_id) @@ -415,11 +426,8 @@ impl TilingLayout { } None => {} // root } - - return true; } } - false } pub fn output_for_element(&self, elem: &CosmicMapped) -> Option<&Output> { diff --git a/src/shell/mod.rs b/src/shell/mod.rs index ec546cd5..a6d8fe10 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -1006,58 +1006,55 @@ impl Shell { let from_workspace = state.common.shell.workspaces.active_mut(from_output); let maybe_window = from_workspace.focus_stack.get(seat).last().cloned(); - if let Some(mapped) = maybe_window { - let was_floating = from_workspace.floating_layer.unmap(&mapped); - let was_tiling = from_workspace.tiling_layer.unmap(&mapped); - assert!(was_floating != was_tiling); + let Some(mapped) = maybe_window else { return; }; + let Some(window_state) = from_workspace.unmap(&mapped) else { return; }; - for (toplevel, _) in mapped.windows() { - state - .common - .shell - .toplevel_info_state - .toplevel_leave_workspace(&toplevel, &from_workspace.handle); - } - let elements = from_workspace.mapped().cloned().collect::>(); - std::mem::drop(from_workspace); - for mapped in elements.into_iter() { - state.common.shell.update_reactive_popups(&mapped); - } - - let to_workspace = state + for (toplevel, _) in mapped.windows() { + state .common .shell - .workspaces - .get_mut(to_idx, to_output) - .unwrap(); // checked above - let focus_stack = to_workspace.focus_stack.get(&seat); - if was_floating { - to_workspace.floating_layer.map(mapped.clone(), &seat, None); - } else { - to_workspace - .tiling_layer - .map(mapped.clone(), &seat, focus_stack.iter()); - } - for (toplevel, _) in mapped.windows() { - state - .common - .shell - .toplevel_info_state - .toplevel_enter_workspace(&toplevel, &to_workspace.handle); - } - - for mapped in to_workspace - .mapped() - .cloned() - .collect::>() - .into_iter() - { - state.common.shell.update_reactive_popups(&mapped); - } - - state.common.shell.activate(to_output, to_idx); - Common::set_focus(state, Some(&KeyboardFocusTarget::from(mapped)), &seat, None); + .toplevel_info_state + .toplevel_leave_workspace(&toplevel, &from_workspace.handle); } + let elements = from_workspace.mapped().cloned().collect::>(); + std::mem::drop(from_workspace); + for mapped in elements.into_iter() { + state.common.shell.update_reactive_popups(&mapped); + } + + let to_workspace = state + .common + .shell + .workspaces + .get_mut(to_idx, to_output) + .unwrap(); // checked above + let focus_stack = to_workspace.focus_stack.get(&seat); + if window_state == ManagedState::Floating { + to_workspace.floating_layer.map(mapped.clone(), &seat, None); + } else { + to_workspace + .tiling_layer + .map(mapped.clone(), &seat, focus_stack.iter()); + } + for (toplevel, _) in mapped.windows() { + state + .common + .shell + .toplevel_info_state + .toplevel_enter_workspace(&toplevel, &to_workspace.handle); + } + + for mapped in to_workspace + .mapped() + .cloned() + .collect::>() + .into_iter() + { + state.common.shell.update_reactive_popups(&mapped); + } + + state.common.shell.activate(to_output, to_idx); + Common::set_focus(state, Some(&KeyboardFocusTarget::from(mapped)), &seat, None); } pub fn update_reactive_popups(&self, mapped: &CosmicMapped) { diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index 5eb46487..b9c0dbc3 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -55,6 +55,12 @@ pub struct Workspace { #[derive(Debug, Default)] pub struct FocusStacks(HashMap, IndexSet>); +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ManagedState { + Tiling, + Floating, +} + impl Workspace { pub fn new(handle: WorkspaceHandle) -> Workspace { Workspace { @@ -100,6 +106,25 @@ impl Workspace { self.refresh(); } + pub fn unmap(&mut self, mapped: &CosmicMapped) -> Option { + let was_floating = self.floating_layer.unmap(&mapped); + let was_tiling = self.tiling_layer.unmap(&mapped).is_some(); + if was_floating || was_tiling { + assert!(was_floating != was_tiling); + } + self.focus_stack + .0 + .values_mut() + .for_each(|set| set.retain(|m| m != mapped)); + if was_floating { + Some(ManagedState::Floating) + } else if was_tiling { + Some(ManagedState::Tiling) + } else { + None + } + } + pub fn element_for_surface(&self, surface: &WlSurface) -> Option<&CosmicMapped> { self.floating_layer .mapped()