tiling: Add explicit toggle_stacking/_focused

This commit is contained in:
Victoria Brekenfeld 2023-12-07 19:45:19 +00:00 committed by Victoria Brekenfeld
parent 9ecfa8bfda
commit 6ac8fd2f90

View file

@ -382,7 +382,9 @@ impl TilingLayout {
let gaps = self.gaps(); let gaps = self.gaps();
let mut tree = self.queue.trees.back().unwrap().0.copy_clone(); let mut tree = self.queue.trees.back().unwrap().0.copy_clone();
TilingLayout::map_to_tree(&mut tree, window, &self.output, focus_stack, direction); let last_active = focus_stack
.and_then(|focus_stack| TilingLayout::last_active_window(&mut tree, focus_stack));
TilingLayout::map_to_tree(&mut tree, window, &self.output, last_active, direction);
let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps);
self.queue.push_tree(tree, ANIMATION_DURATION, blocker); self.queue.push_tree(tree, ANIMATION_DURATION, blocker);
} }
@ -391,7 +393,7 @@ impl TilingLayout {
mut tree: &mut Tree<Data>, mut tree: &mut Tree<Data>,
window: impl Into<CosmicMapped>, window: impl Into<CosmicMapped>,
output: &Output, output: &Output,
focus_stack: Option<impl Iterator<Item = &'a CosmicMapped> + 'a>, node: Option<(NodeId, CosmicMapped)>,
direction: Option<Direction>, direction: Option<Direction>,
) { ) {
let window = window.into(); let window = window.into();
@ -422,10 +424,7 @@ impl TilingLayout {
tree.insert(new_window, InsertBehavior::AsRoot).unwrap() tree.insert(new_window, InsertBehavior::AsRoot).unwrap()
} }
} else { } else {
let last_active = focus_stack if let Some((ref node_id, mut last_active_window)) = node {
.and_then(|focus_stack| TilingLayout::last_active_window(&mut tree, focus_stack));
if let Some((ref node_id, mut last_active_window)) = last_active {
if window.is_window() && last_active_window.is_stack() { if window.is_window() && last_active_window.is_stack() {
let surface = window.active_window(); let surface = window.active_window();
last_active_window last_active_window
@ -1902,11 +1901,107 @@ impl TilingLayout {
} }
} }
pub fn toggle_stacking<'a>(&mut self, seat: &Seat<State>, mut focus_stack: FocusStackMut) { pub fn toggle_stacking(&mut self, mapped: &CosmicMapped) -> Option<KeyboardFocusTarget> {
let gaps = self.gaps();
let Some(node_id) = mapped.tiling_node_id.lock().unwrap().clone() else {
return None;
};
let mut tree = self.queue.trees.back().unwrap().0.copy_clone();
if tree.get(&node_id).is_err() {
return None;
}
let result = if mapped.is_window() {
// if it is just a window
match tree.get_mut(&node_id).unwrap().data_mut() {
Data::Mapped { mapped, .. } => {
mapped.convert_to_stack((&self.output, mapped.bbox()), self.theme.clone());
}
_ => unreachable!(),
};
KeyboardFocusTarget::Element(mapped.clone())
} else {
// if we have a stack
let mut surfaces = mapped.windows().map(|(s, _)| s);
let first = surfaces.next().expect("Stack without a window?");
let handle = match tree.get_mut(&node_id).unwrap().data_mut() {
Data::Mapped { mapped, .. } => {
let handle = mapped.loop_handle();
mapped.convert_to_surface(
first,
(&self.output, mapped.bbox()),
self.theme.clone(),
);
handle
}
_ => unreachable!(),
};
// map the rest
let mut current_node = (node_id.clone(), mapped.clone());
for other in surfaces {
other.try_force_undecorated(false);
other.set_tiled(false);
let window = CosmicMapped::from(CosmicWindow::new(
other,
handle.clone(),
self.theme.clone(),
));
window.output_enter(&self.output, window.bbox());
{
let layer_map = layer_map_for_output(&self.output);
window.set_bounds(layer_map.non_exclusive_zone().size);
}
TilingLayout::map_to_tree(
&mut tree,
window.clone(),
&self.output,
Some(current_node),
None,
);
let node = window.tiling_node_id.lock().unwrap().clone().unwrap();
current_node = (node, window);
}
// TODO: Focus the new group
if let Some(parent) = tree.get(&node_id).unwrap().parent() {
let Data::Group { alive, .. } = tree.get(&parent).unwrap().data() else { unreachable!() };
KeyboardFocusTarget::Group(WindowGroup {
node: parent.clone(),
alive: Arc::downgrade(alive),
focus_stack: tree
.children_ids(parent)
.unwrap()
.cloned()
.collect::<Vec<_>>(),
})
} else {
KeyboardFocusTarget::Element(mapped.clone())
}
};
let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps);
self.queue.push_tree(tree, ANIMATION_DURATION, blocker);
Some(result)
}
pub fn toggle_stacking_focused<'a>(
&mut self,
seat: &Seat<State>,
mut focus_stack: FocusStackMut,
) -> Option<KeyboardFocusTarget> {
let gaps = self.gaps(); let gaps = self.gaps();
let Some(target) = seat.get_keyboard().unwrap().current_focus() else { let Some(target) = seat.get_keyboard().unwrap().current_focus() else {
return; return None;
}; };
let mut tree = self.queue.trees.back().unwrap().0.copy_clone(); let mut tree = self.queue.trees.back().unwrap().0.copy_clone();
@ -1915,64 +2010,9 @@ impl TilingLayout {
{ {
match last_active_data { match last_active_data {
FocusedNodeData::Window(mapped) => { FocusedNodeData::Window(mapped) => {
if mapped.is_window() { let res = self.toggle_stacking(&mapped);
// if it is just a window focus_stack.append(&mapped);
match tree.get_mut(&last_active).unwrap().data_mut() { return res;
Data::Mapped { mapped, .. } => {
mapped.convert_to_stack(
(&self.output, mapped.bbox()),
self.theme.clone(),
);
focus_stack.append(&mapped);
}
_ => unreachable!(),
};
} else {
// if we have a stack
let mut surfaces = mapped.windows().map(|(s, _)| s);
let first = surfaces.next().expect("Stack without a window?");
let handle = match tree.get_mut(&last_active).unwrap().data_mut() {
Data::Mapped { mapped, .. } => {
let handle = mapped.loop_handle();
mapped.convert_to_surface(
first,
(&self.output, mapped.bbox()),
self.theme.clone(),
);
focus_stack.append(&mapped);
handle
}
_ => unreachable!(),
};
// map the rest
for other in surfaces {
other.try_force_undecorated(false);
other.set_tiled(false);
let window = CosmicMapped::from(CosmicWindow::new(
other,
handle.clone(),
self.theme.clone(),
));
window.output_enter(&self.output, window.bbox());
{
let layer_map = layer_map_for_output(&self.output);
window.set_bounds(layer_map.non_exclusive_zone().size);
}
TilingLayout::map_to_tree(
&mut tree,
window,
&self.output,
Some(focus_stack.iter()),
None,
)
}
// TODO: Focus the new group
}
} }
FocusedNodeData::Group(_, _) => { FocusedNodeData::Group(_, _) => {
let mut handle = None; let mut handle = None;
@ -1992,7 +2032,7 @@ impl TilingLayout {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if surfaces.is_empty() { if surfaces.is_empty() {
return; return None;
} }
let handle = handle.unwrap(); let handle = handle.unwrap();
let stack = CosmicStack::new(surfaces.into_iter(), handle, self.theme.clone()); let stack = CosmicStack::new(surfaces.into_iter(), handle, self.theme.clone());
@ -2010,7 +2050,6 @@ impl TilingLayout {
let data = tree.get_mut(&last_active).unwrap().data_mut(); let data = tree.get_mut(&last_active).unwrap().data_mut();
let geo = *data.geometry(); let geo = *data.geometry();
//stack.set_geometry(geo.as_local());
stack.output_enter(&self.output, stack.bbox()); stack.output_enter(&self.output, stack.bbox());
stack.set_activate(true); stack.set_activate(true);
stack.active().send_configure(); stack.active().send_configure();
@ -2021,15 +2060,19 @@ impl TilingLayout {
*mapped.tiling_node_id.lock().unwrap() = Some(last_active); *mapped.tiling_node_id.lock().unwrap() = Some(last_active);
focus_stack.append(&mapped); focus_stack.append(&mapped);
*data = Data::Mapped { *data = Data::Mapped {
mapped, mapped: mapped.clone(),
last_geometry: geo, last_geometry: geo,
}; };
let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps);
self.queue.push_tree(tree, ANIMATION_DURATION, blocker);
return Some(KeyboardFocusTarget::Element(mapped));
} }
} }
let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps);
self.queue.push_tree(tree, ANIMATION_DURATION, blocker);
} }
None
} }
pub fn recalculate(&mut self) { pub fn recalculate(&mut self) {
@ -2414,13 +2457,7 @@ impl TilingLayout {
} }
} }
_ => { _ => {
TilingLayout::map_to_tree( TilingLayout::map_to_tree(&mut tree, window.clone(), &self.output, None, None);
&mut tree,
window.clone(),
&self.output,
Option::<std::iter::Empty<_>>::None,
None,
);
window window
} }
}; };