mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Auto merge of #26407 - mrobinson:animation-restyle-model, r=jdm
Have animations more closely match the HTML spec These two commits do two major things: **Have animations ticks trigger a restyle**: This corrects synchronization issues with animations, where the values used in layout are out of sync with what is returned by `getComputedStyle`. **Tick the animation timer in script according to spec**: This greatly reduces the flakiness of animation and transitions tests. Fixes #13865. <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #13865 <!-- Either: --> - [x] There are tests for these changes OR - [ ] These changes do not require tests because ___ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
commit
b290ad95c1
76 changed files with 1389 additions and 3701 deletions
|
@ -2,6 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::animation_timeline::AnimationTimeline;
|
||||
use crate::document_loader::{DocumentLoader, LoadType};
|
||||
use crate::dom::attr::Attr;
|
||||
use crate::dom::beforeunloadevent::BeforeUnloadEvent;
|
||||
|
@ -380,6 +381,9 @@ pub struct Document {
|
|||
csp_list: DomRefCell<Option<CspList>>,
|
||||
/// https://w3c.github.io/slection-api/#dfn-selection
|
||||
selection: MutNullableDom<Selection>,
|
||||
/// A timeline for animations which is used for synchronizing animations.
|
||||
/// https://drafts.csswg.org/web-animations/#timeline
|
||||
animation_timeline: DomRefCell<AnimationTimeline>,
|
||||
}
|
||||
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
|
@ -2904,6 +2908,11 @@ impl Document {
|
|||
dirty_webgl_contexts: DomRefCell::new(HashMap::new()),
|
||||
csp_list: DomRefCell::new(None),
|
||||
selection: MutNullableDom::new(None),
|
||||
animation_timeline: if pref!(layout.animations.test.enabled) {
|
||||
DomRefCell::new(AnimationTimeline::new_for_testing())
|
||||
} else {
|
||||
DomRefCell::new(AnimationTimeline::new())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3605,6 +3614,18 @@ impl Document {
|
|||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn advance_animation_timeline_for_testing(&self, delta: f64) {
|
||||
self.animation_timeline.borrow_mut().advance_specific(delta);
|
||||
}
|
||||
|
||||
pub fn update_animation_timeline(&self) {
|
||||
self.animation_timeline.borrow_mut().update();
|
||||
}
|
||||
|
||||
pub fn current_animation_timeline_value(&self) -> f64 {
|
||||
self.animation_timeline.borrow().current_value()
|
||||
}
|
||||
}
|
||||
|
||||
impl Element {
|
||||
|
|
|
@ -60,8 +60,8 @@ use mime::{self, Mime};
|
|||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::image::base::{Image, ImageMetadata};
|
||||
use net_traits::image_cache::{
|
||||
CanRequestImages, CorsStatus, ImageCache, ImageCacheResult, ImageOrMetadataAvailable,
|
||||
ImageResponse, PendingImageId, PendingImageResponse, UsePlaceholder,
|
||||
CorsStatus, ImageCache, ImageCacheResult, ImageOrMetadataAvailable, ImageResponse,
|
||||
PendingImageId, PendingImageResponse, UsePlaceholder,
|
||||
};
|
||||
use net_traits::request::{CorsSettings, Destination, Initiator, RequestBuilder};
|
||||
use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError};
|
||||
|
@ -326,7 +326,6 @@ impl HTMLImageElement {
|
|||
cors_setting_for_element(self.upcast()),
|
||||
sender,
|
||||
UsePlaceholder::Yes,
|
||||
CanRequestImages::Yes,
|
||||
);
|
||||
|
||||
match cache_result {
|
||||
|
@ -1107,7 +1106,6 @@ impl HTMLImageElement {
|
|||
cors_setting_for_element(self.upcast()),
|
||||
sender,
|
||||
UsePlaceholder::No,
|
||||
CanRequestImages::Yes,
|
||||
);
|
||||
|
||||
match cache_result {
|
||||
|
|
|
@ -27,8 +27,8 @@ use html5ever::{LocalName, Prefix};
|
|||
use ipc_channel::ipc;
|
||||
use ipc_channel::router::ROUTER;
|
||||
use net_traits::image_cache::{
|
||||
CanRequestImages, ImageCache, ImageCacheResult, ImageOrMetadataAvailable, ImageResponse,
|
||||
PendingImageId, UsePlaceholder,
|
||||
ImageCache, ImageCacheResult, ImageOrMetadataAvailable, ImageResponse, PendingImageId,
|
||||
UsePlaceholder,
|
||||
};
|
||||
use net_traits::request::{CredentialsMode, Destination, RequestBuilder};
|
||||
use net_traits::{
|
||||
|
@ -163,7 +163,6 @@ impl HTMLVideoElement {
|
|||
None,
|
||||
sender,
|
||||
UsePlaceholder::No,
|
||||
CanRequestImages::Yes,
|
||||
);
|
||||
|
||||
match cache_result {
|
||||
|
|
|
@ -1054,8 +1054,8 @@ impl TestBindingMethods for TestBinding {
|
|||
}
|
||||
}
|
||||
|
||||
fn AdvanceClock(&self, ms: i32, tick: bool) {
|
||||
self.global().as_window().advance_animation_clock(ms, tick);
|
||||
fn AdvanceClock(&self, ms: i32) {
|
||||
self.global().as_window().advance_animation_clock(ms);
|
||||
}
|
||||
|
||||
fn Panic(&self) {
|
||||
|
|
|
@ -517,7 +517,7 @@ interface TestBinding {
|
|||
[Pref="dom.testbinding.prefcontrolled.enabled"]
|
||||
const unsigned short prefControlledConstDisabled = 0;
|
||||
[Pref="layout.animations.test.enabled"]
|
||||
void advanceClock(long millis, optional boolean forceLayoutTick = true);
|
||||
void advanceClock(long millis);
|
||||
|
||||
[Pref="dom.testbinding.prefcontrolled2.enabled"]
|
||||
readonly attribute boolean prefControlledAttributeEnabled;
|
||||
|
|
|
@ -173,6 +173,7 @@ pub enum ReflowReason {
|
|||
IFrameLoadEvent,
|
||||
MissingExplicitReflow,
|
||||
ElementStateChanged,
|
||||
PendingReflow,
|
||||
}
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -1544,16 +1545,13 @@ impl Window {
|
|||
)
|
||||
}
|
||||
|
||||
/// Advances the layout animation clock by `delta` milliseconds, and then
|
||||
/// forces a reflow if `tick` is true.
|
||||
pub fn advance_animation_clock(&self, delta: i32, tick: bool) {
|
||||
self.layout_chan
|
||||
.send(Msg::AdvanceClockMs(
|
||||
delta,
|
||||
tick,
|
||||
self.origin().immutable().clone(),
|
||||
))
|
||||
.unwrap();
|
||||
/// Prepares to tick animations and then does a reflow which also advances the
|
||||
/// layout animation clock.
|
||||
pub fn advance_animation_clock(&self, delta: i32) {
|
||||
let pipeline_id = self.upcast::<GlobalScope>().pipeline_id();
|
||||
self.Document()
|
||||
.advance_animation_timeline_for_testing(delta as f64 / 1000.);
|
||||
ScriptThread::handle_tick_all_animations_for_testing(pipeline_id);
|
||||
}
|
||||
|
||||
/// Reflows the page unconditionally if possible and not suppressed. This
|
||||
|
@ -1626,9 +1624,8 @@ impl Window {
|
|||
|
||||
// If this reflow is for display, ensure webgl canvases are composited with
|
||||
// up-to-date contents.
|
||||
match reflow_goal {
|
||||
ReflowGoal::Full => document.flush_dirty_canvases(),
|
||||
ReflowGoal::TickAnimations | ReflowGoal::LayoutQuery(..) => {},
|
||||
if for_display {
|
||||
document.flush_dirty_canvases();
|
||||
}
|
||||
|
||||
// Send new document and relevant styles to layout.
|
||||
|
@ -1645,6 +1642,7 @@ impl Window {
|
|||
script_join_chan: join_chan,
|
||||
dom_count: document.dom_count(),
|
||||
pending_restyles: document.drain_pending_restyles(),
|
||||
animation_timeline_value: document.current_animation_timeline_value(),
|
||||
};
|
||||
|
||||
self.layout_chan
|
||||
|
@ -2446,8 +2444,7 @@ fn should_move_clip_rect(clip_rect: UntypedRect<Au>, new_viewport: UntypedRect<f
|
|||
}
|
||||
|
||||
fn debug_reflow_events(id: PipelineId, reflow_goal: &ReflowGoal, reason: &ReflowReason) {
|
||||
let mut debug_msg = format!("**** pipeline={}", id);
|
||||
debug_msg.push_str(match *reflow_goal {
|
||||
let goal_string = match *reflow_goal {
|
||||
ReflowGoal::Full => "\tFull",
|
||||
ReflowGoal::TickAnimations => "\tTickAnimations",
|
||||
ReflowGoal::LayoutQuery(ref query_msg, _) => match query_msg {
|
||||
|
@ -2464,32 +2461,9 @@ fn debug_reflow_events(id: PipelineId, reflow_goal: &ReflowGoal, reason: &Reflow
|
|||
&QueryMsg::ElementInnerTextQuery(_) => "\tElementInnerTextQuery",
|
||||
&QueryMsg::InnerWindowDimensionsQuery(_) => "\tInnerWindowDimensionsQuery",
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
debug_msg.push_str(match *reason {
|
||||
ReflowReason::CachedPageNeededReflow => "\tCachedPageNeededReflow",
|
||||
ReflowReason::RefreshTick => "\tRefreshTick",
|
||||
ReflowReason::FirstLoad => "\tFirstLoad",
|
||||
ReflowReason::KeyEvent => "\tKeyEvent",
|
||||
ReflowReason::MouseEvent => "\tMouseEvent",
|
||||
ReflowReason::Query => "\tQuery",
|
||||
ReflowReason::Timer => "\tTimer",
|
||||
ReflowReason::Viewport => "\tViewport",
|
||||
ReflowReason::WindowResize => "\tWindowResize",
|
||||
ReflowReason::DOMContentLoaded => "\tDOMContentLoaded",
|
||||
ReflowReason::DocumentLoaded => "\tDocumentLoaded",
|
||||
ReflowReason::StylesheetLoaded => "\tStylesheetLoaded",
|
||||
ReflowReason::ImageLoaded => "\tImageLoaded",
|
||||
ReflowReason::RequestAnimationFrame => "\tRequestAnimationFrame",
|
||||
ReflowReason::WebFontLoaded => "\tWebFontLoaded",
|
||||
ReflowReason::WorkletLoaded => "\tWorkletLoaded",
|
||||
ReflowReason::FramedContentChanged => "\tFramedContentChanged",
|
||||
ReflowReason::IFrameLoadEvent => "\tIFrameLoadEvent",
|
||||
ReflowReason::MissingExplicitReflow => "\tMissingExplicitReflow",
|
||||
ReflowReason::ElementStateChanged => "\tElementStateChanged",
|
||||
});
|
||||
|
||||
println!("{}", debug_msg);
|
||||
println!("**** pipeline={}\t{}\t{:?}", id, goal_string, reason);
|
||||
}
|
||||
|
||||
impl Window {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue