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

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: 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 87e07f5bf1700c7a5f5cc85c95d46bc1edcbe15b..937fb114b98b2ee56154021be5dc9c5abc7356bc 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"
@@ -2577,39 +2578,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,
ymalik 2016/10/06 19:51:13 @skobes, a note to make reviewing easier. This fu
+ 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.
+ if (layoutObject->document().localOwner()) {
+ found =
+ findScrollAnchors(layoutObject->document().localOwner()->layoutObject(),
+ behavior) ||
+ found;
}
return found;
}
@@ -2643,17 +2670,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() {
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutObject.h ('k') | third_party/WebKit/Source/core/layout/ScrollAnchor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698