| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 2000 Simon Hausmann <hausmann@kde.org> | 3 * (C) 2000 Simon Hausmann <hausmann@kde.org> |
| 4 * (C) 2000 Stefan Schimanski (1Stein@gmx.de) | 4 * (C) 2000 Stefan Schimanski (1Stein@gmx.de) |
| 5 * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. | 5 * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. |
| 6 * Copyright (C) Research In Motion Limited 2011. All rights reserved. | 6 * Copyright (C) Research In Motion Limited 2011. All rights reserved. |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 | 63 |
| 64 Element* element = toElement(node()); | 64 Element* element = toElement(node()); |
| 65 if (element && element->isFrameOwnerElement()) | 65 if (element && element->isFrameOwnerElement()) |
| 66 toHTMLFrameOwnerElement(element)->setWidget(nullptr); | 66 toHTMLFrameOwnerElement(element)->setWidget(nullptr); |
| 67 | 67 |
| 68 LayoutReplaced::willBeDestroyed(); | 68 LayoutReplaced::willBeDestroyed(); |
| 69 } | 69 } |
| 70 | 70 |
| 71 void LayoutPart::destroy() { | 71 void LayoutPart::destroy() { |
| 72 willBeDestroyed(); | 72 willBeDestroyed(); |
| 73 // We call clearNode here because LayoutPart is ref counted. This call to dest
roy | 73 // We call clearNode here because LayoutPart is ref counted. This call to |
| 74 // may not actually destroy the layout object. We can keep it around because o
f | 74 // destroy may not actually destroy the layout object. We can keep it around |
| 75 // references from the FrameView class. (The actual destruction of the class h
appens | 75 // because of references from the FrameView class. (The actual destruction of |
| 76 // in postDestroy() which is called from deref()). | 76 // the class happens in postDestroy() which is called from deref()). |
| 77 // | 77 // |
| 78 // But, we've told the system we've destroyed the layoutObject, which happens
when | 78 // But, we've told the system we've destroyed the layoutObject, which happens |
| 79 // the DOM node is destroyed. So there is a good change the DOM node this obje
ct | 79 // when the DOM node is destroyed. So there is a good change the DOM node this |
| 80 // points too is invalid, so we have to clear the node so we make sure we don'
t | 80 // object points too is invalid, so we have to clear the node so we make sure |
| 81 // access it in the future. | 81 // we don't access it in the future. |
| 82 clearNode(); | 82 clearNode(); |
| 83 deref(); | 83 deref(); |
| 84 } | 84 } |
| 85 | 85 |
| 86 LayoutPart::~LayoutPart() { | 86 LayoutPart::~LayoutPart() { |
| 87 ASSERT(m_refCount <= 0); | 87 ASSERT(m_refCount <= 0); |
| 88 } | 88 } |
| 89 | 89 |
| 90 Widget* LayoutPart::widget() const { | 90 Widget* LayoutPart::widget() const { |
| 91 // Plugin widgets are stored in their DOM node. | 91 // Plugin widgets are stored in their DOM node. |
| 92 Element* element = toElement(node()); | 92 Element* element = toElement(node()); |
| 93 | 93 |
| 94 if (element && element->isFrameOwnerElement()) | 94 if (element && element->isFrameOwnerElement()) |
| 95 return toHTMLFrameOwnerElement(element)->ownedWidget(); | 95 return toHTMLFrameOwnerElement(element)->ownedWidget(); |
| 96 | 96 |
| 97 return nullptr; | 97 return nullptr; |
| 98 } | 98 } |
| 99 | 99 |
| 100 PaintLayerType LayoutPart::layerTypeRequired() const { | 100 PaintLayerType LayoutPart::layerTypeRequired() const { |
| 101 PaintLayerType type = LayoutReplaced::layerTypeRequired(); | 101 PaintLayerType type = LayoutReplaced::layerTypeRequired(); |
| 102 if (type != NoPaintLayer) | 102 if (type != NoPaintLayer) |
| 103 return type; | 103 return type; |
| 104 return ForcedPaintLayer; | 104 return ForcedPaintLayer; |
| 105 } | 105 } |
| 106 | 106 |
| 107 bool LayoutPart::requiresAcceleratedCompositing() const { | 107 bool LayoutPart::requiresAcceleratedCompositing() const { |
| 108 // There are two general cases in which we can return true. First, if this is
a plugin | 108 // There are two general cases in which we can return true. First, if this is |
| 109 // LayoutObject and the plugin has a layer, then we need a layer. Second, if t
his is | 109 // a plugin LayoutObject and the plugin has a layer, then we need a layer. |
| 110 // a LayoutObject with a contentDocument and that document needs a layer, then
we need | 110 // Second, if this is a LayoutObject with a contentDocument and that document |
| 111 // a layer. | 111 // needs a layer, then we need a layer. |
| 112 if (widget() && widget()->isPluginView() && | 112 if (widget() && widget()->isPluginView() && |
| 113 toPluginView(widget())->platformLayer()) | 113 toPluginView(widget())->platformLayer()) |
| 114 return true; | 114 return true; |
| 115 | 115 |
| 116 if (!node() || !node()->isFrameOwnerElement()) | 116 if (!node() || !node()->isFrameOwnerElement()) |
| 117 return false; | 117 return false; |
| 118 | 118 |
| 119 HTMLFrameOwnerElement* element = toHTMLFrameOwnerElement(node()); | 119 HTMLFrameOwnerElement* element = toHTMLFrameOwnerElement(node()); |
| 120 if (element->contentFrame() && element->contentFrame()->isRemoteFrame()) | 120 if (element->contentFrame() && element->contentFrame()->isRemoteFrame()) |
| 121 return true; | 121 return true; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 137 | 137 |
| 138 bool LayoutPart::nodeAtPointOverWidget( | 138 bool LayoutPart::nodeAtPointOverWidget( |
| 139 HitTestResult& result, | 139 HitTestResult& result, |
| 140 const HitTestLocation& locationInContainer, | 140 const HitTestLocation& locationInContainer, |
| 141 const LayoutPoint& accumulatedOffset, | 141 const LayoutPoint& accumulatedOffset, |
| 142 HitTestAction action) { | 142 HitTestAction action) { |
| 143 bool hadResult = result.innerNode(); | 143 bool hadResult = result.innerNode(); |
| 144 bool inside = LayoutReplaced::nodeAtPoint(result, locationInContainer, | 144 bool inside = LayoutReplaced::nodeAtPoint(result, locationInContainer, |
| 145 accumulatedOffset, action); | 145 accumulatedOffset, action); |
| 146 | 146 |
| 147 // Check to see if we are really over the widget itself (and not just in the b
order/padding area). | 147 // Check to see if we are really over the widget itself (and not just in the |
| 148 // border/padding area). |
| 148 if ((inside || result.isRectBasedTest()) && !hadResult && | 149 if ((inside || result.isRectBasedTest()) && !hadResult && |
| 149 result.innerNode() == node()) | 150 result.innerNode() == node()) |
| 150 result.setIsOverWidget(contentBoxRect().contains(result.localPoint())); | 151 result.setIsOverWidget(contentBoxRect().contains(result.localPoint())); |
| 151 return inside; | 152 return inside; |
| 152 } | 153 } |
| 153 | 154 |
| 154 bool LayoutPart::nodeAtPoint(HitTestResult& result, | 155 bool LayoutPart::nodeAtPoint(HitTestResult& result, |
| 155 const HitTestLocation& locationInContainer, | 156 const HitTestLocation& locationInContainer, |
| 156 const LayoutPoint& accumulatedOffset, | 157 const LayoutPoint& accumulatedOffset, |
| 157 HitTestAction action) { | 158 HitTestAction action) { |
| 158 if (!widget() || !widget()->isFrameView() || | 159 if (!widget() || !widget()->isFrameView() || |
| 159 !result.hitTestRequest().allowsChildFrameContent()) | 160 !result.hitTestRequest().allowsChildFrameContent()) |
| 160 return nodeAtPointOverWidget(result, locationInContainer, accumulatedOffset, | 161 return nodeAtPointOverWidget(result, locationInContainer, accumulatedOffset, |
| 161 action); | 162 action); |
| 162 | 163 |
| 163 // A hit test can never hit an off-screen element; only off-screen iframes are
throttled; | 164 // A hit test can never hit an off-screen element; only off-screen iframes are |
| 164 // therefore, hit tests can skip descending into throttled iframes. | 165 // throttled; therefore, hit tests can skip descending into throttled iframes. |
| 165 if (toFrameView(widget())->shouldThrottleRendering()) | 166 if (toFrameView(widget())->shouldThrottleRendering()) |
| 166 return nodeAtPointOverWidget(result, locationInContainer, accumulatedOffset, | 167 return nodeAtPointOverWidget(result, locationInContainer, accumulatedOffset, |
| 167 action); | 168 action); |
| 168 | 169 |
| 169 ASSERT(document().lifecycle().state() >= DocumentLifecycle::CompositingClean); | 170 ASSERT(document().lifecycle().state() >= DocumentLifecycle::CompositingClean); |
| 170 | 171 |
| 171 if (action == HitTestForeground) { | 172 if (action == HitTestForeground) { |
| 172 FrameView* childFrameView = toFrameView(widget()); | 173 FrameView* childFrameView = toFrameView(widget()); |
| 173 LayoutViewItem childRootItem = childFrameView->layoutViewItem(); | 174 LayoutViewItem childRootItem = childFrameView->layoutViewItem(); |
| 174 | 175 |
| 175 if (visibleToHitTestRequest(result.hitTestRequest()) && | 176 if (visibleToHitTestRequest(result.hitTestRequest()) && |
| 176 !childRootItem.isNull()) { | 177 !childRootItem.isNull()) { |
| 177 LayoutPoint adjustedLocation = accumulatedOffset + location(); | 178 LayoutPoint adjustedLocation = accumulatedOffset + location(); |
| 178 LayoutPoint contentOffset = LayoutPoint(borderLeft() + paddingLeft(), | 179 LayoutPoint contentOffset = LayoutPoint(borderLeft() + paddingLeft(), |
| 179 borderTop() + paddingTop()) - | 180 borderTop() + paddingTop()) - |
| 180 LayoutSize(childFrameView->scrollOffsetInt()); | 181 LayoutSize(childFrameView->scrollOffsetInt()); |
| 181 HitTestLocation newHitTestLocation(locationInContainer, | 182 HitTestLocation newHitTestLocation(locationInContainer, |
| 182 -adjustedLocation - contentOffset); | 183 -adjustedLocation - contentOffset); |
| 183 HitTestRequest newHitTestRequest(result.hitTestRequest().type() | | 184 HitTestRequest newHitTestRequest(result.hitTestRequest().type() | |
| 184 HitTestRequest::ChildFrameHitTest); | 185 HitTestRequest::ChildFrameHitTest); |
| 185 HitTestResult childFrameResult(newHitTestRequest, newHitTestLocation); | 186 HitTestResult childFrameResult(newHitTestRequest, newHitTestLocation); |
| 186 | 187 |
| 187 // The frame's layout and style must be up to date if we reach here. | 188 // The frame's layout and style must be up to date if we reach here. |
| 188 bool isInsideChildFrame = | 189 bool isInsideChildFrame = |
| 189 childRootItem.hitTestNoLifecycleUpdate(childFrameResult); | 190 childRootItem.hitTestNoLifecycleUpdate(childFrameResult); |
| 190 | 191 |
| 191 if (result.hitTestRequest().listBased()) { | 192 if (result.hitTestRequest().listBased()) { |
| 192 result.append(childFrameResult); | 193 result.append(childFrameResult); |
| 193 } else if (isInsideChildFrame) { | 194 } else if (isInsideChildFrame) { |
| 194 // Force the result not to be cacheable because the parent | 195 // Force the result not to be cacheable because the parent frame should |
| 195 // frame should not cache this result; as it won't be notified of | 196 // not cache this result; as it won't be notified of changes in the |
| 196 // changes in the child. | 197 // child. |
| 197 childFrameResult.setCacheable(false); | 198 childFrameResult.setCacheable(false); |
| 198 result = childFrameResult; | 199 result = childFrameResult; |
| 199 } | 200 } |
| 200 | 201 |
| 201 // Don't trust |isInsideChildFrame|. For rect-based hit-test, returns | 202 // Don't trust |isInsideChildFrame|. For rect-based hit-test, returns |
| 202 // true only when the hit test rect is totally within the iframe, | 203 // true only when the hit test rect is totally within the iframe, |
| 203 // i.e. nodeAtPointOverWidget() also returns true. | 204 // i.e. nodeAtPointOverWidget() also returns true. |
| 204 // Use a temporary HitTestResult because we don't want to collect the | 205 // Use a temporary HitTestResult because we don't want to collect the |
| 205 // iframe element itself if the hit-test rect is totally within the iframe
. | 206 // iframe element itself if the hit-test rect is totally within the |
| 207 // iframe. |
| 206 if (isInsideChildFrame) { | 208 if (isInsideChildFrame) { |
| 207 if (!locationInContainer.isRectBasedTest()) | 209 if (!locationInContainer.isRectBasedTest()) |
| 208 return true; | 210 return true; |
| 209 HitTestResult pointOverWidgetResult = result; | 211 HitTestResult pointOverWidgetResult = result; |
| 210 bool pointOverWidget = | 212 bool pointOverWidget = |
| 211 nodeAtPointOverWidget(pointOverWidgetResult, locationInContainer, | 213 nodeAtPointOverWidget(pointOverWidgetResult, locationInContainer, |
| 212 accumulatedOffset, action); | 214 accumulatedOffset, action); |
| 213 if (pointOverWidget) | 215 if (pointOverWidget) |
| 214 return true; | 216 return true; |
| 215 result = pointOverWidgetResult; | 217 result = pointOverWidgetResult; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 } | 261 } |
| 260 | 262 |
| 261 void LayoutPart::paintContents(const PaintInfo& paintInfo, | 263 void LayoutPart::paintContents(const PaintInfo& paintInfo, |
| 262 const LayoutPoint& paintOffset) const { | 264 const LayoutPoint& paintOffset) const { |
| 263 PartPainter(*this).paintContents(paintInfo, paintOffset); | 265 PartPainter(*this).paintContents(paintInfo, paintOffset); |
| 264 } | 266 } |
| 265 | 267 |
| 266 CursorDirective LayoutPart::getCursor(const LayoutPoint& point, | 268 CursorDirective LayoutPart::getCursor(const LayoutPoint& point, |
| 267 Cursor& cursor) const { | 269 Cursor& cursor) const { |
| 268 if (widget() && widget()->isPluginView()) { | 270 if (widget() && widget()->isPluginView()) { |
| 269 // A plugin is responsible for setting the cursor when the pointer is over i
t. | 271 // A plugin is responsible for setting the cursor when the pointer is over |
| 272 // it. |
| 270 return DoNotSetCursor; | 273 return DoNotSetCursor; |
| 271 } | 274 } |
| 272 return LayoutReplaced::getCursor(point, cursor); | 275 return LayoutReplaced::getCursor(point, cursor); |
| 273 } | 276 } |
| 274 | 277 |
| 275 LayoutRect LayoutPart::replacedContentRect() const { | 278 LayoutRect LayoutPart::replacedContentRect() const { |
| 276 // We don't propagate sub-pixel into sub-frame layout, in other words, the rec
t is snapped | 279 // We don't propagate sub-pixel into sub-frame layout, in other words, the |
| 277 // at the document boundary, and sub-pixel movement could cause the sub-frame
to layout | 280 // rect is snapped at the document boundary, and sub-pixel movement could |
| 278 // due to the 1px snap difference. In order to avoid that, the size of sub-fra
me is rounded | 281 // cause the sub-frame to layout due to the 1px snap difference. In order to |
| 279 // in advance. | 282 // avoid that, the size of sub-frame is rounded in advance. |
| 280 LayoutRect sizeRoundedRect = contentBoxRect(); | 283 LayoutRect sizeRoundedRect = contentBoxRect(); |
| 281 sizeRoundedRect.setSize(LayoutSize(roundedIntSize(sizeRoundedRect.size()))); | 284 sizeRoundedRect.setSize(LayoutSize(roundedIntSize(sizeRoundedRect.size()))); |
| 282 return sizeRoundedRect; | 285 return sizeRoundedRect; |
| 283 } | 286 } |
| 284 | 287 |
| 285 void LayoutPart::updateOnWidgetChange() { | 288 void LayoutPart::updateOnWidgetChange() { |
| 286 Widget* widget = this->widget(); | 289 Widget* widget = this->widget(); |
| 287 if (!widget) | 290 if (!widget) |
| 288 return; | 291 return; |
| 289 | 292 |
| 290 if (!style()) | 293 if (!style()) |
| 291 return; | 294 return; |
| 292 | 295 |
| 293 if (!needsLayout()) | 296 if (!needsLayout()) |
| 294 updateWidgetGeometryInternal(); | 297 updateWidgetGeometryInternal(); |
| 295 | 298 |
| 296 if (style()->visibility() != EVisibility::Visible) { | 299 if (style()->visibility() != EVisibility::Visible) { |
| 297 widget->hide(); | 300 widget->hide(); |
| 298 } else { | 301 } else { |
| 299 widget->show(); | 302 widget->show(); |
| 300 // FIXME: Why do we issue a full paint invalidation in this case, but not th
e other? | 303 // FIXME: Why do we issue a full paint invalidation in this case, but not |
| 304 // the other? |
| 301 setShouldDoFullPaintInvalidation(); | 305 setShouldDoFullPaintInvalidation(); |
| 302 } | 306 } |
| 303 } | 307 } |
| 304 | 308 |
| 305 void LayoutPart::updateWidgetGeometry() { | 309 void LayoutPart::updateWidgetGeometry() { |
| 306 Widget* widget = this->widget(); | 310 Widget* widget = this->widget(); |
| 307 if (!widget || !node()) // Check the node in case destroy() has been called. | 311 if (!widget || !node()) // Check the node in case destroy() has been called. |
| 308 return; | 312 return; |
| 309 | 313 |
| 310 LayoutRect newFrame = replacedContentRect(); | 314 LayoutRect newFrame = replacedContentRect(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 331 frameView->layout(); | 335 frameView->layout(); |
| 332 | 336 |
| 333 widget->widgetGeometryMayHaveChanged(); | 337 widget->widgetGeometryMayHaveChanged(); |
| 334 } | 338 } |
| 335 | 339 |
| 336 void LayoutPart::updateWidgetGeometryInternal() { | 340 void LayoutPart::updateWidgetGeometryInternal() { |
| 337 Widget* widget = this->widget(); | 341 Widget* widget = this->widget(); |
| 338 ASSERT(widget); | 342 ASSERT(widget); |
| 339 | 343 |
| 340 // Ignore transform here, as we only care about the sub-pixel accumulation. | 344 // Ignore transform here, as we only care about the sub-pixel accumulation. |
| 341 // TODO(trchen): What about multicol? Need a LayoutBox function to query sub-p
ixel accumulation. | 345 // TODO(trchen): What about multicol? Need a LayoutBox function to query |
| 346 // sub-pixel accumulation. |
| 342 LayoutPoint absoluteLocation(localToAbsolute(FloatPoint())); | 347 LayoutPoint absoluteLocation(localToAbsolute(FloatPoint())); |
| 343 LayoutRect absoluteReplacedRect = replacedContentRect(); | 348 LayoutRect absoluteReplacedRect = replacedContentRect(); |
| 344 absoluteReplacedRect.moveBy(absoluteLocation); | 349 absoluteReplacedRect.moveBy(absoluteLocation); |
| 345 | 350 |
| 346 IntRect frameRect(IntPoint(), | 351 IntRect frameRect(IntPoint(), |
| 347 pixelSnappedIntRect(absoluteReplacedRect).size()); | 352 pixelSnappedIntRect(absoluteReplacedRect).size()); |
| 348 // Normally the location of the frame rect is ignored by the painter, but curr
ently it is | 353 // Normally the location of the frame rect is ignored by the painter, but |
| 349 // still used by a family of coordinate conversion function in Widget/FrameVie
w. This is | 354 // currently it is still used by a family of coordinate conversion function in |
| 350 // incorrect because coordinate conversion needs to take transform and into ac
count. | 355 // Widget/FrameView. This is incorrect because coordinate conversion needs to |
| 351 // A few callers still use the family of conversion function, including but no
t exhaustive: | 356 // take transform and into account. |
| 357 // A few callers still use the family of conversion function, including but |
| 358 // not exhaustive: |
| 352 // FrameView::updateViewportIntersectionIfNeeded() | 359 // FrameView::updateViewportIntersectionIfNeeded() |
| 353 // RemoteFrameView::frameRectsChanged(). | 360 // RemoteFrameView::frameRectsChanged(). |
| 354 // WebPluginContainerImpl::reportGeometry() | 361 // WebPluginContainerImpl::reportGeometry() |
| 355 // TODO(trchen): Remove this hack once we fixed all callers. | 362 // TODO(trchen): Remove this hack once we fixed all callers. |
| 356 FloatRect absoluteBoundingBox = | 363 FloatRect absoluteBoundingBox = |
| 357 localToAbsoluteQuad(FloatRect(replacedContentRect())).boundingBox(); | 364 localToAbsoluteQuad(FloatRect(replacedContentRect())).boundingBox(); |
| 358 frameRect.setLocation(roundedIntPoint(absoluteBoundingBox.location())); | 365 frameRect.setLocation(roundedIntPoint(absoluteBoundingBox.location())); |
| 359 | 366 |
| 360 // Why is the protector needed? | 367 // Why is the protector needed? |
| 361 RefPtr<LayoutPart> protector(this); | 368 RefPtr<LayoutPart> protector(this); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 382 } | 389 } |
| 383 | 390 |
| 384 bool LayoutPart::isThrottledFrameView() const { | 391 bool LayoutPart::isThrottledFrameView() const { |
| 385 if (!widget() || !widget()->isFrameView()) | 392 if (!widget() || !widget()->isFrameView()) |
| 386 return false; | 393 return false; |
| 387 const FrameView* frameView = toFrameView(widget()); | 394 const FrameView* frameView = toFrameView(widget()); |
| 388 return frameView->shouldThrottleRendering(); | 395 return frameView->shouldThrottleRendering(); |
| 389 } | 396 } |
| 390 | 397 |
| 391 } // namespace blink | 398 } // namespace blink |
| OLD | NEW |