OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. | 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. |
| 4 * All rights reserved. |
4 * | 5 * |
5 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
6 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
7 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
8 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
9 * | 10 * |
10 * This library is distributed in the hope that it will be useful, | 11 * This library is distributed in the hope that it will be useful, |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 * Library General Public License for more details. | 14 * Library General Public License for more details. |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 m_maxPreferredLogicalWidth = LayoutUnit(); | 104 m_maxPreferredLogicalWidth = LayoutUnit(); |
104 | 105 |
105 setPreferredLogicalWidthsDirty(MarkOnlyThis); | 106 setPreferredLogicalWidthsDirty(MarkOnlyThis); |
106 | 107 |
107 setPositionState(AbsolutePosition); // to 0,0 :) | 108 setPositionState(AbsolutePosition); // to 0,0 :) |
108 } | 109 } |
109 | 110 |
110 LayoutView::~LayoutView() {} | 111 LayoutView::~LayoutView() {} |
111 | 112 |
112 bool LayoutView::hitTest(HitTestResult& result) { | 113 bool LayoutView::hitTest(HitTestResult& result) { |
113 // We have to recursively update layout/style here because otherwise, when the
hit test recurses | 114 // We have to recursively update layout/style here because otherwise, when the |
114 // into a child document, it could trigger a layout on the parent document, wh
ich can destroy PaintLayer | 115 // hit test recurses into a child document, it could trigger a layout on the |
115 // that are higher up in the call stack, leading to crashes. | 116 // parent document, which can destroy PaintLayer that are higher up in the |
| 117 // call stack, leading to crashes. |
116 // Note that Document::updateLayout calls its parent's updateLayout. | 118 // Note that Document::updateLayout calls its parent's updateLayout. |
117 // Note that if an iframe has its render pipeline throttled, it will not updat
e layout here, | 119 // Note that if an iframe has its render pipeline throttled, it will not |
118 // and it will also not propagate the hit test into the iframe's inner documen
t. | 120 // update layout here, and it will also not propagate the hit test into the |
| 121 // iframe's inner document. |
119 frameView()->updateLifecycleToCompositingCleanPlusScrolling(); | 122 frameView()->updateLifecycleToCompositingCleanPlusScrolling(); |
120 HitTestLatencyRecorder hitTestLatencyRecorder( | 123 HitTestLatencyRecorder hitTestLatencyRecorder( |
121 result.hitTestRequest().allowsChildFrameContent()); | 124 result.hitTestRequest().allowsChildFrameContent()); |
122 return hitTestNoLifecycleUpdate(result); | 125 return hitTestNoLifecycleUpdate(result); |
123 } | 126 } |
124 | 127 |
125 bool LayoutView::hitTestNoLifecycleUpdate(HitTestResult& result) { | 128 bool LayoutView::hitTestNoLifecycleUpdate(HitTestResult& result) { |
126 TRACE_EVENT_BEGIN0("blink,devtools.timeline", "HitTest"); | 129 TRACE_EVENT_BEGIN0("blink,devtools.timeline", "HitTest"); |
127 m_hitTestCount++; | 130 m_hitTestCount++; |
128 | 131 |
129 ASSERT(!result.hitTestLocation().isRectBasedTest() || | 132 ASSERT(!result.hitTestLocation().isRectBasedTest() || |
130 result.hitTestRequest().listBased()); | 133 result.hitTestRequest().listBased()); |
131 | 134 |
132 commitPendingSelection(); | 135 commitPendingSelection(); |
133 | 136 |
134 uint64_t domTreeVersion = document().domTreeVersion(); | 137 uint64_t domTreeVersion = document().domTreeVersion(); |
135 HitTestResult cacheResult = result; | 138 HitTestResult cacheResult = result; |
136 bool hitLayer = false; | 139 bool hitLayer = false; |
137 if (m_hitTestCache->lookupCachedResult(cacheResult, domTreeVersion)) { | 140 if (m_hitTestCache->lookupCachedResult(cacheResult, domTreeVersion)) { |
138 m_hitTestCacheHits++; | 141 m_hitTestCacheHits++; |
139 hitLayer = true; | 142 hitLayer = true; |
140 result = cacheResult; | 143 result = cacheResult; |
141 } else { | 144 } else { |
142 hitLayer = layer()->hitTest(result); | 145 hitLayer = layer()->hitTest(result); |
143 | 146 |
144 // FrameView scrollbars are not the same as Layer scrollbars tested by Layer
::hitTestOverflowControls, | 147 // FrameView scrollbars are not the same as Layer scrollbars tested by |
145 // so we need to test FrameView scrollbars separately here. Note that it's i
mportant we do this after | 148 // Layer::hitTestOverflowControls, so we need to test FrameView scrollbars |
146 // the hit test above, because that may overwrite the entire HitTestResult w
hen it finds a hit. | 149 // separately here. Note that it's important we do this after the hit test |
| 150 // above, because that may overwrite the entire HitTestResult when it finds |
| 151 // a hit. |
147 IntPoint framePoint = | 152 IntPoint framePoint = |
148 frameView()->contentsToFrame(result.hitTestLocation().roundedPoint()); | 153 frameView()->contentsToFrame(result.hitTestLocation().roundedPoint()); |
149 if (Scrollbar* frameScrollbar = | 154 if (Scrollbar* frameScrollbar = |
150 frameView()->scrollbarAtFramePoint(framePoint)) | 155 frameView()->scrollbarAtFramePoint(framePoint)) |
151 result.setScrollbar(frameScrollbar); | 156 result.setScrollbar(frameScrollbar); |
152 | 157 |
153 if (hitLayer) | 158 if (hitLayer) |
154 m_hitTestCache->addCachedResult(result, domTreeVersion); | 159 m_hitTestCache->addCachedResult(result, domTreeVersion); |
155 } | 160 } |
156 | 161 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 #endif | 199 #endif |
195 } | 200 } |
196 | 201 |
197 #if ENABLE(ASSERT) | 202 #if ENABLE(ASSERT) |
198 void LayoutView::checkLayoutState() { | 203 void LayoutView::checkLayoutState() { |
199 ASSERT(!m_layoutState->next()); | 204 ASSERT(!m_layoutState->next()); |
200 } | 205 } |
201 #endif | 206 #endif |
202 | 207 |
203 void LayoutView::setShouldDoFullPaintInvalidationOnResizeIfNeeded() { | 208 void LayoutView::setShouldDoFullPaintInvalidationOnResizeIfNeeded() { |
204 // When background-attachment is 'fixed', we treat the viewport (instead of th
e 'root' | 209 // When background-attachment is 'fixed', we treat the viewport (instead of |
205 // i.e. html or body) as the background positioning area, and we should fully
invalidate | 210 // the 'root' i.e. html or body) as the background positioning area, and we |
206 // on viewport resize if the background image is not composited and needs full
paint | 211 // should fully invalidate on viewport resize if the background image is not |
207 // invalidation on background positioning area resize. | 212 // composited and needs full paint invalidation on background positioning area |
| 213 // resize. |
208 if (style()->hasFixedBackgroundImage() && | 214 if (style()->hasFixedBackgroundImage() && |
209 (!m_compositor || | 215 (!m_compositor || |
210 !m_compositor->needsFixedRootBackgroundLayer(layer()))) { | 216 !m_compositor->needsFixedRootBackgroundLayer(layer()))) { |
211 IncludeScrollbarsInRect includeScrollbars = | 217 IncludeScrollbarsInRect includeScrollbars = |
212 RuntimeEnabledFeatures::rootLayerScrollingEnabled() ? IncludeScrollbars | 218 RuntimeEnabledFeatures::rootLayerScrollingEnabled() ? IncludeScrollbars |
213 : ExcludeScrollbars; | 219 : ExcludeScrollbars; |
214 if ((offsetWidth() != viewWidth(includeScrollbars) && | 220 if ((offsetWidth() != viewWidth(includeScrollbars) && |
215 mustInvalidateFillLayersPaintOnWidthChange( | 221 mustInvalidateFillLayersPaintOnWidthChange( |
216 style()->backgroundLayers())) || | 222 style()->backgroundLayers())) || |
217 (offsetHeight() != viewHeight(includeScrollbars) && | 223 (offsetHeight() != viewHeight(includeScrollbars) && |
(...skipping 14 matching lines...) Expand all Loading... |
232 if (!m_fragmentationContext) | 238 if (!m_fragmentationContext) |
233 m_fragmentationContext = wrapUnique(new ViewFragmentationContext(*this)); | 239 m_fragmentationContext = wrapUnique(new ViewFragmentationContext(*this)); |
234 } else if (m_fragmentationContext) { | 240 } else if (m_fragmentationContext) { |
235 m_fragmentationContext.reset(); | 241 m_fragmentationContext.reset(); |
236 } | 242 } |
237 | 243 |
238 SubtreeLayoutScope layoutScope(*this); | 244 SubtreeLayoutScope layoutScope(*this); |
239 | 245 |
240 LayoutRect oldLayoutOverflowRect = layoutOverflowRect(); | 246 LayoutRect oldLayoutOverflowRect = layoutOverflowRect(); |
241 | 247 |
242 // Use calcWidth/Height to get the new width/height, since this will take the
full page zoom factor into account. | 248 // Use calcWidth/Height to get the new width/height, since this will take the |
| 249 // full page zoom factor into account. |
243 bool relayoutChildren = | 250 bool relayoutChildren = |
244 !shouldUsePrintingLayout() && | 251 !shouldUsePrintingLayout() && |
245 (!m_frameView || logicalWidth() != viewLogicalWidthForBoxSizing() || | 252 (!m_frameView || logicalWidth() != viewLogicalWidthForBoxSizing() || |
246 logicalHeight() != viewLogicalHeightForBoxSizing()); | 253 logicalHeight() != viewLogicalHeightForBoxSizing()); |
247 if (relayoutChildren) { | 254 if (relayoutChildren) { |
248 layoutScope.setChildNeedsLayout(this); | 255 layoutScope.setChildNeedsLayout(this); |
249 for (LayoutObject* child = firstChild(); child; | 256 for (LayoutObject* child = firstChild(); child; |
250 child = child->nextSibling()) { | 257 child = child->nextSibling()) { |
251 if (child->isSVGRoot()) | 258 if (child->isSVGRoot()) |
252 continue; | 259 continue; |
(...skipping 16 matching lines...) Expand all Loading... |
269 return; | 276 return; |
270 | 277 |
271 LayoutState rootLayoutState(pageLogicalHeight(), pageLogicalHeightChanged(), | 278 LayoutState rootLayoutState(pageLogicalHeight(), pageLogicalHeightChanged(), |
272 *this); | 279 *this); |
273 | 280 |
274 m_pageLogicalHeightChanged = false; | 281 m_pageLogicalHeightChanged = false; |
275 | 282 |
276 layoutContent(); | 283 layoutContent(); |
277 | 284 |
278 if (layoutOverflowRect() != oldLayoutOverflowRect) { | 285 if (layoutOverflowRect() != oldLayoutOverflowRect) { |
279 // The document element paints the viewport background, so we need to invali
date it when | 286 // The document element paints the viewport background, so we need to |
280 // layout overflow changes. | 287 // invalidate it when layout overflow changes. |
281 // FIXME: Improve viewport background styling/invalidation/painting. crbug.c
om/475115 | 288 // FIXME: Improve viewport background styling/invalidation/painting. |
| 289 // crbug.com/475115 |
282 if (Element* documentElement = document().documentElement()) { | 290 if (Element* documentElement = document().documentElement()) { |
283 if (LayoutObject* rootObject = documentElement->layoutObject()) | 291 if (LayoutObject* rootObject = documentElement->layoutObject()) |
284 rootObject->setShouldDoFullPaintInvalidation(); | 292 rootObject->setShouldDoFullPaintInvalidation(); |
285 } | 293 } |
286 } | 294 } |
287 | 295 |
288 #if ENABLE(ASSERT) | 296 #if ENABLE(ASSERT) |
289 checkLayoutState(); | 297 checkLayoutState(); |
290 #endif | 298 #endif |
291 clearNeedsLayout(); | 299 clearNeedsLayout(); |
292 } | 300 } |
293 | 301 |
294 LayoutRect LayoutView::visualOverflowRect() const { | 302 LayoutRect LayoutView::visualOverflowRect() const { |
295 // In root layer scrolling mode, the LayoutView performs overflow clipping | 303 // In root layer scrolling mode, the LayoutView performs overflow clipping |
296 // like a regular scrollable div. | 304 // like a regular scrollable div. |
297 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) | 305 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) |
298 return LayoutBlockFlow::visualOverflowRect(); | 306 return LayoutBlockFlow::visualOverflowRect(); |
299 | 307 |
300 // Ditto when not in compositing mode. | 308 // Ditto when not in compositing mode. |
301 if (!usesCompositing()) | 309 if (!usesCompositing()) |
302 return LayoutBlockFlow::visualOverflowRect(); | 310 return LayoutBlockFlow::visualOverflowRect(); |
303 | 311 |
304 // In normal compositing mode, LayoutView doesn't actually apply clipping | 312 // In normal compositing mode, LayoutView doesn't actually apply clipping |
305 // on its descendants. Instead their visual overflow is propagated to | 313 // on its descendants. Instead their visual overflow is propagated to |
306 // compositor()->m_rootContentLayer for accelerated scrolling. | 314 // compositor()->m_rootContentLayer for accelerated scrolling. |
307 return layoutOverflowRect(); | 315 return layoutOverflowRect(); |
308 } | 316 } |
309 | 317 |
310 LayoutRect LayoutView::localOverflowRectForPaintInvalidation() const { | 318 LayoutRect LayoutView::localOverflowRectForPaintInvalidation() const { |
311 // TODO(wangxianzhu): This is only required without rootLayerScrolls (though i
t is also correct | 319 // TODO(wangxianzhu): This is only required without rootLayerScrolls (though |
312 // but unnecessary with rootLayerScrolls) because of the special LayoutView ov
erflow model. | 320 // it is also correct but unnecessary with rootLayerScrolls) because of the |
| 321 // special LayoutView overflow model. |
313 return visualOverflowRect(); | 322 return visualOverflowRect(); |
314 } | 323 } |
315 | 324 |
316 void LayoutView::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, | 325 void LayoutView::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, |
317 TransformState& transformState, | 326 TransformState& transformState, |
318 MapCoordinatesFlags mode) const { | 327 MapCoordinatesFlags mode) const { |
319 if (!ancestor && mode & UseTransforms && shouldUseTransformFromContainer(0)) { | 328 if (!ancestor && mode & UseTransforms && shouldUseTransformFromContainer(0)) { |
320 TransformationMatrix t; | 329 TransformationMatrix t; |
321 getTransformFromContainer(0, LayoutSize(), t); | 330 getTransformFromContainer(0, LayoutSize(), t); |
322 transformState.applyTransform(t); | 331 transformState.applyTransform(t); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 | 399 |
391 void LayoutView::mapAncestorToLocal(const LayoutBoxModelObject* ancestor, | 400 void LayoutView::mapAncestorToLocal(const LayoutBoxModelObject* ancestor, |
392 TransformState& transformState, | 401 TransformState& transformState, |
393 MapCoordinatesFlags mode) const { | 402 MapCoordinatesFlags mode) const { |
394 if (this == ancestor) | 403 if (this == ancestor) |
395 return; | 404 return; |
396 | 405 |
397 if (mode & TraverseDocumentBoundaries) { | 406 if (mode & TraverseDocumentBoundaries) { |
398 if (LayoutPart* parentDocLayoutObject = toLayoutPart( | 407 if (LayoutPart* parentDocLayoutObject = toLayoutPart( |
399 LayoutAPIShim::layoutObjectFrom(frame()->ownerLayoutItem()))) { | 408 LayoutAPIShim::layoutObjectFrom(frame()->ownerLayoutItem()))) { |
400 // A LayoutView is a containing block for fixed-position elements, so don'
t carry this state across frames. | 409 // A LayoutView is a containing block for fixed-position elements, so |
| 410 // don't carry this state across frames. |
401 parentDocLayoutObject->mapAncestorToLocal(ancestor, transformState, | 411 parentDocLayoutObject->mapAncestorToLocal(ancestor, transformState, |
402 mode & ~IsFixed); | 412 mode & ~IsFixed); |
403 | 413 |
404 transformState.move(parentDocLayoutObject->contentBoxOffset()); | 414 transformState.move(parentDocLayoutObject->contentBoxOffset()); |
405 transformState.move(LayoutSize(-frame()->view()->scrollOffset())); | 415 transformState.move(LayoutSize(-frame()->view()->scrollOffset())); |
406 } | 416 } |
407 } else { | 417 } else { |
408 ASSERT(!ancestor); | 418 ASSERT(!ancestor); |
409 } | 419 } |
410 | 420 |
411 if (mode & IsFixed) | 421 if (mode & IsFixed) |
412 transformState.move(LayoutSize(frame()->view()->scrollOffset())); | 422 transformState.move(LayoutSize(frame()->view()->scrollOffset())); |
413 } | 423 } |
414 | 424 |
415 void LayoutView::computeSelfHitTestRects(Vector<LayoutRect>& rects, | 425 void LayoutView::computeSelfHitTestRects(Vector<LayoutRect>& rects, |
416 const LayoutPoint&) const { | 426 const LayoutPoint&) const { |
417 // Record the entire size of the contents of the frame. Note that we don't jus
t | 427 // Record the entire size of the contents of the frame. Note that we don't |
418 // use the viewport size (containing block) here because we want to ensure thi
s includes | 428 // just use the viewport size (containing block) here because we want to |
419 // all children (so we can avoid walking them explicitly). | 429 // ensure this includes all children (so we can avoid walking them |
| 430 // explicitly). |
420 rects.append( | 431 rects.append( |
421 LayoutRect(LayoutPoint::zero(), LayoutSize(frameView()->contentsSize()))); | 432 LayoutRect(LayoutPoint::zero(), LayoutSize(frameView()->contentsSize()))); |
422 } | 433 } |
423 | 434 |
424 void LayoutView::paint(const PaintInfo& paintInfo, | 435 void LayoutView::paint(const PaintInfo& paintInfo, |
425 const LayoutPoint& paintOffset) const { | 436 const LayoutPoint& paintOffset) const { |
426 ViewPainter(*this).paint(paintInfo, paintOffset); | 437 ViewPainter(*this).paint(paintInfo, paintOffset); |
427 } | 438 } |
428 | 439 |
429 void LayoutView::paintBoxDecorationBackground(const PaintInfo& paintInfo, | 440 void LayoutView::paintBoxDecorationBackground(const PaintInfo& paintInfo, |
(...skipping 10 matching lines...) Expand all Loading... |
440 } | 451 } |
441 } | 452 } |
442 | 453 |
443 void LayoutView::setShouldDoFullPaintInvalidationForViewAndAllDescendants() { | 454 void LayoutView::setShouldDoFullPaintInvalidationForViewAndAllDescendants() { |
444 setShouldDoFullPaintInvalidationForViewAndAllDescendantsInternal(this); | 455 setShouldDoFullPaintInvalidationForViewAndAllDescendantsInternal(this); |
445 } | 456 } |
446 | 457 |
447 void LayoutView::invalidatePaintForViewAndCompositedLayers() { | 458 void LayoutView::invalidatePaintForViewAndCompositedLayers() { |
448 setShouldDoFullPaintInvalidationIncludingNonCompositingDescendants(); | 459 setShouldDoFullPaintInvalidationIncludingNonCompositingDescendants(); |
449 | 460 |
450 // The only way we know how to hit these ASSERTS below this point is via the C
hromium OS login screen. | 461 // The only way we know how to hit these ASSERTS below this point is via the |
| 462 // Chromium OS login screen. |
451 DisableCompositingQueryAsserts disabler; | 463 DisableCompositingQueryAsserts disabler; |
452 | 464 |
453 if (compositor()->inCompositingMode()) | 465 if (compositor()->inCompositingMode()) |
454 compositor()->fullyInvalidatePaint(); | 466 compositor()->fullyInvalidatePaint(); |
455 } | 467 } |
456 | 468 |
457 bool LayoutView::mapToVisualRectInAncestorSpace( | 469 bool LayoutView::mapToVisualRectInAncestorSpace( |
458 const LayoutBoxModelObject* ancestor, | 470 const LayoutBoxModelObject* ancestor, |
459 LayoutRect& rect, | 471 LayoutRect& rect, |
460 VisualRectFlags visualRectFlags) const { | 472 VisualRectFlags visualRectFlags) const { |
(...skipping 27 matching lines...) Expand all Loading... |
488 if (visualRectFlags & EdgeInclusive) { | 500 if (visualRectFlags & EdgeInclusive) { |
489 if (!rect.inclusiveIntersect(viewRectangle)) | 501 if (!rect.inclusiveIntersect(viewRectangle)) |
490 return false; | 502 return false; |
491 } else { | 503 } else { |
492 rect.intersect(viewRectangle); | 504 rect.intersect(viewRectangle); |
493 } | 505 } |
494 | 506 |
495 // Adjust for scroll offset of the view. | 507 // Adjust for scroll offset of the view. |
496 rect.moveBy(-viewRectangle.location()); | 508 rect.moveBy(-viewRectangle.location()); |
497 } | 509 } |
498 // Frames are painted at rounded-int position. Since we cannot efficiently c
ompute the subpixel offset | 510 // Frames are painted at rounded-int position. Since we cannot efficiently |
499 // of painting at this point in a a bottom-up walk, round to the enclosing i
nt rect, which will enclose | 511 // compute the subpixel offset of painting at this point in a a bottom-up |
500 // the actual visible rect. | 512 // walk, round to the enclosing int rect, which will enclose the actual |
| 513 // visible rect. |
501 rect = LayoutRect(enclosingIntRect(rect)); | 514 rect = LayoutRect(enclosingIntRect(rect)); |
502 | 515 |
503 // Adjust for frame border. | 516 // Adjust for frame border. |
504 rect.move(obj->contentBoxOffset()); | 517 rect.move(obj->contentBoxOffset()); |
505 return obj->mapToVisualRectInAncestorSpace(ancestor, rect, visualRectFlags); | 518 return obj->mapToVisualRectInAncestorSpace(ancestor, rect, visualRectFlags); |
506 } | 519 } |
507 | 520 |
508 // This can happen, e.g., if the iframe element has display:none. | 521 // This can happen, e.g., if the iframe element has display:none. |
509 rect = LayoutRect(); | 522 rect = LayoutRect(); |
510 return false; | 523 return false; |
511 } | 524 } |
512 | 525 |
513 void LayoutView::adjustOffsetForFixedPosition(LayoutRect& rect) const { | 526 void LayoutView::adjustOffsetForFixedPosition(LayoutRect& rect) const { |
514 if (m_frameView) { | 527 if (m_frameView) { |
515 rect.move(LayoutSize(m_frameView->scrollOffset())); | 528 rect.move(LayoutSize(m_frameView->scrollOffset())); |
516 if (hasOverflowClip()) | 529 if (hasOverflowClip()) |
517 rect.move(scrolledContentOffset()); | 530 rect.move(scrolledContentOffset()); |
518 | 531 |
519 // FIXME: Paint invalidation should happen after scroll updates, so there sh
ould be no pending scroll delta. | 532 // FIXME: Paint invalidation should happen after scroll updates, so there |
520 // However, we still have paint invalidation during layout, so we can't ASSE
RT for now. crbug.com/434950. | 533 // should be no pending scroll delta. |
| 534 // However, we still have paint invalidation during layout, so we can't |
| 535 // ASSERT for now. crbug.com/434950. |
521 // ASSERT(m_frameView->pendingScrollDelta().isZero()); | 536 // ASSERT(m_frameView->pendingScrollDelta().isZero()); |
522 // If we have a pending scroll, invalidate the previous scroll position. | 537 // If we have a pending scroll, invalidate the previous scroll position. |
523 if (!m_frameView->pendingScrollDelta().isZero()) | 538 if (!m_frameView->pendingScrollDelta().isZero()) |
524 rect.move(-LayoutSize(m_frameView->pendingScrollDelta())); | 539 rect.move(-LayoutSize(m_frameView->pendingScrollDelta())); |
525 } | 540 } |
526 } | 541 } |
527 | 542 |
528 void LayoutView::absoluteRects(Vector<IntRect>& rects, | 543 void LayoutView::absoluteRects(Vector<IntRect>& rects, |
529 const LayoutPoint& accumulatedOffset) const { | 544 const LayoutPoint& accumulatedOffset) const { |
530 rects.append( | 545 rects.append( |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 VisitedContainingBlockSet visitedContainingBlocks; | 577 VisitedContainingBlockSet visitedContainingBlocks; |
563 | 578 |
564 commitPendingSelection(); | 579 commitPendingSelection(); |
565 LayoutObject* os = m_selectionStart; | 580 LayoutObject* os = m_selectionStart; |
566 LayoutObject* stop = | 581 LayoutObject* stop = |
567 layoutObjectAfterPosition(m_selectionEnd, m_selectionEndPos); | 582 layoutObjectAfterPosition(m_selectionEnd, m_selectionEndPos); |
568 while (os && os != stop) { | 583 while (os && os != stop) { |
569 if ((os->canBeSelectionLeaf() || os == m_selectionStart || | 584 if ((os->canBeSelectionLeaf() || os == m_selectionStart || |
570 os == m_selectionEnd) && | 585 os == m_selectionEnd) && |
571 os->getSelectionState() != SelectionNone) { | 586 os->getSelectionState() != SelectionNone) { |
572 // Blocks are responsible for painting line gaps and margin gaps. They mus
t be examined as well. | 587 // Blocks are responsible for painting line gaps and margin gaps. They |
| 588 // must be examined as well. |
573 selRect.unite(selectionRectForLayoutObject(os)); | 589 selRect.unite(selectionRectForLayoutObject(os)); |
574 const LayoutBlock* cb = os->containingBlock(); | 590 const LayoutBlock* cb = os->containingBlock(); |
575 while (cb && !cb->isLayoutView()) { | 591 while (cb && !cb->isLayoutView()) { |
576 selRect.unite(selectionRectForLayoutObject(cb)); | 592 selRect.unite(selectionRectForLayoutObject(cb)); |
577 VisitedContainingBlockSet::AddResult addResult = | 593 VisitedContainingBlockSet::AddResult addResult = |
578 visitedContainingBlocks.add(cb); | 594 visitedContainingBlocks.add(cb); |
579 if (!addResult.isNewEntry) | 595 if (!addResult.isNewEntry) |
580 break; | 596 break; |
581 cb = cb->containingBlock(); | 597 cb = cb->containingBlock(); |
582 } | 598 } |
(...skipping 15 matching lines...) Expand all Loading... |
598 if (!o->canBeSelectionLeaf() && o != m_selectionStart && | 614 if (!o->canBeSelectionLeaf() && o != m_selectionStart && |
599 o != m_selectionEnd) | 615 o != m_selectionEnd) |
600 continue; | 616 continue; |
601 if (o->getSelectionState() == SelectionNone) | 617 if (o->getSelectionState() == SelectionNone) |
602 continue; | 618 continue; |
603 | 619 |
604 o->setShouldInvalidateSelection(); | 620 o->setShouldInvalidateSelection(); |
605 } | 621 } |
606 } | 622 } |
607 | 623 |
608 // When exploring the LayoutTree looking for the nodes involved in the Selection
, sometimes it's | 624 // When exploring the LayoutTree looking for the nodes involved in the |
609 // required to change the traversing direction because the "start" position is b
elow the "end" one. | 625 // Selection, sometimes it's required to change the traversing direction because |
| 626 // the "start" position is below the "end" one. |
610 static inline LayoutObject* getNextOrPrevLayoutObjectBasedOnDirection( | 627 static inline LayoutObject* getNextOrPrevLayoutObjectBasedOnDirection( |
611 const LayoutObject* o, | 628 const LayoutObject* o, |
612 const LayoutObject* stop, | 629 const LayoutObject* stop, |
613 bool& continueExploring, | 630 bool& continueExploring, |
614 bool& exploringBackwards) { | 631 bool& exploringBackwards) { |
615 LayoutObject* next; | 632 LayoutObject* next; |
616 if (exploringBackwards) { | 633 if (exploringBackwards) { |
617 next = o->previousInPreOrder(); | 634 next = o->previousInPreOrder(); |
618 continueExploring = next && !(next)->isLayoutView(); | 635 continueExploring = next && !(next)->isLayoutView(); |
619 } else { | 636 } else { |
620 next = o->nextInPreOrder(); | 637 next = o->nextInPreOrder(); |
621 continueExploring = next && next != stop; | 638 continueExploring = next && next != stop; |
622 exploringBackwards = !next && (next != stop); | 639 exploringBackwards = !next && (next != stop); |
623 if (exploringBackwards) { | 640 if (exploringBackwards) { |
624 next = stop->previousInPreOrder(); | 641 next = stop->previousInPreOrder(); |
625 continueExploring = next && !next->isLayoutView(); | 642 continueExploring = next && !next->isLayoutView(); |
626 } | 643 } |
627 } | 644 } |
628 | 645 |
629 return next; | 646 return next; |
630 } | 647 } |
631 | 648 |
632 void LayoutView::setSelection( | 649 void LayoutView::setSelection( |
633 LayoutObject* start, | 650 LayoutObject* start, |
634 int startPos, | 651 int startPos, |
635 LayoutObject* end, | 652 LayoutObject* end, |
636 int endPos, | 653 int endPos, |
637 SelectionPaintInvalidationMode blockPaintInvalidationMode) { | 654 SelectionPaintInvalidationMode blockPaintInvalidationMode) { |
638 // This code makes no assumptions as to if the layout tree is up to date or no
t | 655 // This code makes no assumptions as to if the layout tree is up to date or |
639 // and will not try to update it. Currently clearSelection calls this | 656 // not and will not try to update it. Currently clearSelection calls this |
640 // (intentionally) without updating the layout tree as it doesn't care. | 657 // (intentionally) without updating the layout tree as it doesn't care. |
641 // Other callers may want to force recalc style before calling this. | 658 // Other callers may want to force recalc style before calling this. |
642 | 659 |
643 // Make sure both our start and end objects are defined. | 660 // Make sure both our start and end objects are defined. |
644 // Check www.msnbc.com and try clicking around to find the case where this hap
pened. | 661 // Check www.msnbc.com and try clicking around to find the case where this |
| 662 // happened. |
645 if ((start && !end) || (end && !start)) | 663 if ((start && !end) || (end && !start)) |
646 return; | 664 return; |
647 | 665 |
648 // Just return if the selection hasn't changed. | 666 // Just return if the selection hasn't changed. |
649 if (m_selectionStart == start && m_selectionStartPos == startPos && | 667 if (m_selectionStart == start && m_selectionStartPos == startPos && |
650 m_selectionEnd == end && m_selectionEndPos == endPos) | 668 m_selectionEnd == end && m_selectionEndPos == endPos) |
651 return; | 669 return; |
652 | 670 |
653 // Record the old selected objects. These will be used later | 671 // Record the old selected objects. These will be used later when we compare |
654 // when we compare against the new selected objects. | 672 // against the new selected objects. |
655 int oldStartPos = m_selectionStartPos; | 673 int oldStartPos = m_selectionStartPos; |
656 int oldEndPos = m_selectionEndPos; | 674 int oldEndPos = m_selectionEndPos; |
657 | 675 |
658 // Objects each have a single selection rect to examine. | 676 // Objects each have a single selection rect to examine. |
659 typedef HashMap<LayoutObject*, SelectionState> SelectedObjectMap; | 677 typedef HashMap<LayoutObject*, SelectionState> SelectedObjectMap; |
660 SelectedObjectMap oldSelectedObjects; | 678 SelectedObjectMap oldSelectedObjects; |
661 // FIXME: |newSelectedObjects| doesn't really need to store the SelectionState
, it's just more convenient | 679 // FIXME: |newSelectedObjects| doesn't really need to store the |
662 // to have it use the same data structure as |oldSelectedObjects|. | 680 // SelectionState, it's just more convenient to have it use the same data |
| 681 // structure as |oldSelectedObjects|. |
663 SelectedObjectMap newSelectedObjects; | 682 SelectedObjectMap newSelectedObjects; |
664 | 683 |
665 // Blocks contain selected objects and fill gaps between them, either on the l
eft, right, or in between lines and blocks. | 684 // Blocks contain selected objects and fill gaps between them, either on the |
666 // In order to get the paint invalidation rect right, we have to examine left,
middle, and right rects individually, since otherwise | 685 // left, right, or in between lines and blocks. |
667 // the union of those rects might remain the same even when changes have occur
red. | 686 // In order to get the paint invalidation rect right, we have to examine left, |
| 687 // middle, and right rects individually, since otherwise the union of those |
| 688 // rects might remain the same even when changes have occurred. |
668 typedef HashMap<LayoutBlock*, SelectionState> SelectedBlockMap; | 689 typedef HashMap<LayoutBlock*, SelectionState> SelectedBlockMap; |
669 SelectedBlockMap oldSelectedBlocks; | 690 SelectedBlockMap oldSelectedBlocks; |
670 // FIXME: |newSelectedBlocks| doesn't really need to store the SelectionState,
it's just more convenient | 691 // FIXME: |newSelectedBlocks| doesn't really need to store the SelectionState, |
671 // to have it use the same data structure as |oldSelectedBlocks|. | 692 // it's just more convenient to have it use the same data structure as |
| 693 // |oldSelectedBlocks|. |
672 SelectedBlockMap newSelectedBlocks; | 694 SelectedBlockMap newSelectedBlocks; |
673 | 695 |
674 LayoutObject* os = m_selectionStart; | 696 LayoutObject* os = m_selectionStart; |
675 LayoutObject* stop = | 697 LayoutObject* stop = |
676 layoutObjectAfterPosition(m_selectionEnd, m_selectionEndPos); | 698 layoutObjectAfterPosition(m_selectionEnd, m_selectionEndPos); |
677 bool exploringBackwards = false; | 699 bool exploringBackwards = false; |
678 bool continueExploring = os && (os != stop); | 700 bool continueExploring = os && (os != stop); |
679 while (continueExploring) { | 701 while (continueExploring) { |
680 if ((os->canBeSelectionLeaf() || os == m_selectionStart || | 702 if ((os->canBeSelectionLeaf() || os == m_selectionStart || |
681 os == m_selectionEnd) && | 703 os == m_selectionEnd) && |
682 os->getSelectionState() != SelectionNone) { | 704 os->getSelectionState() != SelectionNone) { |
683 // Blocks are responsible for painting line gaps and margin gaps. They mu
st be examined as well. | 705 // Blocks are responsible for painting line gaps and margin gaps. They |
| 706 // must be examined as well. |
684 oldSelectedObjects.set(os, os->getSelectionState()); | 707 oldSelectedObjects.set(os, os->getSelectionState()); |
685 if (blockPaintInvalidationMode == PaintInvalidationNewXOROld) { | 708 if (blockPaintInvalidationMode == PaintInvalidationNewXOROld) { |
686 LayoutBlock* cb = os->containingBlock(); | 709 LayoutBlock* cb = os->containingBlock(); |
687 while (cb && !cb->isLayoutView()) { | 710 while (cb && !cb->isLayoutView()) { |
688 SelectedBlockMap::AddResult result = | 711 SelectedBlockMap::AddResult result = |
689 oldSelectedBlocks.add(cb, cb->getSelectionState()); | 712 oldSelectedBlocks.add(cb, cb->getSelectionState()); |
690 if (!result.isNewEntry) | 713 if (!result.isNewEntry) |
691 break; | 714 break; |
692 cb = cb->containingBlock(); | 715 cb = cb->containingBlock(); |
693 } | 716 } |
694 } | 717 } |
695 } | 718 } |
696 | 719 |
697 os = getNextOrPrevLayoutObjectBasedOnDirection(os, stop, continueExploring, | 720 os = getNextOrPrevLayoutObjectBasedOnDirection(os, stop, continueExploring, |
698 exploringBackwards); | 721 exploringBackwards); |
699 } | 722 } |
700 | 723 |
701 // Now clear the selection. | 724 // Now clear the selection. |
702 SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end(); | 725 SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end(); |
703 for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); | 726 for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); |
704 i != oldObjectsEnd; ++i) | 727 i != oldObjectsEnd; ++i) |
705 i->key->setSelectionStateIfNeeded(SelectionNone); | 728 i->key->setSelectionStateIfNeeded(SelectionNone); |
706 | 729 |
707 // set selection start and end | 730 // set selection start and end |
708 m_selectionStart = start; | 731 m_selectionStart = start; |
709 m_selectionStartPos = startPos; | 732 m_selectionStartPos = startPos; |
710 m_selectionEnd = end; | 733 m_selectionEnd = end; |
711 m_selectionEndPos = endPos; | 734 m_selectionEndPos = endPos; |
712 | 735 |
713 // Update the selection status of all objects between m_selectionStart and m_s
electionEnd | 736 // Update the selection status of all objects between m_selectionStart and |
| 737 // m_selectionEnd |
714 if (start && start == end) { | 738 if (start && start == end) { |
715 start->setSelectionStateIfNeeded(SelectionBoth); | 739 start->setSelectionStateIfNeeded(SelectionBoth); |
716 } else { | 740 } else { |
717 if (start) | 741 if (start) |
718 start->setSelectionStateIfNeeded(SelectionStart); | 742 start->setSelectionStateIfNeeded(SelectionStart); |
719 if (end) | 743 if (end) |
720 end->setSelectionStateIfNeeded(SelectionEnd); | 744 end->setSelectionStateIfNeeded(SelectionEnd); |
721 } | 745 } |
722 | 746 |
723 LayoutObject* o = start; | 747 LayoutObject* o = start; |
724 stop = layoutObjectAfterPosition(end, endPos); | 748 stop = layoutObjectAfterPosition(end, endPos); |
725 | 749 |
726 while (o && o != stop) { | 750 while (o && o != stop) { |
727 if (o != start && o != end && o->canBeSelectionLeaf()) | 751 if (o != start && o != end && o->canBeSelectionLeaf()) |
728 o->setSelectionStateIfNeeded(SelectionInside); | 752 o->setSelectionStateIfNeeded(SelectionInside); |
729 o = o->nextInPreOrder(); | 753 o = o->nextInPreOrder(); |
730 } | 754 } |
731 | 755 |
732 // Now that the selection state has been updated for the new objects, walk the
m again and | 756 // Now that the selection state has been updated for the new objects, walk |
733 // put them in the new objects list. | 757 // them again and put them in the new objects list. |
734 o = start; | 758 o = start; |
735 exploringBackwards = false; | 759 exploringBackwards = false; |
736 continueExploring = o && (o != stop); | 760 continueExploring = o && (o != stop); |
737 while (continueExploring) { | 761 while (continueExploring) { |
738 if ((o->canBeSelectionLeaf() || o == start || o == end) && | 762 if ((o->canBeSelectionLeaf() || o == start || o == end) && |
739 o->getSelectionState() != SelectionNone) { | 763 o->getSelectionState() != SelectionNone) { |
740 newSelectedObjects.set(o, o->getSelectionState()); | 764 newSelectedObjects.set(o, o->getSelectionState()); |
741 LayoutBlock* cb = o->containingBlock(); | 765 LayoutBlock* cb = o->containingBlock(); |
742 while (cb && !cb->isLayoutView()) { | 766 while (cb && !cb->isLayoutView()) { |
743 SelectedBlockMap::AddResult result = | 767 SelectedBlockMap::AddResult result = |
(...skipping 18 matching lines...) Expand all Loading... |
762 SelectionState newSelectionState = obj->getSelectionState(); | 786 SelectionState newSelectionState = obj->getSelectionState(); |
763 SelectionState oldSelectionState = i->value; | 787 SelectionState oldSelectionState = i->value; |
764 if (newSelectionState != oldSelectionState || | 788 if (newSelectionState != oldSelectionState || |
765 (m_selectionStart == obj && oldStartPos != m_selectionStartPos) || | 789 (m_selectionStart == obj && oldStartPos != m_selectionStartPos) || |
766 (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) { | 790 (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) { |
767 obj->setShouldInvalidateSelection(); | 791 obj->setShouldInvalidateSelection(); |
768 newSelectedObjects.remove(obj); | 792 newSelectedObjects.remove(obj); |
769 } | 793 } |
770 } | 794 } |
771 | 795 |
772 // Any new objects that remain were not found in the old objects dict, and so
they need to be updated. | 796 // Any new objects that remain were not found in the old objects dict, and so |
| 797 // they need to be updated. |
773 SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end(); | 798 SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end(); |
774 for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); | 799 for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); |
775 i != newObjectsEnd; ++i) | 800 i != newObjectsEnd; ++i) |
776 i->key->setShouldInvalidateSelection(); | 801 i->key->setShouldInvalidateSelection(); |
777 | 802 |
778 // Have any of the old blocks changed? | 803 // Have any of the old blocks changed? |
779 SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end(); | 804 SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end(); |
780 for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); | 805 for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); |
781 i != oldBlocksEnd; ++i) { | 806 i != oldBlocksEnd; ++i) { |
782 LayoutBlock* block = i->key; | 807 LayoutBlock* block = i->key; |
783 SelectionState newSelectionState = block->getSelectionState(); | 808 SelectionState newSelectionState = block->getSelectionState(); |
784 SelectionState oldSelectionState = i->value; | 809 SelectionState oldSelectionState = i->value; |
785 if (newSelectionState != oldSelectionState) { | 810 if (newSelectionState != oldSelectionState) { |
786 block->setShouldInvalidateSelection(); | 811 block->setShouldInvalidateSelection(); |
787 newSelectedBlocks.remove(block); | 812 newSelectedBlocks.remove(block); |
788 } | 813 } |
789 } | 814 } |
790 | 815 |
791 // Any new blocks that remain were not found in the old blocks dict, and so th
ey need to be updated. | 816 // Any new blocks that remain were not found in the old blocks dict, and so |
| 817 // they need to be updated. |
792 SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end(); | 818 SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end(); |
793 for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); | 819 for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); |
794 i != newBlocksEnd; ++i) | 820 i != newBlocksEnd; ++i) |
795 i->key->setShouldInvalidateSelection(); | 821 i->key->setShouldInvalidateSelection(); |
796 } | 822 } |
797 | 823 |
798 void LayoutView::clearSelection() { | 824 void LayoutView::clearSelection() { |
799 // For querying Layer::compositingState() | 825 // For querying Layer::compositingState() |
800 // This is correct, since destroying layout objects needs to cause eager paint
invalidations. | 826 // This is correct, since destroying layout objects needs to cause eager paint |
| 827 // invalidations. |
801 DisableCompositingQueryAsserts disabler; | 828 DisableCompositingQueryAsserts disabler; |
802 | 829 |
803 setSelection(0, -1, 0, -1, PaintInvalidationNewMinusOld); | 830 setSelection(0, -1, 0, -1, PaintInvalidationNewMinusOld); |
804 } | 831 } |
805 | 832 |
806 bool LayoutView::hasPendingSelection() const { | 833 bool LayoutView::hasPendingSelection() const { |
807 return m_frameView->frame().selection().isAppearanceDirty(); | 834 return m_frameView->frame().selection().isAppearanceDirty(); |
808 } | 835 } |
809 | 836 |
810 void LayoutView::commitPendingSelection() { | 837 void LayoutView::commitPendingSelection() { |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
940 if (!m_compositor) | 967 if (!m_compositor) |
941 m_compositor = wrapUnique(new PaintLayerCompositor(*this)); | 968 m_compositor = wrapUnique(new PaintLayerCompositor(*this)); |
942 | 969 |
943 return m_compositor.get(); | 970 return m_compositor.get(); |
944 } | 971 } |
945 | 972 |
946 void LayoutView::setIsInWindow(bool isInWindow) { | 973 void LayoutView::setIsInWindow(bool isInWindow) { |
947 if (m_compositor) | 974 if (m_compositor) |
948 m_compositor->setIsInWindow(isInWindow); | 975 m_compositor->setIsInWindow(isInWindow); |
949 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 976 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
950 // We don't invalidate layers during Document::detachLayoutTree(), so must cle
ar the should-keep-alive | 977 // We don't invalidate layers during Document::detachLayoutTree(), so must |
951 // DisplayItemClients which may be deleted before the layers being subsequence
owners. | 978 // clear the should-keep-alive DisplayItemClients which may be deleted before |
| 979 // the layers being subsequence owners. |
952 if (!isInWindow && layer()) | 980 if (!isInWindow && layer()) |
953 layer()->endShouldKeepAliveAllClientsRecursive(); | 981 layer()->endShouldKeepAliveAllClientsRecursive(); |
954 #endif | 982 #endif |
955 } | 983 } |
956 | 984 |
957 IntervalArena* LayoutView::intervalArena() { | 985 IntervalArena* LayoutView::intervalArena() { |
958 if (!m_intervalArena) | 986 if (!m_intervalArena) |
959 m_intervalArena = IntervalArena::create(); | 987 m_intervalArena = IntervalArena::create(); |
960 return m_intervalArena.get(); | 988 return m_intervalArena.get(); |
961 } | 989 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1034 if (block) | 1062 if (block) |
1035 block->adjustChildDebugRect(rect); | 1063 block->adjustChildDebugRect(rect); |
1036 | 1064 |
1037 rect.setWidth(LayoutUnit(viewWidth(IncludeScrollbars))); | 1065 rect.setWidth(LayoutUnit(viewWidth(IncludeScrollbars))); |
1038 rect.setHeight(LayoutUnit(viewHeight(IncludeScrollbars))); | 1066 rect.setHeight(LayoutUnit(viewHeight(IncludeScrollbars))); |
1039 | 1067 |
1040 return rect; | 1068 return rect; |
1041 } | 1069 } |
1042 | 1070 |
1043 } // namespace blink | 1071 } // namespace blink |
OLD | NEW |