2021-12-08 04:16:28 +03:00
|
|
|
/* -*- 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 "ScrollTimeline.h"
|
|
|
|
|
|
|
|
#include "mozilla/dom/Animation.h"
|
2022-04-21 20:05:19 +03:00
|
|
|
#include "mozilla/dom/ElementInlines.h"
|
2021-12-08 04:16:31 +03:00
|
|
|
#include "mozilla/AnimationTarget.h"
|
2022-04-05 21:48:17 +03:00
|
|
|
#include "mozilla/DisplayPortUtils.h"
|
2023-03-16 23:00:00 +03:00
|
|
|
#include "mozilla/ElementAnimationData.h"
|
Bug 1676791 - Part 9: Define Scroller to handle the source of ScrollTimeline. r=emilio
Per spec, "auto" represents the scrolling element of the document.
However, the scrolling element might be changed, based on the layout, in
quirks mode. Besides, the content of the root scroll frame is the root
element, instead of the scrolling element (e.g. body element) in both
standard and quirks modes. So now we define a special type, Scroller, to
represent the source of scroll-timeline, and use its |mType| to decide
which scroll frame we would like to use. In addition, hope this change let
us easier to implement nearest scroller.
Note: for auto scroller, we register this ScrollTimeline to the root
element, in both modes. Once we expose ScrollTimeline interface to the
script, we can rely on the |mType| of Scroller to return the correct
source element, whether it is scrolling element or not.
Differential Revision: https://phabricator.services.mozilla.com/D131578
2021-12-08 04:16:31 +03:00
|
|
|
#include "mozilla/PresShell.h"
|
2021-12-08 04:16:29 +03:00
|
|
|
#include "nsIFrame.h"
|
|
|
|
#include "nsIScrollableFrame.h"
|
|
|
|
#include "nsLayoutUtils.h"
|
2021-12-08 04:16:28 +03:00
|
|
|
|
|
|
|
namespace mozilla::dom {
|
|
|
|
|
2021-12-08 04:16:28 +03:00
|
|
|
// ---------------------------------
|
|
|
|
// Methods of ScrollTimeline
|
|
|
|
// ---------------------------------
|
|
|
|
|
2021-12-08 04:16:28 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(ScrollTimeline)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ScrollTimeline,
|
|
|
|
AnimationTimeline)
|
2021-12-08 04:16:28 +03:00
|
|
|
tmp->Teardown();
|
2021-12-08 04:16:28 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
|
Bug 1676791 - Part 9: Define Scroller to handle the source of ScrollTimeline. r=emilio
Per spec, "auto" represents the scrolling element of the document.
However, the scrolling element might be changed, based on the layout, in
quirks mode. Besides, the content of the root scroll frame is the root
element, instead of the scrolling element (e.g. body element) in both
standard and quirks modes. So now we define a special type, Scroller, to
represent the source of scroll-timeline, and use its |mType| to decide
which scroll frame we would like to use. In addition, hope this change let
us easier to implement nearest scroller.
Note: for auto scroller, we register this ScrollTimeline to the root
element, in both modes. Once we expose ScrollTimeline interface to the
script, we can rely on the |mType| of Scroller to return the correct
source element, whether it is scrolling element or not.
Differential Revision: https://phabricator.services.mozilla.com/D131578
2021-12-08 04:16:31 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSource.mElement)
|
2021-12-08 04:16:28 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ScrollTimeline,
|
|
|
|
AnimationTimeline)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
|
Bug 1676791 - Part 9: Define Scroller to handle the source of ScrollTimeline. r=emilio
Per spec, "auto" represents the scrolling element of the document.
However, the scrolling element might be changed, based on the layout, in
quirks mode. Besides, the content of the root scroll frame is the root
element, instead of the scrolling element (e.g. body element) in both
standard and quirks modes. So now we define a special type, Scroller, to
represent the source of scroll-timeline, and use its |mType| to decide
which scroll frame we would like to use. In addition, hope this change let
us easier to implement nearest scroller.
Note: for auto scroller, we register this ScrollTimeline to the root
element, in both modes. Once we expose ScrollTimeline interface to the
script, we can rely on the |mType| of Scroller to return the correct
source element, whether it is scrolling element or not.
Differential Revision: https://phabricator.services.mozilla.com/D131578
2021-12-08 04:16:31 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSource.mElement)
|
2021-12-08 04:16:28 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(ScrollTimeline,
|
|
|
|
AnimationTimeline)
|
|
|
|
|
2022-02-08 21:35:23 +03:00
|
|
|
ScrollTimeline::ScrollTimeline(Document* aDocument, const Scroller& aScroller,
|
2022-04-21 20:05:18 +03:00
|
|
|
StyleScrollAxis aAxis)
|
2022-11-29 16:34:17 +03:00
|
|
|
: AnimationTimeline(aDocument->GetParentObject(),
|
|
|
|
aDocument->GetScopeObject()->GetRTPCallerType()),
|
2021-12-08 04:16:28 +03:00
|
|
|
mDocument(aDocument),
|
|
|
|
mSource(aScroller),
|
2022-04-21 20:05:18 +03:00
|
|
|
mAxis(aAxis) {
|
2021-12-08 04:16:28 +03:00
|
|
|
MOZ_ASSERT(aDocument);
|
2023-03-08 02:57:53 +03:00
|
|
|
RegisterWithScrollSource();
|
2022-06-13 23:26:46 +03:00
|
|
|
}
|
|
|
|
|
2023-04-12 23:52:02 +03:00
|
|
|
/* static */ std::pair<const Element*, PseudoStyleType>
|
|
|
|
ScrollTimeline::FindNearestScroller(Element* aSubject,
|
|
|
|
PseudoStyleType aPseudoType) {
|
2023-03-08 02:57:53 +03:00
|
|
|
MOZ_ASSERT(aSubject);
|
2023-03-16 23:00:00 +03:00
|
|
|
Element* subject =
|
|
|
|
AnimationUtils::GetElementForRestyle(aSubject, aPseudoType);
|
|
|
|
|
|
|
|
Element* curr = subject->GetFlattenedTreeParentElement();
|
|
|
|
Element* root = subject->OwnerDoc()->GetDocumentElement();
|
2023-03-08 02:57:53 +03:00
|
|
|
while (curr && curr != root) {
|
|
|
|
const ComputedStyle* style = Servo_Element_GetMaybeOutOfDateStyle(curr);
|
|
|
|
MOZ_ASSERT(style, "The ancestor should be styled.");
|
|
|
|
if (style->StyleDisplay()->IsScrollableOverflow()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
curr = curr->GetFlattenedTreeParentElement();
|
|
|
|
}
|
|
|
|
// If there is no scroll container, we use root.
|
2023-03-16 23:00:00 +03:00
|
|
|
if (!curr) {
|
|
|
|
return {root, PseudoStyleType::NotPseudo};
|
|
|
|
}
|
|
|
|
return AnimationUtils::GetElementPseudoPair(curr);
|
2023-03-08 02:57:53 +03:00
|
|
|
}
|
|
|
|
|
2022-04-21 20:05:19 +03:00
|
|
|
/* static */
|
2023-03-08 02:57:53 +03:00
|
|
|
already_AddRefed<ScrollTimeline> ScrollTimeline::MakeAnonymous(
|
2022-04-21 20:05:19 +03:00
|
|
|
Document* aDocument, const NonOwningAnimationTarget& aTarget,
|
|
|
|
StyleScrollAxis aAxis, StyleScroller aScroller) {
|
|
|
|
MOZ_ASSERT(aTarget);
|
|
|
|
Scroller scroller;
|
|
|
|
switch (aScroller) {
|
|
|
|
case StyleScroller::Root:
|
|
|
|
scroller = Scroller::Root(aTarget.mElement->OwnerDoc());
|
|
|
|
break;
|
2023-03-08 02:57:53 +03:00
|
|
|
|
2022-04-21 20:05:19 +03:00
|
|
|
case StyleScroller::Nearest: {
|
2023-03-16 23:00:00 +03:00
|
|
|
auto [element, pseudo] =
|
|
|
|
FindNearestScroller(aTarget.mElement, aTarget.mPseudoType);
|
|
|
|
scroller = Scroller::Nearest(const_cast<Element*>(element), pseudo);
|
2023-03-08 02:57:53 +03:00
|
|
|
break;
|
2022-04-21 20:05:19 +03:00
|
|
|
}
|
2023-05-05 00:35:14 +03:00
|
|
|
case StyleScroller::SelfElement:
|
|
|
|
scroller = Scroller::Self(aTarget.mElement, aTarget.mPseudoType);
|
|
|
|
break;
|
2022-04-21 20:05:19 +03:00
|
|
|
}
|
2023-03-08 02:57:53 +03:00
|
|
|
|
2023-05-05 00:35:14 +03:00
|
|
|
// Each use of scroll() corresponds to its own instance of ScrollTimeline in
|
|
|
|
// the Web Animations API, even if multiple elements use scroll() to refer to
|
|
|
|
// the same scroll container with the same arguments.
|
|
|
|
// https://drafts.csswg.org/scroll-animations-1/#scroll-notation
|
2023-03-08 02:57:53 +03:00
|
|
|
return MakeAndAddRef<ScrollTimeline>(aDocument, scroller, aAxis);
|
2022-04-21 20:05:19 +03:00
|
|
|
}
|
|
|
|
|
2023-03-08 02:57:53 +03:00
|
|
|
/* static*/ already_AddRefed<ScrollTimeline> ScrollTimeline::MakeNamed(
|
|
|
|
Document* aDocument, Element* aReferenceElement,
|
2023-03-16 23:00:00 +03:00
|
|
|
PseudoStyleType aPseudoType, const StyleScrollTimeline& aStyleTimeline) {
|
2022-06-13 23:26:45 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2023-03-08 02:57:53 +03:00
|
|
|
|
2023-03-16 23:00:00 +03:00
|
|
|
Scroller scroller = Scroller::Named(aReferenceElement, aPseudoType);
|
2023-03-08 02:57:53 +03:00
|
|
|
return MakeAndAddRef<ScrollTimeline>(aDocument, std::move(scroller),
|
|
|
|
aStyleTimeline.GetAxis());
|
2022-06-13 23:26:45 +03:00
|
|
|
}
|
|
|
|
|
2021-12-08 04:16:29 +03:00
|
|
|
Nullable<TimeDuration> ScrollTimeline::GetCurrentTimeAsDuration() const {
|
2022-04-05 21:48:16 +03:00
|
|
|
// If no layout box, this timeline is inactive.
|
|
|
|
if (!mSource || !mSource.mElement->GetPrimaryFrame()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if this is not a scroller container, this timeline is inactive.
|
Bug 1676791 - Part 9: Define Scroller to handle the source of ScrollTimeline. r=emilio
Per spec, "auto" represents the scrolling element of the document.
However, the scrolling element might be changed, based on the layout, in
quirks mode. Besides, the content of the root scroll frame is the root
element, instead of the scrolling element (e.g. body element) in both
standard and quirks modes. So now we define a special type, Scroller, to
represent the source of scroll-timeline, and use its |mType| to decide
which scroll frame we would like to use. In addition, hope this change let
us easier to implement nearest scroller.
Note: for auto scroller, we register this ScrollTimeline to the root
element, in both modes. Once we expose ScrollTimeline interface to the
script, we can rely on the |mType| of Scroller to return the correct
source element, whether it is scrolling element or not.
Differential Revision: https://phabricator.services.mozilla.com/D131578
2021-12-08 04:16:31 +03:00
|
|
|
const nsIScrollableFrame* scrollFrame = GetScrollFrame();
|
2022-04-05 21:48:16 +03:00
|
|
|
if (!scrollFrame) {
|
2021-12-08 04:16:29 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-04-05 21:48:16 +03:00
|
|
|
const auto orientation = Axis();
|
|
|
|
|
2023-02-16 04:25:56 +03:00
|
|
|
// If there is no scrollable overflow, then the ScrollTimeline is inactive.
|
|
|
|
// https://drafts.csswg.org/scroll-animations-1/#scrolltimeline-interface
|
2021-12-08 04:16:29 +03:00
|
|
|
if (!scrollFrame->GetAvailableScrollingDirections().contains(orientation)) {
|
2023-02-16 04:25:56 +03:00
|
|
|
return nullptr;
|
2021-12-08 04:16:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
const bool isHorizontal = orientation == layers::ScrollDirection::eHorizontal;
|
Bug 1737920 - Part 2: Calculate offsets for ViewTimeline. r=emilio
The definition of at-progress-timeline-boundary is updated to use the
unconstructed current timeline if we have, so we update the
implementation as well. It is necessary for view-timeline.
Basically, we use offsets to control the animation progress.
For scroll-timeline, it's simply 0 to the scroll range.
For view-timeline, its progress is between 0% and 100% if the subject element
is in the view. Otherwise, its progress is outside the range.
This patch series doesn't take Named Timeline Range into account because
I expect we will handle them in different bugs, e.g. support the keyframe
selector with `<timeline-range-name>` in Bug 1823509.
So only the basic scenario is implemented:
1. 0% progress represents the position at which the start border edge of the
element’s principal box coincides with the end edge of its view progress
visibility range. (e.g. the top of the subject touches the bottom of
the scrollport, for the vertical axis.)
2. 100% progress represents the position at which the end border edge of the
element’s principal box coincides with the start edge of its view progress
visibility range. (e.g. the bottom of the subject touches the top of
the scrollport, for the vertical axis.)
So basically, it is equal to `cover` range (i.e. we run the animation
when the scrollport covers the subject), per
https://drafts.csswg.org/scroll-animations-1/#valdef-animation-timeline-range-cover
Note: OMTA will be disabled for view timeline in the next patch. So we
implement this only on the main thread.
Differential Revision: https://phabricator.services.mozilla.com/D170002
2023-04-12 23:52:02 +03:00
|
|
|
const nsPoint& scrollPosition = scrollFrame->GetScrollPosition();
|
|
|
|
const Maybe<ScrollOffsets>& offsets =
|
|
|
|
ComputeOffsets(scrollFrame, orientation);
|
|
|
|
if (!offsets) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2021-12-08 04:16:29 +03:00
|
|
|
|
Bug 1737920 - Part 2: Calculate offsets for ViewTimeline. r=emilio
The definition of at-progress-timeline-boundary is updated to use the
unconstructed current timeline if we have, so we update the
implementation as well. It is necessary for view-timeline.
Basically, we use offsets to control the animation progress.
For scroll-timeline, it's simply 0 to the scroll range.
For view-timeline, its progress is between 0% and 100% if the subject element
is in the view. Otherwise, its progress is outside the range.
This patch series doesn't take Named Timeline Range into account because
I expect we will handle them in different bugs, e.g. support the keyframe
selector with `<timeline-range-name>` in Bug 1823509.
So only the basic scenario is implemented:
1. 0% progress represents the position at which the start border edge of the
element’s principal box coincides with the end edge of its view progress
visibility range. (e.g. the top of the subject touches the bottom of
the scrollport, for the vertical axis.)
2. 100% progress represents the position at which the end border edge of the
element’s principal box coincides with the start edge of its view progress
visibility range. (e.g. the bottom of the subject touches the top of
the scrollport, for the vertical axis.)
So basically, it is equal to `cover` range (i.e. we run the animation
when the scrollport covers the subject), per
https://drafts.csswg.org/scroll-animations-1/#valdef-animation-timeline-range-cover
Note: OMTA will be disabled for view timeline in the next patch. So we
implement this only on the main thread.
Differential Revision: https://phabricator.services.mozilla.com/D170002
2023-04-12 23:52:02 +03:00
|
|
|
// Note: For RTL, scrollPosition.x or scrollPosition.y may be negative,
|
|
|
|
// e.g. the range of its value is [0, -range], so we have to use the
|
|
|
|
// absolute value.
|
|
|
|
nscoord position =
|
|
|
|
std::abs(isHorizontal ? scrollPosition.x : scrollPosition.y);
|
|
|
|
double progress = static_cast<double>(position - offsets->mStart) /
|
|
|
|
static_cast<double>(offsets->mEnd - offsets->mStart);
|
2021-12-08 04:16:29 +03:00
|
|
|
return TimeDuration::FromMilliseconds(progress *
|
Bug 1744850 - Drop ScrollTimeline:sTiming and introduce a normalized timing. r=birtles
`sTiming` is a hack and I believe animation-delay,
animation-iteration-count, animation-direction, and animation-fill-mode
should be meaningful for scroll-linked animations. (I will add the
tentative wpt in Bug 1775327.)
So we need to introduce a normalized timing when resolving the specified
timing.
Also, this patch makes the bug of printing scroll animations detectable.
No behavior is changed and I'd like to remove the magic values and do
normalization in Bug 1775327.
Note: Based on https://github.com/w3c/csswg-drafts/issues/4862 and
web-animations-2, we will introudce CSSNumberish for duration, current
time, and delay. That is, we will accept percentage for
animation-duration, animation-delay. However, Gecko doesn't support
CSSNumberish for those values, so we'd like to normalize these time values
in Bug 1775327. This patch is the 1st step: split the normalized
timing from the specified timing, and use it when resolving the
timing, for progress-based timeline.
Differential Revision: https://phabricator.services.mozilla.com/D149683
2022-06-23 00:19:30 +03:00
|
|
|
PROGRESS_TIMELINE_DURATION_MILLISEC);
|
2021-12-08 04:16:29 +03:00
|
|
|
}
|
|
|
|
|
2022-04-05 21:48:16 +03:00
|
|
|
layers::ScrollDirection ScrollTimeline::Axis() const {
|
|
|
|
MOZ_ASSERT(mSource && mSource.mElement->GetPrimaryFrame());
|
|
|
|
|
|
|
|
const WritingMode wm = mSource.mElement->GetPrimaryFrame()->GetWritingMode();
|
2022-04-21 20:05:18 +03:00
|
|
|
return mAxis == StyleScrollAxis::Horizontal ||
|
|
|
|
(!wm.IsVertical() && mAxis == StyleScrollAxis::Inline) ||
|
|
|
|
(wm.IsVertical() && mAxis == StyleScrollAxis::Block)
|
2022-04-05 21:48:16 +03:00
|
|
|
? layers::ScrollDirection::eHorizontal
|
|
|
|
: layers::ScrollDirection::eVertical;
|
|
|
|
}
|
|
|
|
|
2022-04-05 21:48:17 +03:00
|
|
|
StyleOverflow ScrollTimeline::SourceScrollStyle() const {
|
|
|
|
MOZ_ASSERT(mSource && mSource.mElement->GetPrimaryFrame());
|
|
|
|
|
|
|
|
const nsIScrollableFrame* scrollFrame = GetScrollFrame();
|
|
|
|
MOZ_ASSERT(scrollFrame);
|
|
|
|
|
|
|
|
const ScrollStyles scrollStyles = scrollFrame->GetScrollStyles();
|
|
|
|
|
|
|
|
return Axis() == layers::ScrollDirection::eHorizontal
|
|
|
|
? scrollStyles.mHorizontal
|
|
|
|
: scrollStyles.mVertical;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ScrollTimeline::APZIsActiveForSource() const {
|
|
|
|
MOZ_ASSERT(mSource);
|
|
|
|
return gfxPlatform::AsyncPanZoomEnabled() &&
|
|
|
|
!nsLayoutUtils::ShouldDisableApzForElement(mSource.mElement) &&
|
|
|
|
DisplayPortUtils::HasNonMinimalNonZeroDisplayPort(mSource.mElement);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ScrollTimeline::ScrollingDirectionIsAvailable() const {
|
|
|
|
const nsIScrollableFrame* scrollFrame = GetScrollFrame();
|
|
|
|
MOZ_ASSERT(scrollFrame);
|
|
|
|
return scrollFrame->GetAvailableScrollingDirections().contains(Axis());
|
|
|
|
}
|
|
|
|
|
2023-03-08 02:57:54 +03:00
|
|
|
void ScrollTimeline::ReplacePropertiesWith(const Element* aReferenceElement,
|
2023-03-16 23:00:00 +03:00
|
|
|
PseudoStyleType aPseudoType,
|
2023-03-08 02:57:54 +03:00
|
|
|
const StyleScrollTimeline& aNew) {
|
2023-03-16 23:00:00 +03:00
|
|
|
MOZ_ASSERT(aReferenceElement == mSource.mElement &&
|
|
|
|
aPseudoType == mSource.mPseudoType);
|
2023-03-08 02:57:54 +03:00
|
|
|
mAxis = aNew.GetAxis();
|
|
|
|
|
|
|
|
for (auto* anim = mAnimationOrder.getFirst(); anim;
|
|
|
|
anim = static_cast<LinkedListElement<Animation>*>(anim)->getNext()) {
|
|
|
|
MOZ_ASSERT(anim->GetTimeline() == this);
|
|
|
|
// Set this so we just PostUpdate() for this animation.
|
|
|
|
anim->SetTimeline(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Bug 1737920 - Part 2: Calculate offsets for ViewTimeline. r=emilio
The definition of at-progress-timeline-boundary is updated to use the
unconstructed current timeline if we have, so we update the
implementation as well. It is necessary for view-timeline.
Basically, we use offsets to control the animation progress.
For scroll-timeline, it's simply 0 to the scroll range.
For view-timeline, its progress is between 0% and 100% if the subject element
is in the view. Otherwise, its progress is outside the range.
This patch series doesn't take Named Timeline Range into account because
I expect we will handle them in different bugs, e.g. support the keyframe
selector with `<timeline-range-name>` in Bug 1823509.
So only the basic scenario is implemented:
1. 0% progress represents the position at which the start border edge of the
element’s principal box coincides with the end edge of its view progress
visibility range. (e.g. the top of the subject touches the bottom of
the scrollport, for the vertical axis.)
2. 100% progress represents the position at which the end border edge of the
element’s principal box coincides with the start edge of its view progress
visibility range. (e.g. the bottom of the subject touches the top of
the scrollport, for the vertical axis.)
So basically, it is equal to `cover` range (i.e. we run the animation
when the scrollport covers the subject), per
https://drafts.csswg.org/scroll-animations-1/#valdef-animation-timeline-range-cover
Note: OMTA will be disabled for view timeline in the next patch. So we
implement this only on the main thread.
Differential Revision: https://phabricator.services.mozilla.com/D170002
2023-04-12 23:52:02 +03:00
|
|
|
Maybe<ScrollTimeline::ScrollOffsets> ScrollTimeline::ComputeOffsets(
|
|
|
|
const nsIScrollableFrame* aScrollFrame,
|
|
|
|
layers::ScrollDirection aOrientation) const {
|
|
|
|
const nsRect& scrollRange = aScrollFrame->GetScrollRange();
|
|
|
|
nscoord range = aOrientation == layers::ScrollDirection::eHorizontal
|
|
|
|
? scrollRange.width
|
|
|
|
: scrollRange.height;
|
|
|
|
MOZ_ASSERT(range > 0);
|
|
|
|
return Some(ScrollOffsets{0, range});
|
|
|
|
}
|
|
|
|
|
2023-03-08 02:57:53 +03:00
|
|
|
void ScrollTimeline::RegisterWithScrollSource() {
|
|
|
|
if (!mSource) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-03-16 23:00:00 +03:00
|
|
|
auto& scheduler =
|
|
|
|
ProgressTimelineScheduler::Ensure(mSource.mElement, mSource.mPseudoType);
|
|
|
|
scheduler.AddTimeline(this);
|
2023-03-08 02:57:53 +03:00
|
|
|
}
|
|
|
|
|
2021-12-08 04:16:28 +03:00
|
|
|
void ScrollTimeline::UnregisterFromScrollSource() {
|
|
|
|
if (!mSource) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-03-16 23:00:00 +03:00
|
|
|
auto* scheduler =
|
|
|
|
ProgressTimelineScheduler::Get(mSource.mElement, mSource.mPseudoType);
|
|
|
|
if (!scheduler) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
scheduler->RemoveTimeline(this);
|
|
|
|
if (scheduler->IsEmpty()) {
|
|
|
|
ProgressTimelineScheduler::Destroy(mSource.mElement, mSource.mPseudoType);
|
2021-12-08 04:16:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Bug 1676791 - Part 9: Define Scroller to handle the source of ScrollTimeline. r=emilio
Per spec, "auto" represents the scrolling element of the document.
However, the scrolling element might be changed, based on the layout, in
quirks mode. Besides, the content of the root scroll frame is the root
element, instead of the scrolling element (e.g. body element) in both
standard and quirks modes. So now we define a special type, Scroller, to
represent the source of scroll-timeline, and use its |mType| to decide
which scroll frame we would like to use. In addition, hope this change let
us easier to implement nearest scroller.
Note: for auto scroller, we register this ScrollTimeline to the root
element, in both modes. Once we expose ScrollTimeline interface to the
script, we can rely on the |mType| of Scroller to return the correct
source element, whether it is scrolling element or not.
Differential Revision: https://phabricator.services.mozilla.com/D131578
2021-12-08 04:16:31 +03:00
|
|
|
const nsIScrollableFrame* ScrollTimeline::GetScrollFrame() const {
|
|
|
|
if (!mSource) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (mSource.mType) {
|
2022-06-13 23:26:45 +03:00
|
|
|
case Scroller::Type::Root:
|
Bug 1676791 - Part 9: Define Scroller to handle the source of ScrollTimeline. r=emilio
Per spec, "auto" represents the scrolling element of the document.
However, the scrolling element might be changed, based on the layout, in
quirks mode. Besides, the content of the root scroll frame is the root
element, instead of the scrolling element (e.g. body element) in both
standard and quirks modes. So now we define a special type, Scroller, to
represent the source of scroll-timeline, and use its |mType| to decide
which scroll frame we would like to use. In addition, hope this change let
us easier to implement nearest scroller.
Note: for auto scroller, we register this ScrollTimeline to the root
element, in both modes. Once we expose ScrollTimeline interface to the
script, we can rely on the |mType| of Scroller to return the correct
source element, whether it is scrolling element or not.
Differential Revision: https://phabricator.services.mozilla.com/D131578
2021-12-08 04:16:31 +03:00
|
|
|
if (const PresShell* presShell =
|
|
|
|
mSource.mElement->OwnerDoc()->GetPresShell()) {
|
|
|
|
return presShell->GetRootScrollFrameAsScrollable();
|
|
|
|
}
|
2022-04-21 20:05:19 +03:00
|
|
|
return nullptr;
|
2022-06-13 23:26:45 +03:00
|
|
|
case Scroller::Type::Nearest:
|
|
|
|
case Scroller::Type::Name:
|
2023-05-05 00:35:14 +03:00
|
|
|
case Scroller::Type::Self:
|
Bug 1676791 - Part 9: Define Scroller to handle the source of ScrollTimeline. r=emilio
Per spec, "auto" represents the scrolling element of the document.
However, the scrolling element might be changed, based on the layout, in
quirks mode. Besides, the content of the root scroll frame is the root
element, instead of the scrolling element (e.g. body element) in both
standard and quirks modes. So now we define a special type, Scroller, to
represent the source of scroll-timeline, and use its |mType| to decide
which scroll frame we would like to use. In addition, hope this change let
us easier to implement nearest scroller.
Note: for auto scroller, we register this ScrollTimeline to the root
element, in both modes. Once we expose ScrollTimeline interface to the
script, we can rely on the |mType| of Scroller to return the correct
source element, whether it is scrolling element or not.
Differential Revision: https://phabricator.services.mozilla.com/D131578
2021-12-08 04:16:31 +03:00
|
|
|
return nsLayoutUtils::FindScrollableFrameFor(mSource.mElement);
|
|
|
|
}
|
2022-04-21 20:05:19 +03:00
|
|
|
|
|
|
|
MOZ_ASSERT_UNREACHABLE("Unsupported scroller type");
|
2022-04-21 01:21:14 +03:00
|
|
|
return nullptr;
|
Bug 1676791 - Part 9: Define Scroller to handle the source of ScrollTimeline. r=emilio
Per spec, "auto" represents the scrolling element of the document.
However, the scrolling element might be changed, based on the layout, in
quirks mode. Besides, the content of the root scroll frame is the root
element, instead of the scrolling element (e.g. body element) in both
standard and quirks modes. So now we define a special type, Scroller, to
represent the source of scroll-timeline, and use its |mType| to decide
which scroll frame we would like to use. In addition, hope this change let
us easier to implement nearest scroller.
Note: for auto scroller, we register this ScrollTimeline to the root
element, in both modes. Once we expose ScrollTimeline interface to the
script, we can rely on the |mType| of Scroller to return the correct
source element, whether it is scrolling element or not.
Differential Revision: https://phabricator.services.mozilla.com/D131578
2021-12-08 04:16:31 +03:00
|
|
|
}
|
|
|
|
|
2023-03-16 23:00:00 +03:00
|
|
|
// ------------------------------------
|
|
|
|
// Methods of ProgressTimelineScheduler
|
|
|
|
// ------------------------------------
|
|
|
|
/* static */ ProgressTimelineScheduler* ProgressTimelineScheduler::Get(
|
|
|
|
const Element* aElement, PseudoStyleType aPseudoType) {
|
|
|
|
MOZ_ASSERT(aElement);
|
|
|
|
auto* data = aElement->GetAnimationData();
|
|
|
|
if (!data) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2021-12-08 04:16:28 +03:00
|
|
|
|
2023-03-16 23:00:00 +03:00
|
|
|
return data->GetProgressTimelineScheduler(aPseudoType);
|
2021-12-08 04:16:28 +03:00
|
|
|
}
|
|
|
|
|
2023-03-16 23:00:00 +03:00
|
|
|
/* static */ ProgressTimelineScheduler& ProgressTimelineScheduler::Ensure(
|
|
|
|
Element* aElement, PseudoStyleType aPseudoType) {
|
2021-12-08 04:16:28 +03:00
|
|
|
MOZ_ASSERT(aElement);
|
2023-03-16 23:00:00 +03:00
|
|
|
return aElement->EnsureAnimationData().EnsureProgressTimelineScheduler(
|
|
|
|
*aElement, aPseudoType);
|
2021-12-08 04:16:28 +03:00
|
|
|
}
|
|
|
|
|
2023-03-16 23:00:00 +03:00
|
|
|
/* static */
|
|
|
|
void ProgressTimelineScheduler::Destroy(const Element* aElement,
|
|
|
|
PseudoStyleType aPseudoType) {
|
|
|
|
auto* data = aElement->GetAnimationData();
|
|
|
|
MOZ_ASSERT(data);
|
|
|
|
data->ClearProgressTimelineScheduler(aPseudoType);
|
2021-12-08 04:16:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace mozilla::dom
|