tiling: Minimize animation

This commit is contained in:
Victoria Brekenfeld 2024-02-23 20:08:57 +01:00 • committed by Victoria Brekenfeld
parent 3eb7e5f82e
commit 745267ac24
2 changed files with 172 additions and 174 deletions

View file

@ -1160,17 +1160,17 @@ where
Stack(self::stack::CosmicStackRenderElement<R>), Stack(self::stack::CosmicStackRenderElement<R>),
Window(self::window::CosmicWindowRenderElement<R>), Window(self::window::CosmicWindowRenderElement<R>),
TiledStack( TiledStack(
RelocateRenderElement< CropRenderElement<
RescaleRenderElement<CropRenderElement<self::stack::CosmicStackRenderElement<R>>>, RelocateRenderElement<RescaleRenderElement<self::stack::CosmicStackRenderElement<R>>>,
>, >,
), ),
TiledWindow( TiledWindow(
RelocateRenderElement< CropRenderElement<
RescaleRenderElement<CropRenderElement<self::window::CosmicWindowRenderElement<R>>>, RelocateRenderElement<RescaleRenderElement<self::window::CosmicWindowRenderElement<R>>>,
>, >,
), ),
TiledOverlay( TiledOverlay(
RelocateRenderElement<RescaleRenderElement<CropRenderElement<PixelShaderElement>>>, CropRenderElement<RelocateRenderElement<RescaleRenderElement<PixelShaderElement>>>,
), ),
MovingStack( MovingStack(
RelocateRenderElement<RescaleRenderElement<self::stack::CosmicStackRenderElement<R>>>, RelocateRenderElement<RescaleRenderElement<self::stack::CosmicStackRenderElement<R>>>,

View file

@ -38,7 +38,10 @@ use keyframe::{
use smithay::{ use smithay::{
backend::renderer::{ backend::renderer::{
element::{ element::{
utils::{CropRenderElement, Relocate, RelocateRenderElement, RescaleRenderElement}, utils::{
constrain_render_elements, ConstrainAlign, ConstrainScaleBehavior,
RescaleRenderElement,
},
AsRenderElements, Id, RenderElement, AsRenderElements, Id, RenderElement,
}, },
glow::GlowRenderer, glow::GlowRenderer,
@ -141,7 +144,7 @@ pub enum Data {
Mapped { Mapped {
mapped: CosmicMapped, mapped: CosmicMapped,
last_geometry: Rectangle<i32, Local>, last_geometry: Rectangle<i32, Local>,
minimize_to: Option<Rectangle<i32, Local>>, minimize_rect: Option<Rectangle<i32, Local>>,
}, },
Placeholder { Placeholder {
last_geometry: Rectangle<i32, Local>, last_geometry: Rectangle<i32, Local>,
@ -402,6 +405,7 @@ impl TilingLayout {
tiling_state: Option<MinimizedTilingState>, tiling_state: Option<MinimizedTilingState>,
focus_stack: Option<impl Iterator<Item = &'a CosmicMapped> + 'a>, focus_stack: Option<impl Iterator<Item = &'a CosmicMapped> + 'a>,
) { ) {
window.set_minimized(false);
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();
@ -444,14 +448,13 @@ impl TilingLayout {
let new_node = Node::new(Data::Mapped { let new_node = Node::new(Data::Mapped {
mapped: window.clone(), mapped: window.clone(),
last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)), last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)),
minimize_to: Some(from), minimize_rect: Some(from),
}); });
let new_id = tree let new_id = tree
.insert(new_node, InsertBehavior::UnderNode(&parent)) .insert(new_node, InsertBehavior::UnderNode(&parent))
.unwrap(); .unwrap();
tree.make_nth_sibling(&new_id, idx).unwrap(); tree.make_nth_sibling(&new_id, idx).unwrap();
*window.tiling_node_id.lock().unwrap() = Some(new_id); *window.tiling_node_id.lock().unwrap() = Some(new_id);
window.set_minimized(false);
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);
@ -475,7 +478,7 @@ impl TilingLayout {
let new_window = Node::new(Data::Mapped { let new_window = Node::new(Data::Mapped {
mapped: window.clone(), mapped: window.clone(),
last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)), last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)),
minimize_to: None, minimize_rect: None,
}); });
let window_id = if let Some(direction) = direction { let window_id = if let Some(direction) = direction {
@ -1009,7 +1012,7 @@ impl TilingLayout {
.replace_data(Data::Mapped { .replace_data(Data::Mapped {
mapped, mapped,
last_geometry: geometry, last_geometry: geometry,
minimize_to: None, minimize_rect: None,
}); });
} }
(None, Some(other_surface)) => { (None, Some(other_surface)) => {
@ -1097,7 +1100,7 @@ impl TilingLayout {
.replace_data(Data::Mapped { .replace_data(Data::Mapped {
mapped, mapped,
last_geometry: geometry, last_geometry: geometry,
minimize_to: None, minimize_rect: None,
}); });
} }
(Some(this_surface), Some(other_surface)) => { (Some(this_surface), Some(other_surface)) => {
@ -1288,7 +1291,11 @@ impl TilingLayout {
.get_mut(self.queue.trees.len() - 2) .get_mut(self.queue.trees.len() - 2)
.unwrap() .unwrap()
.0; .0;
if let Data::Mapped { minimize_to, .. } = tree.get_mut(&node_id).unwrap().data_mut() { if let Data::Mapped {
minimize_rect: minimize_to,
..
} = tree.get_mut(&node_id).unwrap().data_mut()
{
*minimize_to = Some(to); *minimize_to = Some(to);
} }
window.set_minimized(true); window.set_minimized(true);
@ -1421,7 +1428,7 @@ impl TilingLayout {
let new_node = Node::new(Data::Mapped { let new_node = Node::new(Data::Mapped {
mapped: mapped.clone(), mapped: mapped.clone(),
last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)), last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)),
minimize_to: None, minimize_rect: None,
}); });
let new_id = tree.insert(new_node, InsertBehavior::AsRoot).unwrap(); let new_id = tree.insert(new_node, InsertBehavior::AsRoot).unwrap();
TilingLayout::new_group(&mut tree, &node_id, &new_id, orientation).unwrap(); TilingLayout::new_group(&mut tree, &node_id, &new_id, orientation).unwrap();
@ -2195,7 +2202,7 @@ impl TilingLayout {
*data = Data::Mapped { *data = Data::Mapped {
mapped: mapped.clone(), mapped: mapped.clone(),
last_geometry: geo, last_geometry: geo,
minimize_to: None, minimize_rect: None,
}; };
let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps);
@ -2257,7 +2264,23 @@ impl TilingLayout {
{ {
let _ = self.queue.animation_start.take(); let _ = self.queue.animation_start.take();
let _ = self.queue.trees.pop_front(); let _ = self.queue.trees.pop_front();
let _ = self.queue.trees.front_mut().unwrap().2.take(); let front = self.queue.trees.front_mut().unwrap();
if let Some(root_id) = front.0.root_node_id() {
for node in front
.0
.traverse_pre_order_ids(root_id)
.unwrap()
.collect::<Vec<_>>()
.into_iter()
{
if let Data::Mapped { minimize_rect, .. } =
front.0.get_mut(&node).unwrap().data_mut()
{
minimize_rect.take();
}
}
}
let _ = front.2.take();
} else { } else {
return clients; return clients;
} }
@ -2532,7 +2555,7 @@ impl TilingLayout {
Node::new(Data::Mapped { Node::new(Data::Mapped {
mapped: window.clone(), mapped: window.clone(),
last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)), last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)),
minimize_to: None, minimize_rect: None,
}), }),
InsertBehavior::UnderNode(group_id), InsertBehavior::UnderNode(group_id),
) )
@ -2568,7 +2591,7 @@ impl TilingLayout {
Node::new(Data::Mapped { Node::new(Data::Mapped {
mapped: window.clone(), mapped: window.clone(),
last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)), last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)),
minimize_to: None, minimize_rect: None,
}), }),
InsertBehavior::UnderNode(group_id), InsertBehavior::UnderNode(group_id),
) )
@ -2590,7 +2613,7 @@ impl TilingLayout {
*data = Data::Mapped { *data = Data::Mapped {
mapped: window.clone(), mapped: window.clone(),
last_geometry: geo, last_geometry: geo,
minimize_to: None, minimize_rect: None,
}; };
*window.tiling_node_id.lock().unwrap() = Some(node_id.clone()); *window.tiling_node_id.lock().unwrap() = Some(node_id.clone());
window window
@ -2601,7 +2624,7 @@ impl TilingLayout {
Node::new(Data::Mapped { Node::new(Data::Mapped {
mapped: window.clone(), mapped: window.clone(),
last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)), last_geometry: Rectangle::from_loc_and_size((0, 0), (100, 100)),
minimize_to: None, minimize_rect: None,
}), }),
InsertBehavior::UnderNode(&window_id), InsertBehavior::UnderNode(&window_id),
) )
@ -3780,7 +3803,9 @@ impl TilingLayout {
geometries.clone(), geometries.clone(),
output_scale, output_scale,
percentage, percentage,
indicator_thickness,
swap_desc.is_some(), swap_desc.is_some(),
theme,
); );
window_elements.extend(w_elements); window_elements.extend(w_elements);
popup_elements.extend(p_elements); popup_elements.extend(p_elements);
@ -4543,7 +4568,9 @@ fn render_old_tree<R>(
geometries: Option<HashMap<NodeId, Rectangle<i32, Local>>>, geometries: Option<HashMap<NodeId, Rectangle<i32, Local>>>,
output_scale: f64, output_scale: f64,
percentage: f32, percentage: f32,
indicator_thickness: u8,
is_swap_mode: bool, is_swap_mode: bool,
theme: &cosmic::theme::CosmicTheme,
) -> ( ) -> (
Vec<CosmicMappedRenderElement<R>>, Vec<CosmicMappedRenderElement<R>>,
Vec<CosmicMappedRenderElement<R>>, Vec<CosmicMappedRenderElement<R>>,
@ -4555,6 +4582,7 @@ where
CosmicWindowRenderElement<R>: RenderElement<R>, CosmicWindowRenderElement<R>: RenderElement<R>,
CosmicStackRenderElement<R>: RenderElement<R>, CosmicStackRenderElement<R>: RenderElement<R>,
{ {
let window_hint = crate::theme::active_window_hint(theme);
let mut window_elements = Vec::new(); let mut window_elements = Vec::new();
let mut popup_elements = Vec::new(); let mut popup_elements = Vec::new();
@ -4569,12 +4597,18 @@ where
Data::Mapped { Data::Mapped {
mapped, mapped,
last_geometry, last_geometry,
minimize_rect,
.. ..
} => (mapped, last_geometry, geometries.get(&node_id)), } => (
mapped,
last_geometry,
geometries.get(&node_id).copied(),
minimize_rect,
),
_ => unreachable!(), _ => unreachable!(),
}, },
) )
.filter(|(mapped, _, _)| { .filter(|(mapped, _, _, _)| {
if let Some(root) = target_tree.root_node_id() { if let Some(root) = target_tree.root_node_id() {
is_swap_mode is_swap_mode
|| !target_tree || !target_tree
@ -4585,9 +4619,20 @@ where
true true
} }
}) })
.for_each(|(mapped, original_geo, scaled_geo)| { .for_each(|(mapped, original_geo, mut scaled_geo, minimize_geo)| {
if let Some(minimize_geo) = minimize_geo {
scaled_geo = Some(
ease(
EaseInOutCubic,
EaseRectangle(*original_geo),
EaseRectangle(*minimize_geo),
percentage,
)
.unwrap(),
);
}
let (scale, offset) = scaled_geo let (scale, offset) = scaled_geo
.map(|adapted_geo| scale_to_center(&original_geo, adapted_geo)) .map(|adapted_geo| scale_to_center(&original_geo, &adapted_geo))
.unwrap_or_else(|| (1.0.into(), (0, 0).into())); .unwrap_or_else(|| (1.0.into(), (0, 0).into()));
let geo = scaled_geo let geo = scaled_geo
.map(|adapted_geo| { .map(|adapted_geo| {
@ -4601,7 +4646,6 @@ where
}) })
.unwrap_or(*original_geo); .unwrap_or(*original_geo);
let crop_rect = geo.clone();
let original_location = original_geo let original_location = original_geo
.loc .loc
.as_logical() .as_logical()
@ -4611,6 +4655,7 @@ where
.loc .loc
.to_physical_precise_round(output_scale); .to_physical_precise_round(output_scale);
let elem_geometry = mapped.geometry().to_physical_precise_round(output_scale);
let (w_elements, p_elements) = mapped let (w_elements, p_elements) = mapped
.split_render_elements::<R, CosmicMappedRenderElement<R>>( .split_render_elements::<R, CosmicMappedRenderElement<R>>(
renderer, renderer,
@ -4619,57 +4664,48 @@ where
1.0 - percentage, 1.0 - percentage,
); );
window_elements.extend(w_elements.into_iter().flat_map(|element| match element { window_elements.extend(w_elements.into_iter().flat_map(|element| {
CosmicMappedRenderElement::Stack(elem) => { match element {
Some(CosmicMappedRenderElement::TiledStack({ CosmicMappedRenderElement::Stack(elem) => constrain_render_elements(
let cropped = CropRenderElement::from_element( std::iter::once(elem),
elem, geo.loc.as_logical().to_physical_precise_round(output_scale)
- elem_geometry.loc,
geo.as_logical().to_physical_precise_round(output_scale),
elem_geometry,
ConstrainScaleBehavior::Stretch,
ConstrainAlign::CENTER,
output_scale, output_scale,
crop_rect )
.as_logical() .next()
.to_physical_precise_round(output_scale), .map(CosmicMappedRenderElement::TiledStack),
)?; CosmicMappedRenderElement::Window(elem) => constrain_render_elements(
let rescaled = RescaleRenderElement::from_element( std::iter::once(elem),
cropped, geo.loc.as_logical().to_physical_precise_round(output_scale)
original_location, - elem_geometry.loc,
scale, geo.as_logical().to_physical_precise_round(output_scale),
); elem_geometry,
let relocated = RelocateRenderElement::from_element( ConstrainScaleBehavior::Stretch,
rescaled, ConstrainAlign::CENTER,
(geo.loc - original_geo.loc)
.as_logical()
.to_physical_precise_round(output_scale),
Relocate::Relative,
);
relocated
}))
}
CosmicMappedRenderElement::Window(elem) => {
Some(CosmicMappedRenderElement::TiledWindow({
let cropped = CropRenderElement::from_element(
elem,
output_scale, output_scale,
crop_rect )
.as_logical() .next()
.to_physical_precise_round(output_scale), .map(CosmicMappedRenderElement::TiledWindow),
)?;
let rescaled = RescaleRenderElement::from_element(
cropped,
original_location,
scale,
);
let relocated = RelocateRenderElement::from_element(
rescaled,
(geo.loc - original_geo.loc)
.as_logical()
.to_physical_precise_round(output_scale),
Relocate::Relative,
);
relocated
}))
}
x => Some(x), x => Some(x),
}
})); }));
if minimize_geo.is_some() && indicator_thickness > 0 {
window_elements.push(CosmicMappedRenderElement::FocusIndicator(
IndicatorShader::focus_element(
renderer,
Key::Window(Usage::FocusIndicator, mapped.clone().into()),
geo,
indicator_thickness,
output_scale,
1.0 - percentage,
[window_hint.red, window_hint.green, window_hint.blue],
),
));
}
popup_elements.extend(p_elements); popup_elements.extend(p_elements);
}); });
} }
@ -4880,26 +4916,36 @@ where
None None
} }
.unzip(); .unzip();
let old_geo = old_original_geo.map(|original_geo| { let mut old_geo = old_original_geo.map(|original_geo| {
let (scale, offset) = old_scaled_geo let (scale, offset) = old_scaled_geo
.unwrap() .unwrap()
.map(|adapted_geo| scale_to_center(original_geo, adapted_geo)) .map(|adapted_geo| scale_to_center(original_geo, adapted_geo))
.unwrap_or_else(|| (1.0.into(), (0, 0).into())); .unwrap_or_else(|| (1.0.into(), (0, 0).into()));
old_scaled_geo (
.unwrap() old_scaled_geo
.map(|adapted_geo| { .unwrap()
Rectangle::from_loc_and_size( .map(|adapted_geo| {
adapted_geo.loc + offset, Rectangle::from_loc_and_size(
( adapted_geo.loc + offset,
(original_geo.size.w as f64 * scale).round() as i32, (
(original_geo.size.h as f64 * scale).round() as i32, (original_geo.size.w as f64 * scale).round() as i32,
), (original_geo.size.h as f64 * scale).round() as i32,
) ),
}) )
.unwrap_or(*original_geo) })
.unwrap_or(*original_geo),
1.0,
)
}); });
let mut crop_rect = original_geo; if let Data::Mapped {
minimize_rect: Some(minimize_rect),
..
} = &data
{
old_geo = Some((*minimize_rect, percentage));
}
let (scale, offset) = scaled_geo let (scale, offset) = scaled_geo
.map(|adapted_geo| scale_to_center(original_geo, adapted_geo)) .map(|adapted_geo| scale_to_center(original_geo, adapted_geo))
.unwrap_or_else(|| (1.0.into(), (0, 0).into())); .unwrap_or_else(|| (1.0.into(), (0, 0).into()));
@ -4915,7 +4961,7 @@ where
}) })
.unwrap_or(*original_geo); .unwrap_or(*original_geo);
let (geo, alpha, animating) = if let Some(old_geo) = old_geo.filter(|_| { let (geo, alpha, animating) = if let Some((old_geo, alpha)) = old_geo.filter(|_| {
swap_desc swap_desc
.as_ref() .as_ref()
.map(|desc| desc.node != node_id && desc.stack_window.is_none()) .map(|desc| desc.node != node_id && desc.stack_window.is_none())
@ -4929,15 +4975,12 @@ where
percentage, percentage,
) )
.unwrap(), .unwrap(),
1.0, alpha,
old_geo != new_geo, old_geo != new_geo,
) )
} else { } else {
(new_geo, percentage, false) (new_geo, percentage, false)
}; };
if matches!(overview.0, OverviewMode::None) {
crop_rect = &geo;
}
if swap_desc.as_ref().map(|desc| &desc.node) == Some(&node_id) if swap_desc.as_ref().map(|desc| &desc.node) == Some(&node_id)
|| focused.as_ref() == Some(&node_id) || focused.as_ref() == Some(&node_id)
@ -4986,7 +5029,7 @@ where
indicator_thickness indicator_thickness
}, },
output_scale, output_scale,
1.0, alpha,
[window_hint.red, window_hint.green, window_hint.blue], [window_hint.red, window_hint.green, window_hint.blue],
)); ));
} }
@ -5067,13 +5110,13 @@ where
} }
if let Data::Mapped { mapped, .. } = data { if let Data::Mapped { mapped, .. } = data {
let original_location = (original_geo.loc.as_logical() - mapped.geometry().loc) let elem_geometry = mapped.geometry().to_physical_precise_round(output_scale);
.to_physical_precise_round(output_scale);
let (mut w_elements, p_elements) = mapped let (mut w_elements, p_elements) = mapped
.split_render_elements::<R, CosmicMappedRenderElement<R>>( .split_render_elements::<R, CosmicMappedRenderElement<R>>(
renderer, renderer,
original_location, //original_location,
geo.loc.as_logical().to_physical_precise_round(output_scale)
- elem_geometry.loc,
Scale::from(output_scale), Scale::from(output_scale),
alpha, alpha,
); );
@ -5113,87 +5156,42 @@ where
} }
let w_elements = w_elements.into_iter().flat_map(|element| match element { let w_elements = w_elements.into_iter().flat_map(|element| match element {
CosmicMappedRenderElement::Stack(elem) => { CosmicMappedRenderElement::Stack(elem) => constrain_render_elements(
Some(CosmicMappedRenderElement::TiledStack({ std::iter::once(elem),
let cropped = CropRenderElement::from_element( geo.loc.as_logical().to_physical_precise_round(output_scale)
elem, - elem_geometry.loc,
geo.as_logical().to_physical_precise_round(output_scale),
elem_geometry,
ConstrainScaleBehavior::Stretch,
ConstrainAlign::CENTER,
output_scale, output_scale,
crop_rect )
.as_logical() .next()
.to_physical_precise_round(output_scale), .map(CosmicMappedRenderElement::TiledStack),
)?; CosmicMappedRenderElement::Window(elem) => constrain_render_elements(
let rescaled = RescaleRenderElement::from_element( std::iter::once(elem),
cropped, geo.loc.as_logical().to_physical_precise_round(output_scale)
original_geo - elem_geometry.loc,
.loc geo.as_logical().to_physical_precise_round(output_scale),
.as_logical() elem_geometry,
.to_physical_precise_round(output_scale), ConstrainScaleBehavior::Stretch,
scale, ConstrainAlign::CENTER,
);
let relocated = RelocateRenderElement::from_element(
rescaled,
(geo.loc - original_geo.loc)
.as_logical()
.to_physical_precise_round(output_scale),
Relocate::Relative,
);
relocated
}))
}
CosmicMappedRenderElement::Window(elem) => {
Some(CosmicMappedRenderElement::TiledWindow({
let cropped = CropRenderElement::from_element(
elem,
output_scale, output_scale,
crop_rect )
.as_logical() .next()
.to_physical_precise_round(output_scale), .map(CosmicMappedRenderElement::TiledWindow),
)?; CosmicMappedRenderElement::Overlay(elem) => constrain_render_elements(
let rescaled = RescaleRenderElement::from_element( std::iter::once(elem),
cropped, geo.loc.as_logical().to_physical_precise_round(output_scale)
original_geo - elem_geometry.loc,
.loc geo.as_logical().to_physical_precise_round(output_scale),
.as_logical() elem_geometry,
.to_physical_precise_round(output_scale), ConstrainScaleBehavior::Stretch,
scale, ConstrainAlign::CENTER,
);
let relocated = RelocateRenderElement::from_element(
rescaled,
(geo.loc - original_geo.loc)
.as_logical()
.to_physical_precise_round(output_scale),
Relocate::Relative,
);
relocated
}))
}
CosmicMappedRenderElement::Overlay(elem) => {
Some(CosmicMappedRenderElement::TiledOverlay({
let cropped = CropRenderElement::from_element(
elem,
output_scale, output_scale,
crop_rect )
.as_logical() .next()
.to_physical_precise_round(output_scale), .map(CosmicMappedRenderElement::TiledOverlay),
)?;
let rescaled = RescaleRenderElement::from_element(
cropped,
original_geo
.loc
.as_logical()
.to_physical_precise_round(output_scale),
scale,
);
let relocated = RelocateRenderElement::from_element(
rescaled,
(geo.loc - original_geo.loc)
.as_logical()
.to_physical_precise_round(output_scale),
Relocate::Relative,
);
relocated
}))
}
x => Some(x), x => Some(x),
}); });
if swap_desc if swap_desc