shell: implement minimize

This commit is contained in:
Victoria Brekenfeld 2024-02-23 17:25:40 +01:00 committed by Victoria Brekenfeld
parent fffae1491d
commit 3eb7e5f82e
20 changed files with 1185 additions and 307 deletions

View file

@ -141,6 +141,7 @@ pub enum Data {
Mapped {
mapped: CosmicMapped,
last_geometry: Rectangle<i32, Local>,
minimize_to: Option<Rectangle<i32, Local>>,
},
Placeholder {
last_geometry: Rectangle<i32, Local>,
@ -317,6 +318,14 @@ enum FocusedNodeData {
Window(CosmicMapped),
}
#[derive(Debug)]
pub struct MinimizedTilingState {
pub parent: id_tree::NodeId,
pub orientation: Orientation,
pub idx: usize,
pub sizes: Vec<i32>,
}
impl TilingLayout {
pub fn new(theme: cosmic::Theme, output: &Output) -> TilingLayout {
TilingLayout {
@ -347,11 +356,7 @@ impl TilingLayout {
.into_iter()
.flatten()
{
if let Data::Mapped {
mapped,
last_geometry: _,
} = node.data()
{
if let Data::Mapped { mapped, .. } = node.data() {
mapped.output_leave(&self.output);
mapped.output_enter(output, mapped.bbox());
}
@ -390,6 +395,75 @@ impl TilingLayout {
self.queue.push_tree(tree, ANIMATION_DURATION, blocker);
}
pub fn remap_minimized<'a>(
&mut self,
window: CosmicMapped,
from: Rectangle<i32, Local>,
tiling_state: Option<MinimizedTilingState>,
focus_stack: Option<impl Iterator<Item = &'a CosmicMapped> + 'a>,
) {
let gaps = self.gaps();
let mut tree = self.queue.trees.back().unwrap().0.copy_clone();
if let Some(MinimizedTilingState {
parent,
orientation,
idx,
mut sizes,
}) = tiling_state
{
if let Ok(node) = tree.get_mut(&parent) {
if let Data::Group {
orientation: current_orientation,
sizes: current_sizes,
..
} = node.data_mut()
{
if *current_orientation == orientation && sizes.len() == current_sizes.len() + 1
{
let previous_length: i32 = sizes.iter().copied().sum();
let new_length: i32 = current_sizes.iter().copied().sum();
if previous_length != new_length {
// rescale sizes
sizes.iter_mut().for_each(|len| {
*len = (((*len as f64) / (previous_length as f64))
* (new_length as f64))
.round() as i32;
});
let sum: i32 = sizes.iter().sum();
// fix rounding issues
if sum != new_length {
let diff = new_length - sum;
*sizes.last_mut().unwrap() += diff;
}
}
}
*current_sizes = sizes;
let new_node = Node::new(Data::Mapped {
mapped: window.clone(),
last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)),
minimize_to: Some(from),
});
let new_id = tree
.insert(new_node, InsertBehavior::UnderNode(&parent))
.unwrap();
tree.make_nth_sibling(&new_id, idx).unwrap();
*window.tiling_node_id.lock().unwrap() = Some(new_id);
window.set_minimized(false);
let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps);
self.queue.push_tree(tree, ANIMATION_DURATION, blocker);
return;
}
}
}
// else add as new_window
self.map_internal(window, focus_stack, None);
}
fn map_to_tree<'a>(
mut tree: &mut Tree<Data>,
window: impl Into<CosmicMapped>,
@ -401,6 +475,7 @@ impl TilingLayout {
let new_window = Node::new(Data::Mapped {
mapped: window.clone(),
last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)),
minimize_to: None,
});
let window_id = if let Some(direction) = direction {
@ -934,6 +1009,7 @@ impl TilingLayout {
.replace_data(Data::Mapped {
mapped,
last_geometry: geometry,
minimize_to: None,
});
}
(None, Some(other_surface)) => {
@ -1021,6 +1097,7 @@ impl TilingLayout {
.replace_data(Data::Mapped {
mapped,
last_geometry: geometry,
minimize_to: None,
});
}
(Some(this_surface), Some(other_surface)) => {
@ -1173,6 +1250,53 @@ impl TilingLayout {
Some(node_id)
}
pub fn unmap_minimize(
&mut self,
window: &CosmicMapped,
to: Rectangle<i32, Local>,
) -> Option<MinimizedTilingState> {
let node_id = window.tiling_node_id.lock().unwrap().clone()?;
let state = {
let tree = &self.queue.trees.back().unwrap().0;
tree.get(&node_id).unwrap().parent().and_then(|parent_id| {
let parent = tree.get(&parent_id).unwrap();
let idx = parent
.children()
.iter()
.position(|id| id == &node_id)
.unwrap();
if let Data::Group {
orientation, sizes, ..
} = parent.data()
{
Some(MinimizedTilingState {
parent: parent_id.clone(),
orientation: *orientation,
idx,
sizes: sizes.clone(),
})
} else {
None
}
})
};
if self.unmap_window_internal(window) {
let tree = &mut self
.queue
.trees
.get_mut(self.queue.trees.len() - 2)
.unwrap()
.0;
if let Data::Mapped { minimize_to, .. } = tree.get_mut(&node_id).unwrap().data_mut() {
*minimize_to = Some(to);
}
window.set_minimized(true);
}
state
}
fn unmap_window_internal(&mut self, mapped: &CosmicMapped) -> bool {
let tiling_node_id = mapped.tiling_node_id.lock().unwrap().as_ref().cloned();
let gaps = self.gaps();
@ -1297,6 +1421,7 @@ impl TilingLayout {
let new_node = Node::new(Data::Mapped {
mapped: mapped.clone(),
last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)),
minimize_to: None,
});
let new_id = tree.insert(new_node, InsertBehavior::AsRoot).unwrap();
TilingLayout::new_group(&mut tree, &node_id, &new_id, orientation).unwrap();
@ -2070,6 +2195,7 @@ impl TilingLayout {
*data = Data::Mapped {
mapped: mapped.clone(),
last_geometry: geo,
minimize_to: None,
};
let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps);
@ -2406,6 +2532,7 @@ impl TilingLayout {
Node::new(Data::Mapped {
mapped: window.clone(),
last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)),
minimize_to: None,
}),
InsertBehavior::UnderNode(group_id),
)
@ -2441,6 +2568,7 @@ impl TilingLayout {
Node::new(Data::Mapped {
mapped: window.clone(),
last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)),
minimize_to: None,
}),
InsertBehavior::UnderNode(group_id),
)
@ -2462,6 +2590,7 @@ impl TilingLayout {
*data = Data::Mapped {
mapped: window.clone(),
last_geometry: geo,
minimize_to: None,
};
*window.tiling_node_id.lock().unwrap() = Some(node_id.clone());
window
@ -2472,6 +2601,7 @@ impl TilingLayout {
Node::new(Data::Mapped {
mapped: window.clone(),
last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)),
minimize_to: None,
}),
InsertBehavior::UnderNode(&window_id),
)
@ -2916,6 +3046,7 @@ impl TilingLayout {
Data::Mapped {
mapped,
last_geometry,
..
},
)) => {
let test_point = (location.to_f64() - last_geometry.loc.to_f64()