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

Unified Diff: third_party/WebKit/Source/core/dom/IntersectionObservation.cpp

Issue 1449623002: IntersectionObserver: second cut. (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Implemented root margin Created 5 years 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/dom/IntersectionObservation.cpp
diff --git a/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp b/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..17940a0ec9aaef0b90a29675f78650f104d94424
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp
@@ -0,0 +1,128 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/dom/IntersectionObservation.h"
+
+#include "core/dom/IntersectionObserver.h"
+#include "core/frame/FrameView.h"
+#include "core/layout/LayoutBox.h"
+#include "core/layout/LayoutText.h"
+#include "core/layout/LayoutView.h"
+#include "core/paint/PaintLayer.h"
+
+namespace blink {
+
+IntersectionObservation::IntersectionObservation(IntersectionObserver& observer, Element* target, bool canReportRootBounds)
+ : m_observer(observer)
+ , m_target(target->createWeakPtr())
esprehn 2015/12/12 00:14:13 your controller should keep the factory, not the e
szager1 2015/12/16 19:15:34 Done.
+ , m_active(true)
+ , m_canReportRootBounds(canReportRootBounds)
+ , m_lastVisibleRatio(0)
+{
+ target->addIntersectionObservation(*this);
+}
+
+bool IntersectionObservation::computeGeometry(LayoutRect& targetRect, LayoutRect& rootRect, LayoutRect& intersectionRect)
+{
+ Element* rootElement = observer()->root();
+ bool rootIsDocumentElement = (rootElement == rootElement->document().documentElement());
ojan 2015/12/12 01:06:28 Not sure this documentElement check is correct. Th
szager1 2015/12/16 19:15:34 If root is not provided in the constructor, it doe
+ LayoutObject* rootLayoutObject = rootIsDocumentElement ? rootElement->document().layoutView() : rootElement->layoutObject();
+ if (!rootLayoutObject->isBoxModelObject())
+ return false;
+ LayoutObject* targetLayoutObject = m_target->layoutObject();
+
+ // Initialize intersectionRect to bounds of target, in target's coordinate space.
+ if (targetLayoutObject->isBoxModelObject())
+ targetRect = intersectionRect = toLayoutBoxModelObject(targetLayoutObject)->visualOverflowRect();
+ else if (targetLayoutObject->isText())
+ targetRect = intersectionRect = toLayoutText(targetLayoutObject)->visualOverflowRect();
+ else
+ return false;
+
+ // Map targetRect into document coordinates.
+ targetRect = LayoutRect(targetLayoutObject->localToAbsoluteQuad(FloatQuad(FloatRect(targetRect)), UseTransforms | ApplyContainerFlip | TraverseDocumentBoundaries).boundingBox());
+
+ // Map and clip intersectionRect into root element coordinates.
+ targetLayoutObject->mapToVisibleRectInContainerSpace(toLayoutBoxModelObject(rootLayoutObject), intersectionRect, nullptr);
+ if (rootLayoutObject->hasOverflowClip()) {
+ LayoutBox* rootLayoutBox = toLayoutBox(rootLayoutObject);
+ LayoutRect clipRect(LayoutPoint(), LayoutSize(rootLayoutBox->layer()->size()));
+ m_observer->applyRootMargin(clipRect);
+ rootLayoutBox->flipForWritingMode(intersectionRect);
+ intersectionRect.intersect(clipRect);
+ rootLayoutBox->flipForWritingMode(intersectionRect);
+ }
+
+ // Map intersectionRect into document coordinates.
+ intersectionRect = LayoutRect(rootLayoutObject->localToAbsoluteQuad(FloatQuad(FloatRect(intersectionRect))).boundingBox());
+
+ // Clip to FrameView visible area if necessary, and get root bounds in document coordinates.
+ if (rootIsDocumentElement) {
+ rootRect = LayoutRect(rootElement->document().view()->visibleContentRect());
+ m_observer->applyRootMargin(rootRect);
+ intersectionRect.intersect(rootRect);
+ } else {
+ if (rootLayoutObject->isBox())
+ rootRect = LayoutRect(toLayoutBox(rootLayoutObject)->absoluteContentBox());
esprehn 2015/12/12 00:14:13 this method is so big, you might want to move some
szager1 2015/12/16 19:15:35 I added helper functions, this method is now short
+ else
+ rootRect = LayoutRect(rootLayoutObject->absoluteBoundingBoxRect());
+ m_observer->applyRootMargin(rootRect);
+ }
+
+ // Map all rects to FrameView coordinates.
+ LayoutPoint scrollPosition(rootElement->document().view()->scrollPosition());
+ targetRect.moveBy(-scrollPosition);
+ intersectionRect.moveBy(-scrollPosition);
+ rootRect.moveBy(-scrollPosition);
+
+ if (intersectionRect.size().isZero())
+ intersectionRect = LayoutRect();
+
+ return true;
+}
+
+void IntersectionObservation::computeIntersectionObservations(int timestamp)
esprehn 2015/12/12 00:14:13 timestamps are doubles on the web, what is this in
szager1 2015/12/16 19:15:34 I think I switched types mid-way through :) I cha
+{
+ // TODO: rootMargin is not yet supported.
+ Element* targetElement = target();
+ if (!targetElement || !isActive())
+ return;
+ LayoutObject* targetLayoutObject = targetElement->layoutObject();
+ // TODO: Support SVG
+ if (!targetLayoutObject || (!targetLayoutObject->isBox() && !targetLayoutObject->isInline()))
esprehn 2015/12/12 00:14:13 break your early returns into multiple statements.
szager1 2015/12/16 19:15:34 Done.
+ return;
+
+ LayoutRect targetRect, rootRect, intersectionRect;
+ if (!computeGeometry(targetRect, rootRect, intersectionRect))
esprehn 2015/12/12 00:14:13 use a struct? having so many out params is kind of
ojan 2015/12/12 01:06:28 We usually use structs for these in the layout cod
szager1 2015/12/16 19:15:34 Added struct IntersectionGeometry for this.
+ return;
+ if (!m_canReportRootBounds)
+ rootRect = LayoutRect();
esprehn 2015/12/12 00:14:13 can computeGeometry do this instead of here?
szager1 2015/12/16 19:15:34 Done.
+
+ float intersectionArea = intersectionRect.size().width().toFloat() * intersectionRect.size().height().toFloat();
+ float targetArea = targetRect.size().width().toFloat() * targetRect.size().height().toFloat();
+ if (!targetArea)
+ return;
esprehn 2015/12/12 00:14:13 can we move this before the intersectionArea compu
szager1 2015/12/16 19:15:34 Done.
+ float newVisibleRatio = intersectionArea / targetArea;
+ size_t newThresholdIndex = observer()->firstThresholdGreaterThan(newVisibleRatio);
+ size_t oldThresholdIndex = observer()->firstThresholdGreaterThan(lastVisibleRatio());
+ setLastVisibleRatio(newVisibleRatio);
ojan 2015/12/12 01:06:28 Can we actually just store the index? We don't nee
szager1 2015/12/16 19:15:34 Done.
+ if (oldThresholdIndex != newThresholdIndex)
+ observer()->enqueueIntersectionObserverEntry(new IntersectionObserverEntry(timestamp / 1000., pixelSnappedIntRect(targetRect), pixelSnappedIntRect(rootRect), pixelSnappedIntRect(intersectionRect), targetElement));
esprehn 2015/12/12 00:14:13 .0, but timestamp should be a double too
szager1 2015/12/16 19:15:34 Done.
+}
+
+void IntersectionObservation::disconnect()
+{
+ observer()->disconnect(*this);
+ if (m_target)
+ m_target->removeIntersectionObservation(*this);
+}
+
+DEFINE_TRACE(IntersectionObservation)
+{
+ visitor->trace(m_observer);
+ visitor->trace(m_target);
+}
+
+} // namespace blink {

Powered by Google App Engine
This is Rietveld 408576698