Chromium Code Reviews| Index: Source/core/dom/Element.cpp |
| diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp |
| index ba5c7821706e1435499ee6ffa341c677a4bd57d5..dfc838e80ce2831392351e783f0b95d9bf458352 100644 |
| --- a/Source/core/dom/Element.cpp |
| +++ b/Source/core/dom/Element.cpp |
| @@ -113,7 +113,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" |
| @@ -129,6 +131,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; |
| @@ -156,6 +177,9 @@ Element::~Element() |
| if (isCustomElement()) |
| CustomElement::wasDestroyed(this); |
| + if (RuntimeEnabledFeatures::scrollCustomizationEnabled()) |
| + scrollCustomizationCallbacks().removeCallbacksForElement(this); |
|
Rick Byers
2015/08/30 20:57:50
So in the Oilpan case I assume the weak collection
haraken
2015/08/30 22:21:37
Right :)
|
| + |
| // 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 |
| @@ -471,7 +495,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()) |
| @@ -491,13 +527,29 @@ 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); |
| + return; |
| + } |
| + |
| + if (callback->nativeScrollBehavior() != NativeScrollBehavior::PerformAfterNativeScroll) |
| + callback->handleEvent(&scrollState); |
| + if (callback->nativeScrollBehavior() != NativeScrollBehavior::DisableNativeScroll) |
| + nativeDistributeScroll(scrollState); |
| + if (callback->nativeScrollBehavior() == NativeScrollBehavior::PerformAfterNativeScroll) |
| + callback->handleEvent(&scrollState); |
| +}; |
| + |
| +void Element::nativeApplyScroll(ScrollState& scrollState) |
| { |
| ASSERT(RuntimeEnabledFeatures::scrollCustomizationEnabled()); |
| if (scrollState.fullyConsumed()) |
| @@ -507,8 +559,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; |
| @@ -545,6 +600,22 @@ void Element::applyScroll(ScrollState& scrollState) |
| } |
| }; |
| +void Element::callApplyScroll(ScrollState& scrollState) |
| +{ |
| + ScrollStateCallback* callback = scrollCustomizationCallbacks().getApplyScroll(this); |
| + if (!callback) { |
| + nativeApplyScroll(scrollState); |
| + return; |
| + } |
| + |
| + if (callback->nativeScrollBehavior() != NativeScrollBehavior::PerformAfterNativeScroll) |
| + callback->handleEvent(&scrollState); |
| + if (callback->nativeScrollBehavior() != NativeScrollBehavior::DisableNativeScroll) |
| + nativeApplyScroll(scrollState); |
| + if (callback->nativeScrollBehavior() == NativeScrollBehavior::PerformAfterNativeScroll) |
| + callback->handleEvent(&scrollState); |
| +}; |
| + |
| static float localZoomForLayoutObject(LayoutObject& layoutObject) |
| { |
| // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each |