commit 10f1e6fd496063286b46bbe33a9ce525f5e2f90c
parent 4a691496e764f7d9935454a3126745dad99be714
Author: Boris Chiou <boris.chiou@gmail.com>
Date: Tue, 16 Dec 2025 07:13:40 +0000
Bug 1817051 - Part 1: Add AnimationTimelinesController. r=layout-reviewers,hiro,dom-core,smaug
We wrap the list of timelines attached to the document into a controller,
so this makes it easier to support diffrerent types of timelines, e.g.
scroll-timeline.
We will add the implementation of scroll timelines in the following
patches.
Differential Revision: https://phabricator.services.mozilla.com/D269663
Diffstat:
10 files changed, 115 insertions(+), 20 deletions(-)
diff --git a/dom/animation/AnimationTimelinesController.cpp b/dom/animation/AnimationTimelinesController.cpp
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "AnimationTimelinesController.h"
+
+#include "mozilla/dom/DocumentTimeline.h"
+
+namespace mozilla::dom {
+
+void AnimationTimelinesController::AddDocumentTimeline(
+ DocumentTimeline& aTimeline) {
+ mTimelines.insertBack(&aTimeline);
+}
+
+void AnimationTimelinesController::WillRefresh() {
+ for (DocumentTimeline* tl :
+ ToTArray<AutoTArray<RefPtr<DocumentTimeline>, 32>>(mTimelines)) {
+ tl->WillRefresh();
+ }
+
+ // TODO: Add scroll timelines in the following patches.
+}
+
+void AnimationTimelinesController::UpdateLastRefreshDriverTime() {
+ for (DocumentTimeline* timeline : mTimelines) {
+ timeline->UpdateLastRefreshDriverTime();
+ }
+ // We don't use refresh driver time stamp for scroll timelines.
+}
+
+void AnimationTimelinesController::TriggerAllPendingAnimationsNow() {
+ for (DocumentTimeline* timeline : mTimelines) {
+ timeline->TriggerAllPendingAnimationsNow();
+ }
+
+ // FIXME: Bug 1805950. This is used for testing and printing. We may have to
+ // revisit there when supporting printing for scroll-timelines ()
+}
+
+void AnimationTimelinesController::UpdateHiddenByContentVisibility() {
+ for (AnimationTimeline* timeline : mTimelines) {
+ timeline->UpdateHiddenByContentVisibility();
+ }
+
+ // TODO: Add scroll timelines in the following patches.
+}
+
+} // namespace mozilla::dom
diff --git a/dom/animation/AnimationTimelinesController.h b/dom/animation/AnimationTimelinesController.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_AnimationTimelinesController_h
+#define mozilla_dom_AnimationTimelinesController_h
+
+#include "mozilla/LinkedList.h"
+
+namespace mozilla::dom {
+class DocumentTimeline;
+
+/**
+ * The controller which keeps track of all timelines in a document. So basically
+ * each document should have its own AnimationTimelinesController.
+ */
+class AnimationTimelinesController final {
+ public:
+ AnimationTimelinesController() = default;
+ ~AnimationTimelinesController() {
+ // We expect the timelines should remove themself from the controller
+ // already.
+ MOZ_ASSERT(mTimelines.isEmpty());
+ }
+
+ void AddDocumentTimeline(DocumentTimeline& aTimeline);
+
+ void WillRefresh();
+ void UpdateLastRefreshDriverTime();
+ void TriggerAllPendingAnimationsNow();
+ void UpdateHiddenByContentVisibility();
+
+ private:
+ LinkedList<DocumentTimeline> mTimelines;
+
+ // TODO: add scroll timelines (and view timelines)
+};
+
+} // namespace mozilla::dom
+
+#endif // mozilla_dom_AnimationTimelinesController_h
diff --git a/dom/animation/DocumentTimeline.cpp b/dom/animation/DocumentTimeline.cpp
@@ -47,7 +47,7 @@ DocumentTimeline::DocumentTimeline(Document* aDocument,
mDocument(aDocument),
mOriginTime(aOriginTime) {
if (mDocument) {
- mDocument->Timelines().insertBack(this);
+ mDocument->TimelinesController().AddDocumentTimeline(*this);
}
// Ensure mLastRefreshDriverTime is valid.
UpdateLastRefreshDriverTime();
diff --git a/dom/animation/moz.build b/dom/animation/moz.build
@@ -14,6 +14,7 @@ EXPORTS.mozilla.dom += [
"Animation.h",
"AnimationEffect.h",
"AnimationTimeline.h",
+ "AnimationTimelinesController.h",
"CSSAnimation.h",
"CSSPseudoElement.h",
"CSSTransition.h",
@@ -50,6 +51,7 @@ UNIFIED_SOURCES += [
"AnimationEventDispatcher.cpp",
"AnimationPerformanceWarning.cpp",
"AnimationTimeline.cpp",
+ "AnimationTimelinesController.cpp",
"AnimationUtils.cpp",
"CSSAnimation.cpp",
"CSSPseudoElement.cpp",
diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp
@@ -2567,8 +2567,6 @@ Document::~Document() {
mAnimationController->Disconnect();
}
- MOZ_ASSERT(mTimelines.isEmpty());
-
mParentDocument = nullptr;
// Kill the subdocument map, doing this will release its strong
@@ -20940,9 +20938,7 @@ RadioGroupContainer& Document::OwnedRadioGroupContainer() {
}
void Document::UpdateHiddenByContentVisibilityForAnimations() {
- for (AnimationTimeline* timeline : Timelines()) {
- timeline->UpdateHiddenByContentVisibility();
- }
+ mTimelinesController.UpdateHiddenByContentVisibility();
}
void Document::SetAllowDeclarativeShadowRoots(
diff --git a/dom/base/Document.h b/dom/base/Document.h
@@ -47,6 +47,7 @@
#include "mozilla/WeakPtr.h"
#include "mozilla/css/StylePreloadKind.h"
#include "mozilla/dom/AnimationFrameProvider.h"
+#include "mozilla/dom/AnimationTimelinesController.h"
#include "mozilla/dom/DocumentOrShadowRoot.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/EventTarget.h"
@@ -3224,7 +3225,12 @@ class Document : public nsINode,
using DocumentOrShadowRoot::GetElementsByTagNameNS;
DocumentTimeline* Timeline();
- LinkedList<DocumentTimeline>& Timelines() { return mTimelines; }
+ const AnimationTimelinesController& TimelinesController() const {
+ return mTimelinesController;
+ }
+ AnimationTimelinesController& TimelinesController() {
+ return mTimelinesController;
+ }
void UpdateHiddenByContentVisibilityForAnimations();
SVGSVGElement* GetSVGRootElement() const;
@@ -5564,8 +5570,11 @@ class Document : public nsINode,
// A set of responsive images keyed by address pointer.
nsTHashSet<HTMLImageElement*> mResponsiveContent;
+ // The default document timeline associated to this document.
RefPtr<DocumentTimeline> mDocumentTimeline;
- LinkedList<DocumentTimeline> mTimelines;
+ // The timeline controller which holds the timelines attached to this
+ // document.
+ AnimationTimelinesController mTimelinesController;
RefPtr<dom::ScriptLoader> mScriptLoader;
diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp
@@ -92,6 +92,7 @@
#include "mozilla/ViewportUtils.h"
#include "mozilla/css/ImageLoader.h"
#include "mozilla/dom/AncestorIterator.h"
+#include "mozilla/dom/AnimationTimelinesController.h"
#include "mozilla/dom/BrowserBridgeChild.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/BrowsingContext.h"
@@ -889,9 +890,7 @@ void PresShell::Init(nsPresContext* aPresContext) {
}
#endif
- for (DocumentTimeline* timelines : mDocument->Timelines()) {
- timelines->UpdateLastRefreshDriverTime();
- }
+ mDocument->TimelinesController().UpdateLastRefreshDriverTime();
// Get our activeness from the docShell.
ActivenessMaybeChanged();
diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp
@@ -60,6 +60,7 @@
#include "mozilla/TaskController.h"
#include "mozilla/VsyncDispatcher.h"
#include "mozilla/VsyncTaskManager.h"
+#include "mozilla/dom/AnimationTimelinesController.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/CallbackDebuggerNotification.h"
#include "mozilla/dom/ContentChild.h"
@@ -2039,11 +2040,7 @@ void nsRefreshDriver::UpdateRemoteFrameEffects() {
}
static void UpdateAndReduceAnimations(Document& aDocument) {
- for (DocumentTimeline* tl :
- ToTArray<AutoTArray<RefPtr<DocumentTimeline>, 32>>(
- aDocument.Timelines())) {
- tl->WillRefresh();
- }
+ aDocument.TimelinesController().WillRefresh();
if (nsPresContext* pc = aDocument.GetPresContext()) {
if (pc->EffectCompositor()->NeedsReducing()) {
diff --git a/layout/printing/nsPrintJob.cpp b/layout/printing/nsPrintJob.cpp
@@ -15,6 +15,7 @@
#include "mozilla/PresShellInlines.h"
#include "mozilla/StaticPrefs_print.h"
#include "mozilla/Try.h"
+#include "mozilla/dom/AnimationTimelinesController.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/CustomEvent.h"
@@ -1374,9 +1375,7 @@ nsresult nsPrintJob::ReflowPrintObject(const UniquePtr<nsPrintObject>& aPO) {
}
}
// Make sure animations are active.
- for (DocumentTimeline* tl : aPO->mDocument->Timelines()) {
- tl->TriggerAllPendingAnimationsNow();
- }
+ aPO->mDocument->TimelinesController().TriggerAllPendingAnimationsNow();
// Process the reflow event Initialize posted
presShell->FlushPendingNotifications(FlushType::Layout);
aPO->mDocument->UpdateRemoteFrameEffects();
diff --git a/layout/style/ServoBindings.toml b/layout/style/ServoBindings.toml
@@ -308,7 +308,6 @@ opaque-types = [
"std::unique_ptr.*",
"std::.*::unique_ptr.*",
"mozilla::dom::FrameRequestManager",
-
"mozilla::dom::Touch",
"mozilla::dom::Sequence",
"mozilla::SmallPointerArray",