| Index: Source/core/dom/Element.cpp
|
| diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp
|
| index 9b72286ae6c846cfcce1055b957dd715018fe121..f635b5d48fe2260f689530a8f06435e86abaa3c7 100644
|
| --- a/Source/core/dom/Element.cpp
|
| +++ b/Source/core/dom/Element.cpp
|
| @@ -112,7 +112,9 @@
|
| #include "core/page/Page.h"
|
| #include "core/page/PointerLockController.h"
|
| #include "core/page/SpatialNavigation.h"
|
| +#include "core/page/scrolling/ScrollCustomizationCallbacks.h"
|
| #include "core/page/scrolling/ScrollState.h"
|
| +#include "core/page/scrolling/ScrollStateCallback.h"
|
| #include "core/paint/DeprecatedPaintLayer.h"
|
| #include "core/svg/SVGDocumentExtensions.h"
|
| #include "core/svg/SVGElement.h"
|
| @@ -128,6 +130,25 @@
|
|
|
| namespace blink {
|
|
|
| +namespace {
|
| +
|
| +// We need to retain the scroll customization callbacks until the element
|
| +// they're associated with is destroyed. It would be simplest if the callbacks
|
| +// could be stored in ElementRareData, but we can't afford the space
|
| +// increase. Instead, keep the scroll customization callbacks here. The other
|
| +// option would be to store these callbacks on the FrameHost or document, but
|
| +// that necessitates a bunch more logic for transferring the callbacks between
|
| +// FrameHosts when elements are moved around.
|
| +ScrollCustomizationCallbacks& scrollCustomizationCallbacks()
|
| +{
|
| + ASSERT(RuntimeEnabledFeatures::scrollCustomizationEnabled());
|
| + DEFINE_STATIC_LOCAL(Persistent<ScrollCustomizationCallbacks>,
|
| + scrollCustomizationCallbacks, (new ScrollCustomizationCallbacks()));
|
| + return *scrollCustomizationCallbacks;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| using namespace HTMLNames;
|
| using namespace XMLNames;
|
|
|
| @@ -155,6 +176,9 @@ Element::~Element()
|
| if (isCustomElement())
|
| CustomElement::wasDestroyed(this);
|
|
|
| + if (RuntimeEnabledFeatures::scrollCustomizationEnabled())
|
| + scrollCustomizationCallbacks().removeCallbacksForElement(this);
|
| +
|
| // With Oilpan, either the Element has been removed from the Document
|
| // or the Document is dead as well. If the Element has been removed from
|
| // the Document the element has already been removed from the pending
|
| @@ -470,7 +494,19 @@ void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
|
| layoutObject()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
|
| }
|
|
|
| -void Element::distributeScroll(ScrollState& scrollState)
|
| +void Element::setDistributeScroll(ScrollStateCallback* scrollStateCallback, String nativeScrollBehavior)
|
| +{
|
| + scrollStateCallback->setNativeScrollBehavior(ScrollStateCallback::toNativeScrollBehavior(nativeScrollBehavior));
|
| + scrollCustomizationCallbacks().setDistributeScroll(this, scrollStateCallback);
|
| +}
|
| +
|
| +void Element::setApplyScroll(ScrollStateCallback* scrollStateCallback, String nativeScrollBehavior)
|
| +{
|
| + scrollStateCallback->setNativeScrollBehavior(ScrollStateCallback::toNativeScrollBehavior(nativeScrollBehavior));
|
| + scrollCustomizationCallbacks().setApplyScroll(this, scrollStateCallback);
|
| +}
|
| +
|
| +void Element::nativeDistributeScroll(ScrollState& scrollState)
|
| {
|
| ASSERT(RuntimeEnabledFeatures::scrollCustomizationEnabled());
|
| if (scrollState.fullyConsumed())
|
| @@ -490,13 +526,27 @@ void Element::distributeScroll(ScrollState& scrollState)
|
| const double deltaX = scrollState.deltaX();
|
| const double deltaY = scrollState.deltaY();
|
|
|
| - applyScroll(scrollState);
|
| + callApplyScroll(scrollState);
|
|
|
| if (deltaX != scrollState.deltaX() || deltaY != scrollState.deltaY())
|
| scrollState.setCurrentNativeScrollingElement(this);
|
| }
|
|
|
| -void Element::applyScroll(ScrollState& scrollState)
|
| +void Element::callDistributeScroll(ScrollState& scrollState)
|
| +{
|
| + ScrollStateCallback* callback = scrollCustomizationCallbacks().getDistributeScroll(this);
|
| + if (!callback) {
|
| + nativeDistributeScroll(scrollState);
|
| + } else {
|
| + if (callback->nativeScrollBehavior() == NativeScrollBehavior::PerformAfterNativeScroll)
|
| + nativeDistributeScroll(scrollState);
|
| + callback->handleEvent(&scrollState);
|
| + if (callback->nativeScrollBehavior() == NativeScrollBehavior::PerformBeforeNativeScroll)
|
| + nativeDistributeScroll(scrollState);
|
| + }
|
| +};
|
| +
|
| +void Element::nativeApplyScroll(ScrollState& scrollState)
|
| {
|
| ASSERT(RuntimeEnabledFeatures::scrollCustomizationEnabled());
|
| if (scrollState.fullyConsumed())
|
| @@ -506,8 +556,11 @@ void Element::applyScroll(ScrollState& scrollState)
|
| const double deltaY = scrollState.deltaY();
|
| bool scrolled = false;
|
|
|
| - // Handle the documentElement separately, as it scrolls the FrameView.
|
| - if (this == document().documentElement()) {
|
| + if (deltaY || deltaX)
|
| + document().updateLayoutIgnorePendingStylesheets();
|
| +
|
| + // Handle the scrollingElement separately, as it scrolls the viewport.
|
| + if (this == document().scrollingElement()) {
|
| FloatSize delta(deltaX, deltaY);
|
| if (document().frame()->applyScrollDelta(delta, scrollState.isBeginning()).didScroll()) {
|
| scrolled = true;
|
| @@ -542,6 +595,20 @@ void Element::applyScroll(ScrollState& scrollState)
|
| document().frame()->view()->setWasScrolledByUser(true);
|
| };
|
|
|
| +void Element::callApplyScroll(ScrollState& scrollState)
|
| +{
|
| + ScrollStateCallback* callback = scrollCustomizationCallbacks().getApplyScroll(this);
|
| + if (!callback) {
|
| + nativeApplyScroll(scrollState);
|
| + } else {
|
| + if (callback->nativeScrollBehavior() == NativeScrollBehavior::PerformAfterNativeScroll)
|
| + nativeApplyScroll(scrollState);
|
| + callback->handleEvent(&scrollState);
|
| + if (callback->nativeScrollBehavior() == NativeScrollBehavior::PerformBeforeNativeScroll)
|
| + nativeApplyScroll(scrollState);
|
| + }
|
| +};
|
| +
|
| static float localZoomForLayoutObject(LayoutObject& layoutObject)
|
| {
|
| // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
|
|
|