1 /* 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. 3 * 4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. 5 * 6 * Other contributors: 7 * Robert O'Callahan <roc+@cs.cmu.edu> 8 * David Baron <dbaron (at) fas.harvard.edu> 9 * Christian Biesinger <cbiesinger (at) web.de> 10 * Randall Jesup <rjesup (at) wgate.com> 11 * Roland Mainz <roland.mainz (at) informatik.med.uni-giessen.de> 12 * Josh Soref <timeless (at) mac.com> 13 * Boris Zbarsky <bzbarsky (at) mit.edu> 14 * 15 * This library is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU Lesser General Public 17 * License as published by the Free Software Foundation; either 18 * version 2.1 of the License, or (at your option) any later version. 19 * 20 * This library is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 * Lesser General Public License for more details. 24 * 25 * You should have received a copy of the GNU Lesser General Public 26 * License along with this library; if not, write to the Free Software 27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 28 * 29 * Alternatively, the contents of this file may be used under the terms 30 * of either the Mozilla Public License Version 1.1, found at 31 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public 32 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html 33 * (the "GPL"), in which case the provisions of the MPL or the GPL are 34 * applicable instead of those above. If you wish to allow use of your 35 * version of this file only under the terms of one of those two 36 * licenses (the MPL or the GPL) and not to allow others to use your 37 * version of this file under the LGPL, indicate your decision by 38 * deletingthe provisions above and replace them with the notice and 39 * other provisions required by the MPL or the GPL, as the case may be. 40 * If you do not delete the provisions above, a recipient may use your 41 * version of this file under any of the LGPL, the MPL or the GPL. 42 */ 43 44 #include "config.h" 45 #include "RenderLayer.h" 46 47 #include "ColumnInfo.h" 48 #include "CSSPropertyNames.h" 49 #include "CSSStyleDeclaration.h" 50 #include "CSSStyleSelector.h" 51 #include "Chrome.h" 52 #include "Document.h" 53 #include "EventHandler.h" 54 #include "EventQueue.h" 55 #include "FloatPoint3D.h" 56 #include "FloatRect.h" 57 #include "FocusController.h" 58 #include "Frame.h" 59 #include "FrameTree.h" 60 #include "FrameView.h" 61 #include "Gradient.h" 62 #include "GraphicsContext.h" 63 #include "HTMLFrameOwnerElement.h" 64 #include "HTMLNames.h" 65 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 66 #include "HTMLTextAreaElement.h" 67 #include "GraphicsLayerAndroid.h" 68 #endif 69 #include "HitTestRequest.h" 70 #include "HitTestResult.h" 71 #include "OverflowEvent.h" 72 #include "OverlapTestRequestClient.h" 73 #include "Page.h" 74 #include "PlatformMouseEvent.h" 75 #include "RenderArena.h" 76 #include "RenderInline.h" 77 #include "RenderMarquee.h" 78 #include "RenderReplica.h" 79 #include "RenderScrollbar.h" 80 #include "RenderScrollbarPart.h" 81 #include "RenderTheme.h" 82 #include "RenderTreeAsText.h" 83 #include "RenderView.h" 84 #include "ScaleTransformOperation.h" 85 #include "Scrollbar.h" 86 #include "ScrollbarTheme.h" 87 #include "SelectionController.h" 88 #include "TextStream.h" 89 #include "TransformState.h" 90 #include "TransformationMatrix.h" 91 #include "TranslateTransformOperation.h" 92 #include <wtf/StdLibExtras.h> 93 #include <wtf/UnusedParam.h> 94 #include <wtf/text/CString.h> 95 96 #if USE(ACCELERATED_COMPOSITING) 97 #include "RenderLayerBacking.h" 98 #include "RenderLayerCompositor.h" 99 #endif 100 101 #if ENABLE(SVG) 102 #include "SVGNames.h" 103 #endif 104 105 #define MIN_INTERSECT_FOR_REVEAL 32 106 107 using namespace std; 108 109 namespace WebCore { 110 111 using namespace HTMLNames; 112 113 const int MinimumWidthWhileResizing = 100; 114 const int MinimumHeightWhileResizing = 40; 115 116 void* ClipRects::operator new(size_t sz, RenderArena* renderArena) throw() 117 { 118 return renderArena->allocate(sz); 119 } 120 121 void ClipRects::operator delete(void* ptr, size_t sz) 122 { 123 // Stash size where destroy can find it. 124 *(size_t *)ptr = sz; 125 } 126 127 void ClipRects::destroy(RenderArena* renderArena) 128 { 129 delete this; 130 131 // Recover the size left there for us by operator delete and free the memory. 132 renderArena->free(*(size_t *)this, this); 133 } 134 135 RenderLayer::RenderLayer(RenderBoxModelObject* renderer) 136 : m_renderer(renderer) 137 , m_parent(0) 138 , m_previous(0) 139 , m_next(0) 140 , m_first(0) 141 , m_last(0) 142 , m_relX(0) 143 , m_relY(0) 144 , m_x(0) 145 , m_y(0) 146 , m_width(0) 147 , m_height(0) 148 , m_scrollX(0) 149 , m_scrollY(0) 150 , m_scrollLeftOverflow(0) 151 , m_scrollTopOverflow(0) 152 , m_scrollWidth(0) 153 , m_scrollHeight(0) 154 , m_inResizeMode(false) 155 , m_posZOrderList(0) 156 , m_negZOrderList(0) 157 , m_normalFlowList(0) 158 , m_clipRects(0) 159 #ifndef NDEBUG 160 , m_clipRectsRoot(0) 161 #endif 162 , m_scrollDimensionsDirty(true) 163 , m_zOrderListsDirty(true) 164 , m_normalFlowListDirty(true) 165 , m_isNormalFlowOnly(shouldBeNormalFlowOnly()) 166 , m_usedTransparency(false) 167 , m_paintingInsideReflection(false) 168 , m_inOverflowRelayout(false) 169 , m_needsFullRepaint(false) 170 , m_overflowStatusDirty(true) 171 , m_visibleContentStatusDirty(true) 172 , m_hasVisibleContent(false) 173 , m_visibleDescendantStatusDirty(false) 174 , m_hasVisibleDescendant(false) 175 , m_isPaginated(false) 176 , m_3DTransformedDescendantStatusDirty(true) 177 , m_has3DTransformedDescendant(false) 178 #if USE(ACCELERATED_COMPOSITING) 179 , m_hasCompositingDescendant(false) 180 , m_mustOverlapCompositedLayers(false) 181 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) 182 , m_shouldComposite(false) 183 #endif 184 #endif 185 , m_containsDirtyOverlayScrollbars(false) 186 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 187 , m_hasOverflowScroll(false) 188 #endif 189 , m_marquee(0) 190 , m_staticInlinePosition(0) 191 , m_staticBlockPosition(0) 192 , m_reflection(0) 193 , m_scrollCorner(0) 194 , m_resizer(0) 195 { 196 ScrollableArea::setConstrainsScrollingToContentEdge(false); 197 198 if (!renderer->firstChild() && renderer->style()) { 199 m_visibleContentStatusDirty = false; 200 m_hasVisibleContent = renderer->style()->visibility() == VISIBLE; 201 } 202 203 if (Frame* frame = renderer->frame()) { 204 if (Page* page = frame->page()) { 205 m_page = page; 206 m_page->addScrollableArea(this); 207 } 208 } 209 } 210 211 RenderLayer::~RenderLayer() 212 { 213 if (inResizeMode() && !renderer()->documentBeingDestroyed()) { 214 if (Frame* frame = renderer()->frame()) 215 frame->eventHandler()->resizeLayerDestroyed(); 216 } 217 218 if (m_page) 219 m_page->removeScrollableArea(this); 220 221 destroyScrollbar(HorizontalScrollbar); 222 destroyScrollbar(VerticalScrollbar); 223 224 if (m_reflection) 225 removeReflection(); 226 227 // Child layers will be deleted by their corresponding render objects, so 228 // we don't need to delete them ourselves. 229 230 delete m_posZOrderList; 231 delete m_negZOrderList; 232 delete m_normalFlowList; 233 delete m_marquee; 234 235 #if USE(ACCELERATED_COMPOSITING) 236 clearBacking(); 237 #endif 238 239 // Make sure we have no lingering clip rects. 240 ASSERT(!m_clipRects); 241 242 if (m_scrollCorner) 243 m_scrollCorner->destroy(); 244 if (m_resizer) 245 m_resizer->destroy(); 246 } 247 248 #if USE(ACCELERATED_COMPOSITING) 249 RenderLayerCompositor* RenderLayer::compositor() const 250 { 251 ASSERT(renderer()->view()); 252 return renderer()->view()->compositor(); 253 } 254 255 void RenderLayer::contentChanged(ContentChangeType changeType) 256 { 257 // This can get called when video becomes accelerated, so the layers may change. 258 if ((changeType == CanvasChanged || changeType == VideoChanged || changeType == FullScreenChanged) && compositor()->updateLayerCompositingState(this)) 259 compositor()->setCompositingLayersNeedRebuild(); 260 261 if (m_backing) 262 m_backing->contentChanged(changeType); 263 } 264 #endif // USE(ACCELERATED_COMPOSITING) 265 266 bool RenderLayer::hasAcceleratedCompositing() const 267 { 268 #if USE(ACCELERATED_COMPOSITING) 269 return compositor()->hasAcceleratedCompositing(); 270 #else 271 return false; 272 #endif 273 } 274 275 bool RenderLayer::canRender3DTransforms() const 276 { 277 #if USE(ACCELERATED_COMPOSITING) 278 return compositor()->canRender3DTransforms(); 279 #else 280 return false; 281 #endif 282 } 283 284 void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags, IntPoint* cachedOffset) 285 { 286 updateLayerPosition(); // For relpositioned layers or non-positioned layers, 287 // we need to keep in sync, since we may have shifted relative 288 // to our parent layer. 289 IntPoint oldCachedOffset; 290 if (cachedOffset) { 291 // We can't cache our offset to the repaint container if the mapping is anything more complex than a simple translation 292 bool disableOffsetCache = renderer()->hasColumns() || renderer()->hasTransform() || isComposited(); 293 #if ENABLE(SVG) 294 disableOffsetCache = disableOffsetCache || renderer()->isSVGRoot(); 295 #endif 296 if (disableOffsetCache) 297 cachedOffset = 0; // If our cached offset is invalid make sure it's not passed to any of our children 298 else { 299 oldCachedOffset = *cachedOffset; 300 // Frequently our parent layer's renderer will be the same as our renderer's containing block. In that case, 301 // we just update the cache using our offset to our parent (which is m_x / m_y). Otherwise, regenerated cached 302 // offsets to the root from the render tree. 303 if (!m_parent || m_parent->renderer() == renderer()->containingBlock()) 304 cachedOffset->move(m_x, m_y); // Fast case 305 else { 306 int x = 0; 307 int y = 0; 308 convertToLayerCoords(root(), x, y); 309 *cachedOffset = IntPoint(x, y); 310 } 311 } 312 } 313 314 int x = 0; 315 int y = 0; 316 if (cachedOffset) { 317 x += cachedOffset->x(); 318 y += cachedOffset->y(); 319 #ifndef NDEBUG 320 int nonCachedX = 0; 321 int nonCachedY = 0; 322 convertToLayerCoords(root(), nonCachedX, nonCachedY); 323 ASSERT(x == nonCachedX); 324 ASSERT(y == nonCachedY); 325 #endif 326 } else 327 convertToLayerCoords(root(), x, y); 328 positionOverflowControls(x, y); 329 330 updateVisibilityStatus(); 331 332 if (flags & UpdatePagination) 333 updatePagination(); 334 else 335 m_isPaginated = false; 336 337 if (m_hasVisibleContent) { 338 RenderView* view = renderer()->view(); 339 ASSERT(view); 340 // FIXME: Optimize using LayoutState and remove the disableLayoutState() call 341 // from updateScrollInfoAfterLayout(). 342 ASSERT(!view->layoutStateEnabled()); 343 344 RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint(); 345 IntRect newRect = renderer()->clippedOverflowRectForRepaint(repaintContainer); 346 IntRect newOutlineBox = renderer()->outlineBoundsForRepaint(repaintContainer, cachedOffset); 347 // FIXME: Should ASSERT that value calculated for newOutlineBox using the cached offset is the same 348 // as the value not using the cached offset, but we can't due to https://bugs.webkit.org/show_bug.cgi?id=37048 349 if (flags & CheckForRepaint) { 350 if (view && !view->printing()) { 351 if (m_needsFullRepaint) { 352 renderer()->repaintUsingContainer(repaintContainer, m_repaintRect); 353 if (newRect != m_repaintRect) 354 renderer()->repaintUsingContainer(repaintContainer, newRect); 355 } else 356 renderer()->repaintAfterLayoutIfNeeded(repaintContainer, m_repaintRect, m_outlineBox, &newRect, &newOutlineBox); 357 } 358 } 359 m_repaintRect = newRect; 360 m_outlineBox = newOutlineBox; 361 } else { 362 m_repaintRect = IntRect(); 363 m_outlineBox = IntRect(); 364 } 365 366 m_needsFullRepaint = false; 367 368 // Go ahead and update the reflection's position and size. 369 if (m_reflection) 370 m_reflection->layout(); 371 372 #if USE(ACCELERATED_COMPOSITING) 373 // Clear the IsCompositingUpdateRoot flag once we've found the first compositing layer in this update. 374 bool isUpdateRoot = (flags & IsCompositingUpdateRoot); 375 if (isComposited()) 376 flags &= ~IsCompositingUpdateRoot; 377 #endif 378 379 if (renderer()->hasColumns()) 380 flags |= UpdatePagination; 381 382 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 383 child->updateLayerPositions(flags, cachedOffset); 384 385 #if USE(ACCELERATED_COMPOSITING) 386 if ((flags & UpdateCompositingLayers) && isComposited()) 387 backing()->updateAfterLayout(RenderLayerBacking::CompositingChildren, isUpdateRoot); 388 #endif 389 390 // With all our children positioned, now update our marquee if we need to. 391 if (m_marquee) 392 m_marquee->updateMarqueePosition(); 393 394 if (cachedOffset) 395 *cachedOffset = oldCachedOffset; 396 } 397 398 IntRect RenderLayer::repaintRectIncludingDescendants() const 399 { 400 IntRect repaintRect = m_repaintRect; 401 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 402 repaintRect.unite(child->repaintRectIncludingDescendants()); 403 return repaintRect; 404 } 405 406 void RenderLayer::computeRepaintRects() 407 { 408 RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint(); 409 m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer); 410 m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer); 411 } 412 413 void RenderLayer::updateRepaintRectsAfterScroll(bool fixed) 414 { 415 if (fixed || renderer()->style()->position() == FixedPosition) { 416 computeRepaintRects(); 417 fixed = true; 418 } else if (renderer()->hasTransform() && !renderer()->isRenderView()) { 419 // Transforms act as fixed position containers, so nothing inside a 420 // transformed element can be fixed relative to the viewport if the 421 // transformed element is not fixed itself or child of a fixed element. 422 return; 423 } 424 425 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 426 child->updateRepaintRectsAfterScroll(fixed); 427 } 428 429 void RenderLayer::updateTransform() 430 { 431 // hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set, 432 // so check style too. 433 bool hasTransform = renderer()->hasTransform() && renderer()->style()->hasTransform(); 434 bool had3DTransform = has3DTransform(); 435 436 bool hadTransform = m_transform; 437 if (hasTransform != hadTransform) { 438 if (hasTransform) 439 m_transform.set(new TransformationMatrix); 440 else 441 m_transform.clear(); 442 } 443 444 if (hasTransform) { 445 RenderBox* box = renderBox(); 446 ASSERT(box); 447 m_transform->makeIdentity(); 448 box->style()->applyTransform(*m_transform, box->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin); 449 makeMatrixRenderable(*m_transform, canRender3DTransforms()); 450 } 451 452 if (had3DTransform != has3DTransform()) 453 dirty3DTransformedDescendantStatus(); 454 } 455 456 TransformationMatrix RenderLayer::currentTransform() const 457 { 458 if (!m_transform) 459 return TransformationMatrix(); 460 461 #if USE(ACCELERATED_COMPOSITING) 462 if (renderer()->style()->isRunningAcceleratedAnimation()) { 463 TransformationMatrix currTransform; 464 RefPtr<RenderStyle> style = renderer()->animation()->getAnimatedStyleForRenderer(renderer()); 465 style->applyTransform(currTransform, renderBox()->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin); 466 makeMatrixRenderable(currTransform, canRender3DTransforms()); 467 return currTransform; 468 } 469 #endif 470 471 return *m_transform; 472 } 473 474 TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavior) const 475 { 476 if (!m_transform) 477 return TransformationMatrix(); 478 479 if (paintBehavior & PaintBehaviorFlattenCompositingLayers) { 480 TransformationMatrix matrix = *m_transform; 481 makeMatrixRenderable(matrix, false /* flatten 3d */); 482 return matrix; 483 } 484 485 return *m_transform; 486 } 487 488 static bool checkContainingBlockChainForPagination(RenderBoxModelObject* renderer, RenderBox* ancestorColumnsRenderer) 489 { 490 RenderView* view = renderer->view(); 491 RenderBoxModelObject* prevBlock = renderer; 492 RenderBlock* containingBlock; 493 for (containingBlock = renderer->containingBlock(); 494 containingBlock && containingBlock != view && containingBlock != ancestorColumnsRenderer; 495 containingBlock = containingBlock->containingBlock()) 496 prevBlock = containingBlock; 497 498 // If the columns block wasn't in our containing block chain, then we aren't paginated by it. 499 if (containingBlock != ancestorColumnsRenderer) 500 return false; 501 502 // If the previous block is absolutely positioned, then we can't be paginated by the columns block. 503 if (prevBlock->isPositioned()) 504 return false; 505 506 // Otherwise we are paginated by the columns block. 507 return true; 508 } 509 510 void RenderLayer::updatePagination() 511 { 512 m_isPaginated = false; 513 if (isComposited() || !parent()) 514 return; // FIXME: We will have to deal with paginated compositing layers someday. 515 // FIXME: For now the RenderView can't be paginated. Eventually printing will move to a model where it is though. 516 517 if (isNormalFlowOnly()) { 518 m_isPaginated = parent()->renderer()->hasColumns(); 519 return; 520 } 521 522 // If we're not normal flow, then we need to look for a multi-column object between us and our stacking context. 523 RenderLayer* ancestorStackingContext = stackingContext(); 524 for (RenderLayer* curr = parent(); curr; curr = curr->parent()) { 525 if (curr->renderer()->hasColumns()) { 526 m_isPaginated = checkContainingBlockChainForPagination(renderer(), curr->renderBox()); 527 return; 528 } 529 if (curr == ancestorStackingContext) 530 return; 531 } 532 } 533 534 void RenderLayer::setHasVisibleContent(bool b) 535 { 536 if (m_hasVisibleContent == b && !m_visibleContentStatusDirty) 537 return; 538 m_visibleContentStatusDirty = false; 539 m_hasVisibleContent = b; 540 if (m_hasVisibleContent) { 541 RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint(); 542 m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer); 543 m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer); 544 if (!isNormalFlowOnly()) { 545 for (RenderLayer* sc = stackingContext(); sc; sc = sc->stackingContext()) { 546 sc->dirtyZOrderLists(); 547 if (sc->hasVisibleContent()) 548 break; 549 } 550 } 551 } 552 if (parent()) 553 parent()->childVisibilityChanged(m_hasVisibleContent); 554 } 555 556 void RenderLayer::dirtyVisibleContentStatus() 557 { 558 m_visibleContentStatusDirty = true; 559 if (parent()) 560 parent()->dirtyVisibleDescendantStatus(); 561 } 562 563 void RenderLayer::childVisibilityChanged(bool newVisibility) 564 { 565 if (m_hasVisibleDescendant == newVisibility || m_visibleDescendantStatusDirty) 566 return; 567 if (newVisibility) { 568 RenderLayer* l = this; 569 while (l && !l->m_visibleDescendantStatusDirty && !l->m_hasVisibleDescendant) { 570 l->m_hasVisibleDescendant = true; 571 l = l->parent(); 572 } 573 } else 574 dirtyVisibleDescendantStatus(); 575 } 576 577 void RenderLayer::dirtyVisibleDescendantStatus() 578 { 579 RenderLayer* l = this; 580 while (l && !l->m_visibleDescendantStatusDirty) { 581 l->m_visibleDescendantStatusDirty = true; 582 l = l->parent(); 583 } 584 } 585 586 void RenderLayer::updateVisibilityStatus() 587 { 588 if (m_visibleDescendantStatusDirty) { 589 m_hasVisibleDescendant = false; 590 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) { 591 child->updateVisibilityStatus(); 592 if (child->m_hasVisibleContent || child->m_hasVisibleDescendant) { 593 m_hasVisibleDescendant = true; 594 break; 595 } 596 } 597 m_visibleDescendantStatusDirty = false; 598 } 599 600 if (m_visibleContentStatusDirty) { 601 if (renderer()->style()->visibility() == VISIBLE) 602 m_hasVisibleContent = true; 603 else { 604 // layer may be hidden but still have some visible content, check for this 605 m_hasVisibleContent = false; 606 RenderObject* r = renderer()->firstChild(); 607 while (r) { 608 if (r->style()->visibility() == VISIBLE && !r->hasLayer()) { 609 m_hasVisibleContent = true; 610 break; 611 } 612 if (r->firstChild() && !r->hasLayer()) 613 r = r->firstChild(); 614 else if (r->nextSibling()) 615 r = r->nextSibling(); 616 else { 617 do { 618 r = r->parent(); 619 if (r == renderer()) 620 r = 0; 621 } while (r && !r->nextSibling()); 622 if (r) 623 r = r->nextSibling(); 624 } 625 } 626 } 627 m_visibleContentStatusDirty = false; 628 } 629 } 630 631 void RenderLayer::dirty3DTransformedDescendantStatus() 632 { 633 RenderLayer* curr = stackingContext(); 634 if (curr) 635 curr->m_3DTransformedDescendantStatusDirty = true; 636 637 // This propagates up through preserve-3d hierarchies to the enclosing flattening layer. 638 // Note that preserves3D() creates stacking context, so we can just run up the stacking contexts. 639 while (curr && curr->preserves3D()) { 640 curr->m_3DTransformedDescendantStatusDirty = true; 641 curr = curr->stackingContext(); 642 } 643 } 644 645 // Return true if this layer or any preserve-3d descendants have 3d. 646 bool RenderLayer::update3DTransformedDescendantStatus() 647 { 648 if (m_3DTransformedDescendantStatusDirty) { 649 m_has3DTransformedDescendant = false; 650 651 // Transformed or preserve-3d descendants can only be in the z-order lists, not 652 // in the normal flow list, so we only need to check those. 653 if (m_posZOrderList) { 654 for (unsigned i = 0; i < m_posZOrderList->size(); ++i) 655 m_has3DTransformedDescendant |= m_posZOrderList->at(i)->update3DTransformedDescendantStatus(); 656 } 657 658 // Now check our negative z-index children. 659 if (m_negZOrderList) { 660 for (unsigned i = 0; i < m_negZOrderList->size(); ++i) 661 m_has3DTransformedDescendant |= m_negZOrderList->at(i)->update3DTransformedDescendantStatus(); 662 } 663 664 m_3DTransformedDescendantStatusDirty = false; 665 } 666 667 // If we live in a 3d hierarchy, then the layer at the root of that hierarchy needs 668 // the m_has3DTransformedDescendant set. 669 if (preserves3D()) 670 return has3DTransform() || m_has3DTransformedDescendant; 671 672 return has3DTransform(); 673 } 674 675 void RenderLayer::updateLayerPosition() 676 { 677 IntPoint localPoint; 678 IntSize inlineBoundingBoxOffset; // We don't put this into the RenderLayer x/y for inlines, so we need to subtract it out when done. 679 if (renderer()->isRenderInline()) { 680 RenderInline* inlineFlow = toRenderInline(renderer()); 681 IntRect lineBox = inlineFlow->linesBoundingBox(); 682 setWidth(lineBox.width()); 683 setHeight(lineBox.height()); 684 inlineBoundingBoxOffset = IntSize(lineBox.x(), lineBox.y()); 685 localPoint += inlineBoundingBoxOffset; 686 } else if (RenderBox* box = renderBox()) { 687 setWidth(box->width()); 688 setHeight(box->height()); 689 localPoint += box->locationOffsetIncludingFlipping(); 690 } 691 692 // Clear our cached clip rect information. 693 clearClipRects(); 694 695 if (!renderer()->isPositioned() && renderer()->parent()) { 696 // We must adjust our position by walking up the render tree looking for the 697 // nearest enclosing object with a layer. 698 RenderObject* curr = renderer()->parent(); 699 while (curr && !curr->hasLayer()) { 700 if (curr->isBox() && !curr->isTableRow()) { 701 // Rows and cells share the same coordinate space (that of the section). 702 // Omit them when computing our xpos/ypos. 703 localPoint += toRenderBox(curr)->locationOffsetIncludingFlipping(); 704 } 705 curr = curr->parent(); 706 } 707 if (curr->isBox() && curr->isTableRow()) { 708 // Put ourselves into the row coordinate space. 709 localPoint -= toRenderBox(curr)->locationOffsetIncludingFlipping(); 710 } 711 } 712 713 // Subtract our parent's scroll offset. 714 if (renderer()->isPositioned() && enclosingPositionedAncestor()) { 715 RenderLayer* positionedParent = enclosingPositionedAncestor(); 716 717 // For positioned layers, we subtract out the enclosing positioned layer's scroll offset. 718 IntSize offset = positionedParent->scrolledContentOffset(); 719 localPoint -= offset; 720 721 if (renderer()->isPositioned() && positionedParent->renderer()->isRelPositioned() && positionedParent->renderer()->isRenderInline()) { 722 IntSize offset = toRenderInline(positionedParent->renderer())->relativePositionedInlineOffset(toRenderBox(renderer())); 723 localPoint += offset; 724 } 725 } else if (parent()) { 726 if (isComposited()) { 727 // FIXME: Composited layers ignore pagination, so about the best we can do is make sure they're offset into the appropriate column. 728 // They won't split across columns properly. 729 IntSize columnOffset; 730 parent()->renderer()->adjustForColumns(columnOffset, localPoint); 731 localPoint += columnOffset; 732 } 733 734 IntSize scrollOffset = parent()->scrolledContentOffset(); 735 localPoint -= scrollOffset; 736 } 737 738 m_relX = m_relY = 0; 739 if (renderer()->isRelPositioned()) { 740 m_relX = renderer()->relativePositionOffsetX(); 741 m_relY = renderer()->relativePositionOffsetY(); 742 localPoint.move(m_relX, m_relY); 743 } 744 745 // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers. 746 localPoint -= inlineBoundingBoxOffset; 747 setLocation(localPoint.x(), localPoint.y()); 748 } 749 750 TransformationMatrix RenderLayer::perspectiveTransform() const 751 { 752 if (!renderer()->hasTransform()) 753 return TransformationMatrix(); 754 755 RenderStyle* style = renderer()->style(); 756 if (!style->hasPerspective()) 757 return TransformationMatrix(); 758 759 // Maybe fetch the perspective from the backing? 760 const IntRect borderBox = toRenderBox(renderer())->borderBoxRect(); 761 const float boxWidth = borderBox.width(); 762 const float boxHeight = borderBox.height(); 763 764 float perspectiveOriginX = style->perspectiveOriginX().calcFloatValue(boxWidth); 765 float perspectiveOriginY = style->perspectiveOriginY().calcFloatValue(boxHeight); 766 767 // A perspective origin of 0,0 makes the vanishing point in the center of the element. 768 // We want it to be in the top-left, so subtract half the height and width. 769 perspectiveOriginX -= boxWidth / 2.0f; 770 perspectiveOriginY -= boxHeight / 2.0f; 771 772 TransformationMatrix t; 773 t.translate(perspectiveOriginX, perspectiveOriginY); 774 t.applyPerspective(style->perspective()); 775 t.translate(-perspectiveOriginX, -perspectiveOriginY); 776 777 return t; 778 } 779 780 FloatPoint RenderLayer::perspectiveOrigin() const 781 { 782 if (!renderer()->hasTransform()) 783 return FloatPoint(); 784 785 const IntRect borderBox = toRenderBox(renderer())->borderBoxRect(); 786 RenderStyle* style = renderer()->style(); 787 788 return FloatPoint(style->perspectiveOriginX().calcFloatValue(borderBox.width()), 789 style->perspectiveOriginY().calcFloatValue(borderBox.height())); 790 } 791 792 RenderLayer* RenderLayer::stackingContext() const 793 { 794 RenderLayer* layer = parent(); 795 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) || ENABLE(ANDROID_OVERFLOW_SCROLL) 796 // When using composited fixed elements, they are turned into a stacking 797 // context and we thus need to return them. 798 // We can simplify the while loop by using isStackingContext(); with 799 // composited fixed elements turned on, this will return true for them, 800 // and is otherwise equivalent to the replaced statements. 801 while (layer && !layer->renderer()->isRoot() && !layer->isStackingContext()) 802 #else 803 while (layer && !layer->renderer()->isRenderView() && !layer->renderer()->isRoot() && layer->renderer()->style()->hasAutoZIndex()) 804 #endif 805 layer = layer->parent(); 806 return layer; 807 } 808 809 static inline bool isPositionedContainer(RenderLayer* layer) 810 { 811 RenderObject* o = layer->renderer(); 812 return o->isRenderView() || o->isPositioned() || o->isRelPositioned() || layer->hasTransform(); 813 } 814 815 static inline bool isFixedPositionedContainer(RenderLayer* layer) 816 { 817 RenderObject* o = layer->renderer(); 818 return o->isRenderView() || layer->hasTransform(); 819 } 820 821 RenderLayer* RenderLayer::enclosingPositionedAncestor() const 822 { 823 RenderLayer* curr = parent(); 824 while (curr && !isPositionedContainer(curr)) 825 curr = curr->parent(); 826 827 return curr; 828 } 829 830 RenderLayer* RenderLayer::enclosingTransformedAncestor() const 831 { 832 RenderLayer* curr = parent(); 833 while (curr && !curr->renderer()->isRenderView() && !curr->transform()) 834 curr = curr->parent(); 835 836 return curr; 837 } 838 839 static inline const RenderLayer* compositingContainer(const RenderLayer* layer) 840 { 841 return layer->isNormalFlowOnly() ? layer->parent() : layer->stackingContext(); 842 } 843 844 #if USE(ACCELERATED_COMPOSITING) 845 RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const 846 { 847 if (includeSelf && isComposited()) 848 return const_cast<RenderLayer*>(this); 849 850 for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) { 851 if (curr->isComposited()) 852 return const_cast<RenderLayer*>(curr); 853 } 854 855 return 0; 856 } 857 #endif 858 859 RenderLayer* RenderLayer::clippingRoot() const 860 { 861 #if USE(ACCELERATED_COMPOSITING) 862 if (isComposited()) 863 return const_cast<RenderLayer*>(this); 864 #endif 865 866 const RenderLayer* current = this; 867 while (current) { 868 if (current->renderer()->isRenderView()) 869 return const_cast<RenderLayer*>(current); 870 871 current = compositingContainer(current); 872 ASSERT(current); 873 if (current->transform() 874 #if USE(ACCELERATED_COMPOSITING) 875 || current->isComposited() 876 #endif 877 ) 878 return const_cast<RenderLayer*>(current); 879 } 880 881 ASSERT_NOT_REACHED(); 882 return 0; 883 } 884 885 IntPoint RenderLayer::absoluteToContents(const IntPoint& absolutePoint) const 886 { 887 // We don't use convertToLayerCoords because it doesn't know about transforms 888 return roundedIntPoint(renderer()->absoluteToLocal(absolutePoint, false, true)); 889 } 890 891 bool RenderLayer::requiresSlowRepaints() const 892 { 893 if (isTransparent() || hasReflection() || hasTransform()) 894 return true; 895 if (!parent()) 896 return false; 897 return parent()->requiresSlowRepaints(); 898 } 899 900 bool RenderLayer::isTransparent() const 901 { 902 #if ENABLE(SVG) 903 if (renderer()->node() && renderer()->node()->namespaceURI() == SVGNames::svgNamespaceURI) 904 return false; 905 #endif 906 return renderer()->isTransparent() || renderer()->hasMask(); 907 } 908 909 RenderLayer* RenderLayer::transparentPaintingAncestor() 910 { 911 if (isComposited()) 912 return 0; 913 914 for (RenderLayer* curr = parent(); curr; curr = curr->parent()) { 915 if (curr->isComposited()) 916 return 0; 917 if (curr->isTransparent()) 918 return curr; 919 } 920 return 0; 921 } 922 923 static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior); 924 925 static void expandClipRectForDescendantsAndReflection(IntRect& clipRect, const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior) 926 { 927 // If we have a mask, then the clip is limited to the border box area (and there is 928 // no need to examine child layers). 929 if (!l->renderer()->hasMask()) { 930 // Note: we don't have to walk z-order lists since transparent elements always establish 931 // a stacking context. This means we can just walk the layer tree directly. 932 for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling()) { 933 if (!l->reflection() || l->reflectionLayer() != curr) 934 clipRect.unite(transparencyClipBox(curr, rootLayer, paintBehavior)); 935 } 936 } 937 938 // If we have a reflection, then we need to account for that when we push the clip. Reflect our entire 939 // current transparencyClipBox to catch all child layers. 940 // FIXME: Accelerated compositing will eventually want to do something smart here to avoid incorporating this 941 // size into the parent layer. 942 if (l->renderer()->hasReflection()) { 943 int deltaX = 0; 944 int deltaY = 0; 945 l->convertToLayerCoords(rootLayer, deltaX, deltaY); 946 clipRect.move(-deltaX, -deltaY); 947 clipRect.unite(l->renderBox()->reflectedRect(clipRect)); 948 clipRect.move(deltaX, deltaY); 949 } 950 } 951 952 static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior) 953 { 954 // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the 955 // paintDirtyRect, and that should cut down on the amount we have to paint. Still it 956 // would be better to respect clips. 957 958 if (rootLayer != l && l->paintsWithTransform(paintBehavior)) { 959 // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass 960 // the transformed layer and all of its children. 961 int x = 0; 962 int y = 0; 963 l->convertToLayerCoords(rootLayer, x, y); 964 965 TransformationMatrix transform; 966 transform.translate(x, y); 967 transform = transform * *l->transform(); 968 969 IntRect clipRect = l->boundingBox(l); 970 expandClipRectForDescendantsAndReflection(clipRect, l, l, paintBehavior); 971 return transform.mapRect(clipRect); 972 } 973 974 IntRect clipRect = l->boundingBox(rootLayer); 975 expandClipRectForDescendantsAndReflection(clipRect, l, rootLayer, paintBehavior); 976 return clipRect; 977 } 978 979 void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer* rootLayer, PaintBehavior paintBehavior) 980 { 981 if (p->paintingDisabled() || (paintsWithTransparency(paintBehavior) && m_usedTransparency)) 982 return; 983 984 RenderLayer* ancestor = transparentPaintingAncestor(); 985 if (ancestor) 986 ancestor->beginTransparencyLayers(p, rootLayer, paintBehavior); 987 988 if (paintsWithTransparency(paintBehavior)) { 989 m_usedTransparency = true; 990 p->save(); 991 IntRect clipRect = transparencyClipBox(this, rootLayer, paintBehavior); 992 p->clip(clipRect); 993 p->beginTransparencyLayer(renderer()->opacity()); 994 #ifdef REVEAL_TRANSPARENCY_LAYERS 995 p->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f), ColorSpaceDeviceRGB); 996 p->fillRect(clipRect); 997 #endif 998 } 999 } 1000 1001 void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw() 1002 { 1003 return renderArena->allocate(sz); 1004 } 1005 1006 void RenderLayer::operator delete(void* ptr, size_t sz) 1007 { 1008 // Stash size where destroy can find it. 1009 *(size_t *)ptr = sz; 1010 } 1011 1012 void RenderLayer::destroy(RenderArena* renderArena) 1013 { 1014 delete this; 1015 1016 // Recover the size left there for us by operator delete and free the memory. 1017 renderArena->free(*(size_t *)this, this); 1018 } 1019 1020 void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild) 1021 { 1022 RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild(); 1023 if (prevSibling) { 1024 child->setPreviousSibling(prevSibling); 1025 prevSibling->setNextSibling(child); 1026 ASSERT(prevSibling != child); 1027 } else 1028 setFirstChild(child); 1029 1030 if (beforeChild) { 1031 beforeChild->setPreviousSibling(child); 1032 child->setNextSibling(beforeChild); 1033 ASSERT(beforeChild != child); 1034 } else 1035 setLastChild(child); 1036 1037 child->setParent(this); 1038 1039 if (child->isNormalFlowOnly()) 1040 dirtyNormalFlowList(); 1041 1042 if (!child->isNormalFlowOnly() || child->firstChild()) { 1043 // Dirty the z-order list in which we are contained. The stackingContext() can be null in the 1044 // case where we're building up generated content layers. This is ok, since the lists will start 1045 // off dirty in that case anyway. 1046 child->dirtyStackingContextZOrderLists(); 1047 } 1048 1049 child->updateVisibilityStatus(); 1050 if (child->m_hasVisibleContent || child->m_hasVisibleDescendant) 1051 childVisibilityChanged(true); 1052 1053 #if USE(ACCELERATED_COMPOSITING) 1054 compositor()->layerWasAdded(this, child); 1055 #endif 1056 } 1057 1058 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild) 1059 { 1060 #if USE(ACCELERATED_COMPOSITING) 1061 if (!renderer()->documentBeingDestroyed()) 1062 compositor()->layerWillBeRemoved(this, oldChild); 1063 #endif 1064 1065 // remove the child 1066 if (oldChild->previousSibling()) 1067 oldChild->previousSibling()->setNextSibling(oldChild->nextSibling()); 1068 if (oldChild->nextSibling()) 1069 oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling()); 1070 1071 if (m_first == oldChild) 1072 m_first = oldChild->nextSibling(); 1073 if (m_last == oldChild) 1074 m_last = oldChild->previousSibling(); 1075 1076 if (oldChild->isNormalFlowOnly()) 1077 dirtyNormalFlowList(); 1078 if (!oldChild->isNormalFlowOnly() || oldChild->firstChild()) { 1079 // Dirty the z-order list in which we are contained. When called via the 1080 // reattachment process in removeOnlyThisLayer, the layer may already be disconnected 1081 // from the main layer tree, so we need to null-check the |stackingContext| value. 1082 oldChild->dirtyStackingContextZOrderLists(); 1083 } 1084 1085 oldChild->setPreviousSibling(0); 1086 oldChild->setNextSibling(0); 1087 oldChild->setParent(0); 1088 1089 oldChild->updateVisibilityStatus(); 1090 if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant) 1091 childVisibilityChanged(false); 1092 1093 return oldChild; 1094 } 1095 1096 void RenderLayer::removeOnlyThisLayer() 1097 { 1098 if (!m_parent) 1099 return; 1100 1101 // Mark that we are about to lose our layer. This makes render tree 1102 // walks ignore this layer while we're removing it. 1103 m_renderer->setHasLayer(false); 1104 1105 #if USE(ACCELERATED_COMPOSITING) 1106 compositor()->layerWillBeRemoved(m_parent, this); 1107 #endif 1108 1109 // Dirty the clip rects. 1110 clearClipRectsIncludingDescendants(); 1111 1112 // Remove us from the parent. 1113 RenderLayer* parent = m_parent; 1114 RenderLayer* nextSib = nextSibling(); 1115 parent->removeChild(this); 1116 1117 if (reflection()) 1118 removeChild(reflectionLayer()); 1119 1120 // Now walk our kids and reattach them to our parent. 1121 RenderLayer* current = m_first; 1122 while (current) { 1123 RenderLayer* next = current->nextSibling(); 1124 removeChild(current); 1125 parent->addChild(current, nextSib); 1126 current->setNeedsFullRepaint(); 1127 current->updateLayerPositions(); // Depends on hasLayer() already being false for proper layout. 1128 current = next; 1129 } 1130 1131 m_renderer->destroyLayer(); 1132 } 1133 1134 void RenderLayer::insertOnlyThisLayer() 1135 { 1136 if (!m_parent && renderer()->parent()) { 1137 // We need to connect ourselves when our renderer() has a parent. 1138 // Find our enclosingLayer and add ourselves. 1139 RenderLayer* parentLayer = renderer()->parent()->enclosingLayer(); 1140 ASSERT(parentLayer); 1141 RenderLayer* beforeChild = parentLayer->reflectionLayer() != this ? renderer()->parent()->findNextLayer(parentLayer, renderer()) : 0; 1142 parentLayer->addChild(this, beforeChild); 1143 } 1144 1145 // Remove all descendant layers from the hierarchy and add them to the new position. 1146 for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling()) 1147 curr->moveLayers(m_parent, this); 1148 1149 // Clear out all the clip rects. 1150 clearClipRectsIncludingDescendants(); 1151 } 1152 1153 void 1154 RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, int& yPos) const 1155 { 1156 if (ancestorLayer == this) 1157 return; 1158 1159 EPosition position = renderer()->style()->position(); 1160 if (position == FixedPosition && (!ancestorLayer || ancestorLayer == renderer()->view()->layer())) { 1161 // If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling 1162 // localToAbsolute() on the RenderView. 1163 FloatPoint absPos = renderer()->localToAbsolute(FloatPoint(), true); 1164 xPos += absPos.x(); 1165 yPos += absPos.y(); 1166 return; 1167 } 1168 1169 if (position == FixedPosition) { 1170 // For a fixed layers, we need to walk up to the root to see if there's a fixed position container 1171 // (e.g. a transformed layer). It's an error to call convertToLayerCoords() across a layer with a transform, 1172 // so we should always find the ancestor at or before we find the fixed position container. 1173 RenderLayer* fixedPositionContainerLayer = 0; 1174 bool foundAncestor = false; 1175 for (RenderLayer* currLayer = parent(); currLayer; currLayer = currLayer->parent()) { 1176 if (currLayer == ancestorLayer) 1177 foundAncestor = true; 1178 1179 if (isFixedPositionedContainer(currLayer)) { 1180 fixedPositionContainerLayer = currLayer; 1181 ASSERT(foundAncestor); 1182 break; 1183 } 1184 } 1185 1186 ASSERT(fixedPositionContainerLayer); // We should have hit the RenderView's layer at least. 1187 1188 if (fixedPositionContainerLayer != ancestorLayer) { 1189 int fixedContainerX = 0; 1190 int fixedContainerY = 0; 1191 convertToLayerCoords(fixedPositionContainerLayer, fixedContainerX, fixedContainerY); 1192 1193 int ancestorX = 0; 1194 int ancestorY = 0; 1195 ancestorLayer->convertToLayerCoords(fixedPositionContainerLayer, ancestorX, ancestorY); 1196 1197 xPos += (fixedContainerX - ancestorX); 1198 yPos += (fixedContainerY - ancestorY); 1199 return; 1200 } 1201 } 1202 1203 1204 RenderLayer* parentLayer; 1205 if (position == AbsolutePosition || position == FixedPosition) { 1206 // Do what enclosingPositionedAncestor() does, but check for ancestorLayer along the way. 1207 parentLayer = parent(); 1208 bool foundAncestorFirst = false; 1209 while (parentLayer) { 1210 if (isPositionedContainer(parentLayer)) 1211 break; 1212 1213 if (parentLayer == ancestorLayer) { 1214 foundAncestorFirst = true; 1215 break; 1216 } 1217 1218 parentLayer = parentLayer->parent(); 1219 } 1220 1221 if (foundAncestorFirst) { 1222 // Found ancestorLayer before the abs. positioned container, so compute offset of both relative 1223 // to enclosingPositionedAncestor and subtract. 1224 RenderLayer* positionedAncestor = parentLayer->enclosingPositionedAncestor(); 1225 1226 int thisX = 0; 1227 int thisY = 0; 1228 convertToLayerCoords(positionedAncestor, thisX, thisY); 1229 1230 int ancestorX = 0; 1231 int ancestorY = 0; 1232 ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorX, ancestorY); 1233 1234 xPos += (thisX - ancestorX); 1235 yPos += (thisY - ancestorY); 1236 return; 1237 } 1238 } else 1239 parentLayer = parent(); 1240 1241 if (!parentLayer) 1242 return; 1243 1244 parentLayer->convertToLayerCoords(ancestorLayer, xPos, yPos); 1245 1246 xPos += x(); 1247 yPos += y(); 1248 } 1249 1250 static inline int adjustedScrollDelta(int beginningDelta) { 1251 // This implemention matches Firefox's. 1252 // http://mxr.mozilla.org/firefox/source/toolkit/content/widgets/browser.xml#856. 1253 const int speedReducer = 12; 1254 1255 int adjustedDelta = beginningDelta / speedReducer; 1256 if (adjustedDelta > 1) 1257 adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(adjustedDelta))) - 1; 1258 else if (adjustedDelta < -1) 1259 adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(-adjustedDelta))) + 1; 1260 1261 return adjustedDelta; 1262 } 1263 1264 void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint) 1265 { 1266 Frame* frame = renderer()->frame(); 1267 if (!frame) 1268 return; 1269 1270 IntPoint currentMousePosition = frame->eventHandler()->currentMousePosition(); 1271 1272 // We need to check if the current mouse position is out of the window. When the mouse is out of the window, the position is incoherent 1273 static IntPoint previousMousePosition; 1274 if (currentMousePosition.x() < 0 || currentMousePosition.y() < 0) 1275 currentMousePosition = previousMousePosition; 1276 else 1277 previousMousePosition = currentMousePosition; 1278 1279 int xDelta = currentMousePosition.x() - sourcePoint.x(); 1280 int yDelta = currentMousePosition.y() - sourcePoint.y(); 1281 1282 if (abs(xDelta) <= ScrollView::noPanScrollRadius) // at the center we let the space for the icon 1283 xDelta = 0; 1284 if (abs(yDelta) <= ScrollView::noPanScrollRadius) 1285 yDelta = 0; 1286 1287 scrollByRecursively(adjustedScrollDelta(xDelta), adjustedScrollDelta(yDelta)); 1288 } 1289 1290 void RenderLayer::scrollByRecursively(int xDelta, int yDelta) 1291 { 1292 if (!xDelta && !yDelta) 1293 return; 1294 1295 bool restrictedByLineClamp = false; 1296 if (renderer()->parent()) 1297 restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone(); 1298 1299 if (renderer()->hasOverflowClip() && !restrictedByLineClamp) { 1300 int newOffsetX = scrollXOffset() + xDelta; 1301 int newOffsetY = scrollYOffset() + yDelta; 1302 scrollToOffset(newOffsetX, newOffsetY); 1303 1304 // If this layer can't do the scroll we ask the next layer up that can scroll to try 1305 int leftToScrollX = newOffsetX - scrollXOffset(); 1306 int leftToScrollY = newOffsetY - scrollYOffset(); 1307 if ((leftToScrollX || leftToScrollY) && renderer()->parent()) { 1308 RenderObject* nextRenderer = renderer()->parent(); 1309 while (nextRenderer) { 1310 if (nextRenderer->isBox() && toRenderBox(nextRenderer)->canBeScrolledAndHasScrollableArea()) { 1311 nextRenderer->enclosingLayer()->scrollByRecursively(leftToScrollX, leftToScrollY); 1312 break; 1313 } 1314 nextRenderer = nextRenderer->parent(); 1315 } 1316 1317 Frame* frame = renderer()->frame(); 1318 if (frame) 1319 frame->eventHandler()->updateAutoscrollRenderer(); 1320 } 1321 } else if (renderer()->view()->frameView()) { 1322 // If we are here, we were called on a renderer that can be programmatically scrolled, but doesn't 1323 // have an overflow clip. Which means that it is a document node that can be scrolled. 1324 renderer()->view()->frameView()->scrollBy(IntSize(xDelta, yDelta)); 1325 // FIXME: If we didn't scroll the whole way, do we want to try looking at the frames ownerElement? 1326 // https://bugs.webkit.org/show_bug.cgi?id=28237 1327 } 1328 } 1329 1330 void RenderLayer::scrollToOffset(int x, int y) 1331 { 1332 ScrollableArea::scrollToOffsetWithoutAnimation(IntPoint(x, y)); 1333 } 1334 1335 void RenderLayer::scrollTo(int x, int y) 1336 { 1337 RenderBox* box = renderBox(); 1338 if (!box) 1339 return; 1340 1341 if (box->style()->overflowX() != OMARQUEE) { 1342 if (x < 0) 1343 x = 0; 1344 if (y < 0) 1345 y = 0; 1346 1347 // Call the scrollWidth/Height functions so that the dimensions will be computed if they need 1348 // to be (for overflow:hidden blocks). 1349 int maxX = scrollWidth() - box->clientWidth(); 1350 if (maxX < 0) 1351 maxX = 0; 1352 int maxY = scrollHeight() - box->clientHeight(); 1353 if (maxY < 0) 1354 maxY = 0; 1355 1356 if (x > maxX) 1357 x = maxX; 1358 if (y > maxY) 1359 y = maxY; 1360 } 1361 1362 // FIXME: Eventually, we will want to perform a blit. For now never 1363 // blit, since the check for blitting is going to be very 1364 // complicated (since it will involve testing whether our layer 1365 // is either occluded by another layer or clipped by an enclosing 1366 // layer or contains fixed backgrounds, etc.). 1367 int newScrollX = x - m_scrollOrigin.x(); 1368 int newScrollY = y - m_scrollOrigin.y(); 1369 if (m_scrollY == newScrollY && m_scrollX == newScrollX) 1370 return; 1371 m_scrollX = newScrollX; 1372 m_scrollY = newScrollY; 1373 1374 // Update the positions of our child layers. Don't have updateLayerPositions() update 1375 // compositing layers, because we need to do a deep update from the compositing ancestor. 1376 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 1377 child->updateLayerPositions(0); 1378 1379 RenderView* view = renderer()->view(); 1380 1381 // We should have a RenderView if we're trying to scroll. 1382 ASSERT(view); 1383 if (view) { 1384 #if ENABLE(DASHBOARD_SUPPORT) 1385 // Update dashboard regions, scrolling may change the clip of a 1386 // particular region. 1387 view->frameView()->updateDashboardRegions(); 1388 #endif 1389 1390 view->updateWidgetPositions(); 1391 } 1392 1393 #if PLATFORM(ANDROID) 1394 GraphicsLayerAndroid* backingLayer = 0; 1395 bool scrollableContent = false; 1396 #endif 1397 1398 #if USE(ACCELERATED_COMPOSITING) 1399 if (compositor()->inCompositingMode()) { 1400 // Our stacking context is guaranteed to contain all of our descendants that may need 1401 // repositioning, so update compositing layers from there. 1402 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 1403 if (view && backing() && backing()->graphicsLayer()) { 1404 backingLayer = static_cast<GraphicsLayerAndroid*>(backing()->graphicsLayer()); 1405 scrollableContent = backingLayer->contentLayer() 1406 && backingLayer->contentLayer()->contentIsScrollable(); 1407 } 1408 // If we have a scrollable content, no need to do this 1409 RenderLayer* compositingAncestor = enclosingCompositingLayer(); 1410 if (!scrollableContent && compositingAncestor) { 1411 #else 1412 if (RenderLayer* compositingAncestor = stackingContext()->enclosingCompositingLayer()) { 1413 #endif 1414 if (compositor()->compositingConsultsOverlap()) 1415 compositor()->updateCompositingLayers(CompositingUpdateOnScroll, compositingAncestor); 1416 else { 1417 bool isUpdateRoot = true; 1418 compositingAncestor->backing()->updateAfterLayout(RenderLayerBacking::AllDescendants, isUpdateRoot); 1419 } 1420 } 1421 } 1422 #endif 1423 1424 RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint(); 1425 IntRect rectForRepaint = renderer()->clippedOverflowRectForRepaint(repaintContainer); 1426 1427 Frame* frame = renderer()->frame(); 1428 if (frame) { 1429 // The caret rect needs to be invalidated after scrolling 1430 frame->selection()->setCaretRectNeedsUpdate(); 1431 1432 #if !ENABLE(ANDROID_OVERFLOW_SCROLL) 1433 FloatQuad quadForFakeMouseMoveEvent = FloatQuad(rectForRepaint); 1434 if (repaintContainer) 1435 quadForFakeMouseMoveEvent = repaintContainer->localToAbsoluteQuad(quadForFakeMouseMoveEvent); 1436 frame->eventHandler()->dispatchFakeMouseMoveEventSoonInQuad(quadForFakeMouseMoveEvent); 1437 #endif 1438 } 1439 1440 // Just schedule a full repaint of our object. 1441 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 1442 // On android, scrollable areas are put on composited layers, so we 1443 // do not need to repaint simply because we are scrolling 1444 if (view && !(hasOverflowScroll() || scrollableContent)) 1445 renderer()->repaintUsingContainer(repaintContainer, rectForRepaint); 1446 if (backingLayer && (hasOverflowScroll() || scrollableContent)) 1447 backingLayer->updateScrollOffset(); 1448 #else 1449 if (view) 1450 renderer()->repaintUsingContainer(repaintContainer, rectForRepaint); 1451 #endif 1452 1453 // Schedule the scroll DOM event. 1454 if (renderer()->node()) 1455 renderer()->node()->document()->eventQueue()->enqueueOrDispatchScrollEvent(renderer()->node(), EventQueue::ScrollEventElementTarget); 1456 } 1457 1458 void RenderLayer::scrollRectToVisible(const IntRect& rect, bool scrollToAnchor, const ScrollAlignment& alignX, const ScrollAlignment& alignY) 1459 { 1460 RenderLayer* parentLayer = 0; 1461 IntRect newRect = rect; 1462 int xOffset = 0, yOffset = 0; 1463 1464 // We may end up propagating a scroll event. It is important that we suspend events until 1465 // the end of the function since they could delete the layer or the layer's renderer(). 1466 FrameView* frameView = renderer()->document()->view(); 1467 if (frameView) 1468 frameView->pauseScheduledEvents(); 1469 1470 bool restrictedByLineClamp = false; 1471 if (renderer()->parent()) { 1472 parentLayer = renderer()->parent()->enclosingLayer(); 1473 restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone(); 1474 } 1475 1476 if (renderer()->hasOverflowClip() && !restrictedByLineClamp) { 1477 // Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property. 1478 // This will prevent us from revealing text hidden by the slider in Safari RSS. 1479 RenderBox* box = renderBox(); 1480 ASSERT(box); 1481 FloatPoint absPos = box->localToAbsolute(); 1482 absPos.move(box->borderLeft(), box->borderTop()); 1483 1484 IntRect layerBounds = IntRect(absPos.x() + scrollXOffset(), absPos.y() + scrollYOffset(), box->clientWidth(), box->clientHeight()); 1485 IntRect exposeRect = IntRect(rect.x() + scrollXOffset(), rect.y() + scrollYOffset(), rect.width(), rect.height()); 1486 IntRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY); 1487 1488 xOffset = r.x() - absPos.x(); 1489 yOffset = r.y() - absPos.y(); 1490 // Adjust offsets if they're outside of the allowable range. 1491 xOffset = max(0, min(scrollWidth() - layerBounds.width(), xOffset)); 1492 yOffset = max(0, min(scrollHeight() - layerBounds.height(), yOffset)); 1493 1494 if (xOffset != scrollXOffset() || yOffset != scrollYOffset()) { 1495 int diffX = scrollXOffset(); 1496 int diffY = scrollYOffset(); 1497 scrollToOffset(xOffset, yOffset); 1498 diffX = scrollXOffset() - diffX; 1499 diffY = scrollYOffset() - diffY; 1500 newRect.setX(rect.x() - diffX); 1501 newRect.setY(rect.y() - diffY); 1502 } 1503 } else if (!parentLayer && renderer()->isBox() && renderBox()->canBeProgramaticallyScrolled(scrollToAnchor)) { 1504 if (frameView) { 1505 if (renderer()->document() && renderer()->document()->ownerElement() && renderer()->document()->ownerElement()->renderer()) { 1506 IntRect viewRect = frameView->visibleContentRect(); 1507 IntRect r = getRectToExpose(viewRect, rect, alignX, alignY); 1508 1509 xOffset = r.x(); 1510 yOffset = r.y(); 1511 // Adjust offsets if they're outside of the allowable range. 1512 xOffset = max(0, min(frameView->contentsWidth(), xOffset)); 1513 yOffset = max(0, min(frameView->contentsHeight(), yOffset)); 1514 1515 frameView->setScrollPosition(IntPoint(xOffset, yOffset)); 1516 parentLayer = renderer()->document()->ownerElement()->renderer()->enclosingLayer(); 1517 newRect.setX(rect.x() - frameView->scrollX() + frameView->x()); 1518 newRect.setY(rect.y() - frameView->scrollY() + frameView->y()); 1519 } else { 1520 IntRect viewRect = frameView->visibleContentRect(); 1521 IntRect r = getRectToExpose(viewRect, rect, alignX, alignY); 1522 1523 frameView->setScrollPosition(r.location()); 1524 1525 // This is the outermost view of a web page, so after scrolling this view we 1526 // scroll its container by calling Page::scrollRectIntoView. 1527 // This only has an effect on the Mac platform in applications 1528 // that put web views into scrolling containers, such as Mac OS X Mail. 1529 // The canAutoscroll function in EventHandler also knows about this. 1530 if (Frame* frame = frameView->frame()) { 1531 if (Page* page = frame->page()) 1532 page->chrome()->scrollRectIntoView(rect); 1533 } 1534 } 1535 } 1536 } 1537 1538 if (parentLayer) 1539 parentLayer->scrollRectToVisible(newRect, scrollToAnchor, alignX, alignY); 1540 1541 if (frameView) 1542 frameView->resumeScheduledEvents(); 1543 } 1544 1545 IntRect RenderLayer::getRectToExpose(const IntRect &visibleRect, const IntRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY) 1546 { 1547 // Determine the appropriate X behavior. 1548 ScrollBehavior scrollX; 1549 IntRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height()); 1550 int intersectWidth = intersection(visibleRect, exposeRectX).width(); 1551 if (intersectWidth == exposeRect.width() || intersectWidth >= MIN_INTERSECT_FOR_REVEAL) 1552 // If the rectangle is fully visible, use the specified visible behavior. 1553 // If the rectangle is partially visible, but over a certain threshold, 1554 // then treat it as fully visible to avoid unnecessary horizontal scrolling 1555 scrollX = ScrollAlignment::getVisibleBehavior(alignX); 1556 else if (intersectWidth == visibleRect.width()) { 1557 // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work. 1558 scrollX = ScrollAlignment::getVisibleBehavior(alignX); 1559 if (scrollX == alignCenter) 1560 scrollX = noScroll; 1561 } else if (intersectWidth > 0) 1562 // If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior 1563 scrollX = ScrollAlignment::getPartialBehavior(alignX); 1564 else 1565 scrollX = ScrollAlignment::getHiddenBehavior(alignX); 1566 // If we're trying to align to the closest edge, and the exposeRect is further right 1567 // than the visibleRect, and not bigger than the visible area, then align with the right. 1568 if (scrollX == alignToClosestEdge && exposeRect.maxX() > visibleRect.maxX() && exposeRect.width() < visibleRect.width()) 1569 scrollX = alignRight; 1570 1571 // Given the X behavior, compute the X coordinate. 1572 int x; 1573 if (scrollX == noScroll) 1574 x = visibleRect.x(); 1575 else if (scrollX == alignRight) 1576 x = exposeRect.maxX() - visibleRect.width(); 1577 else if (scrollX == alignCenter) 1578 x = exposeRect.x() + (exposeRect.width() - visibleRect.width()) / 2; 1579 else 1580 x = exposeRect.x(); 1581 1582 // Determine the appropriate Y behavior. 1583 ScrollBehavior scrollY; 1584 IntRect exposeRectY(visibleRect.x(), exposeRect.y(), visibleRect.width(), exposeRect.height()); 1585 int intersectHeight = intersection(visibleRect, exposeRectY).height(); 1586 if (intersectHeight == exposeRect.height()) 1587 // If the rectangle is fully visible, use the specified visible behavior. 1588 scrollY = ScrollAlignment::getVisibleBehavior(alignY); 1589 else if (intersectHeight == visibleRect.height()) { 1590 // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work. 1591 scrollY = ScrollAlignment::getVisibleBehavior(alignY); 1592 if (scrollY == alignCenter) 1593 scrollY = noScroll; 1594 } else if (intersectHeight > 0) 1595 // If the rectangle is partially visible, use the specified partial behavior 1596 scrollY = ScrollAlignment::getPartialBehavior(alignY); 1597 else 1598 scrollY = ScrollAlignment::getHiddenBehavior(alignY); 1599 // If we're trying to align to the closest edge, and the exposeRect is further down 1600 // than the visibleRect, and not bigger than the visible area, then align with the bottom. 1601 if (scrollY == alignToClosestEdge && exposeRect.maxY() > visibleRect.maxY() && exposeRect.height() < visibleRect.height()) 1602 scrollY = alignBottom; 1603 1604 // Given the Y behavior, compute the Y coordinate. 1605 int y; 1606 if (scrollY == noScroll) 1607 y = visibleRect.y(); 1608 else if (scrollY == alignBottom) 1609 y = exposeRect.maxY() - visibleRect.height(); 1610 else if (scrollY == alignCenter) 1611 y = exposeRect.y() + (exposeRect.height() - visibleRect.height()) / 2; 1612 else 1613 y = exposeRect.y(); 1614 1615 return IntRect(IntPoint(x, y), visibleRect.size()); 1616 } 1617 1618 void RenderLayer::autoscroll() 1619 { 1620 Frame* frame = renderer()->frame(); 1621 if (!frame) 1622 return; 1623 1624 FrameView* frameView = frame->view(); 1625 if (!frameView) 1626 return; 1627 1628 #if ENABLE(DRAG_SUPPORT) 1629 frame->eventHandler()->updateSelectionForMouseDrag(); 1630 #endif 1631 1632 IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->currentMousePosition()); 1633 scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); 1634 } 1635 1636 void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset) 1637 { 1638 // FIXME: This should be possible on generated content but is not right now. 1639 if (!inResizeMode() || !renderer()->hasOverflowClip() || !renderer()->node()) 1640 return; 1641 1642 // Set the width and height of the shadow ancestor node if there is one. 1643 // This is necessary for textarea elements since the resizable layer is in the shadow content. 1644 Element* element = static_cast<Element*>(renderer()->node()->shadowAncestorNode()); 1645 RenderBox* renderer = toRenderBox(element->renderer()); 1646 1647 EResize resize = renderer->style()->resize(); 1648 if (resize == RESIZE_NONE) 1649 return; 1650 1651 Document* document = element->document(); 1652 if (!document->frame()->eventHandler()->mousePressed()) 1653 return; 1654 1655 float zoomFactor = renderer->style()->effectiveZoom(); 1656 1657 IntSize newOffset = offsetFromResizeCorner(document->view()->windowToContents(evt.pos())); 1658 newOffset.setWidth(newOffset.width() / zoomFactor); 1659 newOffset.setHeight(newOffset.height() / zoomFactor); 1660 1661 IntSize currentSize = IntSize(renderer->width() / zoomFactor, renderer->height() / zoomFactor); 1662 IntSize minimumSize = element->minimumSizeForResizing().shrunkTo(currentSize); 1663 element->setMinimumSizeForResizing(minimumSize); 1664 1665 IntSize adjustedOldOffset = IntSize(oldOffset.width() / zoomFactor, oldOffset.height() / zoomFactor); 1666 1667 IntSize difference = (currentSize + newOffset - adjustedOldOffset).expandedTo(minimumSize) - currentSize; 1668 1669 CSSStyleDeclaration* style = element->style(); 1670 bool isBoxSizingBorder = renderer->style()->boxSizing() == BORDER_BOX; 1671 1672 ExceptionCode ec; 1673 1674 if (resize != RESIZE_VERTICAL && difference.width()) { 1675 if (element->isFormControlElement()) { 1676 // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>). 1677 style->setProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false, ec); 1678 style->setProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false, ec); 1679 } 1680 int baseWidth = renderer->width() - (isBoxSizingBorder ? 0 : renderer->borderAndPaddingWidth()); 1681 baseWidth = baseWidth / zoomFactor; 1682 style->setProperty(CSSPropertyWidth, String::number(baseWidth + difference.width()) + "px", false, ec); 1683 } 1684 1685 if (resize != RESIZE_HORIZONTAL && difference.height()) { 1686 if (element->isFormControlElement()) { 1687 // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>). 1688 style->setProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false, ec); 1689 style->setProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false, ec); 1690 } 1691 int baseHeight = renderer->height() - (isBoxSizingBorder ? 0 : renderer->borderAndPaddingHeight()); 1692 baseHeight = baseHeight / zoomFactor; 1693 style->setProperty(CSSPropertyHeight, String::number(baseHeight + difference.height()) + "px", false, ec); 1694 } 1695 1696 document->updateLayout(); 1697 1698 // FIXME (Radar 4118564): We should also autoscroll the window as necessary to keep the point under the cursor in view. 1699 } 1700 1701 int RenderLayer::scrollSize(ScrollbarOrientation orientation) const 1702 { 1703 Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_hBar : m_vBar).get(); 1704 return scrollbar ? (scrollbar->totalSize() - scrollbar->visibleSize()) : 0; 1705 } 1706 1707 void RenderLayer::setScrollOffset(const IntPoint& offset) 1708 { 1709 scrollTo(offset.x(), offset.y()); 1710 } 1711 1712 int RenderLayer::scrollPosition(Scrollbar* scrollbar) const 1713 { 1714 if (scrollbar->orientation() == HorizontalScrollbar) 1715 return scrollXOffset(); 1716 if (scrollbar->orientation() == VerticalScrollbar) 1717 return scrollYOffset(); 1718 return 0; 1719 } 1720 1721 bool RenderLayer::isActive() const 1722 { 1723 Page* page = renderer()->frame()->page(); 1724 return page && page->focusController()->isActive(); 1725 } 1726 1727 static IntRect cornerRect(const RenderLayer* layer, const IntRect& bounds) 1728 { 1729 int horizontalThickness; 1730 int verticalThickness; 1731 if (!layer->verticalScrollbar() && !layer->horizontalScrollbar()) { 1732 // FIXME: This isn't right. We need to know the thickness of custom scrollbars 1733 // even when they don't exist in order to set the resizer square size properly. 1734 horizontalThickness = ScrollbarTheme::nativeTheme()->scrollbarThickness(); 1735 verticalThickness = horizontalThickness; 1736 } else if (layer->verticalScrollbar() && !layer->horizontalScrollbar()) { 1737 horizontalThickness = layer->verticalScrollbar()->width(); 1738 verticalThickness = horizontalThickness; 1739 } else if (layer->horizontalScrollbar() && !layer->verticalScrollbar()) { 1740 verticalThickness = layer->horizontalScrollbar()->height(); 1741 horizontalThickness = verticalThickness; 1742 } else { 1743 horizontalThickness = layer->verticalScrollbar()->width(); 1744 verticalThickness = layer->horizontalScrollbar()->height(); 1745 } 1746 return IntRect(bounds.maxX() - horizontalThickness - layer->renderer()->style()->borderRightWidth(), 1747 bounds.maxY() - verticalThickness - layer->renderer()->style()->borderBottomWidth(), 1748 horizontalThickness, verticalThickness); 1749 } 1750 1751 IntRect RenderLayer::scrollCornerRect() const 1752 { 1753 // We have a scrollbar corner when a scrollbar is visible and not filling the entire length of the box. 1754 // This happens when: 1755 // (a) A resizer is present and at least one scrollbar is present 1756 // (b) Both scrollbars are present. 1757 bool hasHorizontalBar = horizontalScrollbar(); 1758 bool hasVerticalBar = verticalScrollbar(); 1759 bool hasResizer = renderer()->style()->resize() != RESIZE_NONE; 1760 if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar || hasVerticalBar))) 1761 return cornerRect(this, renderBox()->borderBoxRect()); 1762 return IntRect(); 1763 } 1764 1765 static IntRect resizerCornerRect(const RenderLayer* layer, const IntRect& bounds) 1766 { 1767 ASSERT(layer->renderer()->isBox()); 1768 if (layer->renderer()->style()->resize() == RESIZE_NONE) 1769 return IntRect(); 1770 return cornerRect(layer, bounds); 1771 } 1772 1773 IntRect RenderLayer::scrollCornerAndResizerRect() const 1774 { 1775 RenderBox* box = renderBox(); 1776 if (!box) 1777 return IntRect(); 1778 IntRect scrollCornerAndResizer = scrollCornerRect(); 1779 if (scrollCornerAndResizer.isEmpty()) 1780 scrollCornerAndResizer = resizerCornerRect(this, box->borderBoxRect()); 1781 return scrollCornerAndResizer; 1782 } 1783 1784 bool RenderLayer::isScrollCornerVisible() const 1785 { 1786 ASSERT(renderer()->isBox()); 1787 return !scrollCornerRect().isEmpty(); 1788 } 1789 1790 IntRect RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const 1791 { 1792 RenderView* view = renderer()->view(); 1793 if (!view) 1794 return scrollbarRect; 1795 1796 IntRect rect = scrollbarRect; 1797 rect.move(scrollbarOffset(scrollbar)); 1798 1799 return view->frameView()->convertFromRenderer(renderer(), rect); 1800 } 1801 1802 IntRect RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const 1803 { 1804 RenderView* view = renderer()->view(); 1805 if (!view) 1806 return parentRect; 1807 1808 IntRect rect = view->frameView()->convertToRenderer(renderer(), parentRect); 1809 rect.move(-scrollbarOffset(scrollbar)); 1810 return rect; 1811 } 1812 1813 IntPoint RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const 1814 { 1815 RenderView* view = renderer()->view(); 1816 if (!view) 1817 return scrollbarPoint; 1818 1819 IntPoint point = scrollbarPoint; 1820 point.move(scrollbarOffset(scrollbar)); 1821 return view->frameView()->convertFromRenderer(renderer(), point); 1822 } 1823 1824 IntPoint RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const 1825 { 1826 RenderView* view = renderer()->view(); 1827 if (!view) 1828 return parentPoint; 1829 1830 IntPoint point = view->frameView()->convertToRenderer(renderer(), parentPoint); 1831 1832 point.move(-scrollbarOffset(scrollbar)); 1833 return point; 1834 } 1835 1836 IntSize RenderLayer::contentsSize() const 1837 { 1838 return IntSize(const_cast<RenderLayer*>(this)->scrollWidth(), const_cast<RenderLayer*>(this)->scrollHeight()); 1839 } 1840 1841 int RenderLayer::visibleHeight() const 1842 { 1843 return m_height; 1844 } 1845 1846 int RenderLayer::visibleWidth() const 1847 { 1848 return m_width; 1849 } 1850 1851 bool RenderLayer::shouldSuspendScrollAnimations() const 1852 { 1853 RenderView* view = renderer()->view(); 1854 if (!view) 1855 return true; 1856 return view->frameView()->shouldSuspendScrollAnimations(); 1857 } 1858 1859 IntPoint RenderLayer::currentMousePosition() const 1860 { 1861 return renderer()->frame() ? renderer()->frame()->eventHandler()->currentMousePosition() : IntPoint(); 1862 } 1863 1864 IntSize RenderLayer::scrollbarOffset(const Scrollbar* scrollbar) const 1865 { 1866 RenderBox* box = renderBox(); 1867 1868 if (scrollbar == m_vBar.get()) 1869 return IntSize(box->width() - box->borderRight() - scrollbar->width(), box->borderTop()); 1870 1871 if (scrollbar == m_hBar.get()) 1872 return IntSize(box->borderLeft(), box->height() - box->borderBottom() - scrollbar->height()); 1873 1874 ASSERT_NOT_REACHED(); 1875 return IntSize(); 1876 } 1877 1878 void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect) 1879 { 1880 #if USE(ACCELERATED_COMPOSITING) 1881 if (scrollbar == m_vBar.get()) { 1882 if (GraphicsLayer* layer = layerForVerticalScrollbar()) { 1883 layer->setNeedsDisplayInRect(rect); 1884 return; 1885 } 1886 } else { 1887 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) { 1888 layer->setNeedsDisplayInRect(rect); 1889 return; 1890 } 1891 } 1892 #endif 1893 IntRect scrollRect = rect; 1894 RenderBox* box = renderBox(); 1895 ASSERT(box); 1896 if (scrollbar == m_vBar.get()) 1897 scrollRect.move(box->width() - box->borderRight() - scrollbar->width(), box->borderTop()); 1898 else 1899 scrollRect.move(box->borderLeft(), box->height() - box->borderBottom() - scrollbar->height()); 1900 renderer()->repaintRectangle(scrollRect); 1901 } 1902 1903 void RenderLayer::invalidateScrollCornerRect(const IntRect& rect) 1904 { 1905 #if USE(ACCELERATED_COMPOSITING) 1906 if (GraphicsLayer* layer = layerForScrollCorner()) { 1907 layer->setNeedsDisplayInRect(rect); 1908 return; 1909 } 1910 #endif 1911 if (m_scrollCorner) 1912 m_scrollCorner->repaintRectangle(rect); 1913 if (m_resizer) 1914 m_resizer->repaintRectangle(rect); 1915 } 1916 1917 PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientation) 1918 { 1919 RefPtr<Scrollbar> widget; 1920 RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer(); 1921 bool hasCustomScrollbarStyle = actualRenderer->isBox() && actualRenderer->style()->hasPseudoStyle(SCROLLBAR); 1922 if (hasCustomScrollbarStyle) 1923 widget = RenderScrollbar::createCustomScrollbar(this, orientation, toRenderBox(actualRenderer)); 1924 else { 1925 widget = Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar); 1926 if (orientation == HorizontalScrollbar) 1927 didAddHorizontalScrollbar(widget.get()); 1928 else 1929 didAddVerticalScrollbar(widget.get()); 1930 } 1931 renderer()->document()->view()->addChild(widget.get()); 1932 return widget.release(); 1933 } 1934 1935 void RenderLayer::destroyScrollbar(ScrollbarOrientation orientation) 1936 { 1937 RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar; 1938 if (scrollbar) { 1939 if (scrollbar->isCustomScrollbar()) 1940 static_cast<RenderScrollbar*>(scrollbar.get())->clearOwningRenderer(); 1941 else { 1942 if (orientation == HorizontalScrollbar) 1943 willRemoveHorizontalScrollbar(scrollbar.get()); 1944 else 1945 willRemoveVerticalScrollbar(scrollbar.get()); 1946 } 1947 1948 scrollbar->removeFromParent(); 1949 scrollbar->disconnectFromScrollableArea(); 1950 scrollbar = 0; 1951 } 1952 } 1953 1954 void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar) 1955 { 1956 if (hasScrollbar == (m_hBar != 0)) 1957 return; 1958 1959 if (hasScrollbar) 1960 m_hBar = createScrollbar(HorizontalScrollbar); 1961 else 1962 destroyScrollbar(HorizontalScrollbar); 1963 1964 // Destroying or creating one bar can cause our scrollbar corner to come and go. We need to update the opposite scrollbar's style. 1965 if (m_hBar) 1966 m_hBar->styleChanged(); 1967 if (m_vBar) 1968 m_vBar->styleChanged(); 1969 1970 #if ENABLE(DASHBOARD_SUPPORT) 1971 // Force an update since we know the scrollbars have changed things. 1972 if (renderer()->document()->hasDashboardRegions()) 1973 renderer()->document()->setDashboardRegionsDirty(true); 1974 #endif 1975 } 1976 1977 void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar) 1978 { 1979 if (hasScrollbar == (m_vBar != 0)) 1980 return; 1981 1982 if (hasScrollbar) 1983 m_vBar = createScrollbar(VerticalScrollbar); 1984 else 1985 destroyScrollbar(VerticalScrollbar); 1986 1987 // Destroying or creating one bar can cause our scrollbar corner to come and go. We need to update the opposite scrollbar's style. 1988 if (m_hBar) 1989 m_hBar->styleChanged(); 1990 if (m_vBar) 1991 m_vBar->styleChanged(); 1992 1993 #if ENABLE(DASHBOARD_SUPPORT) 1994 // Force an update since we know the scrollbars have changed things. 1995 if (renderer()->document()->hasDashboardRegions()) 1996 renderer()->document()->setDashboardRegionsDirty(true); 1997 #endif 1998 } 1999 2000 int RenderLayer::verticalScrollbarWidth(OverlayScrollbarSizeRelevancy relevancy) const 2001 { 2002 if (!m_vBar || (m_vBar->isOverlayScrollbar() && relevancy == IgnoreOverlayScrollbarSize)) 2003 return 0; 2004 return m_vBar->width(); 2005 } 2006 2007 int RenderLayer::horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevancy) const 2008 { 2009 if (!m_hBar || (m_hBar->isOverlayScrollbar() && relevancy == IgnoreOverlayScrollbarSize)) 2010 return 0; 2011 return m_hBar->height(); 2012 } 2013 2014 IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& absolutePoint) const 2015 { 2016 // Currently the resize corner is always the bottom right corner 2017 IntPoint bottomRight(width(), height()); 2018 IntPoint localPoint = absoluteToContents(absolutePoint); 2019 return localPoint - bottomRight; 2020 } 2021 2022 bool RenderLayer::hasOverflowControls() const 2023 { 2024 return m_hBar || m_vBar || m_scrollCorner || renderer()->style()->resize() != RESIZE_NONE; 2025 } 2026 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 2027 bool RenderLayer::hasOverflowParent() const 2028 { 2029 const RenderLayer* layer = this; 2030 while (layer && !layer->hasOverflowScroll()) 2031 layer = layer->parent(); 2032 return layer; 2033 } 2034 #endif 2035 2036 void RenderLayer::positionOverflowControls(int tx, int ty) 2037 { 2038 if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE)) 2039 return; 2040 2041 RenderBox* box = renderBox(); 2042 if (!box) 2043 return; 2044 2045 const IntRect& borderBox = box->borderBoxRect(); 2046 const IntRect& scrollCorner = scrollCornerRect(); 2047 IntRect absBounds(borderBox.x() + tx, borderBox.y() + ty, borderBox.width(), borderBox.height()); 2048 if (m_vBar) 2049 m_vBar->setFrameRect(IntRect(absBounds.maxX() - box->borderRight() - m_vBar->width(), 2050 absBounds.y() + box->borderTop(), 2051 m_vBar->width(), 2052 absBounds.height() - (box->borderTop() + box->borderBottom()) - scrollCorner.height())); 2053 2054 if (m_hBar) 2055 m_hBar->setFrameRect(IntRect(absBounds.x() + box->borderLeft(), 2056 absBounds.maxY() - box->borderBottom() - m_hBar->height(), 2057 absBounds.width() - (box->borderLeft() + box->borderRight()) - scrollCorner.width(), 2058 m_hBar->height())); 2059 2060 #if USE(ACCELERATED_COMPOSITING) 2061 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) { 2062 if (m_hBar) { 2063 layer->setPosition(IntPoint(m_hBar->frameRect().x() - tx, m_hBar->frameRect().y() - ty)); 2064 layer->setSize(m_hBar->frameRect().size()); 2065 } 2066 layer->setDrawsContent(m_hBar); 2067 } 2068 if (GraphicsLayer* layer = layerForVerticalScrollbar()) { 2069 if (m_vBar) { 2070 layer->setPosition(IntPoint(m_vBar->frameRect().x() - tx, m_vBar->frameRect().y() - ty)); 2071 layer->setSize(m_vBar->frameRect().size()); 2072 } 2073 layer->setDrawsContent(m_vBar); 2074 } 2075 2076 if (GraphicsLayer* layer = layerForScrollCorner()) { 2077 const IntRect& scrollCornerAndResizer = scrollCornerAndResizerRect(); 2078 layer->setPosition(scrollCornerAndResizer.location()); 2079 layer->setSize(scrollCornerAndResizer.size()); 2080 layer->setDrawsContent(!scrollCornerAndResizer.isEmpty()); 2081 } 2082 #endif 2083 2084 if (m_scrollCorner) 2085 m_scrollCorner->setFrameRect(scrollCorner); 2086 if (m_resizer) 2087 m_resizer->setFrameRect(resizerCornerRect(this, borderBox)); 2088 } 2089 2090 #if PLATFORM(ANDROID) 2091 // When width/height change, the scrollWidth/scrollHeight should be dirty. 2092 // And this should be upstreamed to webkit. 2093 void RenderLayer::setWidth(int w) 2094 { 2095 if (m_width != w) { 2096 m_scrollDimensionsDirty = true; 2097 m_width = w; 2098 } 2099 } 2100 2101 void RenderLayer::setHeight(int h) 2102 { 2103 if (m_height != h) { 2104 m_scrollDimensionsDirty = true; 2105 m_height = h; 2106 } 2107 } 2108 #endif 2109 2110 int RenderLayer::scrollWidth() 2111 { 2112 if (m_scrollDimensionsDirty) 2113 computeScrollDimensions(); 2114 return m_scrollWidth; 2115 } 2116 2117 int RenderLayer::scrollHeight() 2118 { 2119 if (m_scrollDimensionsDirty) 2120 computeScrollDimensions(); 2121 return m_scrollHeight; 2122 } 2123 2124 int RenderLayer::overflowTop() const 2125 { 2126 RenderBox* box = renderBox(); 2127 IntRect overflowRect(box->layoutOverflowRect()); 2128 box->flipForWritingMode(overflowRect); 2129 return overflowRect.y(); 2130 } 2131 2132 int RenderLayer::overflowBottom() const 2133 { 2134 RenderBox* box = renderBox(); 2135 IntRect overflowRect(box->layoutOverflowRect()); 2136 box->flipForWritingMode(overflowRect); 2137 return overflowRect.maxY(); 2138 } 2139 2140 int RenderLayer::overflowLeft() const 2141 { 2142 RenderBox* box = renderBox(); 2143 IntRect overflowRect(box->layoutOverflowRect()); 2144 box->flipForWritingMode(overflowRect); 2145 return overflowRect.x(); 2146 } 2147 2148 int RenderLayer::overflowRight() const 2149 { 2150 RenderBox* box = renderBox(); 2151 IntRect overflowRect(box->layoutOverflowRect()); 2152 box->flipForWritingMode(overflowRect); 2153 return overflowRect.maxX(); 2154 } 2155 2156 void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar) 2157 { 2158 RenderBox* box = renderBox(); 2159 ASSERT(box); 2160 2161 m_scrollDimensionsDirty = false; 2162 2163 m_scrollLeftOverflow = overflowLeft() - box->borderLeft(); 2164 m_scrollTopOverflow = overflowTop() - box->borderTop(); 2165 2166 m_scrollWidth = overflowRight() - overflowLeft(); 2167 m_scrollHeight = overflowBottom() - overflowTop(); 2168 2169 m_scrollOrigin = IntPoint(-m_scrollLeftOverflow, -m_scrollTopOverflow); 2170 2171 if (needHBar) 2172 *needHBar = m_scrollWidth > box->clientWidth(); 2173 if (needVBar) 2174 *needVBar = m_scrollHeight > box->clientHeight(); 2175 } 2176 2177 void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow) 2178 { 2179 if (m_overflowStatusDirty) { 2180 m_horizontalOverflow = horizontalOverflow; 2181 m_verticalOverflow = verticalOverflow; 2182 m_overflowStatusDirty = false; 2183 return; 2184 } 2185 2186 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow); 2187 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow); 2188 2189 if (horizontalOverflowChanged || verticalOverflowChanged) { 2190 m_horizontalOverflow = horizontalOverflow; 2191 m_verticalOverflow = verticalOverflow; 2192 2193 if (FrameView* frameView = renderer()->document()->view()) { 2194 frameView->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow), 2195 renderer()->node()); 2196 } 2197 } 2198 } 2199 2200 void RenderLayer::updateScrollInfoAfterLayout() 2201 { 2202 RenderBox* box = renderBox(); 2203 if (!box) 2204 return; 2205 2206 m_scrollDimensionsDirty = true; 2207 2208 bool horizontalOverflow, verticalOverflow; 2209 computeScrollDimensions(&horizontalOverflow, &verticalOverflow); 2210 2211 if (box->style()->overflowX() != OMARQUEE) { 2212 // Layout may cause us to be in an invalid scroll position. In this case we need 2213 // to pull our scroll offsets back to the max (or push them up to the min). 2214 int newX = max(0, min(scrollXOffset(), scrollWidth() - box->clientWidth())); 2215 int newY = max(0, min(scrollYOffset(), scrollHeight() - box->clientHeight())); 2216 if (newX != scrollXOffset() || newY != scrollYOffset()) { 2217 RenderView* view = renderer()->view(); 2218 ASSERT(view); 2219 // scrollToOffset() may call updateLayerPositions(), which doesn't work 2220 // with LayoutState. 2221 // FIXME: Remove the disableLayoutState/enableLayoutState if the above changes. 2222 if (view) 2223 view->disableLayoutState(); 2224 scrollToOffset(newX, newY); 2225 if (view) 2226 view->enableLayoutState(); 2227 } 2228 } 2229 2230 bool haveHorizontalBar = m_hBar; 2231 bool haveVerticalBar = m_vBar; 2232 2233 // overflow:scroll should just enable/disable. 2234 if (renderer()->style()->overflowX() == OSCROLL) 2235 m_hBar->setEnabled(horizontalOverflow); 2236 if (renderer()->style()->overflowY() == OSCROLL) 2237 m_vBar->setEnabled(verticalOverflow); 2238 2239 // A dynamic change from a scrolling overflow to overflow:hidden means we need to get rid of any 2240 // scrollbars that may be present. 2241 if (renderer()->style()->overflowX() == OHIDDEN && haveHorizontalBar) 2242 setHasHorizontalScrollbar(false); 2243 if (renderer()->style()->overflowY() == OHIDDEN && haveVerticalBar) 2244 setHasVerticalScrollbar(false); 2245 2246 // overflow:auto may need to lay out again if scrollbars got added/removed. 2247 bool scrollbarsChanged = (box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow) || 2248 (box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow); 2249 if (scrollbarsChanged) { 2250 if (box->hasAutoHorizontalScrollbar()) 2251 setHasHorizontalScrollbar(horizontalOverflow); 2252 if (box->hasAutoVerticalScrollbar()) 2253 setHasVerticalScrollbar(verticalOverflow); 2254 2255 #if ENABLE(DASHBOARD_SUPPORT) 2256 // Force an update since we know the scrollbars have changed things. 2257 if (renderer()->document()->hasDashboardRegions()) 2258 renderer()->document()->setDashboardRegionsDirty(true); 2259 #endif 2260 2261 renderer()->repaint(); 2262 2263 if (renderer()->style()->overflowX() == OAUTO || renderer()->style()->overflowY() == OAUTO) { 2264 if (!m_inOverflowRelayout) { 2265 // Our proprietary overflow: overlay value doesn't trigger a layout. 2266 m_inOverflowRelayout = true; 2267 renderer()->setNeedsLayout(true, false); 2268 if (renderer()->isRenderBlock()) { 2269 RenderBlock* block = toRenderBlock(renderer()); 2270 block->scrollbarsChanged(box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow, 2271 box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow); 2272 block->layoutBlock(true); 2273 } else 2274 renderer()->layout(); 2275 m_inOverflowRelayout = false; 2276 } 2277 } 2278 } 2279 2280 // If overflow:scroll is turned into overflow:auto a bar might still be disabled (Bug 11985). 2281 if (m_hBar && box->hasAutoHorizontalScrollbar()) 2282 m_hBar->setEnabled(true); 2283 if (m_vBar && box->hasAutoVerticalScrollbar()) 2284 m_vBar->setEnabled(true); 2285 2286 // Set up the range (and page step/line step). 2287 if (m_hBar) { 2288 int clientWidth = box->clientWidth(); 2289 int pageStep = max(max<int>(clientWidth * Scrollbar::minFractionToStepWhenPaging(), clientWidth - Scrollbar::maxOverlapBetweenPages()), 1); 2290 m_hBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep); 2291 m_hBar->setProportion(clientWidth, m_scrollWidth); 2292 } 2293 if (m_vBar) { 2294 int clientHeight = box->clientHeight(); 2295 int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1); 2296 m_vBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep); 2297 m_vBar->setProportion(clientHeight, m_scrollHeight); 2298 } 2299 2300 RenderView* view = renderer()->view(); 2301 view->disableLayoutState(); 2302 scrollToOffset(scrollXOffset(), scrollYOffset()); 2303 view->enableLayoutState(); 2304 2305 if (renderer()->node() && renderer()->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER)) 2306 updateOverflowStatus(horizontalOverflow, verticalOverflow); 2307 2308 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 2309 bool hasOverflowScroll = ((horizontalOverflow && m_hBar) || (verticalOverflow && m_vBar)); 2310 if (hasOverflowScroll) { 2311 // Disable UI side scrolling for non-readonly textareas. 2312 if (renderer()->isTextArea() && (!renderer()->node() 2313 || !static_cast<HTMLTextAreaElement*>(renderer()->node())->readOnly())) 2314 hasOverflowScroll = false; 2315 } 2316 if (hasOverflowScroll != m_hasOverflowScroll) { 2317 m_hasOverflowScroll = hasOverflowScroll; 2318 dirtyZOrderLists(); 2319 dirtyStackingContextZOrderLists(); 2320 if (renderer()->node()) 2321 renderer()->node()->setNeedsStyleRecalc(SyntheticStyleChange); 2322 } 2323 #endif 2324 } 2325 2326 void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty, const IntRect& damageRect, bool paintingOverlayControls) 2327 { 2328 // Don't do anything if we have no overflow. 2329 if (!renderer()->hasOverflowClip()) 2330 return; 2331 2332 // Overlay scrollbars paint in a second pass through the layer tree so that they will paint 2333 // on top of everything else. If this is the normal painting pass, paintingOverlayControls 2334 // will be false, and we should just tell the root layer that there are overlay scrollbars 2335 // that need to be painted. That will cause the second pass through the layer tree to run, 2336 // and we'll paint the scrollbars then. In the meantime, cache tx and ty so that the 2337 // second pass doesn't need to re-enter the RenderTree to get it right. 2338 if (hasOverlayScrollbars() && !paintingOverlayControls) { 2339 RenderView* renderView = renderer()->view(); 2340 renderView->layer()->setContainsDirtyOverlayScrollbars(true); 2341 m_cachedOverlayScrollbarOffset = IntPoint(tx, ty); 2342 renderView->frameView()->setContainsScrollableAreaWithOverlayScrollbars(true); 2343 return; 2344 } 2345 2346 int offsetX = tx; 2347 int offsetY = ty; 2348 if (paintingOverlayControls) { 2349 offsetX = m_cachedOverlayScrollbarOffset.x(); 2350 offsetY = m_cachedOverlayScrollbarOffset.y(); 2351 } 2352 2353 // Move the scrollbar widgets if necessary. We normally move and resize widgets during layout, but sometimes 2354 // widgets can move without layout occurring (most notably when you scroll a document that 2355 // contains fixed positioned elements). 2356 positionOverflowControls(offsetX, offsetY); 2357 2358 // Now that we're sure the scrollbars are in the right place, paint them. 2359 if (m_hBar 2360 #if USE(ACCELERATED_COMPOSITING) 2361 && !layerForHorizontalScrollbar() 2362 #endif 2363 ) 2364 m_hBar->paint(context, damageRect); 2365 if (m_vBar 2366 #if USE(ACCELERATED_COMPOSITING) 2367 && !layerForVerticalScrollbar() 2368 #endif 2369 ) 2370 m_vBar->paint(context, damageRect); 2371 2372 #if USE(ACCELERATED_COMPOSITING) 2373 if (layerForScrollCorner()) 2374 return; 2375 #endif 2376 2377 // We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the 2378 // edge of the box. 2379 paintScrollCorner(context, offsetX, offsetY, damageRect); 2380 2381 // Paint our resizer last, since it sits on top of the scroll corner. 2382 paintResizer(context, offsetX, offsetY, damageRect); 2383 } 2384 2385 void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, const IntRect& damageRect) 2386 { 2387 RenderBox* box = renderBox(); 2388 ASSERT(box); 2389 2390 IntRect cornerRect = scrollCornerRect(); 2391 IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height()); 2392 if (!absRect.intersects(damageRect)) 2393 return; 2394 2395 if (context->updatingControlTints()) { 2396 updateScrollCornerStyle(); 2397 return; 2398 } 2399 2400 if (m_scrollCorner) { 2401 m_scrollCorner->paintIntoRect(context, tx, ty, absRect); 2402 return; 2403 } 2404 2405 // We don't want to paint white if we have overlay scrollbars, since we need 2406 // to see what is behind it. 2407 if (!hasOverlayScrollbars()) 2408 context->fillRect(absRect, Color::white, box->style()->colorSpace()); 2409 } 2410 2411 void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const IntRect& damageRect) 2412 { 2413 if (renderer()->style()->resize() == RESIZE_NONE) 2414 return; 2415 2416 RenderBox* box = renderBox(); 2417 ASSERT(box); 2418 2419 IntRect cornerRect = resizerCornerRect(this, box->borderBoxRect()); 2420 IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height()); 2421 if (!absRect.intersects(damageRect)) 2422 return; 2423 2424 if (context->updatingControlTints()) { 2425 updateResizerStyle(); 2426 return; 2427 } 2428 2429 if (m_resizer) { 2430 m_resizer->paintIntoRect(context, tx, ty, absRect); 2431 return; 2432 } 2433 2434 // Paint the resizer control. 2435 DEFINE_STATIC_LOCAL(RefPtr<Image>, resizeCornerImage, (Image::loadPlatformResource("textAreaResizeCorner"))); 2436 IntPoint imagePoint(absRect.maxX() - resizeCornerImage->width(), absRect.maxY() - resizeCornerImage->height()); 2437 context->drawImage(resizeCornerImage.get(), box->style()->colorSpace(), imagePoint); 2438 2439 // Draw a frame around the resizer (1px grey line) if there are any scrollbars present. 2440 // Clipping will exclude the right and bottom edges of this frame. 2441 if (!hasOverlayScrollbars() && (m_vBar || m_hBar)) { 2442 context->save(); 2443 context->clip(absRect); 2444 IntRect largerCorner = absRect; 2445 largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.height() + 1)); 2446 context->setStrokeColor(Color(makeRGB(217, 217, 217)), ColorSpaceDeviceRGB); 2447 context->setStrokeThickness(1.0f); 2448 context->setFillColor(Color::transparent, ColorSpaceDeviceRGB); 2449 context->drawRect(largerCorner); 2450 context->restore(); 2451 } 2452 } 2453 2454 bool RenderLayer::isPointInResizeControl(const IntPoint& absolutePoint) const 2455 { 2456 if (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE) 2457 return false; 2458 2459 RenderBox* box = renderBox(); 2460 ASSERT(box); 2461 2462 IntPoint localPoint = absoluteToContents(absolutePoint); 2463 2464 IntRect localBounds(0, 0, box->width(), box->height()); 2465 return resizerCornerRect(this, localBounds).contains(localPoint); 2466 } 2467 2468 bool RenderLayer::hitTestOverflowControls(HitTestResult& result, const IntPoint& localPoint) 2469 { 2470 if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE)) 2471 return false; 2472 2473 RenderBox* box = renderBox(); 2474 ASSERT(box); 2475 2476 IntRect resizeControlRect; 2477 if (renderer()->style()->resize() != RESIZE_NONE) { 2478 resizeControlRect = resizerCornerRect(this, box->borderBoxRect()); 2479 if (resizeControlRect.contains(localPoint)) 2480 return true; 2481 } 2482 2483 int resizeControlSize = max(resizeControlRect.height(), 0); 2484 2485 if (m_vBar) { 2486 IntRect vBarRect(box->width() - box->borderRight() - m_vBar->width(), 2487 box->borderTop(), 2488 m_vBar->width(), 2489 box->height() - (box->borderTop() + box->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize)); 2490 if (vBarRect.contains(localPoint)) { 2491 result.setScrollbar(m_vBar.get()); 2492 return true; 2493 } 2494 } 2495 2496 resizeControlSize = max(resizeControlRect.width(), 0); 2497 if (m_hBar) { 2498 IntRect hBarRect(box->borderLeft(), 2499 box->height() - box->borderBottom() - m_hBar->height(), 2500 box->width() - (box->borderLeft() + box->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize), 2501 m_hBar->height()); 2502 if (hBarRect.contains(localPoint)) { 2503 result.setScrollbar(m_hBar.get()); 2504 return true; 2505 } 2506 } 2507 2508 return false; 2509 } 2510 2511 bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier) 2512 { 2513 return ScrollableArea::scroll(direction, granularity, multiplier); 2514 } 2515 2516 void RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintBehavior paintBehavior, RenderObject *paintingRoot) 2517 { 2518 OverlapTestRequestMap overlapTestRequests; 2519 paintLayer(this, p, damageRect, paintBehavior, paintingRoot, &overlapTestRequests); 2520 OverlapTestRequestMap::iterator end = overlapTestRequests.end(); 2521 for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) 2522 it->first->setOverlapTestResult(false); 2523 } 2524 2525 void RenderLayer::paintOverlayScrollbars(GraphicsContext* p, const IntRect& damageRect, PaintBehavior paintBehavior, RenderObject *paintingRoot) 2526 { 2527 if (!m_containsDirtyOverlayScrollbars) 2528 return; 2529 paintLayer(this, p, damageRect, paintBehavior, paintingRoot, 0, PaintLayerHaveTransparency | PaintLayerTemporaryClipRects 2530 | PaintLayerPaintingOverlayScrollbars); 2531 m_containsDirtyOverlayScrollbars = false; 2532 } 2533 2534 static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect) 2535 { 2536 if (paintDirtyRect == clipRect) 2537 return; 2538 p->save(); 2539 p->clip(clipRect); 2540 } 2541 2542 static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect) 2543 { 2544 if (paintDirtyRect == clipRect) 2545 return; 2546 p->restore(); 2547 } 2548 2549 static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer) 2550 { 2551 Vector<OverlapTestRequestClient*> overlappedRequestClients; 2552 OverlapTestRequestMap::iterator end = overlapTestRequests.end(); 2553 IntRect boundingBox = layer->boundingBox(rootLayer); 2554 for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) { 2555 if (!boundingBox.intersects(it->second)) 2556 continue; 2557 2558 it->first->setOverlapTestResult(true); 2559 overlappedRequestClients.append(it->first); 2560 } 2561 for (size_t i = 0; i < overlappedRequestClients.size(); ++i) 2562 overlapTestRequests.remove(overlappedRequestClients[i]); 2563 } 2564 2565 #if USE(ACCELERATED_COMPOSITING) 2566 static bool shouldDoSoftwarePaint(const RenderLayer* layer, bool paintingReflection) 2567 { 2568 return paintingReflection && !layer->has3DTransform(); 2569 } 2570 #endif 2571 2572 void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, 2573 const IntRect& paintDirtyRect, PaintBehavior paintBehavior, 2574 RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests, 2575 PaintLayerFlags paintFlags) 2576 { 2577 #if USE(ACCELERATED_COMPOSITING) 2578 if (isComposited()) { 2579 // The updatingControlTints() painting pass goes through compositing layers, 2580 // but we need to ensure that we don't cache clip rects computed with the wrong root in this case. 2581 if (p->updatingControlTints() || (paintBehavior & PaintBehaviorFlattenCompositingLayers)) 2582 paintFlags |= PaintLayerTemporaryClipRects; 2583 else if (!backing()->paintingGoesToWindow() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) { 2584 // If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer(). 2585 return; 2586 } 2587 } 2588 #endif 2589 2590 // Avoid painting layers when stylesheets haven't loaded. This eliminates FOUC. 2591 // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document 2592 // will do a full repaint(). 2593 if (renderer()->document()->didLayoutWithPendingStylesheets() && !renderer()->isRenderView() && !renderer()->isRoot()) 2594 return; 2595 2596 // If this layer is totally invisible then there is nothing to paint. 2597 if (!renderer()->opacity()) 2598 return; 2599 2600 if (paintsWithTransparency(paintBehavior)) 2601 paintFlags |= PaintLayerHaveTransparency; 2602 2603 // Apply a transform if we have one. A reflection is considered to be a transform, since it is a flip and a translate. 2604 if (paintsWithTransform(paintBehavior) && !(paintFlags & PaintLayerAppliedTransform)) { 2605 TransformationMatrix layerTransform = renderableTransform(paintBehavior); 2606 // If the transform can't be inverted, then don't paint anything. 2607 if (!layerTransform.isInvertible()) 2608 return; 2609 2610 // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency 2611 // layer from the parent now. 2612 if (paintFlags & PaintLayerHaveTransparency) 2613 parent()->beginTransparencyLayers(p, rootLayer, paintBehavior); 2614 2615 // Make sure the parent's clip rects have been calculated. 2616 IntRect clipRect = paintDirtyRect; 2617 if (parent()) { 2618 clipRect = backgroundClipRect(rootLayer, paintFlags & PaintLayerTemporaryClipRects); 2619 clipRect.intersect(paintDirtyRect); 2620 } 2621 2622 // Push the parent coordinate space's clip. 2623 setClip(p, paintDirtyRect, clipRect); 2624 2625 // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space. 2626 // This involves subtracting out the position of the layer in our current coordinate space. 2627 int x = 0; 2628 int y = 0; 2629 convertToLayerCoords(rootLayer, x, y); 2630 TransformationMatrix transform(layerTransform); 2631 transform.translateRight(x, y); 2632 2633 // Apply the transform. 2634 p->save(); 2635 p->concatCTM(transform.toAffineTransform()); 2636 2637 // Now do a paint with the root layer shifted to be us. 2638 paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), paintBehavior, paintingRoot, overlapTestRequests, paintFlags | PaintLayerAppliedTransform); 2639 2640 p->restore(); 2641 2642 // Restore the clip. 2643 restoreClip(p, paintDirtyRect, clipRect); 2644 2645 return; 2646 } 2647 2648 PaintLayerFlags localPaintFlags = paintFlags & ~PaintLayerAppliedTransform; 2649 bool haveTransparency = localPaintFlags & PaintLayerHaveTransparency; 2650 2651 // Paint the reflection first if we have one. 2652 if (m_reflection && !m_paintingInsideReflection) { 2653 // Mark that we are now inside replica painting. 2654 m_paintingInsideReflection = true; 2655 reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags | PaintLayerPaintingReflection); 2656 m_paintingInsideReflection = false; 2657 } 2658 2659 // Calculate the clip rects we should use. 2660 IntRect layerBounds, damageRect, clipRectToApply, outlineRect; 2661 calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, localPaintFlags & PaintLayerTemporaryClipRects); 2662 int x = layerBounds.x(); 2663 int y = layerBounds.y(); 2664 int tx = x - renderBoxX(); 2665 int ty = y - renderBoxY(); 2666 2667 // Ensure our lists are up-to-date. 2668 updateCompositingAndLayerListsIfNeeded(); 2669 2670 bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText; 2671 bool selectionOnly = paintBehavior & PaintBehaviorSelectionOnly; 2672 2673 // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which 2674 // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set). 2675 // Else, our renderer tree may or may not contain the painting root, so we pass that root along 2676 // so it will be tested against as we descend through the renderers. 2677 RenderObject* paintingRootForRenderer = 0; 2678 if (paintingRoot && !renderer()->isDescendantOf(paintingRoot)) 2679 paintingRootForRenderer = paintingRoot; 2680 2681 if (overlapTestRequests && isSelfPaintingLayer()) 2682 performOverlapTests(*overlapTestRequests, rootLayer, this); 2683 2684 bool paintingOverlayScrollbars = paintFlags & PaintLayerPaintingOverlayScrollbars; 2685 2686 // We want to paint our layer, but only if we intersect the damage rect. 2687 bool shouldPaint = intersectsDamageRect(layerBounds, damageRect, rootLayer) && m_hasVisibleContent && isSelfPaintingLayer(); 2688 if (shouldPaint && !selectionOnly && !damageRect.isEmpty() && !paintingOverlayScrollbars) { 2689 // Begin transparency layers lazily now that we know we have to paint something. 2690 if (haveTransparency) 2691 beginTransparencyLayers(p, rootLayer, paintBehavior); 2692 2693 // Paint our background first, before painting any child layers. 2694 // Establish the clip used to paint our background. 2695 setClip(p, paintDirtyRect, damageRect); 2696 2697 // Paint the background. 2698 PaintInfo paintInfo(p, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0); 2699 renderer()->paint(paintInfo, tx, ty); 2700 2701 // Restore the clip. 2702 restoreClip(p, paintDirtyRect, damageRect); 2703 } 2704 2705 // Now walk the sorted list of children with negative z-indices. 2706 paintList(m_negZOrderList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); 2707 2708 // Now establish the appropriate clip and paint our child RenderObjects. 2709 if (shouldPaint && !clipRectToApply.isEmpty() && !paintingOverlayScrollbars) { 2710 // Begin transparency layers lazily now that we know we have to paint something. 2711 if (haveTransparency) 2712 beginTransparencyLayers(p, rootLayer, paintBehavior); 2713 2714 // Set up the clip used when painting our children. 2715 setClip(p, paintDirtyRect, clipRectToApply); 2716 PaintInfo paintInfo(p, clipRectToApply, 2717 selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds, 2718 forceBlackText, paintingRootForRenderer, 0); 2719 renderer()->paint(paintInfo, tx, ty); 2720 if (!selectionOnly) { 2721 paintInfo.phase = PaintPhaseFloat; 2722 renderer()->paint(paintInfo, tx, ty); 2723 paintInfo.phase = PaintPhaseForeground; 2724 paintInfo.overlapTestRequests = overlapTestRequests; 2725 renderer()->paint(paintInfo, tx, ty); 2726 paintInfo.phase = PaintPhaseChildOutlines; 2727 renderer()->paint(paintInfo, tx, ty); 2728 } 2729 2730 // Now restore our clip. 2731 restoreClip(p, paintDirtyRect, clipRectToApply); 2732 } 2733 2734 if (!outlineRect.isEmpty() && isSelfPaintingLayer() && !paintingOverlayScrollbars) { 2735 // Paint our own outline 2736 PaintInfo paintInfo(p, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0); 2737 setClip(p, paintDirtyRect, outlineRect); 2738 renderer()->paint(paintInfo, tx, ty); 2739 restoreClip(p, paintDirtyRect, outlineRect); 2740 } 2741 2742 // Paint any child layers that have overflow. 2743 paintList(m_normalFlowList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); 2744 2745 // Now walk the sorted list of children with positive z-indices. 2746 paintList(m_posZOrderList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); 2747 2748 if (renderer()->hasMask() && shouldPaint && !selectionOnly && !damageRect.isEmpty() && !paintingOverlayScrollbars) { 2749 setClip(p, paintDirtyRect, damageRect); 2750 2751 // Paint the mask. 2752 PaintInfo paintInfo(p, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0); 2753 renderer()->paint(paintInfo, tx, ty); 2754 2755 // Restore the clip. 2756 restoreClip(p, paintDirtyRect, damageRect); 2757 } 2758 2759 if (paintingOverlayScrollbars) { 2760 setClip(p, paintDirtyRect, damageRect); 2761 paintOverflowControls(p, tx, ty, damageRect, true); 2762 restoreClip(p, paintDirtyRect, damageRect); 2763 } 2764 2765 // End our transparency layer 2766 if (haveTransparency && m_usedTransparency && !m_paintingInsideReflection) { 2767 p->endTransparencyLayer(); 2768 p->restore(); 2769 m_usedTransparency = false; 2770 } 2771 } 2772 2773 void RenderLayer::paintList(Vector<RenderLayer*>* list, RenderLayer* rootLayer, GraphicsContext* p, 2774 const IntRect& paintDirtyRect, PaintBehavior paintBehavior, 2775 RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests, 2776 PaintLayerFlags paintFlags) 2777 { 2778 if (!list) 2779 return; 2780 2781 for (size_t i = 0; i < list->size(); ++i) { 2782 RenderLayer* childLayer = list->at(i); 2783 if (!childLayer->isPaginated()) 2784 childLayer->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags); 2785 else 2786 paintPaginatedChildLayer(childLayer, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags); 2787 } 2788 } 2789 2790 void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context, 2791 const IntRect& paintDirtyRect, PaintBehavior paintBehavior, 2792 RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests, 2793 PaintLayerFlags paintFlags) 2794 { 2795 // We need to do multiple passes, breaking up our child layer into strips. 2796 Vector<RenderLayer*> columnLayers; 2797 RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext(); 2798 for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) { 2799 if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox())) 2800 columnLayers.append(curr); 2801 if (curr == ancestorLayer) 2802 break; 2803 } 2804 2805 ASSERT(columnLayers.size()); 2806 2807 paintChildLayerIntoColumns(childLayer, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags, columnLayers, columnLayers.size() - 1); 2808 } 2809 2810 void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context, 2811 const IntRect& paintDirtyRect, PaintBehavior paintBehavior, 2812 RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests, 2813 PaintLayerFlags paintFlags, const Vector<RenderLayer*>& columnLayers, size_t colIndex) 2814 { 2815 RenderBlock* columnBlock = toRenderBlock(columnLayers[colIndex]->renderer()); 2816 2817 ASSERT(columnBlock && columnBlock->hasColumns()); 2818 if (!columnBlock || !columnBlock->hasColumns()) 2819 return; 2820 2821 int layerX = 0; 2822 int layerY = 0; 2823 columnBlock->layer()->convertToLayerCoords(rootLayer, layerX, layerY); 2824 2825 bool isHorizontal = columnBlock->style()->isHorizontalWritingMode(); 2826 2827 ColumnInfo* colInfo = columnBlock->columnInfo(); 2828 unsigned colCount = columnBlock->columnCount(colInfo); 2829 int currLogicalTopOffset = 0; 2830 for (unsigned i = 0; i < colCount; i++) { 2831 // For each rect, we clip to the rect, and then we adjust our coords. 2832 IntRect colRect = columnBlock->columnRectAt(colInfo, i); 2833 columnBlock->flipForWritingMode(colRect); 2834 int logicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - columnBlock->logicalLeftOffsetForContent(); 2835 IntSize offset = isHorizontal ? IntSize(logicalLeftOffset, currLogicalTopOffset) : IntSize(currLogicalTopOffset, logicalLeftOffset); 2836 2837 colRect.move(layerX, layerY); 2838 2839 IntRect localDirtyRect(paintDirtyRect); 2840 localDirtyRect.intersect(colRect); 2841 2842 if (!localDirtyRect.isEmpty()) { 2843 context->save(); 2844 2845 // Each strip pushes a clip, since column boxes are specified as being 2846 // like overflow:hidden. 2847 context->clip(colRect); 2848 2849 if (!colIndex) { 2850 // Apply a translation transform to change where the layer paints. 2851 TransformationMatrix oldTransform; 2852 bool oldHasTransform = childLayer->transform(); 2853 if (oldHasTransform) 2854 oldTransform = *childLayer->transform(); 2855 TransformationMatrix newTransform(oldTransform); 2856 newTransform.translateRight(offset.width(), offset.height()); 2857 2858 childLayer->m_transform.set(new TransformationMatrix(newTransform)); 2859 childLayer->paintLayer(rootLayer, context, localDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags); 2860 if (oldHasTransform) 2861 childLayer->m_transform.set(new TransformationMatrix(oldTransform)); 2862 else 2863 childLayer->m_transform.clear(); 2864 } else { 2865 // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space. 2866 // This involves subtracting out the position of the layer in our current coordinate space. 2867 int childX = 0; 2868 int childY = 0; 2869 columnLayers[colIndex - 1]->convertToLayerCoords(rootLayer, childX, childY); 2870 TransformationMatrix transform; 2871 transform.translateRight(childX + offset.width(), childY + offset.height()); 2872 2873 // Apply the transform. 2874 context->concatCTM(transform.toAffineTransform()); 2875 2876 // Now do a paint with the root layer shifted to be the next multicol block. 2877 paintChildLayerIntoColumns(childLayer, columnLayers[colIndex - 1], context, transform.inverse().mapRect(localDirtyRect), paintBehavior, 2878 paintingRoot, overlapTestRequests, paintFlags, 2879 columnLayers, colIndex - 1); 2880 } 2881 2882 context->restore(); 2883 } 2884 2885 // Move to the next position. 2886 int blockDelta = isHorizontal ? colRect.height() : colRect.width(); 2887 if (columnBlock->style()->isFlippedBlocksWritingMode()) 2888 currLogicalTopOffset += blockDelta; 2889 else 2890 currLogicalTopOffset -= blockDelta; 2891 } 2892 } 2893 2894 static inline IntRect frameVisibleRect(RenderObject* renderer) 2895 { 2896 FrameView* frameView = renderer->document()->view(); 2897 if (!frameView) 2898 return IntRect(); 2899 2900 return frameView->visibleContentRect(); 2901 } 2902 2903 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result) 2904 { 2905 renderer()->document()->updateLayout(); 2906 2907 IntRect hitTestArea = renderer()->view()->documentRect(); 2908 if (!request.ignoreClipping()) 2909 hitTestArea.intersect(frameVisibleRect(renderer())); 2910 2911 RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, result.point(), false); 2912 if (!insideLayer) { 2913 // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down, 2914 // return ourselves. We do this so mouse events continue getting delivered after a drag has 2915 // exited the WebView, and so hit testing over a scrollbar hits the content document. 2916 if ((request.active() || request.mouseUp()) && renderer()->isRenderView()) { 2917 renderer()->updateHitTestResult(result, result.point()); 2918 insideLayer = this; 2919 } 2920 } 2921 2922 // Now determine if the result is inside an anchor - if the urlElement isn't already set. 2923 Node* node = result.innerNode(); 2924 if (node && !result.URLElement()) 2925 result.setURLElement(static_cast<Element*>(node->enclosingLinkEventParentOrSelf())); 2926 2927 // Next set up the correct :hover/:active state along the new chain. 2928 updateHoverActiveState(request, result); 2929 2930 // Now return whether we were inside this layer (this will always be true for the root 2931 // layer). 2932 return insideLayer; 2933 } 2934 2935 Node* RenderLayer::enclosingElement() const 2936 { 2937 for (RenderObject* r = renderer(); r; r = r->parent()) { 2938 if (Node* e = r->node()) 2939 return e; 2940 } 2941 ASSERT_NOT_REACHED(); 2942 return 0; 2943 } 2944 2945 // Compute the z-offset of the point in the transformState. 2946 // This is effectively projecting a ray normal to the plane of ancestor, finding where that 2947 // ray intersects target, and computing the z delta between those two points. 2948 static double computeZOffset(const HitTestingTransformState& transformState) 2949 { 2950 // We got an affine transform, so no z-offset 2951 if (transformState.m_accumulatedTransform.isAffine()) 2952 return 0; 2953 2954 // Flatten the point into the target plane 2955 FloatPoint targetPoint = transformState.mappedPoint(); 2956 2957 // Now map the point back through the transform, which computes Z. 2958 FloatPoint3D backmappedPoint = transformState.m_accumulatedTransform.mapPoint(FloatPoint3D(targetPoint)); 2959 return backmappedPoint.z(); 2960 } 2961 2962 PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer, 2963 const IntRect& hitTestRect, const IntPoint& hitTestPoint, 2964 const HitTestingTransformState* containerTransformState) const 2965 { 2966 RefPtr<HitTestingTransformState> transformState; 2967 int offsetX = 0; 2968 int offsetY = 0; 2969 if (containerTransformState) { 2970 // If we're already computing transform state, then it's relative to the container (which we know is non-null). 2971 transformState = HitTestingTransformState::create(*containerTransformState); 2972 convertToLayerCoords(containerLayer, offsetX, offsetY); 2973 } else { 2974 // If this is the first time we need to make transform state, then base it off of hitTestPoint, 2975 // which is relative to rootLayer. 2976 transformState = HitTestingTransformState::create(hitTestPoint, FloatQuad(hitTestRect)); 2977 convertToLayerCoords(rootLayer, offsetX, offsetY); 2978 } 2979 2980 RenderObject* containerRenderer = containerLayer ? containerLayer->renderer() : 0; 2981 if (renderer()->shouldUseTransformFromContainer(containerRenderer)) { 2982 TransformationMatrix containerTransform; 2983 renderer()->getTransformFromContainer(containerRenderer, IntSize(offsetX, offsetY), containerTransform); 2984 transformState->applyTransform(containerTransform, HitTestingTransformState::AccumulateTransform); 2985 } else { 2986 transformState->translate(offsetX, offsetY, HitTestingTransformState::AccumulateTransform); 2987 } 2988 2989 return transformState; 2990 } 2991 2992 2993 static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, double* zOffset, const HitTestingTransformState* transformState) 2994 { 2995 if (!hitLayer) 2996 return false; 2997 2998 // The hit layer is depth-sorting with other layers, so just say that it was hit. 2999 if (canDepthSort) 3000 return true; 3001 3002 // We need to look at z-depth to decide if this layer was hit. 3003 if (zOffset) { 3004 ASSERT(transformState); 3005 // This is actually computing our z, but that's OK because the hitLayer is coplanar with us. 3006 double childZOffset = computeZOffset(*transformState); 3007 if (childZOffset > *zOffset) { 3008 *zOffset = childZOffset; 3009 return true; 3010 } 3011 return false; 3012 } 3013 3014 return true; 3015 } 3016 3017 // hitTestPoint and hitTestRect are relative to rootLayer. 3018 // A 'flattening' layer is one preserves3D() == false. 3019 // transformState.m_accumulatedTransform holds the transform from the containing flattening layer. 3020 // transformState.m_lastPlanarPoint is the hitTestPoint in the plane of the containing flattening layer. 3021 // transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of the containing flattening layer. 3022 // 3023 // If zOffset is non-null (which indicates that the caller wants z offset information), 3024 // *zOffset on return is the z offset of the hit point relative to the containing flattening layer. 3025 RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result, 3026 const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform, 3027 const HitTestingTransformState* transformState, double* zOffset) 3028 { 3029 // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate. 3030 3031 bool useTemporaryClipRects = false; 3032 #if USE(ACCELERATED_COMPOSITING) 3033 useTemporaryClipRects = compositor()->inCompositingMode(); 3034 #endif 3035 useTemporaryClipRects |= renderer()->view()->frameView()->containsScrollableAreaWithOverlayScrollbars(); 3036 3037 IntRect hitTestArea = result.rectForPoint(hitTestPoint); 3038 3039 // Apply a transform if we have one. 3040 if (transform() && !appliedTransform) { 3041 // Make sure the parent's clip rects have been calculated. 3042 if (parent()) { 3043 IntRect clipRect = backgroundClipRect(rootLayer, useTemporaryClipRects, IncludeOverlayScrollbarSize); 3044 // Go ahead and test the enclosing clip now. 3045 if (!clipRect.intersects(hitTestArea)) 3046 return 0; 3047 } 3048 3049 // Create a transform state to accumulate this transform. 3050 RefPtr<HitTestingTransformState> newTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState); 3051 3052 // If the transform can't be inverted, then don't hit test this layer at all. 3053 if (!newTransformState->m_accumulatedTransform.isInvertible()) 3054 return 0; 3055 3056 // Compute the point and the hit test rect in the coords of this layer by using the values 3057 // from the transformState, which store the point and quad in the coords of the last flattened 3058 // layer, and the accumulated transform which lets up map through preserve-3d layers. 3059 // 3060 // We can't just map hitTestPoint and hitTestRect because they may have been flattened (losing z) 3061 // by our container. 3062 IntPoint localPoint = roundedIntPoint(newTransformState->mappedPoint()); 3063 IntRect localHitTestRect; 3064 #if USE(ACCELERATED_COMPOSITING) 3065 if (isComposited()) { 3066 // It doesn't make sense to project hitTestRect into the plane of this layer, so use the same bounds we use for painting. 3067 localHitTestRect = backing()->compositedBounds(); 3068 } else 3069 #endif 3070 localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox(); 3071 3072 // Now do a hit test with the root layer shifted to be us. 3073 return hitTestLayer(this, containerLayer, request, result, localHitTestRect, localPoint, true, newTransformState.get(), zOffset); 3074 } 3075 3076 // Ensure our lists and 3d status are up-to-date. 3077 updateCompositingAndLayerListsIfNeeded(); 3078 update3DTransformedDescendantStatus(); 3079 3080 RefPtr<HitTestingTransformState> localTransformState; 3081 if (appliedTransform) { 3082 // We computed the correct state in the caller (above code), so just reference it. 3083 ASSERT(transformState); 3084 localTransformState = const_cast<HitTestingTransformState*>(transformState); 3085 } else if (transformState || m_has3DTransformedDescendant || preserves3D()) { 3086 // We need transform state for the first time, or to offset the container state, so create it here. 3087 localTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState); 3088 } 3089 3090 // Check for hit test on backface if backface-visibility is 'hidden' 3091 if (localTransformState && renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden) { 3092 TransformationMatrix invertedMatrix = localTransformState->m_accumulatedTransform.inverse(); 3093 // If the z-vector of the matrix is negative, the back is facing towards the viewer. 3094 if (invertedMatrix.m33() < 0) 3095 return 0; 3096 } 3097 3098 RefPtr<HitTestingTransformState> unflattenedTransformState = localTransformState; 3099 if (localTransformState && !preserves3D()) { 3100 // Keep a copy of the pre-flattening state, for computing z-offsets for the container 3101 unflattenedTransformState = HitTestingTransformState::create(*localTransformState); 3102 // This layer is flattening, so flatten the state passed to descendants. 3103 localTransformState->flatten(); 3104 } 3105 3106 // Calculate the clip rects we should use. 3107 IntRect layerBounds; 3108 IntRect bgRect; 3109 IntRect fgRect; 3110 IntRect outlineRect; 3111 calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, useTemporaryClipRects, IncludeOverlayScrollbarSize); 3112 3113 // The following are used for keeping track of the z-depth of the hit point of 3d-transformed 3114 // descendants. 3115 double localZOffset = -numeric_limits<double>::infinity(); 3116 double* zOffsetForDescendantsPtr = 0; 3117 double* zOffsetForContentsPtr = 0; 3118 3119 bool depthSortDescendants = false; 3120 if (preserves3D()) { 3121 depthSortDescendants = true; 3122 // Our layers can depth-test with our container, so share the z depth pointer with the container, if it passed one down. 3123 zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset; 3124 zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset; 3125 } else if (m_has3DTransformedDescendant) { 3126 // Flattening layer with 3d children; use a local zOffset pointer to depth-test children and foreground. 3127 depthSortDescendants = true; 3128 zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset; 3129 zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset; 3130 } else if (zOffset) { 3131 zOffsetForDescendantsPtr = 0; 3132 // Container needs us to give back a z offset for the hit layer. 3133 zOffsetForContentsPtr = zOffset; 3134 } 3135 3136 // This variable tracks which layer the mouse ends up being inside. 3137 RenderLayer* candidateLayer = 0; 3138 3139 // Begin by walking our list of positive layers from highest z-index down to the lowest z-index. 3140 RenderLayer* hitLayer = hitTestList(m_posZOrderList, rootLayer, request, result, hitTestRect, hitTestPoint, 3141 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants); 3142 if (hitLayer) { 3143 if (!depthSortDescendants) 3144 return hitLayer; 3145 candidateLayer = hitLayer; 3146 } 3147 3148 // Now check our overflow objects. 3149 hitLayer = hitTestList(m_normalFlowList, rootLayer, request, result, hitTestRect, hitTestPoint, 3150 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants); 3151 if (hitLayer) { 3152 if (!depthSortDescendants) 3153 return hitLayer; 3154 candidateLayer = hitLayer; 3155 } 3156 3157 // Next we want to see if the mouse pos is inside the child RenderObjects of the layer. 3158 if (fgRect.intersects(hitTestArea) && isSelfPaintingLayer()) { 3159 // Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost. 3160 HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding()); 3161 if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestDescendants) && 3162 isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) { 3163 if (result.isRectBasedTest()) 3164 result.append(tempResult); 3165 else 3166 result = tempResult; 3167 if (!depthSortDescendants) 3168 return this; 3169 // Foreground can depth-sort with descendant layers, so keep this as a candidate. 3170 candidateLayer = this; 3171 } else if (result.isRectBasedTest()) 3172 result.append(tempResult); 3173 } 3174 3175 // Now check our negative z-index children. 3176 hitLayer = hitTestList(m_negZOrderList, rootLayer, request, result, hitTestRect, hitTestPoint, 3177 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants); 3178 if (hitLayer) { 3179 if (!depthSortDescendants) 3180 return hitLayer; 3181 candidateLayer = hitLayer; 3182 } 3183 3184 // If we found a layer, return. Child layers, and foreground always render in front of background. 3185 if (candidateLayer) 3186 return candidateLayer; 3187 3188 if (bgRect.intersects(hitTestArea) && isSelfPaintingLayer()) { 3189 HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding()); 3190 if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestSelf) && 3191 isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) { 3192 if (result.isRectBasedTest()) 3193 result.append(tempResult); 3194 else 3195 result = tempResult; 3196 return this; 3197 } else if (result.isRectBasedTest()) 3198 result.append(tempResult); 3199 } 3200 3201 return 0; 3202 } 3203 3204 bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const IntRect& layerBounds, const IntPoint& hitTestPoint, HitTestFilter hitTestFilter) const 3205 { 3206 if (!renderer()->hitTest(request, result, hitTestPoint, 3207 layerBounds.x() - renderBoxX(), 3208 layerBounds.y() - renderBoxY(), 3209 hitTestFilter)) { 3210 // It's wrong to set innerNode, but then claim that you didn't hit anything, unless it is 3211 // a rect-based test. 3212 ASSERT(!result.innerNode() || (result.isRectBasedTest() && result.rectBasedTestResult().size())); 3213 return false; 3214 } 3215 3216 // For positioned generated content, we might still not have a 3217 // node by the time we get to the layer level, since none of 3218 // the content in the layer has an element. So just walk up 3219 // the tree. 3220 if (!result.innerNode() || !result.innerNonSharedNode()) { 3221 Node* e = enclosingElement(); 3222 if (!result.innerNode()) 3223 result.setInnerNode(e); 3224 if (!result.innerNonSharedNode()) 3225 result.setInnerNonSharedNode(e); 3226 } 3227 3228 return true; 3229 } 3230 3231 RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* rootLayer, 3232 const HitTestRequest& request, HitTestResult& result, 3233 const IntRect& hitTestRect, const IntPoint& hitTestPoint, 3234 const HitTestingTransformState* transformState, 3235 double* zOffsetForDescendants, double* zOffset, 3236 const HitTestingTransformState* unflattenedTransformState, 3237 bool depthSortDescendants) 3238 { 3239 if (!list) 3240 return 0; 3241 3242 RenderLayer* resultLayer = 0; 3243 for (int i = list->size() - 1; i >= 0; --i) { 3244 RenderLayer* childLayer = list->at(i); 3245 RenderLayer* hitLayer = 0; 3246 HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding()); 3247 if (childLayer->isPaginated()) 3248 hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestPoint, transformState, zOffsetForDescendants); 3249 else 3250 hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, transformState, zOffsetForDescendants); 3251 3252 // If it a rect-based test, we can safely append the temporary result since it might had hit 3253 // nodes but not necesserily had hitLayer set. 3254 if (result.isRectBasedTest()) 3255 result.append(tempResult); 3256 3257 if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState)) { 3258 resultLayer = hitLayer; 3259 if (!result.isRectBasedTest()) 3260 result = tempResult; 3261 if (!depthSortDescendants) 3262 break; 3263 } 3264 } 3265 3266 return resultLayer; 3267 } 3268 3269 RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result, 3270 const IntRect& hitTestRect, const IntPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset) 3271 { 3272 Vector<RenderLayer*> columnLayers; 3273 RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext(); 3274 for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) { 3275 if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox())) 3276 columnLayers.append(curr); 3277 if (curr == ancestorLayer) 3278 break; 3279 } 3280 3281 ASSERT(columnLayers.size()); 3282 return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitTestRect, hitTestPoint, transformState, zOffset, 3283 columnLayers, columnLayers.size() - 1); 3284 } 3285 3286 RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result, 3287 const IntRect& hitTestRect, const IntPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset, 3288 const Vector<RenderLayer*>& columnLayers, size_t columnIndex) 3289 { 3290 RenderBlock* columnBlock = toRenderBlock(columnLayers[columnIndex]->renderer()); 3291 3292 ASSERT(columnBlock && columnBlock->hasColumns()); 3293 if (!columnBlock || !columnBlock->hasColumns()) 3294 return 0; 3295 3296 int layerX = 0; 3297 int layerY = 0; 3298 columnBlock->layer()->convertToLayerCoords(rootLayer, layerX, layerY); 3299 3300 ColumnInfo* colInfo = columnBlock->columnInfo(); 3301 int colCount = columnBlock->columnCount(colInfo); 3302 3303 // We have to go backwards from the last column to the first. 3304 bool isHorizontal = columnBlock->style()->isHorizontalWritingMode(); 3305 int logicalLeft = columnBlock->logicalLeftOffsetForContent(); 3306 int currLogicalTopOffset = 0; 3307 int i; 3308 for (i = 0; i < colCount; i++) { 3309 IntRect colRect = columnBlock->columnRectAt(colInfo, i); 3310 int blockDelta = (isHorizontal ? colRect.height() : colRect.width()); 3311 if (columnBlock->style()->isFlippedBlocksWritingMode()) 3312 currLogicalTopOffset += blockDelta; 3313 else 3314 currLogicalTopOffset -= blockDelta; 3315 } 3316 for (i = colCount - 1; i >= 0; i--) { 3317 // For each rect, we clip to the rect, and then we adjust our coords. 3318 IntRect colRect = columnBlock->columnRectAt(colInfo, i); 3319 columnBlock->flipForWritingMode(colRect); 3320 int currLogicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - logicalLeft; 3321 int blockDelta = (isHorizontal ? colRect.height() : colRect.width()); 3322 if (columnBlock->style()->isFlippedBlocksWritingMode()) 3323 currLogicalTopOffset -= blockDelta; 3324 else 3325 currLogicalTopOffset += blockDelta; 3326 colRect.move(layerX, layerY); 3327 3328 IntRect localClipRect(hitTestRect); 3329 localClipRect.intersect(colRect); 3330 3331 IntSize offset = isHorizontal ? IntSize(currLogicalLeftOffset, currLogicalTopOffset) : IntSize(currLogicalTopOffset, currLogicalLeftOffset); 3332 3333 if (!localClipRect.isEmpty() && localClipRect.intersects(result.rectForPoint(hitTestPoint))) { 3334 RenderLayer* hitLayer = 0; 3335 if (!columnIndex) { 3336 // Apply a translation transform to change where the layer paints. 3337 TransformationMatrix oldTransform; 3338 bool oldHasTransform = childLayer->transform(); 3339 if (oldHasTransform) 3340 oldTransform = *childLayer->transform(); 3341 TransformationMatrix newTransform(oldTransform); 3342 newTransform.translateRight(offset.width(), offset.height()); 3343 3344 childLayer->m_transform.set(new TransformationMatrix(newTransform)); 3345 hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestPoint, false, transformState, zOffset); 3346 if (oldHasTransform) 3347 childLayer->m_transform.set(new TransformationMatrix(oldTransform)); 3348 else 3349 childLayer->m_transform.clear(); 3350 } else { 3351 // Adjust the transform such that the renderer's upper left corner will be at (0,0) in user space. 3352 // This involves subtracting out the position of the layer in our current coordinate space. 3353 RenderLayer* nextLayer = columnLayers[columnIndex - 1]; 3354 RefPtr<HitTestingTransformState> newTransformState = nextLayer->createLocalTransformState(rootLayer, nextLayer, localClipRect, hitTestPoint, transformState); 3355 newTransformState->translate(offset.width(), offset.height(), HitTestingTransformState::AccumulateTransform); 3356 IntPoint localPoint = roundedIntPoint(newTransformState->mappedPoint()); 3357 IntRect localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox(); 3358 newTransformState->flatten(); 3359 3360 hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[columnIndex - 1], request, result, localHitTestRect, localPoint, 3361 newTransformState.get(), zOffset, columnLayers, columnIndex - 1); 3362 } 3363 3364 if (hitLayer) 3365 return hitLayer; 3366 } 3367 } 3368 3369 return 0; 3370 } 3371 3372 void RenderLayer::updateClipRects(const RenderLayer* rootLayer, OverlayScrollbarSizeRelevancy relevancy) 3373 { 3374 if (m_clipRects) { 3375 ASSERT(rootLayer == m_clipRectsRoot); 3376 return; // We have the correct cached value. 3377 } 3378 3379 // For transformed layers, the root layer was shifted to be us, so there is no need to 3380 // examine the parent. We want to cache clip rects with us as the root. 3381 RenderLayer* parentLayer = rootLayer != this ? parent() : 0; 3382 if (parentLayer) 3383 parentLayer->updateClipRects(rootLayer, relevancy); 3384 3385 ClipRects clipRects; 3386 calculateClipRects(rootLayer, clipRects, true, relevancy); 3387 3388 if (parentLayer && parentLayer->clipRects() && clipRects == *parentLayer->clipRects()) 3389 m_clipRects = parentLayer->clipRects(); 3390 else 3391 m_clipRects = new (renderer()->renderArena()) ClipRects(clipRects); 3392 m_clipRects->ref(); 3393 #ifndef NDEBUG 3394 m_clipRectsRoot = rootLayer; 3395 #endif 3396 } 3397 3398 void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool useCached, OverlayScrollbarSizeRelevancy relevancy) const 3399 { 3400 if (!parent()) { 3401 // The root layer's clip rect is always infinite. 3402 clipRects.reset(PaintInfo::infiniteRect()); 3403 return; 3404 } 3405 3406 // For transformed layers, the root layer was shifted to be us, so there is no need to 3407 // examine the parent. We want to cache clip rects with us as the root. 3408 RenderLayer* parentLayer = rootLayer != this ? parent() : 0; 3409 3410 // Ensure that our parent's clip has been calculated so that we can examine the values. 3411 if (parentLayer) { 3412 if (useCached && parentLayer->clipRects()) 3413 clipRects = *parentLayer->clipRects(); 3414 else 3415 parentLayer->calculateClipRects(rootLayer, clipRects); 3416 } 3417 else 3418 clipRects.reset(PaintInfo::infiniteRect()); 3419 3420 // A fixed object is essentially the root of its containing block hierarchy, so when 3421 // we encounter such an object, we reset our clip rects to the fixedClipRect. 3422 if (renderer()->style()->position() == FixedPosition) { 3423 clipRects.setPosClipRect(clipRects.fixedClipRect()); 3424 clipRects.setOverflowClipRect(clipRects.fixedClipRect()); 3425 clipRects.setFixed(true); 3426 } 3427 else if (renderer()->style()->position() == RelativePosition) 3428 clipRects.setPosClipRect(clipRects.overflowClipRect()); 3429 else if (renderer()->style()->position() == AbsolutePosition) 3430 clipRects.setOverflowClipRect(clipRects.posClipRect()); 3431 3432 // Update the clip rects that will be passed to child layers. 3433 if (renderer()->hasOverflowClip() || renderer()->hasClip()) { 3434 // This layer establishes a clip of some kind. 3435 int x = 0; 3436 int y = 0; 3437 convertToLayerCoords(rootLayer, x, y); 3438 RenderView* view = renderer()->view(); 3439 ASSERT(view); 3440 if (view && clipRects.fixed() && rootLayer->renderer() == view) { 3441 x -= view->frameView()->scrollXForFixedPosition(); 3442 y -= view->frameView()->scrollYForFixedPosition(); 3443 } 3444 3445 if (renderer()->hasOverflowClip()) { 3446 IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x, y, relevancy); 3447 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 3448 if (hasOverflowScroll()) { 3449 RenderBox* box = toRenderBox(renderer()); 3450 newOverflowClip = 3451 IntRect(x + box->borderLeft(), y + box->borderTop(), 3452 m_scrollWidth, m_scrollHeight); 3453 } 3454 #endif 3455 clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect())); 3456 if (renderer()->isPositioned() || renderer()->isRelPositioned()) 3457 clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect())); 3458 } 3459 if (renderer()->hasClip()) { 3460 IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y); 3461 clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect())); 3462 clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect())); 3463 clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect())); 3464 } 3465 } 3466 } 3467 3468 void RenderLayer::parentClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool temporaryClipRects, OverlayScrollbarSizeRelevancy relevancy) const 3469 { 3470 ASSERT(parent()); 3471 if (temporaryClipRects) { 3472 parent()->calculateClipRects(rootLayer, clipRects, false, relevancy); 3473 return; 3474 } 3475 3476 parent()->updateClipRects(rootLayer, relevancy); 3477 clipRects = *parent()->clipRects(); 3478 } 3479 3480 IntRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects, OverlayScrollbarSizeRelevancy relevancy) const 3481 { 3482 IntRect backgroundRect; 3483 if (parent()) { 3484 ClipRects parentRects; 3485 parentClipRects(rootLayer, parentRects, temporaryClipRects, relevancy); 3486 backgroundRect = renderer()->style()->position() == FixedPosition ? parentRects.fixedClipRect() : 3487 (renderer()->isPositioned() ? parentRects.posClipRect() : 3488 parentRects.overflowClipRect()); 3489 RenderView* view = renderer()->view(); 3490 ASSERT(view); 3491 if (view && parentRects.fixed() && rootLayer->renderer() == view) 3492 backgroundRect.move(view->frameView()->scrollXForFixedPosition(), view->frameView()->scrollYForFixedPosition()); 3493 } 3494 return backgroundRect; 3495 } 3496 3497 void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds, 3498 IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects, 3499 OverlayScrollbarSizeRelevancy relevancy) const 3500 { 3501 if (rootLayer != this && parent()) { 3502 backgroundRect = backgroundClipRect(rootLayer, temporaryClipRects, relevancy); 3503 backgroundRect.intersect(paintDirtyRect); 3504 } else 3505 backgroundRect = paintDirtyRect; 3506 3507 foregroundRect = backgroundRect; 3508 outlineRect = backgroundRect; 3509 3510 int x = 0; 3511 int y = 0; 3512 convertToLayerCoords(rootLayer, x, y); 3513 layerBounds = IntRect(x, y, width(), height()); 3514 3515 // Update the clip rects that will be passed to child layers. 3516 if (renderer()->hasOverflowClip() || renderer()->hasClip()) { 3517 // This layer establishes a clip of some kind. 3518 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 3519 if (hasOverflowScroll()) { 3520 // Use the entire foreground rectangle to record the contents. 3521 RenderBox* box = toRenderBox(renderer()); 3522 foregroundRect = 3523 IntRect(x + box->borderLeft(), y + box->borderTop(), 3524 m_scrollWidth, m_scrollHeight); 3525 } else 3526 #endif 3527 if (renderer()->hasOverflowClip()) 3528 foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(x, y, relevancy)); 3529 if (renderer()->hasClip()) { 3530 // Clip applies to *us* as well, so go ahead and update the damageRect. 3531 IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y); 3532 backgroundRect.intersect(newPosClip); 3533 foregroundRect.intersect(newPosClip); 3534 outlineRect.intersect(newPosClip); 3535 } 3536 3537 // If we establish a clip at all, then go ahead and make sure our background 3538 // rect is intersected with our layer's bounds. 3539 // FIXME: This could be changed to just use generic visual overflow. 3540 // See https://bugs.webkit.org/show_bug.cgi?id=37467 for more information. 3541 if (const ShadowData* boxShadow = renderer()->style()->boxShadow()) { 3542 IntRect overflow = layerBounds; 3543 do { 3544 if (boxShadow->style() == Normal) { 3545 IntRect shadowRect = layerBounds; 3546 shadowRect.move(boxShadow->x(), boxShadow->y()); 3547 shadowRect.inflate(boxShadow->blur() + boxShadow->spread()); 3548 overflow.unite(shadowRect); 3549 } 3550 3551 boxShadow = boxShadow->next(); 3552 } while (boxShadow); 3553 backgroundRect.intersect(overflow); 3554 } else 3555 backgroundRect.intersect(layerBounds); 3556 } 3557 } 3558 3559 IntRect RenderLayer::childrenClipRect() const 3560 { 3561 RenderView* renderView = renderer()->view(); 3562 RenderLayer* clippingRootLayer = clippingRoot(); 3563 IntRect layerBounds, backgroundRect, foregroundRect, outlineRect; 3564 calculateRects(clippingRootLayer, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect); 3565 return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect)).enclosingBoundingBox(); 3566 } 3567 3568 IntRect RenderLayer::selfClipRect() const 3569 { 3570 RenderView* renderView = renderer()->view(); 3571 RenderLayer* clippingRootLayer = clippingRoot(); 3572 IntRect layerBounds, backgroundRect, foregroundRect, outlineRect; 3573 calculateRects(clippingRootLayer, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect); 3574 return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect)).enclosingBoundingBox(); 3575 } 3576 3577 void RenderLayer::addBlockSelectionGapsBounds(const IntRect& bounds) 3578 { 3579 m_blockSelectionGapsBounds.unite(bounds); 3580 } 3581 3582 void RenderLayer::clearBlockSelectionGapsBounds() 3583 { 3584 m_blockSelectionGapsBounds = IntRect(); 3585 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 3586 child->clearBlockSelectionGapsBounds(); 3587 } 3588 3589 void RenderLayer::repaintBlockSelectionGaps() 3590 { 3591 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 3592 child->repaintBlockSelectionGaps(); 3593 3594 if (m_blockSelectionGapsBounds.isEmpty()) 3595 return; 3596 3597 IntRect rect = m_blockSelectionGapsBounds; 3598 rect.move(-scrolledContentOffset()); 3599 if (renderer()->hasOverflowClip()) 3600 rect.intersect(toRenderBox(renderer())->overflowClipRect(0, 0)); 3601 if (renderer()->hasClip()) 3602 rect.intersect(toRenderBox(renderer())->clipRect(0, 0)); 3603 if (!rect.isEmpty()) 3604 renderer()->repaintRectangle(rect); 3605 } 3606 3607 bool RenderLayer::intersectsDamageRect(const IntRect& layerBounds, const IntRect& damageRect, const RenderLayer* rootLayer) const 3608 { 3609 // Always examine the canvas and the root. 3610 // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView 3611 // paints the root's background. 3612 if (renderer()->isRenderView() || renderer()->isRoot()) 3613 return true; 3614 3615 // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we 3616 // can go ahead and return true. 3617 RenderView* view = renderer()->view(); 3618 ASSERT(view); 3619 if (view && !renderer()->isRenderInline()) { 3620 IntRect b = layerBounds; 3621 b.inflate(view->maximalOutlineSize()); 3622 if (b.intersects(damageRect)) 3623 return true; 3624 } 3625 3626 // Otherwise we need to compute the bounding box of this single layer and see if it intersects 3627 // the damage rect. 3628 return boundingBox(rootLayer).intersects(damageRect); 3629 } 3630 3631 IntRect RenderLayer::localBoundingBox() const 3632 { 3633 // There are three special cases we need to consider. 3634 // (1) Inline Flows. For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the 3635 // inline. In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the 3636 // line boxes of all three lines (including overflow on those lines). 3637 // (2) Left/Top Overflow. The width/height of layers already includes right/bottom overflow. However, in the case of left/top 3638 // overflow, we have to create a bounding box that will extend to include this overflow. 3639 // (3) Floats. When a layer has overhanging floats that it paints, we need to make sure to include these overhanging floats 3640 // as part of our bounding box. We do this because we are the responsible layer for both hit testing and painting those 3641 // floats. 3642 IntRect result; 3643 if (renderer()->isRenderInline()) 3644 result = toRenderInline(renderer())->linesVisualOverflowBoundingBox(); 3645 else if (renderer()->isTableRow()) { 3646 // Our bounding box is just the union of all of our cells' border/overflow rects. 3647 for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) { 3648 if (child->isTableCell()) { 3649 IntRect bbox = toRenderBox(child)->borderBoxRect(); 3650 result.unite(bbox); 3651 IntRect overflowRect = renderBox()->visualOverflowRect(); 3652 if (bbox != overflowRect) 3653 result.unite(overflowRect); 3654 } 3655 } 3656 } else { 3657 RenderBox* box = renderBox(); 3658 ASSERT(box); 3659 if (box->hasMask()) 3660 result = box->maskClipRect(); 3661 else { 3662 IntRect bbox = box->borderBoxRect(); 3663 result = bbox; 3664 IntRect overflowRect = box->visualOverflowRect(); 3665 if (bbox != overflowRect) 3666 result.unite(overflowRect); 3667 } 3668 } 3669 3670 RenderView* view = renderer()->view(); 3671 ASSERT(view); 3672 if (view) 3673 result.inflate(view->maximalOutlineSize()); // Used to apply a fudge factor to dirty-rect checks on blocks/tables. 3674 3675 return result; 3676 } 3677 3678 IntRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer) const 3679 { 3680 IntRect result = localBoundingBox(); 3681 if (renderer()->isBox()) 3682 renderBox()->flipForWritingMode(result); 3683 else 3684 renderer()->containingBlock()->flipForWritingMode(result); 3685 int deltaX = 0, deltaY = 0; 3686 convertToLayerCoords(ancestorLayer, deltaX, deltaY); 3687 result.move(deltaX, deltaY); 3688 return result; 3689 } 3690 3691 IntRect RenderLayer::absoluteBoundingBox() const 3692 { 3693 return boundingBox(root()); 3694 } 3695 3696 void RenderLayer::clearClipRectsIncludingDescendants() 3697 { 3698 if (!m_clipRects) 3699 return; 3700 3701 clearClipRects(); 3702 3703 for (RenderLayer* l = firstChild(); l; l = l->nextSibling()) 3704 l->clearClipRectsIncludingDescendants(); 3705 } 3706 3707 void RenderLayer::clearClipRects() 3708 { 3709 if (m_clipRects) { 3710 m_clipRects->deref(renderer()->renderArena()); 3711 m_clipRects = 0; 3712 #ifndef NDEBUG 3713 m_clipRectsRoot = 0; 3714 #endif 3715 } 3716 } 3717 3718 #if USE(ACCELERATED_COMPOSITING) 3719 RenderLayerBacking* RenderLayer::ensureBacking() 3720 { 3721 if (!m_backing) 3722 m_backing.set(new RenderLayerBacking(this)); 3723 return m_backing.get(); 3724 } 3725 3726 void RenderLayer::clearBacking() 3727 { 3728 m_backing.clear(); 3729 } 3730 3731 bool RenderLayer::hasCompositedMask() const 3732 { 3733 return m_backing && m_backing->hasMaskLayer(); 3734 } 3735 3736 GraphicsLayer* RenderLayer::layerForHorizontalScrollbar() const 3737 { 3738 return m_backing ? m_backing->layerForHorizontalScrollbar() : 0; 3739 } 3740 3741 GraphicsLayer* RenderLayer::layerForVerticalScrollbar() const 3742 { 3743 return m_backing ? m_backing->layerForVerticalScrollbar() : 0; 3744 } 3745 3746 GraphicsLayer* RenderLayer::layerForScrollCorner() const 3747 { 3748 return m_backing ? m_backing->layerForScrollCorner() : 0; 3749 } 3750 #endif 3751 3752 bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const 3753 { 3754 #if USE(ACCELERATED_COMPOSITING) 3755 bool paintsToWindow = !isComposited() || backing()->paintingGoesToWindow(); 3756 #else 3757 bool paintsToWindow = true; 3758 #endif 3759 return transform() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || paintsToWindow); 3760 } 3761 3762 void RenderLayer::setParent(RenderLayer* parent) 3763 { 3764 if (parent == m_parent) 3765 return; 3766 3767 #if USE(ACCELERATED_COMPOSITING) 3768 if (m_parent && !renderer()->documentBeingDestroyed()) 3769 compositor()->layerWillBeRemoved(m_parent, this); 3770 #endif 3771 3772 m_parent = parent; 3773 3774 #if USE(ACCELERATED_COMPOSITING) 3775 if (m_parent && !renderer()->documentBeingDestroyed()) 3776 compositor()->layerWasAdded(m_parent, this); 3777 #endif 3778 } 3779 3780 static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2) 3781 { 3782 if (!obj1 || !obj2) 3783 return 0; 3784 3785 for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAncestor()) 3786 for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hoverAncestor()) 3787 if (currObj1 == currObj2) 3788 return currObj1; 3789 3790 return 0; 3791 } 3792 3793 void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestResult& result) 3794 { 3795 // We don't update :hover/:active state when the result is marked as readOnly. 3796 if (request.readOnly()) 3797 return; 3798 3799 Document* doc = renderer()->document(); 3800 3801 Node* activeNode = doc->activeNode(); 3802 if (activeNode && !request.active()) { 3803 // We are clearing the :active chain because the mouse has been released. 3804 for (RenderObject* curr = activeNode->renderer(); curr; curr = curr->parent()) { 3805 if (curr->node() && !curr->isText()) 3806 curr->node()->clearInActiveChain(); 3807 } 3808 doc->setActiveNode(0); 3809 } else { 3810 Node* newActiveNode = result.innerNode(); 3811 if (!activeNode && newActiveNode && request.active()) { 3812 // We are setting the :active chain and freezing it. If future moves happen, they 3813 // will need to reference this chain. 3814 for (RenderObject* curr = newActiveNode->renderer(); curr; curr = curr->parent()) { 3815 if (curr->node() && !curr->isText()) { 3816 curr->node()->setInActiveChain(); 3817 } 3818 } 3819 doc->setActiveNode(newActiveNode); 3820 } 3821 } 3822 3823 // If the mouse is down and if this is a mouse move event, we want to restrict changes in 3824 // :hover/:active to only apply to elements that are in the :active chain that we froze 3825 // at the time the mouse went down. 3826 bool mustBeInActiveChain = request.active() && request.mouseMove(); 3827 3828 // Check to see if the hovered node has changed. If not, then we don't need to 3829 // do anything. 3830 RefPtr<Node> oldHoverNode = doc->hoverNode(); 3831 Node* newHoverNode = result.innerNode(); 3832 3833 // Update our current hover node. 3834 doc->setHoverNode(newHoverNode); 3835 3836 // We have two different objects. Fetch their renderers. 3837 RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0; 3838 RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0; 3839 3840 // Locate the common ancestor render object for the two renderers. 3841 RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj); 3842 3843 Vector<RefPtr<Node>, 32> nodesToRemoveFromChain; 3844 Vector<RefPtr<Node>, 32> nodesToAddToChain; 3845 3846 if (oldHoverObj != newHoverObj) { 3847 // The old hover path only needs to be cleared up to (and not including) the common ancestor; 3848 for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) { 3849 if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) 3850 nodesToRemoveFromChain.append(curr->node()); 3851 } 3852 } 3853 3854 // Now set the hover state for our new object up to the root. 3855 for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) { 3856 if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) 3857 nodesToAddToChain.append(curr->node()); 3858 } 3859 3860 size_t removeCount = nodesToRemoveFromChain.size(); 3861 for (size_t i = 0; i < removeCount; ++i) { 3862 nodesToRemoveFromChain[i]->setActive(false); 3863 nodesToRemoveFromChain[i]->setHovered(false); 3864 } 3865 3866 size_t addCount = nodesToAddToChain.size(); 3867 for (size_t i = 0; i < addCount; ++i) { 3868 nodesToAddToChain[i]->setActive(request.active()); 3869 nodesToAddToChain[i]->setHovered(true); 3870 } 3871 } 3872 3873 // Helper for the sorting of layers by z-index. 3874 static inline bool compareZIndex(RenderLayer* first, RenderLayer* second) 3875 { 3876 return first->zIndex() < second->zIndex(); 3877 } 3878 3879 void RenderLayer::dirtyZOrderLists() 3880 { 3881 if (m_posZOrderList) 3882 m_posZOrderList->clear(); 3883 if (m_negZOrderList) 3884 m_negZOrderList->clear(); 3885 m_zOrderListsDirty = true; 3886 3887 #if USE(ACCELERATED_COMPOSITING) 3888 if (!renderer()->documentBeingDestroyed()) 3889 compositor()->setCompositingLayersNeedRebuild(); 3890 #endif 3891 } 3892 3893 void RenderLayer::dirtyStackingContextZOrderLists() 3894 { 3895 RenderLayer* sc = stackingContext(); 3896 if (sc) 3897 sc->dirtyZOrderLists(); 3898 } 3899 3900 void RenderLayer::dirtyNormalFlowList() 3901 { 3902 if (m_normalFlowList) 3903 m_normalFlowList->clear(); 3904 m_normalFlowListDirty = true; 3905 3906 #if USE(ACCELERATED_COMPOSITING) 3907 if (!renderer()->documentBeingDestroyed()) 3908 compositor()->setCompositingLayersNeedRebuild(); 3909 #endif 3910 } 3911 3912 void RenderLayer::updateZOrderLists() 3913 { 3914 if (!isStackingContext() || !m_zOrderListsDirty) 3915 return; 3916 3917 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 3918 if (!m_reflection || reflectionLayer() != child) 3919 child->collectLayers(m_posZOrderList, m_negZOrderList); 3920 3921 // Sort the two lists. 3922 if (m_posZOrderList) 3923 std::stable_sort(m_posZOrderList->begin(), m_posZOrderList->end(), compareZIndex); 3924 3925 if (m_negZOrderList) 3926 std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex); 3927 3928 m_zOrderListsDirty = false; 3929 } 3930 3931 void RenderLayer::updateNormalFlowList() 3932 { 3933 if (!m_normalFlowListDirty) 3934 return; 3935 3936 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) { 3937 // Ignore non-overflow layers and reflections. 3938 if (child->isNormalFlowOnly() && (!m_reflection || reflectionLayer() != child)) { 3939 if (!m_normalFlowList) 3940 m_normalFlowList = new Vector<RenderLayer*>; 3941 m_normalFlowList->append(child); 3942 } 3943 } 3944 3945 m_normalFlowListDirty = false; 3946 } 3947 3948 void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderLayer*>*& negBuffer) 3949 { 3950 updateVisibilityStatus(); 3951 3952 // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists. 3953 if ((m_hasVisibleContent || (m_hasVisibleDescendant && isStackingContext())) && !isNormalFlowOnly()) { 3954 // Determine which buffer the child should be in. 3955 Vector<RenderLayer*>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer; 3956 3957 // Create the buffer if it doesn't exist yet. 3958 if (!buffer) 3959 buffer = new Vector<RenderLayer*>; 3960 3961 // Append ourselves at the end of the appropriate buffer. 3962 buffer->append(this); 3963 } 3964 3965 // Recur into our children to collect more layers, but only if we don't establish 3966 // a stacking context. 3967 if (m_hasVisibleDescendant && !isStackingContext()) { 3968 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) { 3969 // Ignore reflections. 3970 if (!m_reflection || reflectionLayer() != child) 3971 child->collectLayers(posBuffer, negBuffer); 3972 } 3973 } 3974 } 3975 3976 void RenderLayer::updateLayerListsIfNeeded() 3977 { 3978 updateZOrderLists(); 3979 updateNormalFlowList(); 3980 } 3981 3982 void RenderLayer::updateCompositingAndLayerListsIfNeeded() 3983 { 3984 #if USE(ACCELERATED_COMPOSITING) 3985 if (compositor()->inCompositingMode()) { 3986 if ((isStackingContext() && m_zOrderListsDirty) || m_normalFlowListDirty) 3987 compositor()->updateCompositingLayers(CompositingUpdateOnPaitingOrHitTest, this); 3988 return; 3989 } 3990 #endif 3991 updateLayerListsIfNeeded(); 3992 } 3993 3994 void RenderLayer::repaintIncludingDescendants() 3995 { 3996 renderer()->repaint(); 3997 for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling()) 3998 curr->repaintIncludingDescendants(); 3999 } 4000 4001 #if USE(ACCELERATED_COMPOSITING) 4002 void RenderLayer::setBackingNeedsRepaint() 4003 { 4004 ASSERT(isComposited()); 4005 if (backing()->paintingGoesToWindow()) { 4006 // If we're trying to repaint the placeholder document layer, propagate the 4007 // repaint to the native view system. 4008 RenderView* view = renderer()->view(); 4009 if (view) 4010 view->repaintViewRectangle(absoluteBoundingBox()); 4011 } else 4012 backing()->setContentsNeedDisplay(); 4013 } 4014 4015 void RenderLayer::setBackingNeedsRepaintInRect(const IntRect& r) 4016 { 4017 ASSERT(isComposited()); 4018 if (backing()->paintingGoesToWindow()) { 4019 // If we're trying to repaint the placeholder document layer, propagate the 4020 // repaint to the native view system. 4021 IntRect absRect(r); 4022 int x = 0; 4023 int y = 0; 4024 convertToLayerCoords(root(), x, y); 4025 absRect.move(x, y); 4026 4027 RenderView* view = renderer()->view(); 4028 if (view) 4029 view->repaintViewRectangle(absRect); 4030 } else 4031 backing()->setContentsNeedDisplayInRect(r); 4032 } 4033 4034 // Since we're only painting non-composited layers, we know that they all share the same repaintContainer. 4035 void RenderLayer::repaintIncludingNonCompositingDescendants(RenderBoxModelObject* repaintContainer) 4036 { 4037 renderer()->repaintUsingContainer(repaintContainer, renderer()->clippedOverflowRectForRepaint(repaintContainer)); 4038 4039 for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling()) { 4040 if (!curr->isComposited()) 4041 curr->repaintIncludingNonCompositingDescendants(repaintContainer); 4042 } 4043 } 4044 #endif 4045 4046 bool RenderLayer::shouldBeNormalFlowOnly() const 4047 { 4048 return (renderer()->hasOverflowClip() 4049 || renderer()->hasReflection() 4050 || renderer()->hasMask() 4051 || renderer()->isVideo() 4052 || renderer()->isEmbeddedObject() 4053 || renderer()->isApplet() 4054 || renderer()->isRenderIFrame() 4055 || renderer()->style()->specifiesColumns()) 4056 && !renderer()->isPositioned() 4057 && !renderer()->isRelPositioned() 4058 && !renderer()->hasTransform() 4059 && !isTransparent(); 4060 } 4061 4062 bool RenderLayer::isSelfPaintingLayer() const 4063 { 4064 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 4065 if (hasOverflowScroll()) 4066 return true; 4067 #endif 4068 return !isNormalFlowOnly() 4069 || renderer()->hasReflection() 4070 || renderer()->hasMask() 4071 || renderer()->isTableRow() 4072 || renderer()->isVideo() 4073 || renderer()->isEmbeddedObject() 4074 || renderer()->isApplet() 4075 || renderer()->isRenderIFrame(); 4076 } 4077 4078 void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle) 4079 { 4080 bool isNormalFlowOnly = shouldBeNormalFlowOnly(); 4081 if (isNormalFlowOnly != m_isNormalFlowOnly) { 4082 m_isNormalFlowOnly = isNormalFlowOnly; 4083 RenderLayer* p = parent(); 4084 if (p) 4085 p->dirtyNormalFlowList(); 4086 dirtyStackingContextZOrderLists(); 4087 } 4088 4089 if (renderer()->style()->overflowX() == OMARQUEE && renderer()->style()->marqueeBehavior() != MNONE && renderer()->isBox()) { 4090 if (!m_marquee) 4091 m_marquee = new RenderMarquee(this); 4092 m_marquee->updateMarqueeStyle(); 4093 } 4094 else if (m_marquee) { 4095 delete m_marquee; 4096 m_marquee = 0; 4097 } 4098 4099 if (!hasReflection() && m_reflection) 4100 removeReflection(); 4101 else if (hasReflection()) { 4102 if (!m_reflection) 4103 createReflection(); 4104 updateReflectionStyle(); 4105 } 4106 4107 // FIXME: Need to detect a swap from custom to native scrollbars (and vice versa). 4108 if (m_hBar) 4109 m_hBar->styleChanged(); 4110 if (m_vBar) 4111 m_vBar->styleChanged(); 4112 4113 updateScrollCornerStyle(); 4114 updateResizerStyle(); 4115 4116 #if USE(ACCELERATED_COMPOSITING) 4117 updateTransform(); 4118 4119 if (compositor()->updateLayerCompositingState(this)) 4120 compositor()->setCompositingLayersNeedRebuild(); 4121 else if (m_backing) 4122 m_backing->updateGraphicsLayerGeometry(); 4123 else if (oldStyle && oldStyle->overflowX() != renderer()->style()->overflowX()) { 4124 if (stackingContext()->hasCompositingDescendant()) 4125 compositor()->setCompositingLayersNeedRebuild(); 4126 } 4127 4128 if (m_backing && diff >= StyleDifferenceRepaint) 4129 m_backing->setContentsNeedDisplay(); 4130 #else 4131 UNUSED_PARAM(diff); 4132 #endif 4133 } 4134 4135 void RenderLayer::updateScrollCornerStyle() 4136 { 4137 RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer(); 4138 RefPtr<RenderStyle> corner = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, actualRenderer->style()) : 0; 4139 if (corner) { 4140 if (!m_scrollCorner) { 4141 m_scrollCorner = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document()); 4142 m_scrollCorner->setParent(renderer()); 4143 } 4144 m_scrollCorner->setStyle(corner.release()); 4145 } else if (m_scrollCorner) { 4146 m_scrollCorner->destroy(); 4147 m_scrollCorner = 0; 4148 } 4149 } 4150 4151 void RenderLayer::updateResizerStyle() 4152 { 4153 RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer(); 4154 RefPtr<RenderStyle> resizer = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RESIZER, actualRenderer->style()) : 0; 4155 if (resizer) { 4156 if (!m_resizer) { 4157 m_resizer = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document()); 4158 m_resizer->setParent(renderer()); 4159 } 4160 m_resizer->setStyle(resizer.release()); 4161 } else if (m_resizer) { 4162 m_resizer->destroy(); 4163 m_resizer = 0; 4164 } 4165 } 4166 4167 RenderLayer* RenderLayer::reflectionLayer() const 4168 { 4169 return m_reflection ? m_reflection->layer() : 0; 4170 } 4171 4172 void RenderLayer::createReflection() 4173 { 4174 ASSERT(!m_reflection); 4175 m_reflection = new (renderer()->renderArena()) RenderReplica(renderer()->document()); 4176 m_reflection->setParent(renderer()); // We create a 1-way connection. 4177 } 4178 4179 void RenderLayer::removeReflection() 4180 { 4181 if (!m_reflection->documentBeingDestroyed()) 4182 m_reflection->removeLayers(this); 4183 4184 m_reflection->setParent(0); 4185 m_reflection->destroy(); 4186 m_reflection = 0; 4187 } 4188 4189 void RenderLayer::updateReflectionStyle() 4190 { 4191 RefPtr<RenderStyle> newStyle = RenderStyle::create(); 4192 newStyle->inheritFrom(renderer()->style()); 4193 4194 // Map in our transform. 4195 TransformOperations transform; 4196 switch (renderer()->style()->boxReflect()->direction()) { 4197 case ReflectionBelow: 4198 transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE)); 4199 transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE)); 4200 transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE)); 4201 break; 4202 case ReflectionAbove: 4203 transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE)); 4204 transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE)); 4205 transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE)); 4206 break; 4207 case ReflectionRight: 4208 transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE)); 4209 transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE)); 4210 transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE)); 4211 break; 4212 case ReflectionLeft: 4213 transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE)); 4214 transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE)); 4215 transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE)); 4216 break; 4217 } 4218 newStyle->setTransform(transform); 4219 4220 // Map in our mask. 4221 newStyle->setMaskBoxImage(renderer()->style()->boxReflect()->mask()); 4222 4223 m_reflection->setStyle(newStyle.release()); 4224 } 4225 4226 void RenderLayer::updateContentsScale(float scale) 4227 { 4228 #if USE(ACCELERATED_COMPOSITING) 4229 if (m_backing) 4230 m_backing->updateContentsScale(scale); 4231 #endif 4232 } 4233 4234 } // namespace WebCore 4235 4236 #ifndef NDEBUG 4237 void showLayerTree(const WebCore::RenderLayer* layer) 4238 { 4239 if (!layer) 4240 return; 4241 4242 if (WebCore::Frame* frame = layer->renderer()->frame()) { 4243 WTF::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses | WebCore::RenderAsTextShowIDAndClass | WebCore::RenderAsTextDontUpdateLayout | WebCore::RenderAsTextShowLayoutState); 4244 fprintf(stderr, "%s\n", output.utf8().data()); 4245 } 4246 } 4247 4248 void showLayerTree(const WebCore::RenderObject* renderer) 4249 { 4250 if (!renderer) 4251 return; 4252 showLayerTree(renderer->enclosingLayer()); 4253 } 4254 #endif 4255