Add linear tiled window animations
This commit is contained in:
parent
a29937ebe8
commit
3540cdc4be
17 changed files with 913 additions and 64 deletions
100
src/state.rs
100
src/state.rs
|
|
@ -2,6 +2,7 @@ use {
|
|||
crate::{
|
||||
acceptor::Acceptor,
|
||||
allocator::BufferObject,
|
||||
animation::{AnimationCurve, AnimationState, AnimationTick, expand_damage_rect},
|
||||
async_engine::{AsyncEngine, SpawnedFuture},
|
||||
backend::{
|
||||
Backend, BackendConnectorState, BackendConnectorStateSerials, BackendDrmDevice,
|
||||
|
|
@ -102,11 +103,10 @@ use {
|
|||
time::Time,
|
||||
tree::{
|
||||
ContainerNode, ContainerSplit, Direction, DisplayNode, FindTreeUsecase, FloatNode,
|
||||
FoundNode, LatchListener, Node, NodeIds, NodeVisitorBase, OutputNode, PlaceholderNode,
|
||||
TearingMode, TileState, ToplevelData, ToplevelIdentifier, ToplevelNode,
|
||||
ToplevelNodeBase, Transform, VrrMode, WorkspaceDisplayOrder, WorkspaceNode,
|
||||
WorkspaceNodeId,
|
||||
WsMoveConfig, generic_node_visitor, move_ws_to_output,
|
||||
FoundNode, LatchListener, Node, NodeId, NodeIds, NodeVisitorBase, OutputNode,
|
||||
PlaceholderNode, TearingMode, TileState, ToplevelData, ToplevelIdentifier,
|
||||
ToplevelNode, ToplevelNodeBase, Transform, VrrMode, WorkspaceDisplayOrder,
|
||||
WorkspaceNode, WorkspaceNodeId, WsMoveConfig, generic_node_visitor, move_ws_to_output,
|
||||
},
|
||||
udmabuf::UdmabufHolder,
|
||||
utils::{
|
||||
|
|
@ -264,6 +264,10 @@ pub struct State {
|
|||
pub cpu_worker: Rc<CpuWorker>,
|
||||
pub ui_drag_enabled: Cell<bool>,
|
||||
pub ui_drag_threshold_squared: Cell<i32>,
|
||||
pub animations: AnimationState,
|
||||
pub layout_animations_requested: Cell<bool>,
|
||||
pub layout_animations_active: Cell<bool>,
|
||||
pub suppress_animations_for_next_layout: Cell<bool>,
|
||||
pub toplevels: CopyHashMap<ToplevelIdentifier, Weak<dyn ToplevelNode>>,
|
||||
pub const_40hz_latch: EventSource<dyn LatchListener>,
|
||||
pub tray_item_ids: TrayItemIds,
|
||||
|
|
@ -1115,6 +1119,10 @@ impl State {
|
|||
self.pending_screencast_reallocs_or_reconfigures.clear();
|
||||
self.pending_placeholder_render_textures.clear();
|
||||
self.pending_container_tab_render_textures.clear();
|
||||
self.animations.clear();
|
||||
self.layout_animations_requested.set(false);
|
||||
self.layout_animations_active.set(false);
|
||||
self.suppress_animations_for_next_layout.set(false);
|
||||
self.render_ctx_watchers.clear();
|
||||
self.workspace_watchers.clear();
|
||||
self.toplevel_lists.clear();
|
||||
|
|
@ -1461,6 +1469,88 @@ impl State {
|
|||
self.eng.now().msec()
|
||||
}
|
||||
|
||||
pub fn queue_tiled_animation(self: &Rc<Self>, node_id: NodeId, old: Rect, new: Rect) {
|
||||
if !self.animations.enabled.get()
|
||||
|| !self.layout_animations_active.get()
|
||||
|| self.suppress_animations_for_next_layout.get()
|
||||
{
|
||||
return;
|
||||
}
|
||||
let (old_output, old_scale) = {
|
||||
let (x, y) = old.center();
|
||||
let (output, _, _) = self.find_closest_output(x, y);
|
||||
(output.id, output.global.persistent.scale.get())
|
||||
};
|
||||
let (new_output, new_scale) = {
|
||||
let (x, y) = new.center();
|
||||
let (output, _, _) = self.find_closest_output(x, y);
|
||||
(output.id, output.global.persistent.scale.get())
|
||||
};
|
||||
if old_output != new_output || old_scale != new_scale {
|
||||
return;
|
||||
}
|
||||
let now = self.now_nsec();
|
||||
let started = self.animations.set_target(
|
||||
node_id,
|
||||
old,
|
||||
new,
|
||||
now,
|
||||
self.animations.duration_ms.get(),
|
||||
self.animations.curve.get(),
|
||||
);
|
||||
if started {
|
||||
self.damage(expand_damage_rect(
|
||||
old.union(new),
|
||||
self.theme.sizes.border_width.get().max(0),
|
||||
));
|
||||
self.ensure_animation_tick();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_animations_enabled(&self, enabled: bool) {
|
||||
if self.animations.enabled.replace(enabled) && !enabled {
|
||||
self.animations.clear();
|
||||
self.damage(self.root.extents.get());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_animation_duration_ms(&self, duration_ms: u32) {
|
||||
self.animations.duration_ms.set(duration_ms);
|
||||
}
|
||||
|
||||
pub fn set_animation_curve(&self, curve: u32) {
|
||||
self.animations
|
||||
.curve
|
||||
.set(AnimationCurve::from_config(curve));
|
||||
}
|
||||
|
||||
pub fn with_layout_animations<T>(&self, f: impl FnOnce() -> T) -> T {
|
||||
let prev_requested = self.layout_animations_requested.replace(true);
|
||||
let prev_active = self.layout_animations_active.replace(true);
|
||||
let res = f();
|
||||
self.layout_animations_requested.set(prev_requested);
|
||||
self.layout_animations_active.set(prev_active);
|
||||
res
|
||||
}
|
||||
|
||||
fn ensure_animation_tick(self: &Rc<Self>) {
|
||||
if self.animations.tick_is_active() {
|
||||
return;
|
||||
}
|
||||
let outputs: Vec<_> = self.root.outputs.lock().values().cloned().collect();
|
||||
if outputs.is_empty() {
|
||||
return;
|
||||
}
|
||||
let tick = Rc::new_cyclic(|weak| AnimationTick::new(self, weak));
|
||||
for output in &outputs {
|
||||
tick.attach(output);
|
||||
}
|
||||
self.animations.set_tick(tick);
|
||||
for output in &outputs {
|
||||
self.damage(output.global.pos.get());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn output_extents_changed(&self) {
|
||||
self.root.update_extents();
|
||||
for seat in self.globals.seats.lock().values() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue