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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "core/dom/IntersectionObservation.h"
7
8 #include "core/dom/IntersectionObserver.h"
9 #include "core/frame/FrameView.h"
10 #include "core/layout/LayoutBox.h"
11 #include "core/layout/LayoutText.h"
12 #include "core/layout/LayoutView.h"
13 #include "core/paint/PaintLayer.h"
14
15 namespace blink {
16
17 IntersectionObservation::IntersectionObservation(IntersectionObserver& observer, Element* target, bool canReportRootBounds)
18 : m_observer(observer)
19 , 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.
20 , m_active(true)
21 , m_canReportRootBounds(canReportRootBounds)
22 , m_lastVisibleRatio(0)
23 {
24 target->addIntersectionObservation(*this);
25 }
26
27 bool IntersectionObservation::computeGeometry(LayoutRect& targetRect, LayoutRect & rootRect, LayoutRect& intersectionRect)
28 {
29 Element* rootElement = observer()->root();
30 bool rootIsDocumentElement = (rootElement == rootElement->document().documen tElement());
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
31 LayoutObject* rootLayoutObject = rootIsDocumentElement ? rootElement->docume nt().layoutView() : rootElement->layoutObject();
32 if (!rootLayoutObject->isBoxModelObject())
33 return false;
34 LayoutObject* targetLayoutObject = m_target->layoutObject();
35
36 // Initialize intersectionRect to bounds of target, in target's coordinate s pace.
37 if (targetLayoutObject->isBoxModelObject())
38 targetRect = intersectionRect = toLayoutBoxModelObject(targetLayoutObjec t)->visualOverflowRect();
39 else if (targetLayoutObject->isText())
40 targetRect = intersectionRect = toLayoutText(targetLayoutObject)->visual OverflowRect();
41 else
42 return false;
43
44 // Map targetRect into document coordinates.
45 targetRect = LayoutRect(targetLayoutObject->localToAbsoluteQuad(FloatQuad(Fl oatRect(targetRect)), UseTransforms | ApplyContainerFlip | TraverseDocumentBound aries).boundingBox());
46
47 // Map and clip intersectionRect into root element coordinates.
48 targetLayoutObject->mapToVisibleRectInContainerSpace(toLayoutBoxModelObject( rootLayoutObject), intersectionRect, nullptr);
49 if (rootLayoutObject->hasOverflowClip()) {
50 LayoutBox* rootLayoutBox = toLayoutBox(rootLayoutObject);
51 LayoutRect clipRect(LayoutPoint(), LayoutSize(rootLayoutBox->layer()->si ze()));
52 m_observer->applyRootMargin(clipRect);
53 rootLayoutBox->flipForWritingMode(intersectionRect);
54 intersectionRect.intersect(clipRect);
55 rootLayoutBox->flipForWritingMode(intersectionRect);
56 }
57
58 // Map intersectionRect into document coordinates.
59 intersectionRect = LayoutRect(rootLayoutObject->localToAbsoluteQuad(FloatQua d(FloatRect(intersectionRect))).boundingBox());
60
61 // Clip to FrameView visible area if necessary, and get root bounds in docum ent coordinates.
62 if (rootIsDocumentElement) {
63 rootRect = LayoutRect(rootElement->document().view()->visibleContentRect ());
64 m_observer->applyRootMargin(rootRect);
65 intersectionRect.intersect(rootRect);
66 } else {
67 if (rootLayoutObject->isBox())
68 rootRect = LayoutRect(toLayoutBox(rootLayoutObject)->absoluteContent Box());
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
69 else
70 rootRect = LayoutRect(rootLayoutObject->absoluteBoundingBoxRect());
71 m_observer->applyRootMargin(rootRect);
72 }
73
74 // Map all rects to FrameView coordinates.
75 LayoutPoint scrollPosition(rootElement->document().view()->scrollPosition()) ;
76 targetRect.moveBy(-scrollPosition);
77 intersectionRect.moveBy(-scrollPosition);
78 rootRect.moveBy(-scrollPosition);
79
80 if (intersectionRect.size().isZero())
81 intersectionRect = LayoutRect();
82
83 return true;
84 }
85
86 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
87 {
88 // TODO: rootMargin is not yet supported.
89 Element* targetElement = target();
90 if (!targetElement || !isActive())
91 return;
92 LayoutObject* targetLayoutObject = targetElement->layoutObject();
93 // TODO: Support SVG
94 if (!targetLayoutObject || (!targetLayoutObject->isBox() && !targetLayoutObj ect->isInline()))
esprehn 2015/12/12 00:14:13 break your early returns into multiple statements.
szager1 2015/12/16 19:15:34 Done.
95 return;
96
97 LayoutRect targetRect, rootRect, intersectionRect;
98 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.
99 return;
100 if (!m_canReportRootBounds)
101 rootRect = LayoutRect();
esprehn 2015/12/12 00:14:13 can computeGeometry do this instead of here?
szager1 2015/12/16 19:15:34 Done.
102
103 float intersectionArea = intersectionRect.size().width().toFloat() * interse ctionRect.size().height().toFloat();
104 float targetArea = targetRect.size().width().toFloat() * targetRect.size().h eight().toFloat();
105 if (!targetArea)
106 return;
esprehn 2015/12/12 00:14:13 can we move this before the intersectionArea compu
szager1 2015/12/16 19:15:34 Done.
107 float newVisibleRatio = intersectionArea / targetArea;
108 size_t newThresholdIndex = observer()->firstThresholdGreaterThan(newVisibleR atio);
109 size_t oldThresholdIndex = observer()->firstThresholdGreaterThan(lastVisible Ratio());
110 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.
111 if (oldThresholdIndex != newThresholdIndex)
112 observer()->enqueueIntersectionObserverEntry(new IntersectionObserverEnt ry(timestamp / 1000., pixelSnappedIntRect(targetRect), pixelSnappedIntRect(rootR ect), 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.
113 }
114
115 void IntersectionObservation::disconnect()
116 {
117 observer()->disconnect(*this);
118 if (m_target)
119 m_target->removeIntersectionObservation(*this);
120 }
121
122 DEFINE_TRACE(IntersectionObservation)
123 {
124 visitor->trace(m_observer);
125 visitor->trace(m_target);
126 }
127
128 } // namespace blink {
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698