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-20 23:28:53 +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"
|
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
|
|
|
|
2021-12-08 04:16:29 +03:00
|
|
|
#define SCROLL_TIMELINE_DURATION_MILLISEC 100000
|
|
|
|
|
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_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(ScrollTimeline,
|
|
|
|
AnimationTimeline)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(ScrollTimeline,
|
|
|
|
AnimationTimeline)
|
|
|
|
|
2021-12-08 04:16:29 +03:00
|
|
|
TimingParams ScrollTimeline::sTiming;
|
|
|
|
|
2022-02-08 21:35:23 +03:00
|
|
|
ScrollTimeline::ScrollTimeline(Document* aDocument, const Scroller& aScroller,
|
2022-04-20 23:28:53 +03:00
|
|
|
StyleScrollAxis aAxis)
|
2021-12-08 04:16:28 +03:00
|
|
|
: AnimationTimeline(aDocument->GetParentObject()),
|
|
|
|
mDocument(aDocument),
|
|
|
|
mSource(aScroller),
|
2022-04-20 23:28:53 +03:00
|
|
|
mAxis(aAxis) {
|
2021-12-08 04:16:28 +03:00
|
|
|
MOZ_ASSERT(aDocument);
|
|
|
|
|
2021-12-08 04:16:29 +03:00
|
|
|
// Use default values except for |mDuration| and |mFill|.
|
|
|
|
// Use a fixed duration defined in SCROLL_TIMELINE_DURATIONMILLISEC, and use
|
|
|
|
// FillMode::Both to make sure the animation is in effect at 100%.
|
2021-12-15 12:54:42 +03:00
|
|
|
sTiming = TimingParams(SCROLL_TIMELINE_DURATION_MILLISEC, 0.0,
|
|
|
|
std::numeric_limits<float>::infinity(),
|
|
|
|
PlaybackDirection::Alternate, FillMode::Both);
|
2021-12-08 04:16:28 +03:00
|
|
|
}
|
|
|
|
|
2022-04-20 23:28:53 +03:00
|
|
|
static StyleScrollAxis ToStyleScrollAxis(
|
|
|
|
const StyleScrollDirection aDirection) {
|
|
|
|
switch (aDirection) {
|
|
|
|
// The spec defines auto, but there is a spec issue:
|
|
|
|
// "ISSUE 5 Define these values." in this section. The DOM interface removed
|
|
|
|
// auto and use block as default value, so we treat auto as block now.
|
|
|
|
// https://drafts.csswg.org/scroll-animations-1/#descdef-scroll-timeline-orientation
|
|
|
|
case StyleScrollDirection::Auto:
|
|
|
|
case StyleScrollDirection::Block:
|
|
|
|
return StyleScrollAxis::Block;
|
|
|
|
case StyleScrollDirection::Inline:
|
|
|
|
return StyleScrollAxis::Inline;
|
|
|
|
case StyleScrollDirection::Horizontal:
|
|
|
|
return StyleScrollAxis::Horizontal;
|
|
|
|
case StyleScrollDirection::Vertical:
|
|
|
|
return StyleScrollAxis::Vertical;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT_UNREACHABLE("Unsupported StyleScrollDirection");
|
|
|
|
return StyleScrollAxis::Block;
|
|
|
|
}
|
|
|
|
|
2021-12-08 04:16:31 +03:00
|
|
|
already_AddRefed<ScrollTimeline> ScrollTimeline::FromRule(
|
|
|
|
const RawServoScrollTimelineRule& aRule, Document* aDocument,
|
|
|
|
const NonOwningAnimationTarget& aTarget) {
|
|
|
|
// Note: If the rules changes after we build the scroll-timeline rule, we
|
2022-02-08 21:35:23 +03:00
|
|
|
// rebuild all CSS animtions, and then try to look up the scroll-timeline by
|
|
|
|
// the new source and the new direction. If we cannot find a specific
|
|
|
|
// timeline, we create one, and the unused scroll-timeline object will be
|
|
|
|
// dropped automatically becuase no animation owns it and its ref-count
|
|
|
|
// becomes zero.
|
|
|
|
|
2022-04-20 23:28:53 +03:00
|
|
|
StyleScrollAxis axis =
|
|
|
|
ToStyleScrollAxis(Servo_ScrollTimelineRule_GetOrientation(&aRule));
|
2022-02-08 21:35:23 +03:00
|
|
|
|
|
|
|
RefPtr<ScrollTimeline> timeline;
|
2022-04-20 23:28:53 +03:00
|
|
|
auto autoScroller = Scroller::Root(aTarget.mElement->OwnerDoc());
|
2022-02-08 21:35:23 +03:00
|
|
|
auto* set =
|
|
|
|
ScrollTimelineSet::GetOrCreateScrollTimelineSet(autoScroller.mElement);
|
2022-04-20 23:28:53 +03:00
|
|
|
auto p = set->LookupForAdd(axis);
|
2022-02-08 21:35:23 +03:00
|
|
|
if (!p) {
|
2022-04-20 23:28:53 +03:00
|
|
|
timeline = new ScrollTimeline(aDocument, autoScroller, axis);
|
|
|
|
set->Add(p, axis, timeline);
|
2022-02-08 21:35:23 +03:00
|
|
|
} else {
|
|
|
|
timeline = p->value();
|
|
|
|
}
|
2021-12-08 04:16:31 +03:00
|
|
|
return timeline.forget();
|
|
|
|
}
|
|
|
|
|
2022-04-20 23:28:53 +03:00
|
|
|
/* static */
|
|
|
|
already_AddRefed<ScrollTimeline> ScrollTimeline::FromAnonymousScroll(
|
|
|
|
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;
|
|
|
|
case StyleScroller::Nearest: {
|
|
|
|
Element* curr = aTarget.mElement->GetFlattenedTreeParentElement();
|
|
|
|
Element* root = aTarget.mElement->OwnerDoc()->GetDocumentElement();
|
|
|
|
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.
|
|
|
|
scroller = Scroller::Nearest(curr ? curr : root);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<ScrollTimeline> timeline;
|
|
|
|
auto* set =
|
|
|
|
ScrollTimelineSet::GetOrCreateScrollTimelineSet(scroller.mElement);
|
|
|
|
auto p = set->LookupForAdd(aAxis);
|
|
|
|
if (!p) {
|
|
|
|
timeline = new ScrollTimeline(aDocument, scroller, aAxis);
|
|
|
|
set->Add(p, aAxis, timeline);
|
|
|
|
} else {
|
|
|
|
timeline = p->value();
|
|
|
|
}
|
|
|
|
return timeline.forget();
|
|
|
|
}
|
|
|
|
|
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();
|
|
|
|
|
2021-12-08 04:16:29 +03:00
|
|
|
// If this orientation is not ready for scrolling (i.e. the scroll range is
|
|
|
|
// not larger than or equal to one device pixel), we make it 100%.
|
|
|
|
if (!scrollFrame->GetAvailableScrollingDirections().contains(orientation)) {
|
|
|
|
return TimeDuration::FromMilliseconds(SCROLL_TIMELINE_DURATION_MILLISEC);
|
|
|
|
}
|
|
|
|
|
|
|
|
const nsPoint& scrollOffset = scrollFrame->GetScrollPosition();
|
|
|
|
const nsRect& scrollRange = scrollFrame->GetScrollRange();
|
|
|
|
const bool isHorizontal = orientation == layers::ScrollDirection::eHorizontal;
|
|
|
|
|
|
|
|
// Note: For RTL, scrollOffset.x or scrollOffset.y may be negative, e.g. the
|
|
|
|
// range of its value is [0, -range], so we have to use the absolute value.
|
|
|
|
double position = std::abs(isHorizontal ? scrollOffset.x : scrollOffset.y);
|
|
|
|
double range = isHorizontal ? scrollRange.width : scrollRange.height;
|
|
|
|
MOZ_ASSERT(range > 0.0);
|
|
|
|
// Use the definition of interval progress to compute the progress.
|
|
|
|
// Note: We simplify the scroll offsets to [0%, 100%], so offset weight and
|
|
|
|
// offset index are ignored here.
|
|
|
|
// https://drafts.csswg.org/scroll-animations-1/#progress-calculation-algorithm
|
|
|
|
double progress = position / range;
|
|
|
|
return TimeDuration::FromMilliseconds(progress *
|
|
|
|
SCROLL_TIMELINE_DURATION_MILLISEC);
|
|
|
|
}
|
|
|
|
|
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-20 23:28:53 +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());
|
|
|
|
}
|
|
|
|
|
2021-12-08 04:16:28 +03:00
|
|
|
void ScrollTimeline::UnregisterFromScrollSource() {
|
|
|
|
if (!mSource) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ScrollTimelineSet* scrollTimelineSet =
|
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
|
|
|
ScrollTimelineSet::GetScrollTimelineSet(mSource.mElement)) {
|
2022-04-20 23:28:53 +03:00
|
|
|
scrollTimelineSet->Remove(mAxis);
|
2021-12-08 04:16:28 +03:00
|
|
|
if (scrollTimelineSet->IsEmpty()) {
|
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
|
|
|
ScrollTimelineSet::DestroyScrollTimelineSet(mSource.mElement);
|
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-04-20 23:28:53 +03:00
|
|
|
case StyleScroller::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-20 23:28:53 +03:00
|
|
|
return nullptr;
|
2022-04-20 23:28:53 +03:00
|
|
|
case StyleScroller::Nearest:
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-08 04:16:28 +03:00
|
|
|
// ---------------------------------
|
|
|
|
// Methods of ScrollTimelineSet
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
/* static */ ScrollTimelineSet* ScrollTimelineSet::GetScrollTimelineSet(
|
|
|
|
Element* aElement) {
|
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 aElement ? static_cast<ScrollTimelineSet*>(aElement->GetProperty(
|
|
|
|
nsGkAtoms::scrollTimelinesProperty))
|
|
|
|
: nullptr;
|
2021-12-08 04:16:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ ScrollTimelineSet* ScrollTimelineSet::GetOrCreateScrollTimelineSet(
|
|
|
|
Element* aElement) {
|
|
|
|
MOZ_ASSERT(aElement);
|
|
|
|
ScrollTimelineSet* scrollTimelineSet = GetScrollTimelineSet(aElement);
|
|
|
|
if (scrollTimelineSet) {
|
|
|
|
return scrollTimelineSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
scrollTimelineSet = new ScrollTimelineSet();
|
|
|
|
nsresult rv = aElement->SetProperty(
|
|
|
|
nsGkAtoms::scrollTimelinesProperty, scrollTimelineSet,
|
|
|
|
nsINode::DeleteProperty<ScrollTimelineSet>, true);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_WARNING("SetProperty failed");
|
|
|
|
delete scrollTimelineSet;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return scrollTimelineSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ void ScrollTimelineSet::DestroyScrollTimelineSet(
|
|
|
|
Element* aElement) {
|
|
|
|
aElement->RemoveProperty(nsGkAtoms::scrollTimelinesProperty);
|
2021-12-08 04:16:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace mozilla::dom
|