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