OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | |
3 * (C) 2000 Simon Hausmann <hausmann@kde.org> | |
4 * (C) 2000 Stefan Schimanski (1Stein@gmx.de) | |
5 * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. | |
6 * Copyright (C) Research In Motion Limited 2011. All rights reserved. | |
7 * | |
8 * This library is free software; you can redistribute it and/or | |
9 * modify it under the terms of the GNU Library General Public | |
10 * License as published by the Free Software Foundation; either | |
11 * version 2 of the License, or (at your option) any later version. | |
12 * | |
13 * This library is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Library General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Library General Public License | |
19 * along with this library; see the file COPYING.LIB. If not, write to | |
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
21 * Boston, MA 02110-1301, USA. | |
22 * | |
23 */ | |
24 | |
25 #include "config.h" | |
26 #include "core/rendering/RenderPart.h" | |
27 | |
28 #include "core/dom/AXObjectCache.h" | |
29 #include "core/frame/FrameView.h" | |
30 #include "core/frame/LocalFrame.h" | |
31 #include "core/html/HTMLFrameElementBase.h" | |
32 #include "core/layout/HitTestResult.h" | |
33 #include "core/layout/Layer.h" | |
34 #include "core/paint/BoxPainter.h" | |
35 #include "core/paint/PartPainter.h" | |
36 #include "core/plugins/PluginView.h" | |
37 #include "core/rendering/RenderView.h" | |
38 #include "core/rendering/svg/RenderSVGRoot.h" | |
39 | |
40 namespace blink { | |
41 | |
42 RenderPart::RenderPart(Element* element) | |
43 : LayoutReplaced(element) | |
44 // Reference counting is used to prevent the part from being destroyed | |
45 // while inside the Widget code, which might not be able to handle that. | |
46 , m_refCount(1) | |
47 { | |
48 ASSERT(element); | |
49 frameView()->addPart(this); | |
50 setInline(false); | |
51 } | |
52 | |
53 void RenderPart::deref() | |
54 { | |
55 if (--m_refCount <= 0) | |
56 postDestroy(); | |
57 } | |
58 | |
59 void RenderPart::willBeDestroyed() | |
60 { | |
61 frameView()->removePart(this); | |
62 | |
63 if (AXObjectCache* cache = document().existingAXObjectCache()) { | |
64 cache->childrenChanged(this->parent()); | |
65 cache->remove(this); | |
66 } | |
67 | |
68 Element* element = toElement(node()); | |
69 if (element && element->isFrameOwnerElement()) | |
70 toHTMLFrameOwnerElement(element)->setWidget(nullptr); | |
71 | |
72 LayoutReplaced::willBeDestroyed(); | |
73 } | |
74 | |
75 void RenderPart::destroy() | |
76 { | |
77 willBeDestroyed(); | |
78 clearNode(); | |
79 deref(); | |
80 } | |
81 | |
82 RenderPart::~RenderPart() | |
83 { | |
84 ASSERT(m_refCount <= 0); | |
85 } | |
86 | |
87 Widget* RenderPart::widget() const | |
88 { | |
89 // Plugin widgets are stored in their DOM node. This includes HTMLAppletElem
ent. | |
90 Element* element = toElement(node()); | |
91 | |
92 if (element && element->isFrameOwnerElement()) | |
93 return toHTMLFrameOwnerElement(element)->ownedWidget(); | |
94 | |
95 return 0; | |
96 } | |
97 | |
98 LayerType RenderPart::layerTypeRequired() const | |
99 { | |
100 LayerType type = LayoutReplaced::layerTypeRequired(); | |
101 if (type != NoLayer) | |
102 return type; | |
103 return ForcedLayer; | |
104 } | |
105 | |
106 bool RenderPart::requiresAcceleratedCompositing() const | |
107 { | |
108 // There are two general cases in which we can return true. First, if this i
s a plugin | |
109 // renderer and the plugin has a layer, then we need a layer. Second, if thi
s is | |
110 // a renderer with a contentDocument and that document needs a layer, then w
e need | |
111 // a layer. | |
112 if (widget() && widget()->isPluginView() && toPluginView(widget())->platform
Layer()) | |
113 return true; | |
114 | |
115 if (!node() || !node()->isFrameOwnerElement()) | |
116 return false; | |
117 | |
118 HTMLFrameOwnerElement* element = toHTMLFrameOwnerElement(node()); | |
119 if (element->contentFrame() && element->contentFrame()->isRemoteFrame()) | |
120 return true; | |
121 | |
122 if (Document* contentDocument = element->contentDocument()) { | |
123 if (RenderView* view = contentDocument->renderView()) | |
124 return view->usesCompositing(); | |
125 } | |
126 | |
127 return false; | |
128 } | |
129 | |
130 bool RenderPart::needsPreferredWidthsRecalculation() const | |
131 { | |
132 if (LayoutReplaced::needsPreferredWidthsRecalculation()) | |
133 return true; | |
134 return embeddedContentBox(); | |
135 } | |
136 | |
137 bool RenderPart::nodeAtPointOverWidget(const HitTestRequest& request, HitTestRes
ult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accu
mulatedOffset, HitTestAction action) | |
138 { | |
139 bool hadResult = result.innerNode(); | |
140 bool inside = LayoutReplaced::nodeAtPoint(request, result, locationInContain
er, accumulatedOffset, action); | |
141 | |
142 // Check to see if we are really over the widget itself (and not just in the
border/padding area). | |
143 if ((inside || result.isRectBasedTest()) && !hadResult && result.innerNode()
== node()) | |
144 result.setIsOverWidget(contentBoxRect().contains(result.localPoint())); | |
145 return inside; | |
146 } | |
147 | |
148 bool RenderPart::nodeAtPoint(const HitTestRequest& request, HitTestResult& resul
t, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOff
set, HitTestAction action) | |
149 { | |
150 if (!widget() || !widget()->isFrameView() || !request.allowsChildFrameConten
t()) | |
151 return nodeAtPointOverWidget(request, result, locationInContainer, accum
ulatedOffset, action); | |
152 | |
153 FrameView* childFrameView = toFrameView(widget()); | |
154 RenderView* childRoot = childFrameView->renderView(); | |
155 | |
156 if (visibleToHitTestRequest(request) && childRoot) { | |
157 LayoutPoint adjustedLocation = accumulatedOffset + location(); | |
158 LayoutPoint contentOffset = LayoutPoint(borderLeft() + paddingLeft(), bo
rderTop() + paddingTop()) - LayoutSize(childFrameView->scrollOffset()); | |
159 HitTestLocation newHitTestLocation(locationInContainer, -adjustedLocatio
n - contentOffset); | |
160 HitTestRequest newHitTestRequest(request.type() | HitTestRequest::ChildF
rameHitTest); | |
161 HitTestResult childFrameResult(newHitTestLocation); | |
162 | |
163 bool isInsideChildFrame = childRoot->hitTest(newHitTestRequest, newHitTe
stLocation, childFrameResult); | |
164 | |
165 if (newHitTestLocation.isRectBasedTest()) | |
166 result.append(childFrameResult); | |
167 else if (isInsideChildFrame) | |
168 result = childFrameResult; | |
169 | |
170 if (isInsideChildFrame) | |
171 return true; | |
172 } | |
173 | |
174 return nodeAtPointOverWidget(request, result, locationInContainer, accumulat
edOffset, action); | |
175 } | |
176 | |
177 CompositingReasons RenderPart::additionalCompositingReasons() const | |
178 { | |
179 if (requiresAcceleratedCompositing()) | |
180 return CompositingReasonIFrame; | |
181 return CompositingReasonNone; | |
182 } | |
183 | |
184 void RenderPart::styleDidChange(StyleDifference diff, const LayoutStyle* oldStyl
e) | |
185 { | |
186 LayoutReplaced::styleDidChange(diff, oldStyle); | |
187 Widget* widget = this->widget(); | |
188 | |
189 if (!widget) | |
190 return; | |
191 | |
192 // If the iframe has custom scrollbars, recalculate their style. | |
193 if (widget && widget->isFrameView()) | |
194 toFrameView(widget)->recalculateCustomScrollbarStyle(); | |
195 | |
196 if (style()->visibility() != VISIBLE) { | |
197 widget->hide(); | |
198 } else { | |
199 widget->show(); | |
200 } | |
201 } | |
202 | |
203 void RenderPart::layout() | |
204 { | |
205 ASSERT(needsLayout()); | |
206 | |
207 clearNeedsLayout(); | |
208 } | |
209 | |
210 void RenderPart::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffse
t) | |
211 { | |
212 PartPainter(*this).paint(paintInfo, paintOffset); | |
213 } | |
214 | |
215 void RenderPart::paintContents(const PaintInfo& paintInfo, const LayoutPoint& pa
intOffset) | |
216 { | |
217 PartPainter(*this).paintContents(paintInfo, paintOffset); | |
218 } | |
219 | |
220 CursorDirective RenderPart::getCursor(const LayoutPoint& point, Cursor& cursor)
const | |
221 { | |
222 if (widget() && widget()->isPluginView()) { | |
223 // A plug-in is responsible for setting the cursor when the pointer is o
ver it. | |
224 return DoNotSetCursor; | |
225 } | |
226 return LayoutReplaced::getCursor(point, cursor); | |
227 } | |
228 | |
229 void RenderPart::updateOnWidgetChange() | |
230 { | |
231 Widget* widget = this->widget(); | |
232 if (!widget) | |
233 return; | |
234 | |
235 if (!style()) | |
236 return; | |
237 | |
238 if (!needsLayout()) | |
239 updateWidgetGeometry(); | |
240 | |
241 if (style()->visibility() != VISIBLE) { | |
242 widget->hide(); | |
243 } else { | |
244 widget->show(); | |
245 // FIXME: Why do we issue a full paint invalidation in this case, but no
t the other? | |
246 setShouldDoFullPaintInvalidation(); | |
247 } | |
248 } | |
249 | |
250 void RenderPart::updateWidgetPosition() | |
251 { | |
252 Widget* widget = this->widget(); | |
253 if (!widget || !node()) // Check the node in case destroy() has been called. | |
254 return; | |
255 | |
256 bool boundsChanged = updateWidgetGeometry(); | |
257 | |
258 // If the frame bounds got changed, or if view needs layout (possibly indica
ting | |
259 // content size is wrong) we have to do a layout to set the right widget siz
e. | |
260 if (widget && widget->isFrameView()) { | |
261 FrameView* frameView = toFrameView(widget); | |
262 // Check the frame's page to make sure that the frame isn't in the proce
ss of being destroyed. | |
263 if ((boundsChanged || frameView->needsLayout()) && frameView->frame().pa
ge()) | |
264 frameView->layout(); | |
265 } | |
266 } | |
267 | |
268 void RenderPart::widgetPositionsUpdated() | |
269 { | |
270 Widget* widget = this->widget(); | |
271 if (!widget) | |
272 return; | |
273 widget->widgetPositionsUpdated(); | |
274 } | |
275 | |
276 bool RenderPart::updateWidgetGeometry() | |
277 { | |
278 Widget* widget = this->widget(); | |
279 ASSERT(widget); | |
280 | |
281 LayoutRect contentBox = contentBoxRect(); | |
282 LayoutRect absoluteContentBox(localToAbsoluteQuad(FloatQuad(contentBox)).bou
ndingBox()); | |
283 if (widget->isFrameView()) { | |
284 contentBox.setLocation(absoluteContentBox.location()); | |
285 return setWidgetGeometry(contentBox); | |
286 } | |
287 | |
288 return setWidgetGeometry(absoluteContentBox); | |
289 } | |
290 | |
291 // Widgets are always placed on integer boundaries, so rounding the size is actu
ally | |
292 // the desired behavior. This function is here because it's otherwise seldom wha
t we | |
293 // want to do with a LayoutRect. | |
294 static inline IntRect roundedIntRect(const LayoutRect& rect) | |
295 { | |
296 return IntRect(roundedIntPoint(rect.location()), roundedIntSize(rect.size())
); | |
297 } | |
298 | |
299 bool RenderPart::setWidgetGeometry(const LayoutRect& frame) | |
300 { | |
301 if (!node()) | |
302 return false; | |
303 | |
304 Widget* widget = this->widget(); | |
305 ASSERT(widget); | |
306 | |
307 IntRect newFrame = roundedIntRect(frame); | |
308 | |
309 if (widget->frameRect() == newFrame) | |
310 return false; | |
311 | |
312 RefPtrWillBeRawPtr<RenderPart> protector(this); | |
313 RefPtrWillBeRawPtr<Node> protectedNode(node()); | |
314 widget->setFrameRect(newFrame); | |
315 return widget->frameRect().size() != newFrame.size(); | |
316 } | |
317 | |
318 } | |
OLD | NEW |