Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(109)

Unified Diff: third_party/WebKit/Source/core/layout/LayoutObject.cpp

Issue 2394053004: Clear scroll anchor on all parent scrollers from ScrollAnchor::clear (Closed)
Patch Set: rebase and fix merge Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/layout/LayoutObject.cpp
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index eca6b082996a9c4e144924398fe522653d4adbd0..327710e04f05a609be40ae5442f99349c23f2105 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -42,6 +42,7 @@
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLElement.h"
+#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/HTMLHtmlElement.h"
#include "core/html/HTMLTableCellElement.h"
#include "core/html/HTMLTableElement.h"
@@ -2575,39 +2576,65 @@ void LayoutObject::insertedIntoTree() {
flowThread->flowThreadDescendantWasInserted(this);
}
-enum FindReferencingScrollAnchorsBehavior { DontClear, Clear };
-
-static bool findReferencingScrollAnchors(
- LayoutObject* layoutObject,
- FindReferencingScrollAnchorsBehavior behavior) {
+enum FindScrollAnchorsBehavior { FindReferencing, ClearReferencing, ClearAll };
+
+// Returns true if scroller has layoutObject as its anchor.
+static bool clearScrollAnchorForScroller(ScrollableArea* scroller,
+ LayoutObject* layoutObject,
+ FindScrollAnchorsBehavior behavior) {
+ DCHECK(scroller);
+ ScrollAnchor* anchor = scroller->scrollAnchor();
+ DCHECK(anchor);
+ bool refersTo = false;
+ if (anchor->refersTo(layoutObject)) {
+ refersTo = true;
+ if (behavior == FindReferencing)
+ return refersTo;
+ layoutObject->setIsScrollAnchorObject(false);
+ anchor->releaseAnchor();
+ } else if (behavior == ClearAll && anchor->anchorObject()) {
+ anchor->anchorObject()->setIsScrollAnchorObject(false);
+ anchor->releaseAnchor();
+ }
+ return refersTo;
+}
+
+// Returns true if any of scroller in the parent chain of layoutObject has
+// layoutObject as its anchor. If FindScrollAnchorsBehavior is ClearAll, all
+// the scrollers in the parent chain of layoutObject will have their scroll
+// anchor cleared. If FindScrollAnchorsBehavior is ClearReferencing, all the
+// scrollers in the parent chain of layoutObject that have layoutObject as their
+// anchor will have their scroll anchor cleared.
+static bool findScrollAnchors(LayoutObject* layoutObject,
+ FindScrollAnchorsBehavior behavior) {
PaintLayer* layer = nullptr;
if (LayoutObject* parent = layoutObject->parent())
layer = parent->enclosingLayer();
bool found = false;
- // Walk up the layer tree to clear any scroll anchors that reference us.
+ // Walk up the layer tree to clear scroll anchors if required.
while (layer) {
- if (PaintLayerScrollableArea* scrollableArea = layer->getScrollableArea()) {
- ScrollAnchor* anchor = scrollableArea->scrollAnchor();
- DCHECK(anchor);
- if (anchor->refersTo(layoutObject)) {
- found = true;
- if (behavior == Clear)
- anchor->notifyRemoved(layoutObject);
- else
- return true;
- }
+ if (PaintLayerScrollableArea* scroller = layer->getScrollableArea()) {
+ found = clearScrollAnchorForScroller(scroller, layoutObject, behavior) ||
+ found;
+ if (found && behavior == FindReferencing)
+ return found;
}
layer = layer->parent();
}
+
if (FrameView* view = layoutObject->frameView()) {
- ScrollAnchor* anchor = view->scrollAnchor();
- DCHECK(anchor);
- if (anchor->refersTo(layoutObject)) {
- found = true;
- if (behavior == Clear)
- anchor->notifyRemoved(layoutObject);
- }
+ found = clearScrollAnchorForScroller(view, layoutObject, behavior) || found;
+ if (found && behavior == FindReferencing)
+ return found;
+ }
+
+ // Continue walk past frame boundary.
skobes 2016/10/10 21:34:35 Hmm, do we actually want this behavior? We don't
ymalik 2016/10/11 19:54:22 hmm you're right. I was under the impression that
+ if (layoutObject->document().localOwner()) {
+ found =
+ findScrollAnchors(layoutObject->document().localOwner()->layoutObject(),
+ behavior) ||
+ found;
}
return found;
}
@@ -2641,17 +2668,19 @@ void LayoutObject::willBeRemovedFromTree() {
parent()->setNeedsBoundariesUpdate();
if (RuntimeEnabledFeatures::scrollAnchoringEnabled() &&
- m_bitfields.isScrollAnchorObject()) {
- // Clear the bit first so that anchor.clear() doesn't recurse into findReferencingScrollAnchors.
- m_bitfields.setIsScrollAnchorObject(false);
- findReferencingScrollAnchors(this, Clear);
- }
+ m_bitfields.isScrollAnchorObject())
+ findScrollAnchors(this, ClearReferencing);
}
void LayoutObject::maybeClearIsScrollAnchorObject() {
- if (m_bitfields.isScrollAnchorObject())
+ if (m_bitfields.isScrollAnchorObject()) {
m_bitfields.setIsScrollAnchorObject(
- findReferencingScrollAnchors(this, DontClear));
+ findScrollAnchors(this, FindReferencing));
+ }
+}
+
+void LayoutObject::clearScrollAnchors() {
+ findScrollAnchors(this, ClearAll);
}
void LayoutObject::removeFromLayoutFlowThread() {

Powered by Google App Engine
This is Rietveld 408576698