Index: Source/core/dom/Element.cpp |
diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp |
index f55ea51759ea5c6abe84509bb8d47b5478aaf987..7b9fa75bac3f0a14d6f2c94ef04c91afb74cccd0 100644 |
--- a/Source/core/dom/Element.cpp |
+++ b/Source/core/dom/Element.cpp |
@@ -113,6 +113,7 @@ |
#include "core/page/PointerLockController.h" |
#include "core/page/SpatialNavigation.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" |
@@ -470,7 +471,40 @@ void Element::scrollIntoViewIfNeeded(bool centerIfNeeded) |
layoutObject()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); |
} |
-void Element::distributeScroll(ScrollState& scrollState) |
+namespace { |
+ |
+NativeScrollBehavior toNativeScrollBehavior(String nativeScrollBehavior) |
+{ |
+ DEFINE_STATIC_LOCAL(const String, disable, ("disable-native-scroll")); |
+ DEFINE_STATIC_LOCAL(const String, before, ("perform-before-native-scroll")); |
+ DEFINE_STATIC_LOCAL(const String, after, ("perform-after-native-scroll")); |
+ |
+ if (nativeScrollBehavior == disable) |
+ return DisableNativeScroll; |
+ if (nativeScrollBehavior == before) |
+ return PerformBeforeNativeScroll; |
+ if (nativeScrollBehavior == after) |
+ return PerformAfterNativeScroll; |
+ |
+ ASSERT_NOT_REACHED(); |
+ return DisableNativeScroll; |
+} |
+ |
+} // namespace |
+ |
+void Element::setDistributeScroll(ScrollStateCallback* scrollStateCallback, String nativeScrollBehavior) |
+{ |
+ scrollStateCallback->setNativeScrollBehavior(toNativeScrollBehavior(nativeScrollBehavior)); |
+ ensureElementRareData().setDistributeScroll(scrollStateCallback); |
+} |
+ |
+void Element::setApplyScroll(ScrollStateCallback* scrollStateCallback, String nativeScrollBehavior) |
+{ |
+ scrollStateCallback->setNativeScrollBehavior(toNativeScrollBehavior(nativeScrollBehavior)); |
+ ensureElementRareData().setApplyScroll(scrollStateCallback); |
+} |
+ |
+void Element::nativeDistributeScroll(ScrollState& scrollState) |
{ |
ASSERT(RuntimeEnabledFeatures::scrollCustomizationEnabled()); |
if (scrollState.fullyConsumed()) |
@@ -490,15 +524,30 @@ 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) |
+{ |
+ if (!hasRareData() || !elementRareData()->getDistributeScroll()) { |
+ nativeDistributeScroll(scrollState); |
+ } else { |
+ ScrollStateCallback& callback = *elementRareData()->getDistributeScroll(); |
+ if (callback.nativeScrollBehavior() == PerformAfterNativeScroll) |
+ nativeDistributeScroll(scrollState); |
+ callback.handleEvent(&scrollState); |
+ if (callback.nativeScrollBehavior() == PerformBeforeNativeScroll) |
+ nativeDistributeScroll(scrollState); |
+ } |
+}; |
+ |
+void Element::nativeApplyScroll(ScrollState& scrollState) |
{ |
ASSERT(RuntimeEnabledFeatures::scrollCustomizationEnabled()); |
+ |
if (scrollState.fullyConsumed()) |
return; |
@@ -506,8 +555,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 FrameView. |
+ if (this == document().scrollingElement()) { |
FloatSize delta(deltaX, deltaY); |
if (document().frame()->applyScrollDelta(delta, scrollState.isBeginning()).didScroll()) { |
scrolled = true; |
@@ -542,6 +594,20 @@ void Element::applyScroll(ScrollState& scrollState) |
document().frame()->view()->setWasScrolledByUser(true); |
}; |
+void Element::callApplyScroll(ScrollState& scrollState) |
+{ |
+ if (!hasRareData() || !elementRareData()->getApplyScroll()) { |
+ nativeApplyScroll(scrollState); |
+ } else { |
+ ScrollStateCallback& callback = *elementRareData()->getApplyScroll(); |
+ if (callback.nativeScrollBehavior() == PerformAfterNativeScroll) |
+ nativeApplyScroll(scrollState); |
+ callback.handleEvent(&scrollState); |
+ if (callback.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 |