mirror of https://github.com/linebender/xilem
Implement update_anim pass (#539)
This is part of the Pass Specification RFC: https://github.com/linebender/rfcs/pull/7 --------- Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
This commit is contained in:
parent
3726e91a48
commit
2fa8a055bd
|
@ -450,6 +450,7 @@ impl_context_method!(MutateCtx<'_>, EventCtx<'_>, LifeCycleCtx<'_>, {
|
|||
pub fn request_anim_frame(&mut self) {
|
||||
trace!("request_anim_frame");
|
||||
self.widget_state.request_anim = true;
|
||||
self.widget_state.needs_anim = true;
|
||||
}
|
||||
|
||||
/// Indicate that your children have changed.
|
||||
|
|
|
@ -230,3 +230,60 @@ pub(crate) fn run_update_scroll_pass(root: &mut RenderRoot) {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------
|
||||
|
||||
fn update_anim_for_widget(
|
||||
global_state: &mut RenderRootState,
|
||||
mut widget: ArenaMut<'_, Box<dyn Widget>>,
|
||||
mut state: ArenaMut<'_, WidgetState>,
|
||||
elapsed_ns: u64,
|
||||
) {
|
||||
let _span = widget.item.make_trace_span().entered();
|
||||
|
||||
if !state.item.needs_anim {
|
||||
return;
|
||||
}
|
||||
state.item.needs_anim = false;
|
||||
|
||||
// Most passes reset their `needs` and `request` flags after the call to
|
||||
// the widget method, but it's valid and expected for `request_anim` to be
|
||||
// set in response to `AnimFrame`.
|
||||
if state.item.request_anim {
|
||||
state.item.request_anim = false;
|
||||
let mut ctx = LifeCycleCtx {
|
||||
global_state,
|
||||
widget_state: state.item,
|
||||
widget_state_children: state.children.reborrow_mut(),
|
||||
widget_children: widget.children.reborrow_mut(),
|
||||
};
|
||||
widget
|
||||
.item
|
||||
.lifecycle(&mut ctx, &LifeCycle::AnimFrame(elapsed_ns));
|
||||
}
|
||||
|
||||
let id = state.item.id;
|
||||
let parent_state = state.item;
|
||||
recurse_on_children(
|
||||
id,
|
||||
widget.reborrow_mut(),
|
||||
state.children,
|
||||
|widget, mut state| {
|
||||
update_anim_for_widget(global_state, widget, state.reborrow_mut(), elapsed_ns);
|
||||
parent_state.merge_up(state.item);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Run the animation pass.
|
||||
pub(crate) fn run_update_anim_pass(root: &mut RenderRoot, elapsed_ns: u64) {
|
||||
let _span = info_span!("update_anim").entered();
|
||||
|
||||
let (root_widget, mut root_state) = root.widget_arena.get_pair_mut(root.root.id());
|
||||
update_anim_for_widget(
|
||||
&mut root.state,
|
||||
root_widget,
|
||||
root_state.reborrow_mut(),
|
||||
elapsed_ns,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ use crate::passes::layout::root_layout;
|
|||
use crate::passes::mutate::{mutate_widget, run_mutate_pass};
|
||||
use crate::passes::paint::root_paint;
|
||||
use crate::passes::update::{
|
||||
run_update_disabled_pass, run_update_pointer_pass, run_update_scroll_pass,
|
||||
run_update_anim_pass, run_update_disabled_pass, run_update_pointer_pass, run_update_scroll_pass,
|
||||
};
|
||||
use crate::text::TextBrush;
|
||||
use crate::tree_arena::TreeArena;
|
||||
|
@ -208,12 +208,17 @@ impl RenderRoot {
|
|||
// See https://github.com/linebender/druid/issues/85 for discussion.
|
||||
let last = self.last_anim.take();
|
||||
let elapsed_ns = last.map(|t| now.duration_since(t).as_nanos()).unwrap_or(0) as u64;
|
||||
let root_state = self.root_state();
|
||||
if root_state.request_anim {
|
||||
root_state.request_anim = false;
|
||||
self.root_lifecycle(LifeCycle::AnimFrame(elapsed_ns));
|
||||
self.last_anim = Some(now);
|
||||
}
|
||||
|
||||
run_update_anim_pass(self, elapsed_ns);
|
||||
|
||||
let mut root_state = self.widget_arena.get_state_mut(self.root.id()).item.clone();
|
||||
self.post_event_processing(&mut root_state);
|
||||
|
||||
// If this animation will continue, store the time.
|
||||
// If a new animation starts, then it will have zero reported elapsed time.
|
||||
let animation_continues = root_state.needs_anim;
|
||||
self.last_anim = animation_continues.then_some(now);
|
||||
|
||||
Handled::Yes
|
||||
}
|
||||
WindowEvent::RebuildAccessTree => {
|
||||
|
@ -272,8 +277,6 @@ impl RenderRoot {
|
|||
// TODO - Xilem's reconciliation logic will have to be called
|
||||
// by the function that calls this
|
||||
|
||||
// TODO - if root widget's request_anim is still set by the
|
||||
// time this is called, emit a warning
|
||||
if self.root_state().needs_layout {
|
||||
self.root_layout();
|
||||
}
|
||||
|
|
|
@ -333,12 +333,10 @@ impl<W: Widget> WidgetPod<W> {
|
|||
|
||||
true
|
||||
}
|
||||
LifeCycle::AnimFrame(_) => {
|
||||
state.request_anim = false;
|
||||
true
|
||||
}
|
||||
// Routing DisabledChanged has been moved to the update_disabled pass
|
||||
LifeCycle::DisabledChanged(_) => false,
|
||||
// Animations have been moved to the update_anim pass
|
||||
LifeCycle::AnimFrame(_) => false,
|
||||
LifeCycle::BuildFocusChain => {
|
||||
if state.update_focus_chain {
|
||||
// Replace has_focus to check if the value changed in the meantime
|
||||
|
|
|
@ -99,8 +99,10 @@ pub struct WidgetState {
|
|||
/// The accessibility method must be called on this widget or a descendant
|
||||
pub(crate) needs_accessibility: bool,
|
||||
|
||||
/// Any descendant has requested an animation frame.
|
||||
/// An animation must run on this widget
|
||||
pub(crate) request_anim: bool,
|
||||
/// An animation must run on this widget or a descendant
|
||||
pub(crate) needs_anim: bool,
|
||||
|
||||
/// This widget or a descendant changed its `explicitly_disabled` value
|
||||
pub(crate) needs_update_disabled: bool,
|
||||
|
@ -174,6 +176,7 @@ impl WidgetState {
|
|||
needs_accessibility: true,
|
||||
has_focus: false,
|
||||
request_anim: true,
|
||||
needs_anim: true,
|
||||
needs_update_disabled: true,
|
||||
focus_chain: Vec::new(),
|
||||
children_changed: true,
|
||||
|
@ -197,11 +200,12 @@ impl WidgetState {
|
|||
needs_layout: false,
|
||||
request_compose: false,
|
||||
needs_compose: false,
|
||||
needs_paint: false,
|
||||
request_paint: false,
|
||||
needs_paint: false,
|
||||
request_accessibility: false,
|
||||
needs_accessibility: false,
|
||||
request_anim: false,
|
||||
needs_anim: false,
|
||||
needs_update_disabled: false,
|
||||
children_changed: false,
|
||||
update_focus_chain: false,
|
||||
|
@ -231,7 +235,7 @@ impl WidgetState {
|
|||
self.needs_layout |= child_state.needs_layout;
|
||||
self.needs_compose |= child_state.needs_compose;
|
||||
self.needs_paint |= child_state.needs_paint;
|
||||
self.request_anim |= child_state.request_anim;
|
||||
self.needs_anim |= child_state.needs_anim;
|
||||
self.needs_accessibility |= child_state.needs_accessibility;
|
||||
self.needs_update_disabled |= child_state.needs_update_disabled;
|
||||
self.has_focus |= child_state.has_focus;
|
||||
|
|
Loading…
Reference in New Issue