diff --git a/src/input/mod.rs b/src/input/mod.rs index 449cf743..ca629276 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -303,7 +303,7 @@ impl State { if let Some(old_workspace) = old_w.get_mut(0) { if let Some(new_workspace) = other_w.iter_mut().find(|w| w.handle == new_workspace) { if new_workspace.tiling_layer.windows().next().is_none() { - if let Some(focus) = TilingLayout::move_tree(&mut old_workspace.tiling_layer, &mut new_workspace.tiling_layer, &new_workspace.handle, &seat, new_workspace.focus_stack.get(&seat).iter(), old_descriptor.clone()) { + if let Some(focus) = TilingLayout::move_tree(&mut old_workspace.tiling_layer, &mut new_workspace.tiling_layer, &new_workspace.handle, &seat, new_workspace.focus_stack.get(&seat).iter(), old_descriptor.clone(), None) { let seat = seat.clone(); data.common.event_loop_handle.insert_idle(move |state| { Shell::set_focus(state, Some(&focus), &seat, None,true); diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index 2eb5c708..371051b2 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -640,6 +640,7 @@ impl TilingLayout { seat: &Seat, focus_stack: impl Iterator + 'a, desc: NodeDesc, + direction: Option, ) -> Option { let this_handle = &desc.handle; let mut this_tree = this.queue.trees.back().unwrap().0.copy_clone(); @@ -678,7 +679,7 @@ impl TilingLayout { } mapped.set_tiled(true); - other.map(mapped.clone(), Some(focus_stack), None); + other.map(mapped.clone(), Some(focus_stack), direction); return Some(KeyboardFocusTarget::Element(mapped)); } None => { @@ -702,7 +703,12 @@ impl TilingLayout { }) .map(|(id, _)| id) .unwrap_or(other_tree.root_node_id().unwrap().clone()); - let orientation = { + let orientation = if let Some(direction) = direction { + match direction { + Direction::Left | Direction::Right => Orientation::Vertical, + Direction::Up | Direction::Down => Orientation::Horizontal, + } + } else { let window_size = other_tree .get(&focused_node) .unwrap() @@ -718,6 +724,15 @@ impl TilingLayout { let id = other_tree.insert(node, InsertBehavior::AsRoot).unwrap(); TilingLayout::new_group(&mut other_tree, &focused_node, &id, orientation) .unwrap(); + other_tree + .make_nth_sibling( + &id, + match direction { + Some(Direction::Right) | Some(Direction::Down) => 0, + _ => 1, + }, + ) + .unwrap(); id } }; @@ -3762,6 +3777,14 @@ impl TilingLayout { }) } + pub fn element_for_node(&self, node: &NodeId) -> Option<&CosmicMapped> { + let tree = &self.queue.trees.back().unwrap().0; + tree.get(node).ok().and_then(|node| match node.data() { + Data::Mapped { mapped, .. } => Some(mapped), + _ => None, + }) + } + pub fn has_node(&self, node: &NodeId) -> bool { let tree = &self.queue.trees.back().unwrap().0; tree.root_node_id() diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 21670180..d5750272 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -2518,23 +2518,79 @@ impl Shell { .ok_or(InvalidWorkspaceIndex)?; let from_workspace = self.workspaces.active_mut(from_output); - let maybe_window = from_workspace.focus_stack.get(seat).last().cloned(); - - let Some(mapped) = maybe_window else { - return Ok(None); - }; - + let last_focused_window = from_workspace.focus_stack.get(seat).last().cloned(); let from = from_workspace.handle; - Ok(self.move_window( - Some(seat), - &mapped, - &from, - &to, - follow, - direction, - workspace_state, - )) + match seat.get_keyboard().unwrap().current_focus() { + Some(KeyboardFocusTarget::Group(WindowGroup { + node, focus_stack, .. + })) => { + let new_pos = if follow { + seat.set_active_output(&to_output); + self.workspaces + .idx_for_handle(&to_output, &to) + .and_then(|to_idx| { + self.activate( + &to_output, + to_idx, + WorkspaceDelta::new_shortcut(), + workspace_state, + ) + .unwrap() + }) + } else { + None + }; + + let spaces = self.workspaces.spaces_mut(); + let (mut from_w, mut other_w) = spaces.partition::, _>(|w| w.handle == from); + if let Some(from_workspace) = from_w.get_mut(0) { + if let Some(to_workspace) = other_w.iter_mut().find(|w| w.handle == to) { + { + let mut stack = to_workspace.focus_stack.get_mut(&seat); + for elem in focus_stack.iter().flat_map(|node_id| { + from_workspace.tiling_layer.element_for_node(node_id) + }) { + stack.append(elem); + } + } + let res = TilingLayout::move_tree( + &mut from_workspace.tiling_layer, + &mut to_workspace.tiling_layer, + &to, + seat, + to_workspace.focus_stack.get(&seat).iter(), + NodeDesc { + handle: from, + node, + stack_window: None, + }, + direction, + ); + from_workspace.refresh_focus_stack(); + to_workspace.refresh_focus_stack(); + return Ok(res.zip(new_pos)); + } + } + + Ok(None) + } + _ => { + if let Some(mapped) = last_focused_window { + Ok(self.move_window( + Some(seat), + &mapped, + &from, + &to, + follow, + direction, + workspace_state, + )) + } else { + Ok(None) + } + } + } } pub fn update_reactive_popups(&self, mapped: &CosmicMapped) {