Chromium Code Reviews| Index: Source/core/dom/Element.cpp |
| diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp |
| index 55b420d59d027efcb3916839c8f417267efa3cd8..255a33afc84b48584fcd55c23941a947fc48a569 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,24 @@ |
| 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() |
| +{ |
|
haraken
2015/07/15 00:15:18
Can we add ASSERT(RuntimeEnabledFeature::ScrollCus
tdresser
2015/07/15 14:04:54
Done.
|
| + DEFINE_STATIC_LOCAL(Persistent<ScrollCustomizationCallbacks>, |
| + scrollCustomizationCallbacks, (new ScrollCustomizationCallbacks())); |
| + return *scrollCustomizationCallbacks; |
| +} |
| + |
| +} // namespace |
| + |
| using namespace HTMLNames; |
| using namespace XMLNames; |
| @@ -155,6 +175,8 @@ Element::~Element() |
| if (isCustomElement()) |
| CustomElement::wasDestroyed(this); |
| + 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 +492,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 +524,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 +554,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 +593,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 |