shell: Allow moving groups between outputs
This commit is contained in:
parent
b111c9ff48
commit
03430b76c5
3 changed files with 97 additions and 18 deletions
|
|
@ -303,7 +303,7 @@ impl State {
|
||||||
if let Some(old_workspace) = old_w.get_mut(0) {
|
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 let Some(new_workspace) = other_w.iter_mut().find(|w| w.handle == new_workspace) {
|
||||||
if new_workspace.tiling_layer.windows().next().is_none() {
|
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();
|
let seat = seat.clone();
|
||||||
data.common.event_loop_handle.insert_idle(move |state| {
|
data.common.event_loop_handle.insert_idle(move |state| {
|
||||||
Shell::set_focus(state, Some(&focus), &seat, None,true);
|
Shell::set_focus(state, Some(&focus), &seat, None,true);
|
||||||
|
|
|
||||||
|
|
@ -640,6 +640,7 @@ impl TilingLayout {
|
||||||
seat: &Seat<State>,
|
seat: &Seat<State>,
|
||||||
focus_stack: impl Iterator<Item = &'a CosmicMapped> + 'a,
|
focus_stack: impl Iterator<Item = &'a CosmicMapped> + 'a,
|
||||||
desc: NodeDesc,
|
desc: NodeDesc,
|
||||||
|
direction: Option<Direction>,
|
||||||
) -> Option<KeyboardFocusTarget> {
|
) -> Option<KeyboardFocusTarget> {
|
||||||
let this_handle = &desc.handle;
|
let this_handle = &desc.handle;
|
||||||
let mut this_tree = this.queue.trees.back().unwrap().0.copy_clone();
|
let mut this_tree = this.queue.trees.back().unwrap().0.copy_clone();
|
||||||
|
|
@ -678,7 +679,7 @@ impl TilingLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
mapped.set_tiled(true);
|
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));
|
return Some(KeyboardFocusTarget::Element(mapped));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
|
@ -702,7 +703,12 @@ impl TilingLayout {
|
||||||
})
|
})
|
||||||
.map(|(id, _)| id)
|
.map(|(id, _)| id)
|
||||||
.unwrap_or(other_tree.root_node_id().unwrap().clone());
|
.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
|
let window_size = other_tree
|
||||||
.get(&focused_node)
|
.get(&focused_node)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -718,6 +724,15 @@ impl TilingLayout {
|
||||||
let id = other_tree.insert(node, InsertBehavior::AsRoot).unwrap();
|
let id = other_tree.insert(node, InsertBehavior::AsRoot).unwrap();
|
||||||
TilingLayout::new_group(&mut other_tree, &focused_node, &id, orientation)
|
TilingLayout::new_group(&mut other_tree, &focused_node, &id, orientation)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
other_tree
|
||||||
|
.make_nth_sibling(
|
||||||
|
&id,
|
||||||
|
match direction {
|
||||||
|
Some(Direction::Right) | Some(Direction::Down) => 0,
|
||||||
|
_ => 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
id
|
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 {
|
pub fn has_node(&self, node: &NodeId) -> bool {
|
||||||
let tree = &self.queue.trees.back().unwrap().0;
|
let tree = &self.queue.trees.back().unwrap().0;
|
||||||
tree.root_node_id()
|
tree.root_node_id()
|
||||||
|
|
|
||||||
|
|
@ -2518,23 +2518,79 @@ impl Shell {
|
||||||
.ok_or(InvalidWorkspaceIndex)?;
|
.ok_or(InvalidWorkspaceIndex)?;
|
||||||
|
|
||||||
let from_workspace = self.workspaces.active_mut(from_output);
|
let from_workspace = self.workspaces.active_mut(from_output);
|
||||||
let maybe_window = from_workspace.focus_stack.get(seat).last().cloned();
|
let last_focused_window = from_workspace.focus_stack.get(seat).last().cloned();
|
||||||
|
|
||||||
let Some(mapped) = maybe_window else {
|
|
||||||
return Ok(None);
|
|
||||||
};
|
|
||||||
|
|
||||||
let from = from_workspace.handle;
|
let from = from_workspace.handle;
|
||||||
|
|
||||||
Ok(self.move_window(
|
match seat.get_keyboard().unwrap().current_focus() {
|
||||||
Some(seat),
|
Some(KeyboardFocusTarget::Group(WindowGroup {
|
||||||
&mapped,
|
node, focus_stack, ..
|
||||||
&from,
|
})) => {
|
||||||
&to,
|
let new_pos = if follow {
|
||||||
follow,
|
seat.set_active_output(&to_output);
|
||||||
direction,
|
self.workspaces
|
||||||
workspace_state,
|
.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::<Vec<_>, _>(|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) {
|
pub fn update_reactive_popups(&self, mapped: &CosmicMapped) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue