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 (view) 1423 renderer()->repaintUsingContainer(repaintContainer, rectForRepaint); 1424 1425 // Schedule the scroll DOM event. 1426 renderer()->node()->document()->eventQueue()->enqueueOrDispatchScrollEvent(renderer()->node(), EventQueue::ScrollEventElementTarget); 1427 } 1428 1429 void RenderLayer::scrollRectToVisible(const IntRect& rect, bool scrollToAnchor, const ScrollAlignment& alignX, const ScrollAlignment& alignY) 1430 { 1431 RenderLayer* parentLayer = 0; 1432 IntRect newRect = rect; 1433 int xOffset = 0, yOffset = 0; 1434 1435 // We may end up propagating a scroll event. It is important that we suspend events until 1436 // the end of the function since they could delete the layer or the layer's renderer(). 1437 FrameView* frameView = renderer()->document()->view(); 1438 if (frameView) 1439 frameView->pauseScheduledEvents(); 1440 1441 bool restrictedByLineClamp = false; 1442 if (renderer()->parent()) { 1443 parentLayer = renderer()->parent()->enclosingLayer(); 1444 restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone(); 1445 } 1446 1447 if (renderer()->hasOverflowClip() && !restrictedByLineClamp) { 1448 // Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property. 1449 // This will prevent us from revealing text hidden by the slider in Safari RSS. 1450 RenderBox* box = renderBox(); 1451 ASSERT(box); 1452 FloatPoint absPos = box->localToAbsolute(); 1453 absPos.move(box->borderLeft(), box->borderTop()); 1454 1455 IntRect layerBounds = IntRect(absPos.x() + scrollXOffset(), absPos.y() + scrollYOffset(), box->clientWidth(), box->clientHeight()); 1456 IntRect exposeRect = IntRect(rect.x() + scrollXOffset(), rect.y() + scrollYOffset(), rect.width(), rect.height()); 1457 IntRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY); 1458 1459 xOffset = r.x() - absPos.x(); 1460 yOffset = r.y() - absPos.y(); 1461 // Adjust offsets if they're outside of the allowable range. 1462 xOffset = max(0, min(scrollWidth() - layerBounds.width(), xOffset)); 1463 yOffset = max(0, min(scrollHeight() - layerBounds.height(), yOffset)); 1464 1465 if (xOffset != scrollXOffset() || yOffset != scrollYOffset()) { 1466 int diffX = scrollXOffset(); 1467 int diffY = scrollYOffset(); 1468 scrollToOffset(xOffset, yOffset); 1469 diffX = scrollXOffset() - diffX; 1470 diffY = scrollYOffset() - diffY; 1471 newRect.setX(rect.x() - diffX); 1472 newRect.setY(rect.y() - diffY); 1473 } 1474 } else if (!parentLayer && renderer()->isBox() && renderBox()->canBeProgramaticallyScrolled(scrollToAnchor)) { 1475 if (frameView) { 1476 if (renderer()->document() && renderer()->document()->ownerElement() && renderer()->document()->ownerElement()->renderer()) { 1477 IntRect viewRect = frameView->visibleContentRect(); 1478 IntRect r = getRectToExpose(viewRect, rect, alignX, alignY); 1479 1480 xOffset = r.x(); 1481 yOffset = r.y(); 1482 // Adjust offsets if they're outside of the allowable range. 1483 xOffset = max(0, min(frameView->contentsWidth(), xOffset)); 1484 yOffset = max(0, min(frameView->contentsHeight(), yOffset)); 1485 1486 frameView->setScrollPosition(IntPoint(xOffset, yOffset)); 1487 parentLayer = renderer()->document()->ownerElement()->renderer()->enclosingLayer(); 1488 newRect.setX(rect.x() - frameView->scrollX() + frameView->x()); 1489 newRect.setY(rect.y() - frameView->scrollY() + frameView->y()); 1490 } else { 1491 IntRect viewRect = frameView->visibleContentRect(); 1492 IntRect r = getRectToExpose(viewRect, rect, alignX, alignY); 1493 1494 frameView->setScrollPosition(r.location()); 1495 1496 // This is the outermost view of a web page, so after scrolling this view we 1497 // scroll its container by calling Page::scrollRectIntoView. 1498 // This only has an effect on the Mac platform in applications 1499 // that put web views into scrolling containers, such as Mac OS X Mail. 1500 // The canAutoscroll function in EventHandler also knows about this. 1501 if (Frame* frame = frameView->frame()) { 1502 if (Page* page = frame->page()) 1503 page->chrome()->scrollRectIntoView(rect); 1504 } 1505 } 1506 } 1507 } 1508 1509 if (parentLayer) 1510 parentLayer->scrollRectToVisible(newRect, scrollToAnchor, alignX, alignY); 1511 1512 if (frameView) 1513 frameView->resumeScheduledEvents(); 1514 } 1515 1516 IntRect RenderLayer::getRectToExpose(const IntRect &visibleRect, const IntRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY) 1517 { 1518 // Determine the appropriate X behavior. 1519 ScrollBehavior scrollX; 1520 IntRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height()); 1521 int intersectWidth = intersection(visibleRect, exposeRectX).width(); 1522 if (intersectWidth == exposeRect.width() || intersectWidth >= MIN_INTERSECT_FOR_REVEAL) 1523 // If the rectangle is fully visible, use the specified visible behavior. 1524 // If the rectangle is partially visible, but over a certain threshold, 1525 // then treat it as fully visible to avoid unnecessary horizontal scrolling 1526 scrollX = ScrollAlignment::getVisibleBehavior(alignX); 1527 else if (intersectWidth == visibleRect.width()) { 1528 // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work. 1529 scrollX = ScrollAlignment::getVisibleBehavior(alignX); 1530 if (scrollX == alignCenter) 1531 scrollX = noScroll; 1532 } else if (intersectWidth > 0) 1533 // If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior 1534 scrollX = ScrollAlignment::getPartialBehavior(alignX); 1535 else 1536 scrollX = ScrollAlignment::getHiddenBehavior(alignX); 1537 // If we're trying to align to the closest edge, and the exposeRect is further right 1538 // than the visibleRect, and not bigger than the visible area, then align with the right. 1539 if (scrollX == alignToClosestEdge && exposeRect.maxX() > visibleRect.maxX() && exposeRect.width() < visibleRect.width()) 1540 scrollX = alignRight; 1541 1542 // Given the X behavior, compute the X coordinate. 1543 int x; 1544 if (scrollX == noScroll) 1545 x = visibleRect.x(); 1546 else if (scrollX == alignRight) 1547 x = exposeRect.maxX() - visibleRect.width(); 1548 else if (scrollX == alignCenter) 1549 x = exposeRect.x() + (exposeRect.width() - visibleRect.width()) / 2; 1550 else 1551 x = exposeRect.x(); 1552 1553 // Determine the appropriate Y behavior. 1554 ScrollBehavior scrollY; 1555 IntRect exposeRectY(visibleRect.x(), exposeRect.y(), visibleRect.width(), exposeRect.height()); 1556 int intersectHeight = intersection(visibleRect, exposeRectY).height(); 1557 if (intersectHeight == exposeRect.height()) 1558 // If the rectangle is fully visible, use the specified visible behavior. 1559 scrollY = ScrollAlignment::getVisibleBehavior(alignY); 1560 else if (intersectHeight == visibleRect.height()) { 1561 // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work. 1562 scrollY = ScrollAlignment::getVisibleBehavior(alignY); 1563 if (scrollY == alignCenter) 1564 scrollY = noScroll; 1565 } else if (intersectHeight > 0) 1566 // If the rectangle is partially visible, use the specified partial behavior 1567 scrollY = ScrollAlignment::getPartialBehavior(alignY); 1568 else 1569 scrollY = ScrollAlignment::getHiddenBehavior(alignY); 1570 // If we're trying to align to the closest edge, and the exposeRect is further down 1571 // than the visibleRect, and not bigger than the visible area, then align with the bottom. 1572 if (scrollY == alignToClosestEdge && exposeRect.maxY() > visibleRect.maxY() && exposeRect.height() < visibleRect.height()) 1573 scrollY = alignBottom; 1574 1575 // Given the Y behavior, compute the Y coordinate. 1576 int y; 1577 if (scrollY == noScroll) 1578 y = visibleRect.y(); 1579 else if (scrollY == alignBottom) 1580 y = exposeRect.maxY() - visibleRect.height(); 1581 else if (scrollY == alignCenter) 1582 y = exposeRect.y() + (exposeRect.height() - visibleRect.height()) / 2; 1583 else 1584 y = exposeRect.y(); 1585 1586 return IntRect(IntPoint(x, y), visibleRect.size()); 1587 } 1588 1589 void RenderLayer::autoscroll() 1590 { 1591 Frame* frame = renderer()->frame(); 1592 if (!frame) 1593 return; 1594 1595 FrameView* frameView = frame->view(); 1596 if (!frameView) 1597 return; 1598 1599 #if ENABLE(DRAG_SUPPORT) 1600 frame->eventHandler()->updateSelectionForMouseDrag(); 1601 #endif 1602 1603 IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->currentMousePosition()); 1604 scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); 1605 } 1606 1607 void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset) 1608 { 1609 // FIXME: This should be possible on generated content but is not right now. 1610 if (!inResizeMode() || !renderer()->hasOverflowClip() || !renderer()->node()) 1611 return; 1612 1613 // Set the width and height of the shadow ancestor node if there is one. 1614 // This is necessary for textarea elements since the resizable layer is in the shadow content. 1615 Element* element = static_cast<Element*>(renderer()->node()->shadowAncestorNode()); 1616 RenderBox* renderer = toRenderBox(element->renderer()); 1617 1618 EResize resize = renderer->style()->resize(); 1619 if (resize == RESIZE_NONE) 1620 return; 1621 1622 Document* document = element->document(); 1623 if (!document->frame()->eventHandler()->mousePressed()) 1624 return; 1625 1626 float zoomFactor = renderer->style()->effectiveZoom(); 1627 1628 IntSize newOffset = offsetFromResizeCorner(document->view()->windowToContents(evt.pos())); 1629 newOffset.setWidth(newOffset.width() / zoomFactor); 1630 newOffset.setHeight(newOffset.height() / zoomFactor); 1631 1632 IntSize currentSize = IntSize(renderer->width() / zoomFactor, renderer->height() / zoomFactor); 1633 IntSize minimumSize = element->minimumSizeForResizing().shrunkTo(currentSize); 1634 element->setMinimumSizeForResizing(minimumSize); 1635 1636 IntSize adjustedOldOffset = IntSize(oldOffset.width() / zoomFactor, oldOffset.height() / zoomFactor); 1637 1638 IntSize difference = (currentSize + newOffset - adjustedOldOffset).expandedTo(minimumSize) - currentSize; 1639 1640 CSSStyleDeclaration* style = element->style(); 1641 bool isBoxSizingBorder = renderer->style()->boxSizing() == BORDER_BOX; 1642 1643 ExceptionCode ec; 1644 1645 if (resize != RESIZE_VERTICAL && difference.width()) { 1646 if (element->isFormControlElement()) { 1647 // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>). 1648 style->setProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false, ec); 1649 style->setProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false, ec); 1650 } 1651 int baseWidth = renderer->width() - (isBoxSizingBorder ? 0 : renderer->borderAndPaddingWidth()); 1652 baseWidth = baseWidth / zoomFactor; 1653 style->setProperty(CSSPropertyWidth, String::number(baseWidth + difference.width()) + "px", false, ec); 1654 } 1655 1656 if (resize != RESIZE_HORIZONTAL && difference.height()) { 1657 if (element->isFormControlElement()) { 1658 // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>). 1659 style->setProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false, ec); 1660 style->setProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false, ec); 1661 } 1662 int baseHeight = renderer->height() - (isBoxSizingBorder ? 0 : renderer->borderAndPaddingHeight()); 1663 baseHeight = baseHeight / zoomFactor; 1664 style->setProperty(CSSPropertyHeight, String::number(baseHeight + difference.height()) + "px", false, ec); 1665 } 1666 1667 document->updateLayout(); 1668 1669 // FIXME (Radar 4118564): We should also autoscroll the window as necessary to keep the point under the cursor in view. 1670 } 1671 1672 int RenderLayer::scrollSize(ScrollbarOrientation orientation) const 1673 { 1674 Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_hBar : m_vBar).get(); 1675 return scrollbar ? (scrollbar->totalSize() - scrollbar->visibleSize()) : 0; 1676 } 1677 1678 void RenderLayer::setScrollOffset(const IntPoint& offset) 1679 { 1680 scrollTo(offset.x(), offset.y()); 1681 } 1682 1683 int RenderLayer::scrollPosition(Scrollbar* scrollbar) const 1684 { 1685 if (scrollbar->orientation() == HorizontalScrollbar) 1686 return scrollXOffset(); 1687 if (scrollbar->orientation() == VerticalScrollbar) 1688 return scrollYOffset(); 1689 return 0; 1690 } 1691 1692 bool RenderLayer::isActive() const 1693 { 1694 Page* page = renderer()->frame()->page(); 1695 return page && page->focusController()->isActive(); 1696 } 1697 1698 static IntRect cornerRect(const RenderLayer* layer, const IntRect& bounds) 1699 { 1700 int horizontalThickness; 1701 int verticalThickness; 1702 if (!layer->verticalScrollbar() && !layer->horizontalScrollbar()) { 1703 // FIXME: This isn't right. We need to know the thickness of custom scrollbars 1704 // even when they don't exist in order to set the resizer square size properly. 1705 horizontalThickness = ScrollbarTheme::nativeTheme()->scrollbarThickness(); 1706 verticalThickness = horizontalThickness; 1707 } else if (layer->verticalScrollbar() && !layer->horizontalScrollbar()) { 1708 horizontalThickness = layer->verticalScrollbar()->width(); 1709 verticalThickness = horizontalThickness; 1710 } else if (layer->horizontalScrollbar() && !layer->verticalScrollbar()) { 1711 verticalThickness = layer->horizontalScrollbar()->height(); 1712 horizontalThickness = verticalThickness; 1713 } else { 1714 horizontalThickness = layer->verticalScrollbar()->width(); 1715 verticalThickness = layer->horizontalScrollbar()->height(); 1716 } 1717 return IntRect(bounds.maxX() - horizontalThickness - layer->renderer()->style()->borderRightWidth(), 1718 bounds.maxY() - verticalThickness - layer->renderer()->style()->borderBottomWidth(), 1719 horizontalThickness, verticalThickness); 1720 } 1721 1722 IntRect RenderLayer::scrollCornerRect() const 1723 { 1724 // We have a scrollbar corner when a scrollbar is visible and not filling the entire length of the box. 1725 // This happens when: 1726 // (a) A resizer is present and at least one scrollbar is present 1727 // (b) Both scrollbars are present. 1728 bool hasHorizontalBar = horizontalScrollbar(); 1729 bool hasVerticalBar = verticalScrollbar(); 1730 bool hasResizer = renderer()->style()->resize() != RESIZE_NONE; 1731 if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar || hasVerticalBar))) 1732 return cornerRect(this, renderBox()->borderBoxRect()); 1733 return IntRect(); 1734 } 1735 1736 static IntRect resizerCornerRect(const RenderLayer* layer, const IntRect& bounds) 1737 { 1738 ASSERT(layer->renderer()->isBox()); 1739 if (layer->renderer()->style()->resize() == RESIZE_NONE) 1740 return IntRect(); 1741 return cornerRect(layer, bounds); 1742 } 1743 1744 IntRect RenderLayer::scrollCornerAndResizerRect() const 1745 { 1746 RenderBox* box = renderBox(); 1747 if (!box) 1748 return IntRect(); 1749 IntRect scrollCornerAndResizer = scrollCornerRect(); 1750 if (scrollCornerAndResizer.isEmpty()) 1751 scrollCornerAndResizer = resizerCornerRect(this, box->borderBoxRect()); 1752 return scrollCornerAndResizer; 1753 } 1754 1755 bool RenderLayer::isScrollCornerVisible() const 1756 { 1757 ASSERT(renderer()->isBox()); 1758 return !scrollCornerRect().isEmpty(); 1759 } 1760 1761 IntRect RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const 1762 { 1763 RenderView* view = renderer()->view(); 1764 if (!view) 1765 return scrollbarRect; 1766 1767 IntRect rect = scrollbarRect; 1768 rect.move(scrollbarOffset(scrollbar)); 1769 1770 return view->frameView()->convertFromRenderer(renderer(), rect); 1771 } 1772 1773 IntRect RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const 1774 { 1775 RenderView* view = renderer()->view(); 1776 if (!view) 1777 return parentRect; 1778 1779 IntRect rect = view->frameView()->convertToRenderer(renderer(), parentRect); 1780 rect.move(-scrollbarOffset(scrollbar)); 1781 return rect; 1782 } 1783 1784 IntPoint RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const 1785 { 1786 RenderView* view = renderer()->view(); 1787 if (!view) 1788 return scrollbarPoint; 1789 1790 IntPoint point = scrollbarPoint; 1791 point.move(scrollbarOffset(scrollbar)); 1792 return view->frameView()->convertFromRenderer(renderer(), point); 1793 } 1794 1795 IntPoint RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const 1796 { 1797 RenderView* view = renderer()->view(); 1798 if (!view) 1799 return parentPoint; 1800 1801 IntPoint point = view->frameView()->convertToRenderer(renderer(), parentPoint); 1802 1803 point.move(-scrollbarOffset(scrollbar)); 1804 return point; 1805 } 1806 1807 IntSize RenderLayer::contentsSize() const 1808 { 1809 return IntSize(const_cast<RenderLayer*>(this)->scrollWidth(), const_cast<RenderLayer*>(this)->scrollHeight()); 1810 } 1811 1812 int RenderLayer::visibleHeight() const 1813 { 1814 return m_height; 1815 } 1816 1817 int RenderLayer::visibleWidth() const 1818 { 1819 return m_width; 1820 } 1821 1822 bool RenderLayer::shouldSuspendScrollAnimations() const 1823 { 1824 RenderView* view = renderer()->view(); 1825 if (!view) 1826 return true; 1827 return view->frameView()->shouldSuspendScrollAnimations(); 1828 } 1829 1830 IntPoint RenderLayer::currentMousePosition() const 1831 { 1832 return renderer()->frame() ? renderer()->frame()->eventHandler()->currentMousePosition() : IntPoint(); 1833 } 1834 1835 IntSize RenderLayer::scrollbarOffset(const Scrollbar* scrollbar) const 1836 { 1837 RenderBox* box = renderBox(); 1838 1839 if (scrollbar == m_vBar.get()) 1840 return IntSize(box->width() - box->borderRight() - scrollbar->width(), box->borderTop()); 1841 1842 if (scrollbar == m_hBar.get()) 1843 return IntSize(box->borderLeft(), box->height() - box->borderBottom() - scrollbar->height()); 1844 1845 ASSERT_NOT_REACHED(); 1846 return IntSize(); 1847 } 1848 1849 void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect) 1850 { 1851 #if USE(ACCELERATED_COMPOSITING) 1852 if (scrollbar == m_vBar.get()) { 1853 if (GraphicsLayer* layer = layerForVerticalScrollbar()) { 1854 layer->setNeedsDisplayInRect(rect); 1855 return; 1856 } 1857 } else { 1858 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) { 1859 layer->setNeedsDisplayInRect(rect); 1860 return; 1861 } 1862 } 1863 #endif 1864 IntRect scrollRect = rect; 1865 RenderBox* box = renderBox(); 1866 ASSERT(box); 1867 if (scrollbar == m_vBar.get()) 1868 scrollRect.move(box->width() - box->borderRight() - scrollbar->width(), box->borderTop()); 1869 else 1870 scrollRect.move(box->borderLeft(), box->height() - box->borderBottom() - scrollbar->height()); 1871 renderer()->repaintRectangle(scrollRect); 1872 } 1873 1874 void RenderLayer::invalidateScrollCornerRect(const IntRect& rect) 1875 { 1876 #if USE(ACCELERATED_COMPOSITING) 1877 if (GraphicsLayer* layer = layerForScrollCorner()) { 1878 layer->setNeedsDisplayInRect(rect); 1879 return; 1880 } 1881 #endif 1882 if (m_scrollCorner) 1883 m_scrollCorner->repaintRectangle(rect); 1884 if (m_resizer) 1885 m_resizer->repaintRectangle(rect); 1886 } 1887 1888 PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientation) 1889 { 1890 RefPtr<Scrollbar> widget; 1891 RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer(); 1892 bool hasCustomScrollbarStyle = actualRenderer->isBox() && actualRenderer->style()->hasPseudoStyle(SCROLLBAR); 1893 if (hasCustomScrollbarStyle) 1894 widget = RenderScrollbar::createCustomScrollbar(this, orientation, toRenderBox(actualRenderer)); 1895 else { 1896 widget = Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar); 1897 if (orientation == HorizontalScrollbar) 1898 didAddHorizontalScrollbar(widget.get()); 1899 else 1900 didAddVerticalScrollbar(widget.get()); 1901 } 1902 renderer()->document()->view()->addChild(widget.get()); 1903 return widget.release(); 1904 } 1905 1906 void RenderLayer::destroyScrollbar(ScrollbarOrientation orientation) 1907 { 1908 RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar; 1909 if (scrollbar) { 1910 if (scrollbar->isCustomScrollbar()) 1911 static_cast<RenderScrollbar*>(scrollbar.get())->clearOwningRenderer(); 1912 else { 1913 if (orientation == HorizontalScrollbar) 1914 willRemoveHorizontalScrollbar(scrollbar.get()); 1915 else 1916 willRemoveVerticalScrollbar(scrollbar.get()); 1917 } 1918 1919 scrollbar->removeFromParent(); 1920 scrollbar->disconnectFromScrollableArea(); 1921 scrollbar = 0; 1922 } 1923 } 1924 1925 void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar) 1926 { 1927 if (hasScrollbar == (m_hBar != 0)) 1928 return; 1929 1930 if (hasScrollbar) 1931 m_hBar = createScrollbar(HorizontalScrollbar); 1932 else 1933 destroyScrollbar(HorizontalScrollbar); 1934 1935 // Destroying or creating one bar can cause our scrollbar corner to come and go. We need to update the opposite scrollbar's style. 1936 if (m_hBar) 1937 m_hBar->styleChanged(); 1938 if (m_vBar) 1939 m_vBar->styleChanged(); 1940 1941 #if ENABLE(DASHBOARD_SUPPORT) 1942 // Force an update since we know the scrollbars have changed things. 1943 if (renderer()->document()->hasDashboardRegions()) 1944 renderer()->document()->setDashboardRegionsDirty(true); 1945 #endif 1946 } 1947 1948 void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar) 1949 { 1950 if (hasScrollbar == (m_vBar != 0)) 1951 return; 1952 1953 if (hasScrollbar) 1954 m_vBar = createScrollbar(VerticalScrollbar); 1955 else 1956 destroyScrollbar(VerticalScrollbar); 1957 1958 // Destroying or creating one bar can cause our scrollbar corner to come and go. We need to update the opposite scrollbar's style. 1959 if (m_hBar) 1960 m_hBar->styleChanged(); 1961 if (m_vBar) 1962 m_vBar->styleChanged(); 1963 1964 #if ENABLE(DASHBOARD_SUPPORT) 1965 // Force an update since we know the scrollbars have changed things. 1966 if (renderer()->document()->hasDashboardRegions()) 1967 renderer()->document()->setDashboardRegionsDirty(true); 1968 #endif 1969 } 1970 1971 int RenderLayer::verticalScrollbarWidth(OverlayScrollbarSizeRelevancy relevancy) const 1972 { 1973 if (!m_vBar || (m_vBar->isOverlayScrollbar() && relevancy == IgnoreOverlayScrollbarSize)) 1974 return 0; 1975 return m_vBar->width(); 1976 } 1977 1978 int RenderLayer::horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevancy) const 1979 { 1980 if (!m_hBar || (m_hBar->isOverlayScrollbar() && relevancy == IgnoreOverlayScrollbarSize)) 1981 return 0; 1982 return m_hBar->height(); 1983 } 1984 1985 IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& absolutePoint) const 1986 { 1987 // Currently the resize corner is always the bottom right corner 1988 IntPoint bottomRight(width(), height()); 1989 IntPoint localPoint = absoluteToContents(absolutePoint); 1990 return localPoint - bottomRight; 1991 } 1992 1993 bool RenderLayer::hasOverflowControls() const 1994 { 1995 return m_hBar || m_vBar || m_scrollCorner || renderer()->style()->resize() != RESIZE_NONE; 1996 } 1997 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 1998 bool RenderLayer::hasOverflowParent() const 1999 { 2000 const RenderLayer* layer = this; 2001 while (layer && !layer->hasOverflowScroll()) 2002 layer = layer->parent(); 2003 return layer; 2004 } 2005 #endif 2006 2007 void RenderLayer::positionOverflowControls(int tx, int ty) 2008 { 2009 if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE)) 2010 return; 2011 2012 RenderBox* box = renderBox(); 2013 if (!box) 2014 return; 2015 2016 const IntRect& borderBox = box->borderBoxRect(); 2017 const IntRect& scrollCorner = scrollCornerRect(); 2018 IntRect absBounds(borderBox.x() + tx, borderBox.y() + ty, borderBox.width(), borderBox.height()); 2019 if (m_vBar) 2020 m_vBar->setFrameRect(IntRect(absBounds.maxX() - box->borderRight() - m_vBar->width(), 2021 absBounds.y() + box->borderTop(), 2022 m_vBar->width(), 2023 absBounds.height() - (box->borderTop() + box->borderBottom()) - scrollCorner.height())); 2024 2025 if (m_hBar) 2026 m_hBar->setFrameRect(IntRect(absBounds.x() + box->borderLeft(), 2027 absBounds.maxY() - box->borderBottom() - m_hBar->height(), 2028 absBounds.width() - (box->borderLeft() + box->borderRight()) - scrollCorner.width(), 2029 m_hBar->height())); 2030 2031 #if USE(ACCELERATED_COMPOSITING) 2032 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) { 2033 if (m_hBar) { 2034 layer->setPosition(IntPoint(m_hBar->frameRect().x() - tx, m_hBar->frameRect().y() - ty)); 2035 layer->setSize(m_hBar->frameRect().size()); 2036 } 2037 layer->setDrawsContent(m_hBar); 2038 } 2039 if (GraphicsLayer* layer = layerForVerticalScrollbar()) { 2040 if (m_vBar) { 2041 layer->setPosition(IntPoint(m_vBar->frameRect().x() - tx, m_vBar->frameRect().y() - ty)); 2042 layer->setSize(m_vBar->frameRect().size()); 2043 } 2044 layer->setDrawsContent(m_vBar); 2045 } 2046 2047 if (GraphicsLayer* layer = layerForScrollCorner()) { 2048 const IntRect& scrollCornerAndResizer = scrollCornerAndResizerRect(); 2049 layer->setPosition(scrollCornerAndResizer.location()); 2050 layer->setSize(scrollCornerAndResizer.size()); 2051 layer->setDrawsContent(!scrollCornerAndResizer.isEmpty()); 2052 } 2053 #endif 2054 2055 if (m_scrollCorner) 2056 m_scrollCorner->setFrameRect(scrollCorner); 2057 if (m_resizer) 2058 m_resizer->setFrameRect(resizerCornerRect(this, borderBox)); 2059 } 2060 2061 #if PLATFORM(ANDROID) 2062 // When width/height change, the scrollWidth/scrollHeight should be dirty. 2063 // And this should be upstreamed to webkit. 2064 void RenderLayer::setWidth(int w) 2065 { 2066 if (m_width != w) { 2067 m_scrollDimensionsDirty = true; 2068 m_width = w; 2069 } 2070 } 2071 2072 void RenderLayer::setHeight(int h) 2073 { 2074 if (m_height != h) { 2075 m_scrollDimensionsDirty = true; 2076 m_height = h; 2077 } 2078 } 2079 #endif 2080 2081 int RenderLayer::scrollWidth() 2082 { 2083 if (m_scrollDimensionsDirty) 2084 computeScrollDimensions(); 2085 return m_scrollWidth; 2086 } 2087 2088 int RenderLayer::scrollHeight() 2089 { 2090 if (m_scrollDimensionsDirty) 2091 computeScrollDimensions(); 2092 return m_scrollHeight; 2093 } 2094 2095 int RenderLayer::overflowTop() const 2096 { 2097 RenderBox* box = renderBox(); 2098 IntRect overflowRect(box->layoutOverflowRect()); 2099 box->flipForWritingMode(overflowRect); 2100 return overflowRect.y(); 2101 } 2102 2103 int RenderLayer::overflowBottom() const 2104 { 2105 RenderBox* box = renderBox(); 2106 IntRect overflowRect(box->layoutOverflowRect()); 2107 box->flipForWritingMode(overflowRect); 2108 return overflowRect.maxY(); 2109 } 2110 2111 int RenderLayer::overflowLeft() const 2112 { 2113 RenderBox* box = renderBox(); 2114 IntRect overflowRect(box->layoutOverflowRect()); 2115 box->flipForWritingMode(overflowRect); 2116 return overflowRect.x(); 2117 } 2118 2119 int RenderLayer::overflowRight() const 2120 { 2121 RenderBox* box = renderBox(); 2122 IntRect overflowRect(box->layoutOverflowRect()); 2123 box->flipForWritingMode(overflowRect); 2124 return overflowRect.maxX(); 2125 } 2126 2127 void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar) 2128 { 2129 RenderBox* box = renderBox(); 2130 ASSERT(box); 2131 2132 m_scrollDimensionsDirty = false; 2133 2134 m_scrollLeftOverflow = overflowLeft() - box->borderLeft(); 2135 m_scrollTopOverflow = overflowTop() - box->borderTop(); 2136 2137 m_scrollWidth = overflowRight() - overflowLeft(); 2138 m_scrollHeight = overflowBottom() - overflowTop(); 2139 2140 m_scrollOrigin = IntPoint(-m_scrollLeftOverflow, -m_scrollTopOverflow); 2141 2142 if (needHBar) 2143 *needHBar = m_scrollWidth > box->clientWidth(); 2144 if (needVBar) 2145 *needVBar = m_scrollHeight > box->clientHeight(); 2146 } 2147 2148 void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow) 2149 { 2150 if (m_overflowStatusDirty) { 2151 m_horizontalOverflow = horizontalOverflow; 2152 m_verticalOverflow = verticalOverflow; 2153 m_overflowStatusDirty = false; 2154 return; 2155 } 2156 2157 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow); 2158 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow); 2159 2160 if (horizontalOverflowChanged || verticalOverflowChanged) { 2161 m_horizontalOverflow = horizontalOverflow; 2162 m_verticalOverflow = verticalOverflow; 2163 2164 if (FrameView* frameView = renderer()->document()->view()) { 2165 frameView->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow), 2166 renderer()->node()); 2167 } 2168 } 2169 } 2170 2171 void RenderLayer::updateScrollInfoAfterLayout() 2172 { 2173 RenderBox* box = renderBox(); 2174 if (!box) 2175 return; 2176 2177 m_scrollDimensionsDirty = true; 2178 2179 bool horizontalOverflow, verticalOverflow; 2180 computeScrollDimensions(&horizontalOverflow, &verticalOverflow); 2181 2182 if (box->style()->overflowX() != OMARQUEE) { 2183 // Layout may cause us to be in an invalid scroll position. In this case we need 2184 // to pull our scroll offsets back to the max (or push them up to the min). 2185 int newX = max(0, min(scrollXOffset(), scrollWidth() - box->clientWidth())); 2186 int newY = max(0, min(scrollYOffset(), scrollHeight() - box->clientHeight())); 2187 if (newX != scrollXOffset() || newY != scrollYOffset()) { 2188 RenderView* view = renderer()->view(); 2189 ASSERT(view); 2190 // scrollToOffset() may call updateLayerPositions(), which doesn't work 2191 // with LayoutState. 2192 // FIXME: Remove the disableLayoutState/enableLayoutState if the above changes. 2193 if (view) 2194 view->disableLayoutState(); 2195 scrollToOffset(newX, newY); 2196 if (view) 2197 view->enableLayoutState(); 2198 } 2199 } 2200 2201 bool haveHorizontalBar = m_hBar; 2202 bool haveVerticalBar = m_vBar; 2203 2204 // overflow:scroll should just enable/disable. 2205 if (renderer()->style()->overflowX() == OSCROLL) 2206 m_hBar->setEnabled(horizontalOverflow); 2207 if (renderer()->style()->overflowY() == OSCROLL) 2208 m_vBar->setEnabled(verticalOverflow); 2209 2210 // A dynamic change from a scrolling overflow to overflow:hidden means we need to get rid of any 2211 // scrollbars that may be present. 2212 if (renderer()->style()->overflowX() == OHIDDEN && haveHorizontalBar) 2213 setHasHorizontalScrollbar(false); 2214 if (renderer()->style()->overflowY() == OHIDDEN && haveVerticalBar) 2215 setHasVerticalScrollbar(false); 2216 2217 // overflow:auto may need to lay out again if scrollbars got added/removed. 2218 bool scrollbarsChanged = (box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow) || 2219 (box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow); 2220 if (scrollbarsChanged) { 2221 if (box->hasAutoHorizontalScrollbar()) 2222 setHasHorizontalScrollbar(horizontalOverflow); 2223 if (box->hasAutoVerticalScrollbar()) 2224 setHasVerticalScrollbar(verticalOverflow); 2225 2226 #if ENABLE(DASHBOARD_SUPPORT) 2227 // Force an update since we know the scrollbars have changed things. 2228 if (renderer()->document()->hasDashboardRegions()) 2229 renderer()->document()->setDashboardRegionsDirty(true); 2230 #endif 2231 2232 renderer()->repaint(); 2233 2234 if (renderer()->style()->overflowX() == OAUTO || renderer()->style()->overflowY() == OAUTO) { 2235 if (!m_inOverflowRelayout) { 2236 // Our proprietary overflow: overlay value doesn't trigger a layout. 2237 m_inOverflowRelayout = true; 2238 renderer()->setNeedsLayout(true, false); 2239 if (renderer()->isRenderBlock()) { 2240 RenderBlock* block = toRenderBlock(renderer()); 2241 block->scrollbarsChanged(box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow, 2242 box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow); 2243 block->layoutBlock(true); 2244 } else 2245 renderer()->layout(); 2246 m_inOverflowRelayout = false; 2247 } 2248 } 2249 } 2250 2251 // If overflow:scroll is turned into overflow:auto a bar might still be disabled (Bug 11985). 2252 if (m_hBar && box->hasAutoHorizontalScrollbar()) 2253 m_hBar->setEnabled(true); 2254 if (m_vBar && box->hasAutoVerticalScrollbar()) 2255 m_vBar->setEnabled(true); 2256 2257 // Set up the range (and page step/line step). 2258 if (m_hBar) { 2259 int clientWidth = box->clientWidth(); 2260 int pageStep = max(max<int>(clientWidth * Scrollbar::minFractionToStepWhenPaging(), clientWidth - Scrollbar::maxOverlapBetweenPages()), 1); 2261 m_hBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep); 2262 m_hBar->setProportion(clientWidth, m_scrollWidth); 2263 } 2264 if (m_vBar) { 2265 int clientHeight = box->clientHeight(); 2266 int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1); 2267 m_vBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep); 2268 m_vBar->setProportion(clientHeight, m_scrollHeight); 2269 } 2270 2271 RenderView* view = renderer()->view(); 2272 view->disableLayoutState(); 2273 scrollToOffset(scrollXOffset(), scrollYOffset()); 2274 view->enableLayoutState(); 2275 2276 if (renderer()->node() && renderer()->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER)) 2277 updateOverflowStatus(horizontalOverflow, verticalOverflow); 2278 2279 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 2280 bool hasOverflowScroll = ((horizontalOverflow && m_hBar) || (verticalOverflow && m_vBar)); 2281 if (hasOverflowScroll) { 2282 // Disable UI side scrolling for non-readonly textareas. 2283 if (renderer()->isTextArea() && (!renderer()->node() 2284 || !static_cast<HTMLTextAreaElement*>(renderer()->node())->readOnly())) 2285 hasOverflowScroll = false; 2286 } 2287 if (hasOverflowScroll != m_hasOverflowScroll) { 2288 m_hasOverflowScroll = hasOverflowScroll; 2289 dirtyZOrderLists(); 2290 dirtyStackingContextZOrderLists(); 2291 if (renderer()->node()) 2292 renderer()->node()->setNeedsStyleRecalc(SyntheticStyleChange); 2293 } 2294 #endif 2295 } 2296 2297 void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty, const IntRect& damageRect, bool paintingOverlayControls) 2298 { 2299 // Don't do anything if we have no overflow. 2300 if (!renderer()->hasOverflowClip()) 2301 return; 2302 2303 // Overlay scrollbars paint in a second pass through the layer tree so that they will paint 2304 // on top of everything else. If this is the normal painting pass, paintingOverlayControls 2305 // will be false, and we should just tell the root layer that there are overlay scrollbars 2306 // that need to be painted. That will cause the second pass through the layer tree to run, 2307 // and we'll paint the scrollbars then. In the meantime, cache tx and ty so that the 2308 // second pass doesn't need to re-enter the RenderTree to get it right. 2309 if (hasOverlayScrollbars() && !paintingOverlayControls) { 2310 RenderView* renderView = renderer()->view(); 2311 renderView->layer()->setContainsDirtyOverlayScrollbars(true); 2312 m_cachedOverlayScrollbarOffset = IntPoint(tx, ty); 2313 renderView->frameView()->setContainsScrollableAreaWithOverlayScrollbars(true); 2314 return; 2315 } 2316 2317 int offsetX = tx; 2318 int offsetY = ty; 2319 if (paintingOverlayControls) { 2320 offsetX = m_cachedOverlayScrollbarOffset.x(); 2321 offsetY = m_cachedOverlayScrollbarOffset.y(); 2322 } 2323 2324 // Move the scrollbar widgets if necessary. We normally move and resize widgets during layout, but sometimes 2325 // widgets can move without layout occurring (most notably when you scroll a document that 2326 // contains fixed positioned elements). 2327 positionOverflowControls(offsetX, offsetY); 2328 2329 // Now that we're sure the scrollbars are in the right place, paint them. 2330 if (m_hBar 2331 #if USE(ACCELERATED_COMPOSITING) 2332 && !layerForHorizontalScrollbar() 2333 #endif 2334 ) 2335 m_hBar->paint(context, damageRect); 2336 if (m_vBar 2337 #if USE(ACCELERATED_COMPOSITING) 2338 && !layerForVerticalScrollbar() 2339 #endif 2340 ) 2341 m_vBar->paint(context, damageRect); 2342 2343 #if USE(ACCELERATED_COMPOSITING) 2344 if (layerForScrollCorner()) 2345 return; 2346 #endif 2347 2348 // We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the 2349 // edge of the box. 2350 paintScrollCorner(context, offsetX, offsetY, damageRect); 2351 2352 // Paint our resizer last, since it sits on top of the scroll corner. 2353 paintResizer(context, offsetX, offsetY, damageRect); 2354 } 2355 2356 void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, const IntRect& damageRect) 2357 { 2358 RenderBox* box = renderBox(); 2359 ASSERT(box); 2360 2361 IntRect cornerRect = scrollCornerRect(); 2362 IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height()); 2363 if (!absRect.intersects(damageRect)) 2364 return; 2365 2366 if (context->updatingControlTints()) { 2367 updateScrollCornerStyle(); 2368 return; 2369 } 2370 2371 if (m_scrollCorner) { 2372 m_scrollCorner->paintIntoRect(context, tx, ty, absRect); 2373 return; 2374 } 2375 2376 // We don't want to paint white if we have overlay scrollbars, since we need 2377 // to see what is behind it. 2378 if (!hasOverlayScrollbars()) 2379 context->fillRect(absRect, Color::white, box->style()->colorSpace()); 2380 } 2381 2382 void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const IntRect& damageRect) 2383 { 2384 if (renderer()->style()->resize() == RESIZE_NONE) 2385 return; 2386 2387 RenderBox* box = renderBox(); 2388 ASSERT(box); 2389 2390 IntRect cornerRect = resizerCornerRect(this, box->borderBoxRect()); 2391 IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height()); 2392 if (!absRect.intersects(damageRect)) 2393 return; 2394 2395 if (context->updatingControlTints()) { 2396 updateResizerStyle(); 2397 return; 2398 } 2399 2400 if (m_resizer) { 2401 m_resizer->paintIntoRect(context, tx, ty, absRect); 2402 return; 2403 } 2404 2405 // Paint the resizer control. 2406 DEFINE_STATIC_LOCAL(RefPtr<Image>, resizeCornerImage, (Image::loadPlatformResource("textAreaResizeCorner"))); 2407 IntPoint imagePoint(absRect.maxX() - resizeCornerImage->width(), absRect.maxY() - resizeCornerImage->height()); 2408 context->drawImage(resizeCornerImage.get(), box->style()->colorSpace(), imagePoint); 2409 2410 // Draw a frame around the resizer (1px grey line) if there are any scrollbars present. 2411 // Clipping will exclude the right and bottom edges of this frame. 2412 if (!hasOverlayScrollbars() && (m_vBar || m_hBar)) { 2413 context->save(); 2414 context->clip(absRect); 2415 IntRect largerCorner = absRect; 2416 largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.height() + 1)); 2417 context->setStrokeColor(Color(makeRGB(217, 217, 217)), ColorSpaceDeviceRGB); 2418 context->setStrokeThickness(1.0f); 2419 context->setFillColor(Color::transparent, ColorSpaceDeviceRGB); 2420 context->drawRect(largerCorner); 2421 context->restore(); 2422 } 2423 } 2424 2425 bool RenderLayer::isPointInResizeControl(const IntPoint& absolutePoint) const 2426 { 2427 if (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE) 2428 return false; 2429 2430 RenderBox* box = renderBox(); 2431 ASSERT(box); 2432 2433 IntPoint localPoint = absoluteToContents(absolutePoint); 2434 2435 IntRect localBounds(0, 0, box->width(), box->height()); 2436 return resizerCornerRect(this, localBounds).contains(localPoint); 2437 } 2438 2439 bool RenderLayer::hitTestOverflowControls(HitTestResult& result, const IntPoint& localPoint) 2440 { 2441 if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE)) 2442 return false; 2443 2444 RenderBox* box = renderBox(); 2445 ASSERT(box); 2446 2447 IntRect resizeControlRect; 2448 if (renderer()->style()->resize() != RESIZE_NONE) { 2449 resizeControlRect = resizerCornerRect(this, box->borderBoxRect()); 2450 if (resizeControlRect.contains(localPoint)) 2451 return true; 2452 } 2453 2454 int resizeControlSize = max(resizeControlRect.height(), 0); 2455 2456 if (m_vBar) { 2457 IntRect vBarRect(box->width() - box->borderRight() - m_vBar->width(), 2458 box->borderTop(), 2459 m_vBar->width(), 2460 box->height() - (box->borderTop() + box->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize)); 2461 if (vBarRect.contains(localPoint)) { 2462 result.setScrollbar(m_vBar.get()); 2463 return true; 2464 } 2465 } 2466 2467 resizeControlSize = max(resizeControlRect.width(), 0); 2468 if (m_hBar) { 2469 IntRect hBarRect(box->borderLeft(), 2470 box->height() - box->borderBottom() - m_hBar->height(), 2471 box->width() - (box->borderLeft() + box->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize), 2472 m_hBar->height()); 2473 if (hBarRect.contains(localPoint)) { 2474 result.setScrollbar(m_hBar.get()); 2475 return true; 2476 } 2477 } 2478 2479 return false; 2480 } 2481 2482 bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier) 2483 { 2484 return ScrollableArea::scroll(direction, granularity, multiplier); 2485 } 2486 2487 void RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintBehavior paintBehavior, RenderObject *paintingRoot) 2488 { 2489 OverlapTestRequestMap overlapTestRequests; 2490 paintLayer(this, p, damageRect, paintBehavior, paintingRoot, &overlapTestRequests); 2491 OverlapTestRequestMap::iterator end = overlapTestRequests.end(); 2492 for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) 2493 it->first->setOverlapTestResult(false); 2494 } 2495 2496 void RenderLayer::paintOverlayScrollbars(GraphicsContext* p, const IntRect& damageRect, PaintBehavior paintBehavior, RenderObject *paintingRoot) 2497 { 2498 if (!m_containsDirtyOverlayScrollbars) 2499 return; 2500 paintLayer(this, p, damageRect, paintBehavior, paintingRoot, 0, PaintLayerHaveTransparency | PaintLayerTemporaryClipRects 2501 | PaintLayerPaintingOverlayScrollbars); 2502 m_containsDirtyOverlayScrollbars = false; 2503 } 2504 2505 static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect) 2506 { 2507 if (paintDirtyRect == clipRect) 2508 return; 2509 p->save(); 2510 p->clip(clipRect); 2511 } 2512 2513 static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect) 2514 { 2515 if (paintDirtyRect == clipRect) 2516 return; 2517 p->restore(); 2518 } 2519 2520 static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer) 2521 { 2522 Vector<OverlapTestRequestClient*> overlappedRequestClients; 2523 OverlapTestRequestMap::iterator end = overlapTestRequests.end(); 2524 IntRect boundingBox = layer->boundingBox(rootLayer); 2525 for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) { 2526 if (!boundingBox.intersects(it->second)) 2527 continue; 2528 2529 it->first->setOverlapTestResult(true); 2530 overlappedRequestClients.append(it->first); 2531 } 2532 for (size_t i = 0; i < overlappedRequestClients.size(); ++i) 2533 overlapTestRequests.remove(overlappedRequestClients[i]); 2534 } 2535 2536 #if USE(ACCELERATED_COMPOSITING) 2537 static bool shouldDoSoftwarePaint(const RenderLayer* layer, bool paintingReflection) 2538 { 2539 return paintingReflection && !layer->has3DTransform(); 2540 } 2541 #endif 2542 2543 void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, 2544 const IntRect& paintDirtyRect, PaintBehavior paintBehavior, 2545 RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests, 2546 PaintLayerFlags paintFlags) 2547 { 2548 #if USE(ACCELERATED_COMPOSITING) 2549 if (isComposited()) { 2550 // The updatingControlTints() painting pass goes through compositing layers, 2551 // but we need to ensure that we don't cache clip rects computed with the wrong root in this case. 2552 if (p->updatingControlTints() || (paintBehavior & PaintBehaviorFlattenCompositingLayers)) 2553 paintFlags |= PaintLayerTemporaryClipRects; 2554 else if (!backing()->paintingGoesToWindow() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) { 2555 // If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer(). 2556 return; 2557 } 2558 } 2559 #endif 2560 2561 // Avoid painting layers when stylesheets haven't loaded. This eliminates FOUC. 2562 // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document 2563 // will do a full repaint(). 2564 if (renderer()->document()->didLayoutWithPendingStylesheets() && !renderer()->isRenderView() && !renderer()->isRoot()) 2565 return; 2566 2567 // If this layer is totally invisible then there is nothing to paint. 2568 if (!renderer()->opacity()) 2569 return; 2570 2571 if (paintsWithTransparency(paintBehavior)) 2572 paintFlags |= PaintLayerHaveTransparency; 2573 2574 // Apply a transform if we have one. A reflection is considered to be a transform, since it is a flip and a translate. 2575 if (paintsWithTransform(paintBehavior) && !(paintFlags & PaintLayerAppliedTransform)) { 2576 TransformationMatrix layerTransform = renderableTransform(paintBehavior); 2577 // If the transform can't be inverted, then don't paint anything. 2578 if (!layerTransform.isInvertible()) 2579 return; 2580 2581 // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency 2582 // layer from the parent now. 2583 if (paintFlags & PaintLayerHaveTransparency) 2584 parent()->beginTransparencyLayers(p, rootLayer, paintBehavior); 2585 2586 // Make sure the parent's clip rects have been calculated. 2587 IntRect clipRect = paintDirtyRect; 2588 if (parent()) { 2589 clipRect = backgroundClipRect(rootLayer, paintFlags & PaintLayerTemporaryClipRects); 2590 clipRect.intersect(paintDirtyRect); 2591 } 2592 2593 // Push the parent coordinate space's clip. 2594 setClip(p, paintDirtyRect, clipRect); 2595 2596 // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space. 2597 // This involves subtracting out the position of the layer in our current coordinate space. 2598 int x = 0; 2599 int y = 0; 2600 convertToLayerCoords(rootLayer, x, y); 2601 TransformationMatrix transform(layerTransform); 2602 transform.translateRight(x, y); 2603 2604 // Apply the transform. 2605 p->save(); 2606 p->concatCTM(transform.toAffineTransform()); 2607 2608 // Now do a paint with the root layer shifted to be us. 2609 paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), paintBehavior, paintingRoot, overlapTestRequests, paintFlags | PaintLayerAppliedTransform); 2610 2611 p->restore(); 2612 2613 // Restore the clip. 2614 restoreClip(p, paintDirtyRect, clipRect); 2615 2616 return; 2617 } 2618 2619 PaintLayerFlags localPaintFlags = paintFlags & ~PaintLayerAppliedTransform; 2620 bool haveTransparency = localPaintFlags & PaintLayerHaveTransparency; 2621 2622 // Paint the reflection first if we have one. 2623 if (m_reflection && !m_paintingInsideReflection) { 2624 // Mark that we are now inside replica painting. 2625 m_paintingInsideReflection = true; 2626 reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags | PaintLayerPaintingReflection); 2627 m_paintingInsideReflection = false; 2628 } 2629 2630 // Calculate the clip rects we should use. 2631 IntRect layerBounds, damageRect, clipRectToApply, outlineRect; 2632 calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, localPaintFlags & PaintLayerTemporaryClipRects); 2633 int x = layerBounds.x(); 2634 int y = layerBounds.y(); 2635 int tx = x - renderBoxX(); 2636 int ty = y - renderBoxY(); 2637 2638 // Ensure our lists are up-to-date. 2639 updateCompositingAndLayerListsIfNeeded(); 2640 2641 bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText; 2642 bool selectionOnly = paintBehavior & PaintBehaviorSelectionOnly; 2643 2644 // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which 2645 // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set). 2646 // Else, our renderer tree may or may not contain the painting root, so we pass that root along 2647 // so it will be tested against as we descend through the renderers. 2648 RenderObject* paintingRootForRenderer = 0; 2649 if (paintingRoot && !renderer()->isDescendantOf(paintingRoot)) 2650 paintingRootForRenderer = paintingRoot; 2651 2652 if (overlapTestRequests && isSelfPaintingLayer()) 2653 performOverlapTests(*overlapTestRequests, rootLayer, this); 2654 2655 bool paintingOverlayScrollbars = paintFlags & PaintLayerPaintingOverlayScrollbars; 2656 2657 // We want to paint our layer, but only if we intersect the damage rect. 2658 bool shouldPaint = intersectsDamageRect(layerBounds, damageRect, rootLayer) && m_hasVisibleContent && isSelfPaintingLayer(); 2659 if (shouldPaint && !selectionOnly && !damageRect.isEmpty() && !paintingOverlayScrollbars) { 2660 // Begin transparency layers lazily now that we know we have to paint something. 2661 if (haveTransparency) 2662 beginTransparencyLayers(p, rootLayer, paintBehavior); 2663 2664 // Paint our background first, before painting any child layers. 2665 // Establish the clip used to paint our background. 2666 setClip(p, paintDirtyRect, damageRect); 2667 2668 // Paint the background. 2669 PaintInfo paintInfo(p, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0); 2670 renderer()->paint(paintInfo, tx, ty); 2671 2672 // Restore the clip. 2673 restoreClip(p, paintDirtyRect, damageRect); 2674 } 2675 2676 // Now walk the sorted list of children with negative z-indices. 2677 paintList(m_negZOrderList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); 2678 2679 // Now establish the appropriate clip and paint our child RenderObjects. 2680 if (shouldPaint && !clipRectToApply.isEmpty() && !paintingOverlayScrollbars) { 2681 // Begin transparency layers lazily now that we know we have to paint something. 2682 if (haveTransparency) 2683 beginTransparencyLayers(p, rootLayer, paintBehavior); 2684 2685 // Set up the clip used when painting our children. 2686 setClip(p, paintDirtyRect, clipRectToApply); 2687 PaintInfo paintInfo(p, clipRectToApply, 2688 selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds, 2689 forceBlackText, paintingRootForRenderer, 0); 2690 renderer()->paint(paintInfo, tx, ty); 2691 if (!selectionOnly) { 2692 paintInfo.phase = PaintPhaseFloat; 2693 renderer()->paint(paintInfo, tx, ty); 2694 paintInfo.phase = PaintPhaseForeground; 2695 paintInfo.overlapTestRequests = overlapTestRequests; 2696 renderer()->paint(paintInfo, tx, ty); 2697 paintInfo.phase = PaintPhaseChildOutlines; 2698 renderer()->paint(paintInfo, tx, ty); 2699 } 2700 2701 // Now restore our clip. 2702 restoreClip(p, paintDirtyRect, clipRectToApply); 2703 } 2704 2705 if (!outlineRect.isEmpty() && isSelfPaintingLayer() && !paintingOverlayScrollbars) { 2706 // Paint our own outline 2707 PaintInfo paintInfo(p, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0); 2708 setClip(p, paintDirtyRect, outlineRect); 2709 renderer()->paint(paintInfo, tx, ty); 2710 restoreClip(p, paintDirtyRect, outlineRect); 2711 } 2712 2713 // Paint any child layers that have overflow. 2714 paintList(m_normalFlowList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); 2715 2716 // Now walk the sorted list of children with positive z-indices. 2717 paintList(m_posZOrderList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); 2718 2719 if (renderer()->hasMask() && shouldPaint && !selectionOnly && !damageRect.isEmpty() && !paintingOverlayScrollbars) { 2720 setClip(p, paintDirtyRect, damageRect); 2721 2722 // Paint the mask. 2723 PaintInfo paintInfo(p, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0); 2724 renderer()->paint(paintInfo, tx, ty); 2725 2726 // Restore the clip. 2727 restoreClip(p, paintDirtyRect, damageRect); 2728 } 2729 2730 if (paintingOverlayScrollbars) { 2731 setClip(p, paintDirtyRect, damageRect); 2732 paintOverflowControls(p, tx, ty, damageRect, true); 2733 restoreClip(p, paintDirtyRect, damageRect); 2734 } 2735 2736 // End our transparency layer 2737 if (haveTransparency && m_usedTransparency && !m_paintingInsideReflection) { 2738 p->endTransparencyLayer(); 2739 p->restore(); 2740 m_usedTransparency = false; 2741 } 2742 } 2743 2744 void RenderLayer::paintList(Vector<RenderLayer*>* list, RenderLayer* rootLayer, GraphicsContext* p, 2745 const IntRect& paintDirtyRect, PaintBehavior paintBehavior, 2746 RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests, 2747 PaintLayerFlags paintFlags) 2748 { 2749 if (!list) 2750 return; 2751 2752 for (size_t i = 0; i < list->size(); ++i) { 2753 RenderLayer* childLayer = list->at(i); 2754 if (!childLayer->isPaginated()) 2755 childLayer->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags); 2756 else 2757 paintPaginatedChildLayer(childLayer, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags); 2758 } 2759 } 2760 2761 void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context, 2762 const IntRect& paintDirtyRect, PaintBehavior paintBehavior, 2763 RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests, 2764 PaintLayerFlags paintFlags) 2765 { 2766 // We need to do multiple passes, breaking up our child layer into strips. 2767 Vector<RenderLayer*> columnLayers; 2768 RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext(); 2769 for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) { 2770 if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox())) 2771 columnLayers.append(curr); 2772 if (curr == ancestorLayer) 2773 break; 2774 } 2775 2776 ASSERT(columnLayers.size()); 2777 2778 paintChildLayerIntoColumns(childLayer, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags, columnLayers, columnLayers.size() - 1); 2779 } 2780 2781 void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context, 2782 const IntRect& paintDirtyRect, PaintBehavior paintBehavior, 2783 RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests, 2784 PaintLayerFlags paintFlags, const Vector<RenderLayer*>& columnLayers, size_t colIndex) 2785 { 2786 RenderBlock* columnBlock = toRenderBlock(columnLayers[colIndex]->renderer()); 2787 2788 ASSERT(columnBlock && columnBlock->hasColumns()); 2789 if (!columnBlock || !columnBlock->hasColumns()) 2790 return; 2791 2792 int layerX = 0; 2793 int layerY = 0; 2794 columnBlock->layer()->convertToLayerCoords(rootLayer, layerX, layerY); 2795 2796 bool isHorizontal = columnBlock->style()->isHorizontalWritingMode(); 2797 2798 ColumnInfo* colInfo = columnBlock->columnInfo(); 2799 unsigned colCount = columnBlock->columnCount(colInfo); 2800 int currLogicalTopOffset = 0; 2801 for (unsigned i = 0; i < colCount; i++) { 2802 // For each rect, we clip to the rect, and then we adjust our coords. 2803 IntRect colRect = columnBlock->columnRectAt(colInfo, i); 2804 columnBlock->flipForWritingMode(colRect); 2805 int logicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - columnBlock->logicalLeftOffsetForContent(); 2806 IntSize offset = isHorizontal ? IntSize(logicalLeftOffset, currLogicalTopOffset) : IntSize(currLogicalTopOffset, logicalLeftOffset); 2807 2808 colRect.move(layerX, layerY); 2809 2810 IntRect localDirtyRect(paintDirtyRect); 2811 localDirtyRect.intersect(colRect); 2812 2813 if (!localDirtyRect.isEmpty()) { 2814 context->save(); 2815 2816 // Each strip pushes a clip, since column boxes are specified as being 2817 // like overflow:hidden. 2818 context->clip(colRect); 2819 2820 if (!colIndex) { 2821 // Apply a translation transform to change where the layer paints. 2822 TransformationMatrix oldTransform; 2823 bool oldHasTransform = childLayer->transform(); 2824 if (oldHasTransform) 2825 oldTransform = *childLayer->transform(); 2826 TransformationMatrix newTransform(oldTransform); 2827 newTransform.translateRight(offset.width(), offset.height()); 2828 2829 childLayer->m_transform.set(new TransformationMatrix(newTransform)); 2830 childLayer->paintLayer(rootLayer, context, localDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags); 2831 if (oldHasTransform) 2832 childLayer->m_transform.set(new TransformationMatrix(oldTransform)); 2833 else 2834 childLayer->m_transform.clear(); 2835 } else { 2836 // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space. 2837 // This involves subtracting out the position of the layer in our current coordinate space. 2838 int childX = 0; 2839 int childY = 0; 2840 columnLayers[colIndex - 1]->convertToLayerCoords(rootLayer, childX, childY); 2841 TransformationMatrix transform; 2842 transform.translateRight(childX + offset.width(), childY + offset.height()); 2843 2844 // Apply the transform. 2845 context->concatCTM(transform.toAffineTransform()); 2846 2847 // Now do a paint with the root layer shifted to be the next multicol block. 2848 paintChildLayerIntoColumns(childLayer, columnLayers[colIndex - 1], context, transform.inverse().mapRect(localDirtyRect), paintBehavior, 2849 paintingRoot, overlapTestRequests, paintFlags, 2850 columnLayers, colIndex - 1); 2851 } 2852 2853 context->restore(); 2854 } 2855 2856 // Move to the next position. 2857 int blockDelta = isHorizontal ? colRect.height() : colRect.width(); 2858 if (columnBlock->style()->isFlippedBlocksWritingMode()) 2859 currLogicalTopOffset += blockDelta; 2860 else 2861 currLogicalTopOffset -= blockDelta; 2862 } 2863 } 2864 2865 static inline IntRect frameVisibleRect(RenderObject* renderer) 2866 { 2867 FrameView* frameView = renderer->document()->view(); 2868 if (!frameView) 2869 return IntRect(); 2870 2871 return frameView->visibleContentRect(); 2872 } 2873 2874 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result) 2875 { 2876 renderer()->document()->updateLayout(); 2877 2878 IntRect hitTestArea = renderer()->view()->documentRect(); 2879 if (!request.ignoreClipping()) 2880 hitTestArea.intersect(frameVisibleRect(renderer())); 2881 2882 RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, result.point(), false); 2883 if (!insideLayer) { 2884 // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down, 2885 // return ourselves. We do this so mouse events continue getting delivered after a drag has 2886 // exited the WebView, and so hit testing over a scrollbar hits the content document. 2887 if ((request.active() || request.mouseUp()) && renderer()->isRenderView()) { 2888 renderer()->updateHitTestResult(result, result.point()); 2889 insideLayer = this; 2890 } 2891 } 2892 2893 // Now determine if the result is inside an anchor - if the urlElement isn't already set. 2894 Node* node = result.innerNode(); 2895 if (node && !result.URLElement()) 2896 result.setURLElement(static_cast<Element*>(node->enclosingLinkEventParentOrSelf())); 2897 2898 // Next set up the correct :hover/:active state along the new chain. 2899 updateHoverActiveState(request, result); 2900 2901 // Now return whether we were inside this layer (this will always be true for the root 2902 // layer). 2903 return insideLayer; 2904 } 2905 2906 Node* RenderLayer::enclosingElement() const 2907 { 2908 for (RenderObject* r = renderer(); r; r = r->parent()) { 2909 if (Node* e = r->node()) 2910 return e; 2911 } 2912 ASSERT_NOT_REACHED(); 2913 return 0; 2914 } 2915 2916 // Compute the z-offset of the point in the transformState. 2917 // This is effectively projecting a ray normal to the plane of ancestor, finding where that 2918 // ray intersects target, and computing the z delta between those two points. 2919 static double computeZOffset(const HitTestingTransformState& transformState) 2920 { 2921 // We got an affine transform, so no z-offset 2922 if (transformState.m_accumulatedTransform.isAffine()) 2923 return 0; 2924 2925 // Flatten the point into the target plane 2926 FloatPoint targetPoint = transformState.mappedPoint(); 2927 2928 // Now map the point back through the transform, which computes Z. 2929 FloatPoint3D backmappedPoint = transformState.m_accumulatedTransform.mapPoint(FloatPoint3D(targetPoint)); 2930 return backmappedPoint.z(); 2931 } 2932 2933 PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer, 2934 const IntRect& hitTestRect, const IntPoint& hitTestPoint, 2935 const HitTestingTransformState* containerTransformState) const 2936 { 2937 RefPtr<HitTestingTransformState> transformState; 2938 int offsetX = 0; 2939 int offsetY = 0; 2940 if (containerTransformState) { 2941 // If we're already computing transform state, then it's relative to the container (which we know is non-null). 2942 transformState = HitTestingTransformState::create(*containerTransformState); 2943 convertToLayerCoords(containerLayer, offsetX, offsetY); 2944 } else { 2945 // If this is the first time we need to make transform state, then base it off of hitTestPoint, 2946 // which is relative to rootLayer. 2947 transformState = HitTestingTransformState::create(hitTestPoint, FloatQuad(hitTestRect)); 2948 convertToLayerCoords(rootLayer, offsetX, offsetY); 2949 } 2950 2951 RenderObject* containerRenderer = containerLayer ? containerLayer->renderer() : 0; 2952 if (renderer()->shouldUseTransformFromContainer(containerRenderer)) { 2953 TransformationMatrix containerTransform; 2954 renderer()->getTransformFromContainer(containerRenderer, IntSize(offsetX, offsetY), containerTransform); 2955 transformState->applyTransform(containerTransform, HitTestingTransformState::AccumulateTransform); 2956 } else { 2957 transformState->translate(offsetX, offsetY, HitTestingTransformState::AccumulateTransform); 2958 } 2959 2960 return transformState; 2961 } 2962 2963 2964 static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, double* zOffset, const HitTestingTransformState* transformState) 2965 { 2966 if (!hitLayer) 2967 return false; 2968 2969 // The hit layer is depth-sorting with other layers, so just say that it was hit. 2970 if (canDepthSort) 2971 return true; 2972 2973 // We need to look at z-depth to decide if this layer was hit. 2974 if (zOffset) { 2975 ASSERT(transformState); 2976 // This is actually computing our z, but that's OK because the hitLayer is coplanar with us. 2977 double childZOffset = computeZOffset(*transformState); 2978 if (childZOffset > *zOffset) { 2979 *zOffset = childZOffset; 2980 return true; 2981 } 2982 return false; 2983 } 2984 2985 return true; 2986 } 2987 2988 // hitTestPoint and hitTestRect are relative to rootLayer. 2989 // A 'flattening' layer is one preserves3D() == false. 2990 // transformState.m_accumulatedTransform holds the transform from the containing flattening layer. 2991 // transformState.m_lastPlanarPoint is the hitTestPoint in the plane of the containing flattening layer. 2992 // transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of the containing flattening layer. 2993 // 2994 // If zOffset is non-null (which indicates that the caller wants z offset information), 2995 // *zOffset on return is the z offset of the hit point relative to the containing flattening layer. 2996 RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result, 2997 const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform, 2998 const HitTestingTransformState* transformState, double* zOffset) 2999 { 3000 // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate. 3001 3002 bool useTemporaryClipRects = false; 3003 #if USE(ACCELERATED_COMPOSITING) 3004 useTemporaryClipRects = compositor()->inCompositingMode(); 3005 #endif 3006 useTemporaryClipRects |= renderer()->view()->frameView()->containsScrollableAreaWithOverlayScrollbars(); 3007 3008 IntRect hitTestArea = result.rectForPoint(hitTestPoint); 3009 3010 // Apply a transform if we have one. 3011 if (transform() && !appliedTransform) { 3012 // Make sure the parent's clip rects have been calculated. 3013 if (parent()) { 3014 IntRect clipRect = backgroundClipRect(rootLayer, useTemporaryClipRects, IncludeOverlayScrollbarSize); 3015 // Go ahead and test the enclosing clip now. 3016 if (!clipRect.intersects(hitTestArea)) 3017 return 0; 3018 } 3019 3020 // Create a transform state to accumulate this transform. 3021 RefPtr<HitTestingTransformState> newTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState); 3022 3023 // If the transform can't be inverted, then don't hit test this layer at all. 3024 if (!newTransformState->m_accumulatedTransform.isInvertible()) 3025 return 0; 3026 3027 // Compute the point and the hit test rect in the coords of this layer by using the values 3028 // from the transformState, which store the point and quad in the coords of the last flattened 3029 // layer, and the accumulated transform which lets up map through preserve-3d layers. 3030 // 3031 // We can't just map hitTestPoint and hitTestRect because they may have been flattened (losing z) 3032 // by our container. 3033 IntPoint localPoint = roundedIntPoint(newTransformState->mappedPoint()); 3034 IntRect localHitTestRect; 3035 #if USE(ACCELERATED_COMPOSITING) 3036 if (isComposited()) { 3037 // It doesn't make sense to project hitTestRect into the plane of this layer, so use the same bounds we use for painting. 3038 localHitTestRect = backing()->compositedBounds(); 3039 } else 3040 #endif 3041 localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox(); 3042 3043 // Now do a hit test with the root layer shifted to be us. 3044 return hitTestLayer(this, containerLayer, request, result, localHitTestRect, localPoint, true, newTransformState.get(), zOffset); 3045 } 3046 3047 // Ensure our lists and 3d status are up-to-date. 3048 updateCompositingAndLayerListsIfNeeded(); 3049 update3DTransformedDescendantStatus(); 3050 3051 RefPtr<HitTestingTransformState> localTransformState; 3052 if (appliedTransform) { 3053 // We computed the correct state in the caller (above code), so just reference it. 3054 ASSERT(transformState); 3055 localTransformState = const_cast<HitTestingTransformState*>(transformState); 3056 } else if (transformState || m_has3DTransformedDescendant || preserves3D()) { 3057 // We need transform state for the first time, or to offset the container state, so create it here. 3058 localTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState); 3059 } 3060 3061 // Check for hit test on backface if backface-visibility is 'hidden' 3062 if (localTransformState && renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden) { 3063 TransformationMatrix invertedMatrix = localTransformState->m_accumulatedTransform.inverse(); 3064 // If the z-vector of the matrix is negative, the back is facing towards the viewer. 3065 if (invertedMatrix.m33() < 0) 3066 return 0; 3067 } 3068 3069 RefPtr<HitTestingTransformState> unflattenedTransformState = localTransformState; 3070 if (localTransformState && !preserves3D()) { 3071 // Keep a copy of the pre-flattening state, for computing z-offsets for the container 3072 unflattenedTransformState = HitTestingTransformState::create(*localTransformState); 3073 // This layer is flattening, so flatten the state passed to descendants. 3074 localTransformState->flatten(); 3075 } 3076 3077 // Calculate the clip rects we should use. 3078 IntRect layerBounds; 3079 IntRect bgRect; 3080 IntRect fgRect; 3081 IntRect outlineRect; 3082 calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, useTemporaryClipRects, IncludeOverlayScrollbarSize); 3083 3084 // The following are used for keeping track of the z-depth of the hit point of 3d-transformed 3085 // descendants. 3086 double localZOffset = -numeric_limits<double>::infinity(); 3087 double* zOffsetForDescendantsPtr = 0; 3088 double* zOffsetForContentsPtr = 0; 3089 3090 bool depthSortDescendants = false; 3091 if (preserves3D()) { 3092 depthSortDescendants = true; 3093 // Our layers can depth-test with our container, so share the z depth pointer with the container, if it passed one down. 3094 zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset; 3095 zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset; 3096 } else if (m_has3DTransformedDescendant) { 3097 // Flattening layer with 3d children; use a local zOffset pointer to depth-test children and foreground. 3098 depthSortDescendants = true; 3099 zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset; 3100 zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset; 3101 } else if (zOffset) { 3102 zOffsetForDescendantsPtr = 0; 3103 // Container needs us to give back a z offset for the hit layer. 3104 zOffsetForContentsPtr = zOffset; 3105 } 3106 3107 // This variable tracks which layer the mouse ends up being inside. 3108 RenderLayer* candidateLayer = 0; 3109 3110 // Begin by walking our list of positive layers from highest z-index down to the lowest z-index. 3111 RenderLayer* hitLayer = hitTestList(m_posZOrderList, rootLayer, request, result, hitTestRect, hitTestPoint, 3112 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants); 3113 if (hitLayer) { 3114 if (!depthSortDescendants) 3115 return hitLayer; 3116 candidateLayer = hitLayer; 3117 } 3118 3119 // Now check our overflow objects. 3120 hitLayer = hitTestList(m_normalFlowList, rootLayer, request, result, hitTestRect, hitTestPoint, 3121 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants); 3122 if (hitLayer) { 3123 if (!depthSortDescendants) 3124 return hitLayer; 3125 candidateLayer = hitLayer; 3126 } 3127 3128 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 3129 if (hasOverflowParent()) { 3130 ClipRects clipRects; 3131 calculateClipRects(rootLayer, clipRects, useTemporaryClipRects); 3132 fgRect.intersect(clipRects.hitTestClip()); 3133 bgRect.intersect(clipRects.hitTestClip()); 3134 } 3135 #endif 3136 // Next we want to see if the mouse pos is inside the child RenderObjects of the layer. 3137 if (fgRect.intersects(hitTestArea) && isSelfPaintingLayer()) { 3138 // Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost. 3139 HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding()); 3140 if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestDescendants) && 3141 isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) { 3142 if (result.isRectBasedTest()) 3143 result.append(tempResult); 3144 else 3145 result = tempResult; 3146 if (!depthSortDescendants) 3147 return this; 3148 // Foreground can depth-sort with descendant layers, so keep this as a candidate. 3149 candidateLayer = this; 3150 } else if (result.isRectBasedTest()) 3151 result.append(tempResult); 3152 } 3153 3154 // Now check our negative z-index children. 3155 hitLayer = hitTestList(m_negZOrderList, rootLayer, request, result, hitTestRect, hitTestPoint, 3156 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants); 3157 if (hitLayer) { 3158 if (!depthSortDescendants) 3159 return hitLayer; 3160 candidateLayer = hitLayer; 3161 } 3162 3163 // If we found a layer, return. Child layers, and foreground always render in front of background. 3164 if (candidateLayer) 3165 return candidateLayer; 3166 3167 if (bgRect.intersects(hitTestArea) && isSelfPaintingLayer()) { 3168 HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding()); 3169 if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestSelf) && 3170 isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) { 3171 if (result.isRectBasedTest()) 3172 result.append(tempResult); 3173 else 3174 result = tempResult; 3175 return this; 3176 } else if (result.isRectBasedTest()) 3177 result.append(tempResult); 3178 } 3179 3180 return 0; 3181 } 3182 3183 bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const IntRect& layerBounds, const IntPoint& hitTestPoint, HitTestFilter hitTestFilter) const 3184 { 3185 if (!renderer()->hitTest(request, result, hitTestPoint, 3186 layerBounds.x() - renderBoxX(), 3187 layerBounds.y() - renderBoxY(), 3188 hitTestFilter)) { 3189 // It's wrong to set innerNode, but then claim that you didn't hit anything, unless it is 3190 // a rect-based test. 3191 ASSERT(!result.innerNode() || (result.isRectBasedTest() && result.rectBasedTestResult().size())); 3192 return false; 3193 } 3194 3195 // For positioned generated content, we might still not have a 3196 // node by the time we get to the layer level, since none of 3197 // the content in the layer has an element. So just walk up 3198 // the tree. 3199 if (!result.innerNode() || !result.innerNonSharedNode()) { 3200 Node* e = enclosingElement(); 3201 if (!result.innerNode()) 3202 result.setInnerNode(e); 3203 if (!result.innerNonSharedNode()) 3204 result.setInnerNonSharedNode(e); 3205 } 3206 3207 return true; 3208 } 3209 3210 RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* rootLayer, 3211 const HitTestRequest& request, HitTestResult& result, 3212 const IntRect& hitTestRect, const IntPoint& hitTestPoint, 3213 const HitTestingTransformState* transformState, 3214 double* zOffsetForDescendants, double* zOffset, 3215 const HitTestingTransformState* unflattenedTransformState, 3216 bool depthSortDescendants) 3217 { 3218 if (!list) 3219 return 0; 3220 3221 RenderLayer* resultLayer = 0; 3222 for (int i = list->size() - 1; i >= 0; --i) { 3223 RenderLayer* childLayer = list->at(i); 3224 RenderLayer* hitLayer = 0; 3225 HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding()); 3226 if (childLayer->isPaginated()) 3227 hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestPoint, transformState, zOffsetForDescendants); 3228 else 3229 hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, transformState, zOffsetForDescendants); 3230 3231 // If it a rect-based test, we can safely append the temporary result since it might had hit 3232 // nodes but not necesserily had hitLayer set. 3233 if (result.isRectBasedTest()) 3234 result.append(tempResult); 3235 3236 if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState)) { 3237 resultLayer = hitLayer; 3238 if (!result.isRectBasedTest()) 3239 result = tempResult; 3240 if (!depthSortDescendants) 3241 break; 3242 } 3243 } 3244 3245 return resultLayer; 3246 } 3247 3248 RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result, 3249 const IntRect& hitTestRect, const IntPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset) 3250 { 3251 Vector<RenderLayer*> columnLayers; 3252 RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext(); 3253 for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) { 3254 if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox())) 3255 columnLayers.append(curr); 3256 if (curr == ancestorLayer) 3257 break; 3258 } 3259 3260 ASSERT(columnLayers.size()); 3261 return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitTestRect, hitTestPoint, transformState, zOffset, 3262 columnLayers, columnLayers.size() - 1); 3263 } 3264 3265 RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result, 3266 const IntRect& hitTestRect, const IntPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset, 3267 const Vector<RenderLayer*>& columnLayers, size_t columnIndex) 3268 { 3269 RenderBlock* columnBlock = toRenderBlock(columnLayers[columnIndex]->renderer()); 3270 3271 ASSERT(columnBlock && columnBlock->hasColumns()); 3272 if (!columnBlock || !columnBlock->hasColumns()) 3273 return 0; 3274 3275 int layerX = 0; 3276 int layerY = 0; 3277 columnBlock->layer()->convertToLayerCoords(rootLayer, layerX, layerY); 3278 3279 ColumnInfo* colInfo = columnBlock->columnInfo(); 3280 int colCount = columnBlock->columnCount(colInfo); 3281 3282 // We have to go backwards from the last column to the first. 3283 bool isHorizontal = columnBlock->style()->isHorizontalWritingMode(); 3284 int logicalLeft = columnBlock->logicalLeftOffsetForContent(); 3285 int currLogicalTopOffset = 0; 3286 int i; 3287 for (i = 0; i < colCount; i++) { 3288 IntRect colRect = columnBlock->columnRectAt(colInfo, i); 3289 int blockDelta = (isHorizontal ? colRect.height() : colRect.width()); 3290 if (columnBlock->style()->isFlippedBlocksWritingMode()) 3291 currLogicalTopOffset += blockDelta; 3292 else 3293 currLogicalTopOffset -= blockDelta; 3294 } 3295 for (i = colCount - 1; i >= 0; i--) { 3296 // For each rect, we clip to the rect, and then we adjust our coords. 3297 IntRect colRect = columnBlock->columnRectAt(colInfo, i); 3298 columnBlock->flipForWritingMode(colRect); 3299 int currLogicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - logicalLeft; 3300 int blockDelta = (isHorizontal ? colRect.height() : colRect.width()); 3301 if (columnBlock->style()->isFlippedBlocksWritingMode()) 3302 currLogicalTopOffset -= blockDelta; 3303 else 3304 currLogicalTopOffset += blockDelta; 3305 colRect.move(layerX, layerY); 3306 3307 IntRect localClipRect(hitTestRect); 3308 localClipRect.intersect(colRect); 3309 3310 IntSize offset = isHorizontal ? IntSize(currLogicalLeftOffset, currLogicalTopOffset) : IntSize(currLogicalTopOffset, currLogicalLeftOffset); 3311 3312 if (!localClipRect.isEmpty() && localClipRect.intersects(result.rectForPoint(hitTestPoint))) { 3313 RenderLayer* hitLayer = 0; 3314 if (!columnIndex) { 3315 // Apply a translation transform to change where the layer paints. 3316 TransformationMatrix oldTransform; 3317 bool oldHasTransform = childLayer->transform(); 3318 if (oldHasTransform) 3319 oldTransform = *childLayer->transform(); 3320 TransformationMatrix newTransform(oldTransform); 3321 newTransform.translateRight(offset.width(), offset.height()); 3322 3323 childLayer->m_transform.set(new TransformationMatrix(newTransform)); 3324 hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestPoint, false, transformState, zOffset); 3325 if (oldHasTransform) 3326 childLayer->m_transform.set(new TransformationMatrix(oldTransform)); 3327 else 3328 childLayer->m_transform.clear(); 3329 } else { 3330 // Adjust the transform such that the renderer's upper left corner will be at (0,0) in user space. 3331 // This involves subtracting out the position of the layer in our current coordinate space. 3332 RenderLayer* nextLayer = columnLayers[columnIndex - 1]; 3333 RefPtr<HitTestingTransformState> newTransformState = nextLayer->createLocalTransformState(rootLayer, nextLayer, localClipRect, hitTestPoint, transformState); 3334 newTransformState->translate(offset.width(), offset.height(), HitTestingTransformState::AccumulateTransform); 3335 IntPoint localPoint = roundedIntPoint(newTransformState->mappedPoint()); 3336 IntRect localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox(); 3337 newTransformState->flatten(); 3338 3339 hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[columnIndex - 1], request, result, localHitTestRect, localPoint, 3340 newTransformState.get(), zOffset, columnLayers, columnIndex - 1); 3341 } 3342 3343 if (hitLayer) 3344 return hitLayer; 3345 } 3346 } 3347 3348 return 0; 3349 } 3350 3351 void RenderLayer::updateClipRects(const RenderLayer* rootLayer, OverlayScrollbarSizeRelevancy relevancy) 3352 { 3353 if (m_clipRects) { 3354 ASSERT(rootLayer == m_clipRectsRoot); 3355 return; // We have the correct cached value. 3356 } 3357 3358 // For transformed layers, the root layer was shifted to be us, so there is no need to 3359 // examine the parent. We want to cache clip rects with us as the root. 3360 RenderLayer* parentLayer = rootLayer != this ? parent() : 0; 3361 if (parentLayer) 3362 parentLayer->updateClipRects(rootLayer, relevancy); 3363 3364 ClipRects clipRects; 3365 calculateClipRects(rootLayer, clipRects, true, relevancy); 3366 3367 if (parentLayer && parentLayer->clipRects() && clipRects == *parentLayer->clipRects()) 3368 m_clipRects = parentLayer->clipRects(); 3369 else 3370 m_clipRects = new (renderer()->renderArena()) ClipRects(clipRects); 3371 m_clipRects->ref(); 3372 #ifndef NDEBUG 3373 m_clipRectsRoot = rootLayer; 3374 #endif 3375 } 3376 3377 void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool useCached, OverlayScrollbarSizeRelevancy relevancy) const 3378 { 3379 if (!parent()) { 3380 // The root layer's clip rect is always infinite. 3381 clipRects.reset(PaintInfo::infiniteRect()); 3382 return; 3383 } 3384 3385 // For transformed layers, the root layer was shifted to be us, so there is no need to 3386 // examine the parent. We want to cache clip rects with us as the root. 3387 RenderLayer* parentLayer = rootLayer != this ? parent() : 0; 3388 3389 // Ensure that our parent's clip has been calculated so that we can examine the values. 3390 if (parentLayer) { 3391 if (useCached && parentLayer->clipRects()) 3392 clipRects = *parentLayer->clipRects(); 3393 else 3394 parentLayer->calculateClipRects(rootLayer, clipRects); 3395 } 3396 else 3397 clipRects.reset(PaintInfo::infiniteRect()); 3398 3399 // A fixed object is essentially the root of its containing block hierarchy, so when 3400 // we encounter such an object, we reset our clip rects to the fixedClipRect. 3401 if (renderer()->style()->position() == FixedPosition) { 3402 clipRects.setPosClipRect(clipRects.fixedClipRect()); 3403 clipRects.setOverflowClipRect(clipRects.fixedClipRect()); 3404 clipRects.setFixed(true); 3405 } 3406 else if (renderer()->style()->position() == RelativePosition) 3407 clipRects.setPosClipRect(clipRects.overflowClipRect()); 3408 else if (renderer()->style()->position() == AbsolutePosition) 3409 clipRects.setOverflowClipRect(clipRects.posClipRect()); 3410 3411 // Update the clip rects that will be passed to child layers. 3412 if (renderer()->hasOverflowClip() || renderer()->hasClip()) { 3413 // This layer establishes a clip of some kind. 3414 int x = 0; 3415 int y = 0; 3416 convertToLayerCoords(rootLayer, x, y); 3417 RenderView* view = renderer()->view(); 3418 ASSERT(view); 3419 if (view && clipRects.fixed() && rootLayer->renderer() == view) { 3420 x -= view->frameView()->scrollXForFixedPosition(); 3421 y -= view->frameView()->scrollYForFixedPosition(); 3422 } 3423 3424 if (renderer()->hasOverflowClip()) { 3425 IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x, y, relevancy); 3426 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 3427 clipRects.setHitTestClip(intersection(clipRects.fixed() ? clipRects.fixedClipRect() 3428 : newOverflowClip, clipRects.hitTestClip())); 3429 if (hasOverflowScroll()) { 3430 RenderBox* box = toRenderBox(renderer()); 3431 newOverflowClip = 3432 IntRect(x + box->borderLeft(), y + box->borderTop(), 3433 m_scrollWidth, m_scrollHeight); 3434 } 3435 #endif 3436 clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect())); 3437 if (renderer()->isPositioned() || renderer()->isRelPositioned()) 3438 clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect())); 3439 } 3440 if (renderer()->hasClip()) { 3441 IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y); 3442 clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect())); 3443 clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect())); 3444 clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect())); 3445 } 3446 } 3447 } 3448 3449 void RenderLayer::parentClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool temporaryClipRects, OverlayScrollbarSizeRelevancy relevancy) const 3450 { 3451 ASSERT(parent()); 3452 if (temporaryClipRects) { 3453 parent()->calculateClipRects(rootLayer, clipRects, false, relevancy); 3454 return; 3455 } 3456 3457 parent()->updateClipRects(rootLayer, relevancy); 3458 clipRects = *parent()->clipRects(); 3459 } 3460 3461 IntRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects, OverlayScrollbarSizeRelevancy relevancy) const 3462 { 3463 IntRect backgroundRect; 3464 if (parent()) { 3465 ClipRects parentRects; 3466 parentClipRects(rootLayer, parentRects, temporaryClipRects, relevancy); 3467 backgroundRect = renderer()->style()->position() == FixedPosition ? parentRects.fixedClipRect() : 3468 (renderer()->isPositioned() ? parentRects.posClipRect() : 3469 parentRects.overflowClipRect()); 3470 RenderView* view = renderer()->view(); 3471 ASSERT(view); 3472 if (view && parentRects.fixed() && rootLayer->renderer() == view) 3473 backgroundRect.move(view->frameView()->scrollXForFixedPosition(), view->frameView()->scrollYForFixedPosition()); 3474 } 3475 return backgroundRect; 3476 } 3477 3478 void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds, 3479 IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects, 3480 OverlayScrollbarSizeRelevancy relevancy) const 3481 { 3482 if (rootLayer != this && parent()) { 3483 backgroundRect = backgroundClipRect(rootLayer, temporaryClipRects, relevancy); 3484 backgroundRect.intersect(paintDirtyRect); 3485 } else 3486 backgroundRect = paintDirtyRect; 3487 3488 foregroundRect = backgroundRect; 3489 outlineRect = backgroundRect; 3490 3491 int x = 0; 3492 int y = 0; 3493 convertToLayerCoords(rootLayer, x, y); 3494 layerBounds = IntRect(x, y, width(), height()); 3495 3496 // Update the clip rects that will be passed to child layers. 3497 if (renderer()->hasOverflowClip() || renderer()->hasClip()) { 3498 // This layer establishes a clip of some kind. 3499 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 3500 if (hasOverflowScroll()) { 3501 // Use the entire foreground rectangle to record the contents. 3502 RenderBox* box = toRenderBox(renderer()); 3503 foregroundRect = 3504 IntRect(x + box->borderLeft(), y + box->borderTop(), 3505 m_scrollWidth, m_scrollHeight); 3506 } else 3507 #endif 3508 if (renderer()->hasOverflowClip()) 3509 foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(x, y, relevancy)); 3510 if (renderer()->hasClip()) { 3511 // Clip applies to *us* as well, so go ahead and update the damageRect. 3512 IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y); 3513 backgroundRect.intersect(newPosClip); 3514 foregroundRect.intersect(newPosClip); 3515 outlineRect.intersect(newPosClip); 3516 } 3517 3518 // If we establish a clip at all, then go ahead and make sure our background 3519 // rect is intersected with our layer's bounds. 3520 // FIXME: This could be changed to just use generic visual overflow. 3521 // See https://bugs.webkit.org/show_bug.cgi?id=37467 for more information. 3522 if (const ShadowData* boxShadow = renderer()->style()->boxShadow()) { 3523 IntRect overflow = layerBounds; 3524 do { 3525 if (boxShadow->style() == Normal) { 3526 IntRect shadowRect = layerBounds; 3527 shadowRect.move(boxShadow->x(), boxShadow->y()); 3528 shadowRect.inflate(boxShadow->blur() + boxShadow->spread()); 3529 overflow.unite(shadowRect); 3530 } 3531 3532 boxShadow = boxShadow->next(); 3533 } while (boxShadow); 3534 backgroundRect.intersect(overflow); 3535 } else 3536 backgroundRect.intersect(layerBounds); 3537 } 3538 } 3539 3540 IntRect RenderLayer::childrenClipRect() const 3541 { 3542 RenderView* renderView = renderer()->view(); 3543 RenderLayer* clippingRootLayer = clippingRoot(); 3544 IntRect layerBounds, backgroundRect, foregroundRect, outlineRect; 3545 calculateRects(clippingRootLayer, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect); 3546 return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect)).enclosingBoundingBox(); 3547 } 3548 3549 IntRect RenderLayer::selfClipRect() const 3550 { 3551 RenderView* renderView = renderer()->view(); 3552 RenderLayer* clippingRootLayer = clippingRoot(); 3553 IntRect layerBounds, backgroundRect, foregroundRect, outlineRect; 3554 calculateRects(clippingRootLayer, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect); 3555 return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect)).enclosingBoundingBox(); 3556 } 3557 3558 void RenderLayer::addBlockSelectionGapsBounds(const IntRect& bounds) 3559 { 3560 m_blockSelectionGapsBounds.unite(bounds); 3561 } 3562 3563 void RenderLayer::clearBlockSelectionGapsBounds() 3564 { 3565 m_blockSelectionGapsBounds = IntRect(); 3566 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 3567 child->clearBlockSelectionGapsBounds(); 3568 } 3569 3570 void RenderLayer::repaintBlockSelectionGaps() 3571 { 3572 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 3573 child->repaintBlockSelectionGaps(); 3574 3575 if (m_blockSelectionGapsBounds.isEmpty()) 3576 return; 3577 3578 IntRect rect = m_blockSelectionGapsBounds; 3579 rect.move(-scrolledContentOffset()); 3580 if (renderer()->hasOverflowClip()) 3581 rect.intersect(toRenderBox(renderer())->overflowClipRect(0, 0)); 3582 if (renderer()->hasClip()) 3583 rect.intersect(toRenderBox(renderer())->clipRect(0, 0)); 3584 if (!rect.isEmpty()) 3585 renderer()->repaintRectangle(rect); 3586 } 3587 3588 bool RenderLayer::intersectsDamageRect(const IntRect& layerBounds, const IntRect& damageRect, const RenderLayer* rootLayer) const 3589 { 3590 // Always examine the canvas and the root. 3591 // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView 3592 // paints the root's background. 3593 if (renderer()->isRenderView() || renderer()->isRoot()) 3594 return true; 3595 3596 // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we 3597 // can go ahead and return true. 3598 RenderView* view = renderer()->view(); 3599 ASSERT(view); 3600 if (view && !renderer()->isRenderInline()) { 3601 IntRect b = layerBounds; 3602 b.inflate(view->maximalOutlineSize()); 3603 if (b.intersects(damageRect)) 3604 return true; 3605 } 3606 3607 // Otherwise we need to compute the bounding box of this single layer and see if it intersects 3608 // the damage rect. 3609 return boundingBox(rootLayer).intersects(damageRect); 3610 } 3611 3612 IntRect RenderLayer::localBoundingBox() const 3613 { 3614 // There are three special cases we need to consider. 3615 // (1) Inline Flows. For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the 3616 // inline. In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the 3617 // line boxes of all three lines (including overflow on those lines). 3618 // (2) Left/Top Overflow. The width/height of layers already includes right/bottom overflow. However, in the case of left/top 3619 // overflow, we have to create a bounding box that will extend to include this overflow. 3620 // (3) Floats. When a layer has overhanging floats that it paints, we need to make sure to include these overhanging floats 3621 // as part of our bounding box. We do this because we are the responsible layer for both hit testing and painting those 3622 // floats. 3623 IntRect result; 3624 if (renderer()->isRenderInline()) 3625 result = toRenderInline(renderer())->linesVisualOverflowBoundingBox(); 3626 else if (renderer()->isTableRow()) { 3627 // Our bounding box is just the union of all of our cells' border/overflow rects. 3628 for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) { 3629 if (child->isTableCell()) { 3630 IntRect bbox = toRenderBox(child)->borderBoxRect(); 3631 result.unite(bbox); 3632 IntRect overflowRect = renderBox()->visualOverflowRect(); 3633 if (bbox != overflowRect) 3634 result.unite(overflowRect); 3635 } 3636 } 3637 } else { 3638 RenderBox* box = renderBox(); 3639 ASSERT(box); 3640 if (box->hasMask()) 3641 result = box->maskClipRect(); 3642 else { 3643 IntRect bbox = box->borderBoxRect(); 3644 result = bbox; 3645 IntRect overflowRect = box->visualOverflowRect(); 3646 if (bbox != overflowRect) 3647 result.unite(overflowRect); 3648 } 3649 } 3650 3651 RenderView* view = renderer()->view(); 3652 ASSERT(view); 3653 if (view) 3654 result.inflate(view->maximalOutlineSize()); // Used to apply a fudge factor to dirty-rect checks on blocks/tables. 3655 3656 return result; 3657 } 3658 3659 IntRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer) const 3660 { 3661 IntRect result = localBoundingBox(); 3662 if (renderer()->isBox()) 3663 renderBox()->flipForWritingMode(result); 3664 else 3665 renderer()->containingBlock()->flipForWritingMode(result); 3666 int deltaX = 0, deltaY = 0; 3667 convertToLayerCoords(ancestorLayer, deltaX, deltaY); 3668 result.move(deltaX, deltaY); 3669 return result; 3670 } 3671 3672 IntRect RenderLayer::absoluteBoundingBox() const 3673 { 3674 return boundingBox(root()); 3675 } 3676 3677 void RenderLayer::clearClipRectsIncludingDescendants() 3678 { 3679 if (!m_clipRects) 3680 return; 3681 3682 clearClipRects(); 3683 3684 for (RenderLayer* l = firstChild(); l; l = l->nextSibling()) 3685 l->clearClipRectsIncludingDescendants(); 3686 } 3687 3688 void RenderLayer::clearClipRects() 3689 { 3690 if (m_clipRects) { 3691 m_clipRects->deref(renderer()->renderArena()); 3692 m_clipRects = 0; 3693 #ifndef NDEBUG 3694 m_clipRectsRoot = 0; 3695 #endif 3696 } 3697 } 3698 3699 #if USE(ACCELERATED_COMPOSITING) 3700 RenderLayerBacking* RenderLayer::ensureBacking() 3701 { 3702 if (!m_backing) 3703 m_backing.set(new RenderLayerBacking(this)); 3704 return m_backing.get(); 3705 } 3706 3707 void RenderLayer::clearBacking() 3708 { 3709 m_backing.clear(); 3710 } 3711 3712 bool RenderLayer::hasCompositedMask() const 3713 { 3714 return m_backing && m_backing->hasMaskLayer(); 3715 } 3716 3717 GraphicsLayer* RenderLayer::layerForHorizontalScrollbar() const 3718 { 3719 return m_backing ? m_backing->layerForHorizontalScrollbar() : 0; 3720 } 3721 3722 GraphicsLayer* RenderLayer::layerForVerticalScrollbar() const 3723 { 3724 return m_backing ? m_backing->layerForVerticalScrollbar() : 0; 3725 } 3726 3727 GraphicsLayer* RenderLayer::layerForScrollCorner() const 3728 { 3729 return m_backing ? m_backing->layerForScrollCorner() : 0; 3730 } 3731 #endif 3732 3733 bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const 3734 { 3735 #if USE(ACCELERATED_COMPOSITING) 3736 bool paintsToWindow = !isComposited() || backing()->paintingGoesToWindow(); 3737 #else 3738 bool paintsToWindow = true; 3739 #endif 3740 return transform() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || paintsToWindow); 3741 } 3742 3743 void RenderLayer::setParent(RenderLayer* parent) 3744 { 3745 if (parent == m_parent) 3746 return; 3747 3748 #if USE(ACCELERATED_COMPOSITING) 3749 if (m_parent && !renderer()->documentBeingDestroyed()) 3750 compositor()->layerWillBeRemoved(m_parent, this); 3751 #endif 3752 3753 m_parent = parent; 3754 3755 #if USE(ACCELERATED_COMPOSITING) 3756 if (m_parent && !renderer()->documentBeingDestroyed()) 3757 compositor()->layerWasAdded(m_parent, this); 3758 #endif 3759 } 3760 3761 static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2) 3762 { 3763 if (!obj1 || !obj2) 3764 return 0; 3765 3766 for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAncestor()) 3767 for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hoverAncestor()) 3768 if (currObj1 == currObj2) 3769 return currObj1; 3770 3771 return 0; 3772 } 3773 3774 void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestResult& result) 3775 { 3776 // We don't update :hover/:active state when the result is marked as readOnly. 3777 if (request.readOnly()) 3778 return; 3779 3780 Document* doc = renderer()->document(); 3781 3782 Node* activeNode = doc->activeNode(); 3783 if (activeNode && !request.active()) { 3784 // We are clearing the :active chain because the mouse has been released. 3785 for (RenderObject* curr = activeNode->renderer(); curr; curr = curr->parent()) { 3786 if (curr->node() && !curr->isText()) 3787 curr->node()->clearInActiveChain(); 3788 } 3789 doc->setActiveNode(0); 3790 } else { 3791 Node* newActiveNode = result.innerNode(); 3792 if (!activeNode && newActiveNode && request.active()) { 3793 // We are setting the :active chain and freezing it. If future moves happen, they 3794 // will need to reference this chain. 3795 for (RenderObject* curr = newActiveNode->renderer(); curr; curr = curr->parent()) { 3796 if (curr->node() && !curr->isText()) { 3797 curr->node()->setInActiveChain(); 3798 } 3799 } 3800 doc->setActiveNode(newActiveNode); 3801 } 3802 } 3803 3804 // If the mouse is down and if this is a mouse move event, we want to restrict changes in 3805 // :hover/:active to only apply to elements that are in the :active chain that we froze 3806 // at the time the mouse went down. 3807 bool mustBeInActiveChain = request.active() && request.mouseMove(); 3808 3809 // Check to see if the hovered node has changed. If not, then we don't need to 3810 // do anything. 3811 RefPtr<Node> oldHoverNode = doc->hoverNode(); 3812 Node* newHoverNode = result.innerNode(); 3813 3814 // Update our current hover node. 3815 doc->setHoverNode(newHoverNode); 3816 3817 // We have two different objects. Fetch their renderers. 3818 RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0; 3819 RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0; 3820 3821 // Locate the common ancestor render object for the two renderers. 3822 RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj); 3823 3824 Vector<RefPtr<Node>, 32> nodesToRemoveFromChain; 3825 Vector<RefPtr<Node>, 32> nodesToAddToChain; 3826 3827 if (oldHoverObj != newHoverObj) { 3828 // The old hover path only needs to be cleared up to (and not including) the common ancestor; 3829 for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) { 3830 if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) 3831 nodesToRemoveFromChain.append(curr->node()); 3832 } 3833 } 3834 3835 // Now set the hover state for our new object up to the root. 3836 for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) { 3837 if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) 3838 nodesToAddToChain.append(curr->node()); 3839 } 3840 3841 size_t removeCount = nodesToRemoveFromChain.size(); 3842 for (size_t i = 0; i < removeCount; ++i) { 3843 nodesToRemoveFromChain[i]->setActive(false); 3844 nodesToRemoveFromChain[i]->setHovered(false); 3845 } 3846 3847 size_t addCount = nodesToAddToChain.size(); 3848 for (size_t i = 0; i < addCount; ++i) { 3849 nodesToAddToChain[i]->setActive(request.active()); 3850 nodesToAddToChain[i]->setHovered(true); 3851 } 3852 } 3853 3854 // Helper for the sorting of layers by z-index. 3855 static inline bool compareZIndex(RenderLayer* first, RenderLayer* second) 3856 { 3857 return first->zIndex() < second->zIndex(); 3858 } 3859 3860 void RenderLayer::dirtyZOrderLists() 3861 { 3862 if (m_posZOrderList) 3863 m_posZOrderList->clear(); 3864 if (m_negZOrderList) 3865 m_negZOrderList->clear(); 3866 m_zOrderListsDirty = true; 3867 3868 #if USE(ACCELERATED_COMPOSITING) 3869 if (!renderer()->documentBeingDestroyed()) 3870 compositor()->setCompositingLayersNeedRebuild(); 3871 #endif 3872 } 3873 3874 void RenderLayer::dirtyStackingContextZOrderLists() 3875 { 3876 RenderLayer* sc = stackingContext(); 3877 if (sc) 3878 sc->dirtyZOrderLists(); 3879 } 3880 3881 void RenderLayer::dirtyNormalFlowList() 3882 { 3883 if (m_normalFlowList) 3884 m_normalFlowList->clear(); 3885 m_normalFlowListDirty = true; 3886 3887 #if USE(ACCELERATED_COMPOSITING) 3888 if (!renderer()->documentBeingDestroyed()) 3889 compositor()->setCompositingLayersNeedRebuild(); 3890 #endif 3891 } 3892 3893 void RenderLayer::updateZOrderLists() 3894 { 3895 if (!isStackingContext() || !m_zOrderListsDirty) 3896 return; 3897 3898 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 3899 if (!m_reflection || reflectionLayer() != child) 3900 child->collectLayers(m_posZOrderList, m_negZOrderList); 3901 3902 // Sort the two lists. 3903 if (m_posZOrderList) 3904 std::stable_sort(m_posZOrderList->begin(), m_posZOrderList->end(), compareZIndex); 3905 3906 if (m_negZOrderList) 3907 std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex); 3908 3909 m_zOrderListsDirty = false; 3910 } 3911 3912 void RenderLayer::updateNormalFlowList() 3913 { 3914 if (!m_normalFlowListDirty) 3915 return; 3916 3917 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) { 3918 // Ignore non-overflow layers and reflections. 3919 if (child->isNormalFlowOnly() && (!m_reflection || reflectionLayer() != child)) { 3920 if (!m_normalFlowList) 3921 m_normalFlowList = new Vector<RenderLayer*>; 3922 m_normalFlowList->append(child); 3923 } 3924 } 3925 3926 m_normalFlowListDirty = false; 3927 } 3928 3929 void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderLayer*>*& negBuffer) 3930 { 3931 updateVisibilityStatus(); 3932 3933 // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists. 3934 if ((m_hasVisibleContent || (m_hasVisibleDescendant && isStackingContext())) && !isNormalFlowOnly()) { 3935 // Determine which buffer the child should be in. 3936 Vector<RenderLayer*>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer; 3937 3938 // Create the buffer if it doesn't exist yet. 3939 if (!buffer) 3940 buffer = new Vector<RenderLayer*>; 3941 3942 // Append ourselves at the end of the appropriate buffer. 3943 buffer->append(this); 3944 } 3945 3946 // Recur into our children to collect more layers, but only if we don't establish 3947 // a stacking context. 3948 if (m_hasVisibleDescendant && !isStackingContext()) { 3949 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) { 3950 // Ignore reflections. 3951 if (!m_reflection || reflectionLayer() != child) 3952 child->collectLayers(posBuffer, negBuffer); 3953 } 3954 } 3955 } 3956 3957 void RenderLayer::updateLayerListsIfNeeded() 3958 { 3959 updateZOrderLists(); 3960 updateNormalFlowList(); 3961 } 3962 3963 void RenderLayer::updateCompositingAndLayerListsIfNeeded() 3964 { 3965 #if USE(ACCELERATED_COMPOSITING) 3966 if (compositor()->inCompositingMode()) { 3967 if ((isStackingContext() && m_zOrderListsDirty) || m_normalFlowListDirty) 3968 compositor()->updateCompositingLayers(CompositingUpdateOnPaitingOrHitTest, this); 3969 return; 3970 } 3971 #endif 3972 updateLayerListsIfNeeded(); 3973 } 3974 3975 void RenderLayer::repaintIncludingDescendants() 3976 { 3977 renderer()->repaint(); 3978 for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling()) 3979 curr->repaintIncludingDescendants(); 3980 } 3981 3982 #if USE(ACCELERATED_COMPOSITING) 3983 void RenderLayer::setBackingNeedsRepaint() 3984 { 3985 ASSERT(isComposited()); 3986 if (backing()->paintingGoesToWindow()) { 3987 // If we're trying to repaint the placeholder document layer, propagate the 3988 // repaint to the native view system. 3989 RenderView* view = renderer()->view(); 3990 if (view) 3991 view->repaintViewRectangle(absoluteBoundingBox()); 3992 } else 3993 backing()->setContentsNeedDisplay(); 3994 } 3995 3996 void RenderLayer::setBackingNeedsRepaintInRect(const IntRect& r) 3997 { 3998 ASSERT(isComposited()); 3999 if (backing()->paintingGoesToWindow()) { 4000 // If we're trying to repaint the placeholder document layer, propagate the 4001 // repaint to the native view system. 4002 IntRect absRect(r); 4003 int x = 0; 4004 int y = 0; 4005 convertToLayerCoords(root(), x, y); 4006 absRect.move(x, y); 4007 4008 RenderView* view = renderer()->view(); 4009 if (view) 4010 view->repaintViewRectangle(absRect); 4011 } else 4012 backing()->setContentsNeedDisplayInRect(r); 4013 } 4014 4015 // Since we're only painting non-composited layers, we know that they all share the same repaintContainer. 4016 void RenderLayer::repaintIncludingNonCompositingDescendants(RenderBoxModelObject* repaintContainer) 4017 { 4018 renderer()->repaintUsingContainer(repaintContainer, renderer()->clippedOverflowRectForRepaint(repaintContainer)); 4019 4020 for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling()) { 4021 if (!curr->isComposited()) 4022 curr->repaintIncludingNonCompositingDescendants(repaintContainer); 4023 } 4024 } 4025 #endif 4026 4027 bool RenderLayer::shouldBeNormalFlowOnly() const 4028 { 4029 return (renderer()->hasOverflowClip() 4030 || renderer()->hasReflection() 4031 || renderer()->hasMask() 4032 || renderer()->isVideo() 4033 || renderer()->isEmbeddedObject() 4034 || renderer()->isApplet() 4035 || renderer()->isRenderIFrame() 4036 || renderer()->style()->specifiesColumns()) 4037 && !renderer()->isPositioned() 4038 && !renderer()->isRelPositioned() 4039 && !renderer()->hasTransform() 4040 && !isTransparent(); 4041 } 4042 4043 bool RenderLayer::isSelfPaintingLayer() const 4044 { 4045 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 4046 if (hasOverflowScroll()) 4047 return true; 4048 #endif 4049 return !isNormalFlowOnly() 4050 || renderer()->hasReflection() 4051 || renderer()->hasMask() 4052 || renderer()->isTableRow() 4053 || renderer()->isVideo() 4054 || renderer()->isEmbeddedObject() 4055 || renderer()->isApplet() 4056 || renderer()->isRenderIFrame(); 4057 } 4058 4059 void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle) 4060 { 4061 bool isNormalFlowOnly = shouldBeNormalFlowOnly(); 4062 if (isNormalFlowOnly != m_isNormalFlowOnly) { 4063 m_isNormalFlowOnly = isNormalFlowOnly; 4064 RenderLayer* p = parent(); 4065 if (p) 4066 p->dirtyNormalFlowList(); 4067 dirtyStackingContextZOrderLists(); 4068 } 4069 4070 if (renderer()->style()->overflowX() == OMARQUEE && renderer()->style()->marqueeBehavior() != MNONE && renderer()->isBox()) { 4071 if (!m_marquee) 4072 m_marquee = new RenderMarquee(this); 4073 m_marquee->updateMarqueeStyle(); 4074 } 4075 else if (m_marquee) { 4076 delete m_marquee; 4077 m_marquee = 0; 4078 } 4079 4080 if (!hasReflection() && m_reflection) 4081 removeReflection(); 4082 else if (hasReflection()) { 4083 if (!m_reflection) 4084 createReflection(); 4085 updateReflectionStyle(); 4086 } 4087 4088 // FIXME: Need to detect a swap from custom to native scrollbars (and vice versa). 4089 if (m_hBar) 4090 m_hBar->styleChanged(); 4091 if (m_vBar) 4092 m_vBar->styleChanged(); 4093 4094 updateScrollCornerStyle(); 4095 updateResizerStyle(); 4096 4097 #if USE(ACCELERATED_COMPOSITING) 4098 updateTransform(); 4099 4100 if (compositor()->updateLayerCompositingState(this)) 4101 compositor()->setCompositingLayersNeedRebuild(); 4102 else if (m_backing) 4103 m_backing->updateGraphicsLayerGeometry(); 4104 else if (oldStyle && oldStyle->overflowX() != renderer()->style()->overflowX()) { 4105 if (stackingContext()->hasCompositingDescendant()) 4106 compositor()->setCompositingLayersNeedRebuild(); 4107 } 4108 4109 if (m_backing && diff >= StyleDifferenceRepaint) 4110 m_backing->setContentsNeedDisplay(); 4111 #else 4112 UNUSED_PARAM(diff); 4113 #endif 4114 } 4115 4116 void RenderLayer::updateScrollCornerStyle() 4117 { 4118 RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer(); 4119 RefPtr<RenderStyle> corner = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, actualRenderer->style()) : 0; 4120 if (corner) { 4121 if (!m_scrollCorner) { 4122 m_scrollCorner = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document()); 4123 m_scrollCorner->setParent(renderer()); 4124 } 4125 m_scrollCorner->setStyle(corner.release()); 4126 } else if (m_scrollCorner) { 4127 m_scrollCorner->destroy(); 4128 m_scrollCorner = 0; 4129 } 4130 } 4131 4132 void RenderLayer::updateResizerStyle() 4133 { 4134 RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer(); 4135 RefPtr<RenderStyle> resizer = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RESIZER, actualRenderer->style()) : 0; 4136 if (resizer) { 4137 if (!m_resizer) { 4138 m_resizer = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document()); 4139 m_resizer->setParent(renderer()); 4140 } 4141 m_resizer->setStyle(resizer.release()); 4142 } else if (m_resizer) { 4143 m_resizer->destroy(); 4144 m_resizer = 0; 4145 } 4146 } 4147 4148 RenderLayer* RenderLayer::reflectionLayer() const 4149 { 4150 return m_reflection ? m_reflection->layer() : 0; 4151 } 4152 4153 void RenderLayer::createReflection() 4154 { 4155 ASSERT(!m_reflection); 4156 m_reflection = new (renderer()->renderArena()) RenderReplica(renderer()->document()); 4157 m_reflection->setParent(renderer()); // We create a 1-way connection. 4158 } 4159 4160 void RenderLayer::removeReflection() 4161 { 4162 if (!m_reflection->documentBeingDestroyed()) 4163 m_reflection->removeLayers(this); 4164 4165 m_reflection->setParent(0); 4166 m_reflection->destroy(); 4167 m_reflection = 0; 4168 } 4169 4170 void RenderLayer::updateReflectionStyle() 4171 { 4172 RefPtr<RenderStyle> newStyle = RenderStyle::create(); 4173 newStyle->inheritFrom(renderer()->style()); 4174 4175 // Map in our transform. 4176 TransformOperations transform; 4177 switch (renderer()->style()->boxReflect()->direction()) { 4178 case ReflectionBelow: 4179 transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE)); 4180 transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE)); 4181 transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE)); 4182 break; 4183 case ReflectionAbove: 4184 transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE)); 4185 transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE)); 4186 transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE)); 4187 break; 4188 case ReflectionRight: 4189 transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE)); 4190 transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE)); 4191 transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE)); 4192 break; 4193 case ReflectionLeft: 4194 transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE)); 4195 transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE)); 4196 transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE)); 4197 break; 4198 } 4199 newStyle->setTransform(transform); 4200 4201 // Map in our mask. 4202 newStyle->setMaskBoxImage(renderer()->style()->boxReflect()->mask()); 4203 4204 m_reflection->setStyle(newStyle.release()); 4205 } 4206 4207 void RenderLayer::updateContentsScale(float scale) 4208 { 4209 #if USE(ACCELERATED_COMPOSITING) 4210 if (m_backing) 4211 m_backing->updateContentsScale(scale); 4212 #endif 4213 } 4214 4215 } // namespace WebCore 4216 4217 #ifndef NDEBUG 4218 void showLayerTree(const WebCore::RenderLayer* layer) 4219 { 4220 if (!layer) 4221 return; 4222 4223 if (WebCore::Frame* frame = layer->renderer()->frame()) { 4224 WTF::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses | WebCore::RenderAsTextShowIDAndClass | WebCore::RenderAsTextDontUpdateLayout | WebCore::RenderAsTextShowLayoutState); 4225 fprintf(stderr, "%s\n", output.utf8().data()); 4226 } 4227 } 4228 4229 void showLayerTree(const WebCore::RenderObject* renderer) 4230 { 4231 if (!renderer) 4232 return; 4233 showLayerTree(renderer->enclosingLayer()); 4234 } 4235 #endif 4236