Chromium Code Reviews| Index: Source/core/dom/Element.cpp |
| diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp |
| index e09c101c5bdd32d3eb610d18f564b58e72a34805..58526e5bdd12684790250787e28a873ee24ebbb8 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 FrameView. |
|
skobes
2015/07/15 19:52:40
Can you change "FrameView" -> "viewport" here?
tdresser
2015/07/16 17:11:14
Done.
|
| + 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 |