1/* 2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> 3 * 1999 Lars Knoll <knoll@kde.org> 4 * 1999 Antti Koivisto <koivisto@kde.org> 5 * 2000 Dirk Mueller <mueller@kde.org> 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 7 * (C) 2006 Graham Dennis (graham.dennis@gmail.com) 8 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) 9 * Copyright (C) 2009 Google Inc. All rights reserved. 10 * 11 * This library is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Library General Public 13 * License as published by the Free Software Foundation; either 14 * version 2 of the License, or (at your option) any later version. 15 * 16 * This library is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Library General Public License for more details. 20 * 21 * You should have received a copy of the GNU Library General Public License 22 * along with this library; see the file COPYING.LIB. If not, write to 23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 24 * Boston, MA 02110-1301, USA. 25 */ 26 27#include "config.h" 28#include "FrameView.h" 29 30#include "AXObjectCache.h" 31#include "AnimationController.h" 32#include "BackForwardController.h" 33#include "CachedImage.h" 34#include "CachedResourceLoader.h" 35#include "Chrome.h" 36#include "ChromeClient.h" 37#include "DOMWindow.h" 38#include "DocumentMarkerController.h" 39#include "EventHandler.h" 40#include "FloatRect.h" 41#include "FocusController.h" 42#include "FontCache.h" 43#include "FontLoader.h" 44#include "Frame.h" 45#include "FrameLoader.h" 46#include "FrameLoaderClient.h" 47#include "FrameSelection.h" 48#include "FrameTree.h" 49#include "GraphicsContext.h" 50#include "HTMLDocument.h" 51#include "HTMLFrameElement.h" 52#include "HTMLFrameSetElement.h" 53#include "HTMLNames.h" 54#include "HTMLPlugInImageElement.h" 55#include "InspectorClient.h" 56#include "InspectorController.h" 57#include "InspectorInstrumentation.h" 58#include "OverflowEvent.h" 59#include "ProgressTracker.h" 60#include "RenderArena.h" 61#include "RenderEmbeddedObject.h" 62#include "RenderFullScreen.h" 63#include "RenderIFrame.h" 64#include "RenderLayer.h" 65#include "RenderLayerBacking.h" 66#include "RenderPart.h" 67#include "RenderScrollbar.h" 68#include "RenderScrollbarPart.h" 69#include "RenderStyle.h" 70#include "RenderTheme.h" 71#include "RenderView.h" 72#include "ScrollAnimator.h" 73#include "ScrollingCoordinator.h" 74#include "Settings.h" 75#include "StyleResolver.h" 76#include "TextResourceDecoder.h" 77#include "TextStream.h" 78 79#include <wtf/CurrentTime.h> 80#include <wtf/TemporaryChange.h> 81 82#if USE(ACCELERATED_COMPOSITING) 83#include "RenderLayerCompositor.h" 84#include "TiledBacking.h" 85#endif 86 87#if ENABLE(SVG) 88#include "RenderSVGRoot.h" 89#include "SVGDocument.h" 90#include "SVGSVGElement.h" 91#endif 92 93#if USE(TILED_BACKING_STORE) 94#include "TiledBackingStore.h" 95#endif 96 97#if ENABLE(TEXT_AUTOSIZING) 98#include "TextAutosizer.h" 99#endif 100 101namespace WebCore { 102 103using namespace HTMLNames; 104 105double FrameView::sCurrentPaintTimeStamp = 0.0; 106 107 108// REPAINT_THROTTLING now chooses default values for throttling parameters. 109// Should be removed when applications start using runtime configuration. 110#if ENABLE(REPAINT_THROTTLING) 111// Normal delay 112double FrameView::s_normalDeferredRepaintDelay = 0.016; 113// Negative value would mean that first few repaints happen without a delay 114double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0; 115// The delay grows on each repaint to this maximum value 116double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5; 117// On each repaint the delay increses by this amount 118double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5; 119#else 120// FIXME: Repaint throttling could be good to have on all platform. 121// The balance between CPU use and repaint frequency will need some tuning for desktop. 122// More hooks may be needed to reset the delay on things like GIF and CSS animations. 123double FrameView::s_normalDeferredRepaintDelay = 0; 124double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0; 125double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0; 126double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0; 127#endif 128 129// The maximum number of updateWidgets iterations that should be done before returning. 130static const unsigned maxUpdateWidgetsIterations = 2; 131 132static RenderLayer::UpdateLayerPositionsFlags updateLayerPositionFlags(RenderLayer* layer, bool isRelayoutingSubtree, bool didFullRepaint) 133{ 134 RenderLayer::UpdateLayerPositionsFlags flags = RenderLayer::defaultFlags; 135 if (didFullRepaint) { 136 flags &= ~RenderLayer::CheckForRepaint; 137 flags |= RenderLayer::NeedsFullRepaintInBacking; 138 } 139 if (isRelayoutingSubtree && layer->isPaginated()) 140 flags |= RenderLayer::UpdatePagination; 141 return flags; 142} 143 144Pagination::Mode paginationModeForRenderStyle(RenderStyle* style) 145{ 146 EOverflow overflow = style->overflowY(); 147 if (overflow != OPAGEDX && overflow != OPAGEDY) 148 return Pagination::Unpaginated; 149 150 bool isHorizontalWritingMode = style->isHorizontalWritingMode(); 151 TextDirection textDirection = style->direction(); 152 WritingMode writingMode = style->writingMode(); 153 154 // paged-x always corresponds to LeftToRightPaginated or RightToLeftPaginated. If the WritingMode 155 // is horizontal, then we use TextDirection to choose between those options. If the WritingMode 156 // is vertical, then the direction of the verticality dictates the choice. 157 if (overflow == OPAGEDX) { 158 if ((isHorizontalWritingMode && textDirection == LTR) || writingMode == LeftToRightWritingMode) 159 return Pagination::LeftToRightPaginated; 160 return Pagination::RightToLeftPaginated; 161 } 162 163 // paged-y always corresponds to TopToBottomPaginated or BottomToTopPaginated. If the WritingMode 164 // is horizontal, then the direction of the horizontality dictates the choice. If the WritingMode 165 // is vertical, then we use TextDirection to choose between those options. 166 if (writingMode == TopToBottomWritingMode || (!isHorizontalWritingMode && textDirection == RTL)) 167 return Pagination::TopToBottomPaginated; 168 return Pagination::BottomToTopPaginated; 169} 170 171FrameView::FrameView(Frame* frame) 172 : m_frame(frame) 173 , m_canHaveScrollbars(true) 174 , m_layoutTimer(this, &FrameView::layoutTimerFired) 175 , m_layoutRoot(0) 176 , m_inSynchronousPostLayout(false) 177 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired) 178 , m_updateEmbeddedObjectsTimer(this, &FrameView::updateEmbeddedObjectsTimerFired) 179 , m_isTransparent(false) 180 , m_baseBackgroundColor(Color::white) 181 , m_mediaType("screen") 182 , m_overflowStatusDirty(true) 183 , m_viewportRenderer(0) 184 , m_wasScrolledByUser(false) 185 , m_inProgrammaticScroll(false) 186 , m_safeToPropagateScrollToParent(true) 187 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired) 188 , m_disableRepaints(0) 189 , m_isTrackingRepaints(false) 190 , m_shouldUpdateWhileOffscreen(true) 191 , m_deferSetNeedsLayouts(0) 192 , m_setNeedsLayoutWasDeferred(false) 193 , m_scrollCorner(0) 194 , m_shouldAutoSize(false) 195 , m_inAutoSize(false) 196 , m_didRunAutosize(false) 197 , m_autoSizeFixedMinimumHeight(0) 198 , m_headerHeight(0) 199 , m_footerHeight(0) 200 , m_milestonesPendingPaint(0) 201#if ENABLE(CSS_FILTERS) 202 , m_hasSoftwareFilters(false) 203#endif 204 , m_visualUpdatesAllowedByClient(true) 205 , m_scrollPinningBehavior(DoNotPin) 206{ 207 init(); 208 209 // FIXME: Can m_frame ever be null here? 210 if (!m_frame) 211 return; 212 213 Page* page = m_frame->page(); 214 if (!page) 215 return; 216 217 if (m_frame == page->mainFrame()) { 218 ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed); 219 ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed); 220 } 221} 222 223PassRefPtr<FrameView> FrameView::create(Frame* frame) 224{ 225 RefPtr<FrameView> view = adoptRef(new FrameView(frame)); 226 view->show(); 227 return view.release(); 228} 229 230PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize) 231{ 232 RefPtr<FrameView> view = adoptRef(new FrameView(frame)); 233 view->Widget::setFrameRect(IntRect(view->location(), initialSize)); 234 view->show(); 235 return view.release(); 236} 237 238FrameView::~FrameView() 239{ 240 if (m_postLayoutTasksTimer.isActive()) 241 m_postLayoutTasksTimer.stop(); 242 243 removeFromAXObjectCache(); 244 resetScrollbars(); 245 246 // Custom scrollbars should already be destroyed at this point 247 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar()); 248 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar()); 249 250 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow. 251 setHasVerticalScrollbar(false); 252 253 ASSERT(!m_scrollCorner); 254 255 if (m_frame) { 256 ASSERT(m_frame->view() != this || !m_frame->contentRenderer()); 257 RenderPart* renderer = m_frame->ownerRenderer(); 258 if (renderer && renderer->widget() == this) 259 renderer->setWidget(0); 260 } 261} 262 263void FrameView::reset() 264{ 265 m_cannotBlitToWindow = false; 266 m_isOverlapped = false; 267 m_contentIsOpaque = false; 268 m_borderX = 30; 269 m_borderY = 30; 270 m_layoutTimer.stop(); 271 m_layoutRoot = 0; 272 m_delayedLayout = false; 273 m_doFullRepaint = true; 274 m_layoutSchedulingEnabled = true; 275 m_inLayout = false; 276 m_doingPreLayoutStyleUpdate = false; 277 m_inSynchronousPostLayout = false; 278 m_layoutCount = 0; 279 m_nestedLayoutCount = 0; 280 m_postLayoutTasksTimer.stop(); 281 m_updateEmbeddedObjectsTimer.stop(); 282 m_firstLayout = true; 283 m_firstLayoutCallbackPending = false; 284 m_wasScrolledByUser = false; 285 m_safeToPropagateScrollToParent = true; 286 m_lastViewportSize = IntSize(); 287 m_lastZoomFactor = 1.0f; 288 m_deferringRepaints = 0; 289 m_repaintCount = 0; 290 m_repaintRects.clear(); 291 m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading; 292 m_deferredRepaintTimer.stop(); 293 m_isTrackingRepaints = false; 294 m_trackedRepaintRects.clear(); 295 m_lastPaintTime = 0; 296 m_paintBehavior = PaintBehaviorNormal; 297 m_isPainting = false; 298 m_visuallyNonEmptyCharacterCount = 0; 299 m_visuallyNonEmptyPixelCount = 0; 300 m_isVisuallyNonEmpty = false; 301 m_firstVisuallyNonEmptyLayoutCallbackPending = true; 302 m_maintainScrollPositionAnchor = 0; 303 m_disableRepaints = 0; 304} 305 306void FrameView::removeFromAXObjectCache() 307{ 308 if (AXObjectCache* cache = axObjectCache()) 309 cache->remove(this); 310} 311 312void FrameView::clearFrame() 313{ 314 m_frame = 0; 315} 316 317void FrameView::resetScrollbars() 318{ 319 // Reset the document's scrollbars back to our defaults before we yield the floor. 320 m_firstLayout = true; 321 setScrollbarsSuppressed(true); 322 if (m_canHaveScrollbars) 323 setScrollbarModes(ScrollbarAuto, ScrollbarAuto); 324 else 325 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); 326 setScrollbarsSuppressed(false); 327} 328 329void FrameView::resetScrollbarsAndClearContentsSize() 330{ 331 resetScrollbars(); 332 333 setScrollbarsSuppressed(true); 334 setContentsSize(IntSize()); 335 setScrollbarsSuppressed(false); 336} 337 338void FrameView::init() 339{ 340 reset(); 341 342 m_margins = LayoutSize(-1, -1); // undefined 343 m_size = LayoutSize(); 344 345 // Propagate the marginwidth/height and scrolling modes to the view. 346 Element* ownerElement = m_frame ? m_frame->ownerElement() : 0; 347 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) { 348 HTMLFrameElementBase* frameElt = static_cast<HTMLFrameElementBase*>(ownerElement); 349 if (frameElt->scrollingMode() == ScrollbarAlwaysOff) 350 setCanHaveScrollbars(false); 351 LayoutUnit marginWidth = frameElt->marginWidth(); 352 LayoutUnit marginHeight = frameElt->marginHeight(); 353 if (marginWidth != -1) 354 setMarginWidth(marginWidth); 355 if (marginHeight != -1) 356 setMarginHeight(marginHeight); 357 } 358 359 Page* page = frame() ? frame()->page() : 0; 360 if (page && page->chrome().client()->shouldPaintEntireContents()) 361 setPaintsEntireContents(true); 362} 363 364void FrameView::prepareForDetach() 365{ 366 detachCustomScrollbars(); 367 // When the view is no longer associated with a frame, it needs to be removed from the ax object cache 368 // right now, otherwise it won't be able to reach the topDocument()'s axObject cache later. 369 removeFromAXObjectCache(); 370 371 if (m_frame && m_frame->page()) { 372 if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator()) 373 scrollingCoordinator->willDestroyScrollableArea(this); 374 } 375} 376 377void FrameView::detachCustomScrollbars() 378{ 379 Scrollbar* horizontalBar = horizontalScrollbar(); 380 if (horizontalBar && horizontalBar->isCustomScrollbar()) 381 setHasHorizontalScrollbar(false); 382 383 Scrollbar* verticalBar = verticalScrollbar(); 384 if (verticalBar && verticalBar->isCustomScrollbar()) 385 setHasVerticalScrollbar(false); 386 387 if (m_scrollCorner) { 388 m_scrollCorner->destroy(); 389 m_scrollCorner = 0; 390 } 391} 392 393void FrameView::recalculateScrollbarOverlayStyle() 394{ 395 ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle(); 396 ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault; 397 398 Color backgroundColor = documentBackgroundColor(); 399 if (backgroundColor.isValid()) { 400 // Reduce the background color from RGB to a lightness value 401 // and determine which scrollbar style to use based on a lightness 402 // heuristic. 403 double hue, saturation, lightness; 404 backgroundColor.getHSL(hue, saturation, lightness); 405 if (lightness <= .5 && backgroundColor.alpha() > 0) 406 overlayStyle = ScrollbarOverlayStyleLight; 407 } 408 409 if (oldOverlayStyle != overlayStyle) 410 setScrollbarOverlayStyle(overlayStyle); 411} 412 413void FrameView::clear() 414{ 415 setCanBlitOnScroll(true); 416 417 reset(); 418 419 if (m_frame) { 420 if (RenderPart* renderer = m_frame->ownerRenderer()) 421 renderer->viewCleared(); 422 } 423 424 setScrollbarsSuppressed(true); 425} 426 427bool FrameView::didFirstLayout() const 428{ 429 return !m_firstLayout; 430} 431 432void FrameView::invalidateRect(const IntRect& rect) 433{ 434 if (!parent()) { 435 if (HostWindow* window = hostWindow()) 436 window->invalidateContentsAndRootView(rect, false /*immediate*/); 437 return; 438 } 439 440 if (!m_frame) 441 return; 442 443 RenderPart* renderer = m_frame->ownerRenderer(); 444 if (!renderer) 445 return; 446 447 IntRect repaintRect = rect; 448 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(), 449 renderer->borderTop() + renderer->paddingTop()); 450 renderer->repaintRectangle(repaintRect); 451} 452 453void FrameView::setFrameRect(const IntRect& newRect) 454{ 455 IntRect oldRect = frameRect(); 456 if (newRect == oldRect) 457 return; 458 459#if ENABLE(TEXT_AUTOSIZING) 460 // Autosized font sizes depend on the width of the viewing area. 461 if (newRect.width() != oldRect.width()) { 462 Page* page = m_frame ? m_frame->page() : 0; 463 if (page && page->mainFrame() == m_frame && page->settings()->textAutosizingEnabled()) { 464 for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) 465 m_frame->document()->textAutosizer()->recalculateMultipliers(); 466 } 467 } 468#endif 469 470 ScrollView::setFrameRect(newRect); 471 472 updateScrollableAreaSet(); 473 474#if USE(ACCELERATED_COMPOSITING) 475 if (RenderView* renderView = this->renderView()) { 476 if (renderView->usesCompositing()) 477 renderView->compositor()->frameViewDidChangeSize(); 478 } 479#endif 480 481 sendResizeEventIfNeeded(); 482} 483 484#if ENABLE(REQUEST_ANIMATION_FRAME) 485bool FrameView::scheduleAnimation() 486{ 487 if (hostWindow()) { 488 hostWindow()->scheduleAnimation(); 489 return true; 490 } 491 return false; 492} 493#endif 494 495void FrameView::setMarginWidth(LayoutUnit w) 496{ 497 // make it update the rendering area when set 498 m_margins.setWidth(w); 499} 500 501void FrameView::setMarginHeight(LayoutUnit h) 502{ 503 // make it update the rendering area when set 504 m_margins.setHeight(h); 505} 506 507static bool frameFlatteningEnabled(Frame* frame) 508{ 509 return frame && frame->settings() && frame->settings()->frameFlatteningEnabled(); 510} 511 512static bool supportsFrameFlattening(Frame* frame) 513{ 514 if (!frame) 515 return false; 516 517 // Frame flattening is valid only for <frame> and <iframe>. 518 HTMLFrameOwnerElement* owner = frame->ownerElement(); 519 return owner && (owner->hasTagName(frameTag) || owner->hasTagName(iframeTag)); 520} 521 522bool FrameView::avoidScrollbarCreation() const 523{ 524 ASSERT(m_frame); 525 526 // with frame flattening no subframe can have scrollbars 527 // but we also cannot turn scrollbars off as we determine 528 // our flattening policy using that. 529 530 return frameFlatteningEnabled(frame()) && supportsFrameFlattening(frame()); 531} 532 533void FrameView::setCanHaveScrollbars(bool canHaveScrollbars) 534{ 535 m_canHaveScrollbars = canHaveScrollbars; 536 ScrollView::setCanHaveScrollbars(canHaveScrollbars); 537} 538 539void FrameView::updateCanHaveScrollbars() 540{ 541 ScrollbarMode hMode; 542 ScrollbarMode vMode; 543 scrollbarModes(hMode, vMode); 544 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff) 545 setCanHaveScrollbars(false); 546 else 547 setCanHaveScrollbars(true); 548} 549 550PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation) 551{ 552 if (Settings* settings = m_frame->settings()) { 553 if (!settings->allowCustomScrollbarInMainFrame() && m_frame->page() && m_frame->page()->mainFrame() == m_frame) 554 return ScrollView::createScrollbar(orientation); 555 } 556 557 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles). 558 Document* doc = m_frame->document(); 559 560 // Try the <body> element first as a scrollbar source. 561 Element* body = doc ? doc->body() : 0; 562 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR)) 563 return RenderScrollbar::createCustomScrollbar(this, orientation, body); 564 565 // If the <body> didn't have a custom style, then the root element might. 566 Element* docElement = doc ? doc->documentElement() : 0; 567 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR)) 568 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement); 569 570 // If we have an owning iframe/frame element, then it can set the custom scrollbar also. 571 RenderPart* frameRenderer = m_frame->ownerRenderer(); 572 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR)) 573 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get()); 574 575 // Nobody set a custom style, so we just use a native scrollbar. 576 return ScrollView::createScrollbar(orientation); 577} 578 579void FrameView::setContentsSize(const IntSize& size) 580{ 581 if (size == contentsSize()) 582 return; 583 584 m_deferSetNeedsLayouts++; 585 586 ScrollView::setContentsSize(size); 587 ScrollView::contentsResized(); 588 589 Page* page = frame() ? frame()->page() : 0; 590 if (!page) 591 return; 592 593 updateScrollableAreaSet(); 594 595 page->chrome().contentsSizeChanged(frame(), size); // Notify only. 596 597 m_deferSetNeedsLayouts--; 598 599 if (!m_deferSetNeedsLayouts) 600 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen. 601} 602 603void FrameView::adjustViewSize() 604{ 605 RenderView* renderView = this->renderView(); 606 if (!renderView) 607 return; 608 609 ASSERT(m_frame->view() == this); 610 611 const IntRect rect = renderView->documentRect(); 612 const IntSize& size = rect.size(); 613 ScrollView::setScrollOrigin(IntPoint(-rect.x(), -rect.y()), !m_frame->document()->printing(), size == contentsSize()); 614 615 setContentsSize(size); 616} 617 618void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode) 619{ 620 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats 621 // overflow:hidden and overflow:scroll on <body> as applying to the document's 622 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should 623 // use the root element. 624 625 // To combat the inability to scroll on a page with overflow:hidden on the root when scaled, disregard hidden when 626 // there is a frameScaleFactor that is greater than one on the main frame. Also disregard hidden if there is a 627 // header or footer. 628 629 bool overrideHidden = (m_frame->page() && m_frame->page()->mainFrame() == m_frame && m_frame->frameScaleFactor() > 1) 630 || (m_frame->page() && m_frame->page()->mainFrame() == m_frame && (headerHeight() || footerHeight())); 631 632 EOverflow overflowX = o->style()->overflowX(); 633 EOverflow overflowY = o->style()->overflowY(); 634 635#if ENABLE(SVG) 636 if (o->isSVGRoot()) { 637 // overflow is ignored in stand-alone SVG documents. 638 if (!toRenderSVGRoot(o)->isEmbeddedThroughFrameContainingSVGDocument()) 639 return; 640 overflowX = OHIDDEN; 641 overflowY = OHIDDEN; 642 } 643#endif 644 645 switch (overflowX) { 646 case OHIDDEN: 647 if (overrideHidden) 648 hMode = ScrollbarAuto; 649 else 650 hMode = ScrollbarAlwaysOff; 651 break; 652 case OSCROLL: 653 hMode = ScrollbarAlwaysOn; 654 break; 655 case OAUTO: 656 hMode = ScrollbarAuto; 657 break; 658 default: 659 // Don't set it at all. 660 ; 661 } 662 663 switch (overflowY) { 664 case OHIDDEN: 665 if (overrideHidden) 666 vMode = ScrollbarAuto; 667 else 668 vMode = ScrollbarAlwaysOff; 669 break; 670 case OSCROLL: 671 vMode = ScrollbarAlwaysOn; 672 break; 673 case OAUTO: 674 vMode = ScrollbarAuto; 675 break; 676 default: 677 // Don't set it at all. Values of OPAGEDX and OPAGEDY are handled by applyPaginationToViewPort(). 678 ; 679 } 680 681 m_viewportRenderer = o; 682} 683 684void FrameView::applyPaginationToViewport() 685{ 686 Document* document = m_frame->document(); 687 Node* documentElement = document->documentElement(); 688 RenderObject* documentRenderer = documentElement ? documentElement->renderer() : 0; 689 RenderObject* documentOrBodyRenderer = documentRenderer; 690 Node* body = document->body(); 691 if (body && body->renderer()) { 692 if (body->hasTagName(bodyTag)) 693 documentOrBodyRenderer = documentRenderer->style()->overflowX() == OVISIBLE && documentElement->hasTagName(htmlTag) ? body->renderer() : documentRenderer; 694 } 695 696 Pagination pagination; 697 698 if (!documentOrBodyRenderer) { 699 setPagination(pagination); 700 return; 701 } 702 703 EOverflow overflowY = documentOrBodyRenderer->style()->overflowY(); 704 if (overflowY == OPAGEDX || overflowY == OPAGEDY) { 705 pagination.mode = WebCore::paginationModeForRenderStyle(documentOrBodyRenderer->style()); 706 pagination.gap = static_cast<unsigned>(documentOrBodyRenderer->style()->columnGap()); 707 } 708 709 setPagination(pagination); 710} 711 712void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy) 713{ 714 m_viewportRenderer = 0; 715 716 const HTMLFrameOwnerElement* owner = m_frame->ownerElement(); 717 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) { 718 hMode = ScrollbarAlwaysOff; 719 vMode = ScrollbarAlwaysOff; 720 return; 721 } 722 723 if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) { 724 hMode = ScrollbarAuto; 725 // Seamless documents begin with heights of 0; we special case that here 726 // to correctly render documents that don't need scrollbars. 727 IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size(); 728 bool isSeamlessDocument = frame() && frame()->document() && frame()->document()->shouldDisplaySeamlesslyWithParent(); 729 vMode = (isSeamlessDocument && !fullVisibleSize.height()) ? ScrollbarAlwaysOff : ScrollbarAuto; 730 } else { 731 hMode = ScrollbarAlwaysOff; 732 vMode = ScrollbarAlwaysOff; 733 } 734 735 if (!m_layoutRoot) { 736 Document* document = m_frame->document(); 737 Node* documentElement = document->documentElement(); 738 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0; 739 Node* body = document->body(); 740 if (body && body->renderer()) { 741 if (body->hasTagName(framesetTag) && !frameFlatteningEnabled(frame())) { 742 vMode = ScrollbarAlwaysOff; 743 hMode = ScrollbarAlwaysOff; 744 } else if (body->hasTagName(bodyTag)) { 745 // It's sufficient to just check the X overflow, 746 // since it's illegal to have visible in only one direction. 747 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer; 748 applyOverflowToViewport(o, hMode, vMode); 749 } 750 } else if (rootRenderer) 751 applyOverflowToViewport(rootRenderer, hMode, vMode); 752 } 753} 754 755#if USE(ACCELERATED_COMPOSITING) 756void FrameView::updateCompositingLayersAfterStyleChange() 757{ 758 RenderView* renderView = this->renderView(); 759 if (!renderView) 760 return; 761 762 // If we expect to update compositing after an incipient layout, don't do so here. 763 if (m_doingPreLayoutStyleUpdate || layoutPending() || renderView->needsLayout()) 764 return; 765 766 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref 767 renderView->compositor()->cacheAcceleratedCompositingFlags(); 768 renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterStyleChange); 769} 770 771void FrameView::updateCompositingLayersAfterLayout() 772{ 773 RenderView* renderView = this->renderView(); 774 if (!renderView) 775 return; 776 777 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref 778 renderView->compositor()->cacheAcceleratedCompositingFlags(); 779 renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterLayout); 780} 781 782void FrameView::clearBackingStores() 783{ 784 RenderView* renderView = this->renderView(); 785 if (!renderView) 786 return; 787 788 RenderLayerCompositor* compositor = renderView->compositor(); 789 ASSERT(compositor->inCompositingMode()); 790 compositor->enableCompositingMode(false); 791 compositor->clearBackingForAllLayers(); 792} 793 794void FrameView::restoreBackingStores() 795{ 796 RenderView* renderView = this->renderView(); 797 if (!renderView) 798 return; 799 800 RenderLayerCompositor* compositor = renderView->compositor(); 801 compositor->enableCompositingMode(true); 802 compositor->updateCompositingLayers(CompositingUpdateAfterLayout); 803} 804 805bool FrameView::usesCompositedScrolling() const 806{ 807 RenderView* renderView = this->renderView(); 808 if (!renderView) 809 return false; 810 if (m_frame->settings() && m_frame->settings()->compositedScrollingForFramesEnabled()) 811 return renderView->compositor()->inForcedCompositingMode(); 812 return false; 813} 814 815GraphicsLayer* FrameView::layerForScrolling() const 816{ 817 RenderView* renderView = this->renderView(); 818 if (!renderView) 819 return 0; 820 return renderView->compositor()->scrollLayer(); 821} 822 823GraphicsLayer* FrameView::layerForHorizontalScrollbar() const 824{ 825 RenderView* renderView = this->renderView(); 826 if (!renderView) 827 return 0; 828 return renderView->compositor()->layerForHorizontalScrollbar(); 829} 830 831GraphicsLayer* FrameView::layerForVerticalScrollbar() const 832{ 833 RenderView* renderView = this->renderView(); 834 if (!renderView) 835 return 0; 836 return renderView->compositor()->layerForVerticalScrollbar(); 837} 838 839GraphicsLayer* FrameView::layerForScrollCorner() const 840{ 841 RenderView* renderView = this->renderView(); 842 if (!renderView) 843 return 0; 844 return renderView->compositor()->layerForScrollCorner(); 845} 846 847TiledBacking* FrameView::tiledBacking() 848{ 849 RenderView* renderView = this->renderView(); 850 if (!renderView) 851 return 0; 852 853 RenderLayerBacking* backing = renderView->layer()->backing(); 854 if (!backing) 855 return 0; 856 857 return backing->graphicsLayer()->tiledBacking(); 858} 859 860uint64_t FrameView::scrollLayerID() const 861{ 862 RenderView* renderView = this->renderView(); 863 if (!renderView) 864 return 0; 865 866 RenderLayerBacking* backing = renderView->layer()->backing(); 867 if (!backing) 868 return 0; 869 870 return backing->scrollLayerID(); 871} 872 873#if ENABLE(RUBBER_BANDING) 874GraphicsLayer* FrameView::layerForOverhangAreas() const 875{ 876 RenderView* renderView = this->renderView(); 877 if (!renderView) 878 return 0; 879 return renderView->compositor()->layerForOverhangAreas(); 880} 881 882GraphicsLayer* FrameView::setWantsLayerForTopOverHangArea(bool wantsLayer) const 883{ 884 RenderView* renderView = this->renderView(); 885 if (!renderView) 886 return 0; 887 888 return renderView->compositor()->updateLayerForTopOverhangArea(wantsLayer); 889} 890 891GraphicsLayer* FrameView::setWantsLayerForBottomOverHangArea(bool wantsLayer) const 892{ 893 RenderView* renderView = this->renderView(); 894 if (!renderView) 895 return 0; 896 897 return renderView->compositor()->updateLayerForBottomOverhangArea(wantsLayer); 898} 899 900#endif // ENABLE(RUBBER_BANDING) 901 902bool FrameView::scrollbarAnimationsAreSuppressed() const 903{ 904 Page* page = frame() ? frame()->page() : 0; 905 if (!page) 906 return true; 907 return page->shouldSuppressScrollbarAnimations(); 908} 909 910bool FrameView::flushCompositingStateForThisFrame(Frame* rootFrameForFlush) 911{ 912 RenderView* renderView = this->renderView(); 913 if (!renderView) 914 return true; // We don't want to keep trying to update layers if we have no renderer. 915 916 ASSERT(m_frame->view() == this); 917 918 // If we sync compositing layers when a layout is pending, we may cause painting of compositing 919 // layer content to occur before layout has happened, which will cause paintContents() to bail. 920 if (needsLayout()) 921 return false; 922 923 // If we sync compositing layers and allow the repaint to be deferred, there is time for a 924 // visible flash to occur. Instead, stop the deferred repaint timer and repaint immediately. 925 flushDeferredRepaints(); 926 927 renderView->compositor()->flushPendingLayerChanges(rootFrameForFlush == m_frame); 928 929 return true; 930} 931 932void FrameView::setNeedsOneShotDrawingSynchronization() 933{ 934 Page* page = frame() ? frame()->page() : 0; 935 if (page) 936 page->chrome().client()->setNeedsOneShotDrawingSynchronization(); 937} 938 939#endif // USE(ACCELERATED_COMPOSITING) 940 941void FrameView::setHeaderHeight(int headerHeight) 942{ 943 if (m_frame && m_frame->page()) 944 ASSERT(m_frame == m_frame->page()->mainFrame()); 945 m_headerHeight = headerHeight; 946 947 if (RenderView* renderView = this->renderView()) 948 renderView->setNeedsLayout(true); 949} 950 951void FrameView::setFooterHeight(int footerHeight) 952{ 953 if (m_frame && m_frame->page()) 954 ASSERT(m_frame == m_frame->page()->mainFrame()); 955 m_footerHeight = footerHeight; 956 957 if (RenderView* renderView = this->renderView()) 958 renderView->setNeedsLayout(true); 959} 960 961bool FrameView::hasCompositedContent() const 962{ 963#if USE(ACCELERATED_COMPOSITING) 964 if (RenderView* renderView = this->renderView()) 965 return renderView->compositor()->inCompositingMode(); 966#endif 967 return false; 968} 969 970bool FrameView::hasCompositedContentIncludingDescendants() const 971{ 972#if USE(ACCELERATED_COMPOSITING) 973 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 974 RenderView* renderView = frame->contentRenderer(); 975 RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0; 976 if (compositor) { 977 if (compositor->inCompositingMode()) 978 return true; 979 980 if (!RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) 981 break; 982 } 983 } 984#endif 985 return false; 986} 987 988bool FrameView::hasCompositingAncestor() const 989{ 990#if USE(ACCELERATED_COMPOSITING) 991 for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) { 992 if (FrameView* view = frame->view()) { 993 if (view->hasCompositedContent()) 994 return true; 995 } 996 } 997#endif 998 return false; 999} 1000 1001// Sometimes (for plug-ins) we need to eagerly go into compositing mode. 1002void FrameView::enterCompositingMode() 1003{ 1004#if USE(ACCELERATED_COMPOSITING) 1005 if (RenderView* renderView = this->renderView()) { 1006 renderView->compositor()->enableCompositingMode(); 1007 if (!needsLayout()) 1008 renderView->compositor()->scheduleCompositingLayerUpdate(); 1009 } 1010#endif 1011} 1012 1013bool FrameView::isEnclosedInCompositingLayer() const 1014{ 1015#if USE(ACCELERATED_COMPOSITING) 1016 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer(); 1017 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint()) 1018 return true; 1019 1020 if (FrameView* parentView = parentFrameView()) 1021 return parentView->isEnclosedInCompositingLayer(); 1022#endif 1023 return false; 1024} 1025 1026bool FrameView::flushCompositingStateIncludingSubframes() 1027{ 1028#if USE(ACCELERATED_COMPOSITING) 1029 bool allFramesFlushed = flushCompositingStateForThisFrame(m_frame.get()); 1030 1031 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame.get())) { 1032 bool flushed = child->view()->flushCompositingStateForThisFrame(m_frame.get()); 1033 allFramesFlushed &= flushed; 1034 } 1035 return allFramesFlushed; 1036#else // USE(ACCELERATED_COMPOSITING) 1037 return true; 1038#endif 1039} 1040 1041bool FrameView::isSoftwareRenderable() const 1042{ 1043#if USE(ACCELERATED_COMPOSITING) 1044 RenderView* renderView = this->renderView(); 1045 return !renderView || !renderView->compositor()->has3DContent(); 1046#else 1047 return true; 1048#endif 1049} 1050 1051void FrameView::didMoveOnscreen() 1052{ 1053 contentAreaDidShow(); 1054} 1055 1056void FrameView::willMoveOffscreen() 1057{ 1058 contentAreaDidHide(); 1059} 1060 1061void FrameView::setIsInWindow(bool isInWindow) 1062{ 1063 if (RenderView* renderView = this->renderView()) 1064 renderView->setIsInWindow(isInWindow); 1065} 1066 1067RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const 1068{ 1069 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot; 1070} 1071 1072static inline void collectFrameViewChildren(FrameView* frameView, Vector<RefPtr<FrameView> >& frameViews) 1073{ 1074 const HashSet<RefPtr<Widget> >* viewChildren = frameView->children(); 1075 ASSERT(viewChildren); 1076 1077 const HashSet<RefPtr<Widget> >::iterator end = viewChildren->end(); 1078 for (HashSet<RefPtr<Widget> >::iterator current = viewChildren->begin(); current != end; ++current) { 1079 Widget* widget = (*current).get(); 1080 if (widget->isFrameView()) 1081 frameViews.append(toFrameView(widget)); 1082 } 1083} 1084 1085inline void FrameView::forceLayoutParentViewIfNeeded() 1086{ 1087#if ENABLE(SVG) 1088 RenderPart* ownerRenderer = m_frame->ownerRenderer(); 1089 if (!ownerRenderer || !ownerRenderer->frame()) 1090 return; 1091 1092 RenderBox* contentBox = embeddedContentBox(); 1093 if (!contentBox) 1094 return; 1095 1096 RenderSVGRoot* svgRoot = toRenderSVGRoot(contentBox); 1097 if (svgRoot->everHadLayout() && !svgRoot->needsLayout()) 1098 return; 1099 1100 // If the embedded SVG document appears the first time, the ownerRenderer has already finished 1101 // layout without knowing about the existence of the embedded SVG document, because RenderReplaced 1102 // embeddedContentBox() returns 0, as long as the embedded document isn't loaded yet. Before 1103 // bothering to lay out the SVG document, mark the ownerRenderer needing layout and ask its 1104 // FrameView for a layout. After that the RenderEmbeddedObject (ownerRenderer) carries the 1105 // correct size, which RenderSVGRoot::computeReplacedLogicalWidth/Height rely on, when laying 1106 // out for the first time, or when the RenderSVGRoot size has changed dynamically (eg. via <script>). 1107 RefPtr<FrameView> frameView = ownerRenderer->frame()->view(); 1108 1109 // Mark the owner renderer as needing layout. 1110 ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc(); 1111 1112 // Synchronously enter layout, to layout the view containing the host object/embed/iframe. 1113 ASSERT(frameView); 1114 frameView->layout(); 1115#endif 1116} 1117 1118void FrameView::layout(bool allowSubtree) 1119{ 1120 if (m_inLayout) 1121 return; 1122 1123 // Protect the view from being deleted during layout (in recalcStyle) 1124 RefPtr<FrameView> protector(this); 1125 1126 // Every scroll that happens during layout is programmatic. 1127 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true); 1128 1129 bool inChildFrameLayoutWithFrameFlattening = isInChildFrameWithFrameFlattening(); 1130 1131 if (inChildFrameLayoutWithFrameFlattening) { 1132 if (doLayoutWithFrameFlattening(allowSubtree)) 1133 return; 1134 } 1135 1136 m_layoutTimer.stop(); 1137 m_delayedLayout = false; 1138 m_setNeedsLayoutWasDeferred = false; 1139 1140 if (!m_frame) { 1141 // FIXME: Do we need to set m_size.width here? 1142 // FIXME: Should we set m_size.height here too? 1143 m_size.setWidth(layoutWidth()); 1144 return; 1145 } 1146 1147 // we shouldn't enter layout() while painting 1148 ASSERT(!isPainting()); 1149 if (isPainting()) 1150 return; 1151 1152 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get()); 1153 1154 if (!allowSubtree && m_layoutRoot) { 1155 m_layoutRoot->markContainingBlocksForLayout(false); 1156 m_layoutRoot = 0; 1157 } 1158 1159 ASSERT(m_frame->view() == this); 1160 1161 Document* document = m_frame->document(); 1162 ASSERT(!document->inPageCache()); 1163 bool subtree; 1164 RenderObject* root; 1165 1166 { 1167 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false); 1168 1169 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_postLayoutTasksTimer.isActive() && !inChildFrameLayoutWithFrameFlattening) { 1170 // This is a new top-level layout. If there are any remaining tasks from the previous 1171 // layout, finish them now. 1172 m_inSynchronousPostLayout = true; 1173 performPostLayoutTasks(); 1174 m_inSynchronousPostLayout = false; 1175 } 1176 1177 // Viewport-dependent media queries may cause us to need completely different style information. 1178 if (!document->styleResolverIfExists() || document->styleResolverIfExists()->affectedByViewportChange()) { 1179 document->styleResolverChanged(DeferRecalcStyle); 1180 // FIXME: This instrumentation event is not strictly accurate since cached media query results 1181 // do not persist across StyleResolver rebuilds. 1182 InspectorInstrumentation::mediaQueryResultChanged(document); 1183 } else 1184 document->evaluateMediaQueryList(); 1185 1186 // If there is any pagination to apply, it will affect the RenderView's style, so we should 1187 // take care of that now. 1188 applyPaginationToViewport(); 1189 1190 // Always ensure our style info is up-to-date. This can happen in situations where 1191 // the layout beats any sort of style recalc update that needs to occur. 1192 TemporaryChange<bool> changeDoingPreLayoutStyleUpdate(m_doingPreLayoutStyleUpdate, true); 1193 document->updateStyleIfNeeded(); 1194 1195 subtree = m_layoutRoot; 1196 1197 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit, 1198 // so there's no point to continuing to layout 1199 if (protector->hasOneRef()) 1200 return; 1201 1202 root = subtree ? m_layoutRoot : document->renderer(); 1203 if (!root) { 1204 // FIXME: Do we need to set m_size here? 1205 return; 1206 } 1207 } // Reset m_layoutSchedulingEnabled to its previous value. 1208 // The only reason the scoping was closed here is allow fontCachePurgePreventer 1209 // to outlive the change and reset of m_layoutSchedulingEnabled. 1210 1211 FontCachePurgePreventer fontCachePurgePreventer; 1212 RenderLayer* layer; 1213 { 1214 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false); 1215 1216 m_nestedLayoutCount++; 1217 1218 if (!m_layoutRoot) { 1219 Document* document = m_frame->document(); 1220 Node* body = document->body(); 1221 if (body && body->renderer()) { 1222 if (body->hasTagName(framesetTag) && !frameFlatteningEnabled(frame())) { 1223 body->renderer()->setChildNeedsLayout(true); 1224 } else if (body->hasTagName(bodyTag)) { 1225 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport()) 1226 body->renderer()->setChildNeedsLayout(true); 1227 } 1228 } 1229 1230#ifdef INSTRUMENT_LAYOUT_SCHEDULING 1231 if (m_firstLayout && !m_frame->ownerElement()) 1232 printf("Elapsed time before first layout: %d\n", document->elapsedTime()); 1233#endif 1234 } 1235 1236 autoSizeIfEnabled(); 1237 1238 ScrollbarMode hMode; 1239 ScrollbarMode vMode; 1240 calculateScrollbarModesForLayout(hMode, vMode); 1241 1242 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing()); 1243 1244 if (!subtree) { 1245 // Now set our scrollbar state for the layout. 1246 ScrollbarMode currentHMode = horizontalScrollbarMode(); 1247 ScrollbarMode currentVMode = verticalScrollbarMode(); 1248 1249 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) { 1250 if (m_firstLayout) { 1251 setScrollbarsSuppressed(true); 1252 1253 m_firstLayout = false; 1254 m_firstLayoutCallbackPending = true; 1255 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling()) 1256 m_lastViewportSize = fixedLayoutSize(); 1257 else 1258 m_lastViewportSize = visibleContentRect(IncludeScrollbars).size(); 1259 m_lastZoomFactor = root->style()->zoom(); 1260 1261 // Set the initial vMode to AlwaysOn if we're auto. 1262 if (vMode == ScrollbarAuto) 1263 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear. 1264 // Set the initial hMode to AlwaysOff if we're auto. 1265 if (hMode == ScrollbarAuto) 1266 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear. 1267 1268 setScrollbarModes(hMode, vMode); 1269 setScrollbarsSuppressed(false, true); 1270 } else 1271 setScrollbarModes(hMode, vMode); 1272 } 1273 1274 LayoutSize oldSize = m_size; 1275 1276 m_size = layoutSize(); 1277 1278 if (oldSize != m_size) { 1279 m_doFullRepaint = true; 1280 if (!m_firstLayout) { 1281 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0; 1282 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0; 1283 if (bodyRenderer && bodyRenderer->stretchesToViewport()) 1284 bodyRenderer->setChildNeedsLayout(true); 1285 else if (rootRenderer && rootRenderer->stretchesToViewport()) 1286 rootRenderer->setChildNeedsLayout(true); 1287 } 1288 } 1289 } 1290 1291 layer = root->enclosingLayer(); 1292 1293 { 1294 bool disableLayoutState = false; 1295 if (subtree) { 1296 RenderView* view = root->view(); 1297 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root); 1298 view->pushLayoutState(root); 1299 } 1300 LayoutStateDisabler layoutStateDisabler(disableLayoutState ? root->view() : 0); 1301 1302 m_inLayout = true; 1303 beginDeferredRepaints(); 1304 forceLayoutParentViewIfNeeded(); 1305 root->layout(); 1306#if ENABLE(TEXT_AUTOSIZING) 1307 bool autosized = document->textAutosizer()->processSubtree(root); 1308 if (autosized && root->needsLayout()) 1309 root->layout(); 1310#endif 1311 endDeferredRepaints(); 1312 m_inLayout = false; 1313 1314 if (subtree) 1315 root->view()->popLayoutState(root); 1316 } 1317 m_layoutRoot = 0; 1318 } // Reset m_layoutSchedulingEnabled to its previous value. 1319 1320 bool neededFullRepaint = m_doFullRepaint; 1321 1322 if (!subtree && !toRenderView(root)->printing()) 1323 adjustViewSize(); 1324 1325 m_doFullRepaint = neededFullRepaint; 1326 1327 // Now update the positions of all layers. 1328 beginDeferredRepaints(); 1329 if (m_doFullRepaint) 1330 root->view()->repaint(); // FIXME: This isn't really right, since the RenderView doesn't fully encompass the visibleContentRect(). It just happens 1331 // to work out most of the time, since first layouts and printing don't have you scrolled anywhere. 1332 1333 layer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPositionFlags(layer, subtree, m_doFullRepaint)); 1334 1335 endDeferredRepaints(); 1336 1337#if USE(ACCELERATED_COMPOSITING) 1338 updateCompositingLayersAfterLayout(); 1339#endif 1340 1341 m_layoutCount++; 1342 1343#if PLATFORM(MAC) || PLATFORM(WIN) 1344 if (AXObjectCache* cache = root->document()->existingAXObjectCache()) 1345 cache->postNotification(root, AXObjectCache::AXLayoutComplete, true); 1346#endif 1347#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION) 1348 updateAnnotatedRegions(); 1349#endif 1350 1351 ASSERT(!root->needsLayout()); 1352 1353 updateCanBlitOnScrollRecursively(); 1354 1355 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER)) 1356 updateOverflowStatus(layoutWidth() < contentsWidth(), 1357 layoutHeight() < contentsHeight()); 1358 1359 if (!m_postLayoutTasksTimer.isActive()) { 1360 if (!m_inSynchronousPostLayout) { 1361 if (inChildFrameLayoutWithFrameFlattening) { 1362 if (RenderView* renderView = this->renderView()) 1363 renderView->updateWidgetPositions(); 1364 } else { 1365 m_inSynchronousPostLayout = true; 1366 // Calls resumeScheduledEvents() 1367 performPostLayoutTasks(); 1368 m_inSynchronousPostLayout = false; 1369 } 1370 } 1371 1372 if (!m_postLayoutTasksTimer.isActive() && (needsLayout() || m_inSynchronousPostLayout || inChildFrameLayoutWithFrameFlattening)) { 1373 // If we need layout or are already in a synchronous call to postLayoutTasks(), 1374 // defer widget updates and event dispatch until after we return. postLayoutTasks() 1375 // can make us need to update again, and we can get stuck in a nasty cycle unless 1376 // we call it through the timer here. 1377 m_postLayoutTasksTimer.startOneShot(0); 1378 if (needsLayout()) 1379 layout(); 1380 } 1381 } 1382 1383 InspectorInstrumentation::didLayout(cookie, root); 1384 1385 m_nestedLayoutCount--; 1386 if (m_nestedLayoutCount) 1387 return; 1388 1389 Page* page = frame() ? frame()->page() : 0; 1390 if (!page) 1391 return; 1392 1393 page->chrome().client()->layoutUpdated(frame()); 1394} 1395 1396RenderBox* FrameView::embeddedContentBox() const 1397{ 1398#if ENABLE(SVG) 1399 RenderView* renderView = this->renderView(); 1400 if (!renderView) 1401 return 0; 1402 1403 RenderObject* firstChild = renderView->firstChild(); 1404 if (!firstChild || !firstChild->isBox()) 1405 return 0; 1406 1407 // Curently only embedded SVG documents participate in the size-negotiation logic. 1408 if (firstChild->isSVGRoot()) 1409 return toRenderBox(firstChild); 1410#endif 1411 1412 return 0; 1413} 1414 1415void FrameView::addWidgetToUpdate(RenderObject* object) 1416{ 1417 if (!m_widgetUpdateSet) 1418 m_widgetUpdateSet = adoptPtr(new RenderObjectSet); 1419 1420 // Tell the DOM element that it needs a widget update. 1421 Node* node = object->node(); 1422 if (node->hasTagName(objectTag) || node->hasTagName(embedTag)) { 1423 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(node); 1424 if (!pluginElement->needsCheckForSizeChange()) 1425 pluginElement->setNeedsWidgetUpdate(true); 1426 } 1427 1428 m_widgetUpdateSet->add(object); 1429} 1430 1431void FrameView::removeWidgetToUpdate(RenderObject* object) 1432{ 1433 if (!m_widgetUpdateSet) 1434 return; 1435 1436 m_widgetUpdateSet->remove(object); 1437} 1438 1439void FrameView::setMediaType(const String& mediaType) 1440{ 1441 m_mediaType = mediaType; 1442} 1443 1444String FrameView::mediaType() const 1445{ 1446 // See if we have an override type. 1447 String overrideType = m_frame->loader()->client()->overrideMediaType(); 1448 InspectorInstrumentation::applyEmulatedMedia(m_frame.get(), &overrideType); 1449 if (!overrideType.isNull()) 1450 return overrideType; 1451 return m_mediaType; 1452} 1453 1454void FrameView::adjustMediaTypeForPrinting(bool printing) 1455{ 1456 if (printing) { 1457 if (m_mediaTypeWhenNotPrinting.isNull()) 1458 m_mediaTypeWhenNotPrinting = mediaType(); 1459 setMediaType("print"); 1460 } else { 1461 if (!m_mediaTypeWhenNotPrinting.isNull()) 1462 setMediaType(m_mediaTypeWhenNotPrinting); 1463 m_mediaTypeWhenNotPrinting = String(); 1464 } 1465} 1466 1467bool FrameView::useSlowRepaints(bool considerOverlap) const 1468{ 1469 bool mustBeSlow = hasSlowRepaintObjects() || (platformWidget() && hasViewportConstrainedObjects()); 1470 1471 // FIXME: WidgetMac.mm makes the assumption that useSlowRepaints == 1472 // m_contentIsOpaque, so don't take the fast path for composited layers 1473 // if they are a platform widget in order to get painting correctness 1474 // for transparent layers. See the comment in WidgetMac::paint. 1475 if (contentsInCompositedLayer() && !platformWidget()) 1476 return mustBeSlow; 1477 1478 bool isOverlapped = m_isOverlapped && considerOverlap; 1479 1480 if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque) 1481 return true; 1482 1483 if (FrameView* parentView = parentFrameView()) 1484 return parentView->useSlowRepaints(considerOverlap); 1485 1486 return false; 1487} 1488 1489bool FrameView::useSlowRepaintsIfNotOverlapped() const 1490{ 1491 return useSlowRepaints(false); 1492} 1493 1494void FrameView::updateCanBlitOnScrollRecursively() 1495{ 1496 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 1497 if (FrameView* view = frame->view()) 1498 view->setCanBlitOnScroll(!view->useSlowRepaints()); 1499 } 1500} 1501 1502bool FrameView::contentsInCompositedLayer() const 1503{ 1504#if USE(ACCELERATED_COMPOSITING) 1505 RenderView* renderView = this->renderView(); 1506 if (renderView && renderView->isComposited()) { 1507 GraphicsLayer* layer = renderView->layer()->backing()->graphicsLayer(); 1508 if (layer && layer->drawsContent()) 1509 return true; 1510 } 1511#endif 1512 return false; 1513} 1514 1515void FrameView::setCannotBlitToWindow() 1516{ 1517 m_cannotBlitToWindow = true; 1518 updateCanBlitOnScrollRecursively(); 1519} 1520 1521void FrameView::addSlowRepaintObject(RenderObject* o) 1522{ 1523 bool hadSlowRepaintObjects = hasSlowRepaintObjects(); 1524 1525 if (!m_slowRepaintObjects) 1526 m_slowRepaintObjects = adoptPtr(new RenderObjectSet); 1527 1528 m_slowRepaintObjects->add(o); 1529 1530 if (!hadSlowRepaintObjects) { 1531 updateCanBlitOnScrollRecursively(); 1532 1533 if (Page* page = m_frame->page()) { 1534 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) 1535 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this); 1536 } 1537 } 1538} 1539 1540void FrameView::removeSlowRepaintObject(RenderObject* o) 1541{ 1542 if (!m_slowRepaintObjects) 1543 return; 1544 1545 m_slowRepaintObjects->remove(o); 1546 if (m_slowRepaintObjects->isEmpty()) { 1547 m_slowRepaintObjects = nullptr; 1548 updateCanBlitOnScrollRecursively(); 1549 1550 if (Page* page = m_frame->page()) { 1551 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) 1552 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this); 1553 } 1554 } 1555} 1556 1557void FrameView::addViewportConstrainedObject(RenderObject* object) 1558{ 1559 if (!m_viewportConstrainedObjects) 1560 m_viewportConstrainedObjects = adoptPtr(new ViewportConstrainedObjectSet); 1561 1562 if (!m_viewportConstrainedObjects->contains(object)) { 1563 m_viewportConstrainedObjects->add(object); 1564 if (platformWidget()) 1565 updateCanBlitOnScrollRecursively(); 1566 1567 if (Page* page = m_frame->page()) { 1568 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) 1569 scrollingCoordinator->frameViewFixedObjectsDidChange(this); 1570 } 1571 } 1572} 1573 1574void FrameView::removeViewportConstrainedObject(RenderObject* object) 1575{ 1576 if (m_viewportConstrainedObjects && m_viewportConstrainedObjects->contains(object)) { 1577 m_viewportConstrainedObjects->remove(object); 1578 if (Page* page = m_frame->page()) { 1579 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) 1580 scrollingCoordinator->frameViewFixedObjectsDidChange(this); 1581 } 1582 1583 // FIXME: In addFixedObject() we only call this if there's a platform widget, 1584 // why isn't the same check being made here? 1585 updateCanBlitOnScrollRecursively(); 1586 } 1587} 1588 1589LayoutRect FrameView::viewportConstrainedVisibleContentRect() const 1590{ 1591 LayoutRect viewportRect = visibleContentRect(); 1592 viewportRect.setLocation(toPoint(scrollOffsetForFixedPosition())); 1593 return viewportRect; 1594} 1595 1596IntSize FrameView::scrollOffsetForFixedPosition(const IntRect& visibleContentRect, const IntSize& totalContentsSize, const IntPoint& scrollPosition, const IntPoint& scrollOrigin, float frameScaleFactor, bool fixedElementsLayoutRelativeToFrame, int headerHeight, int footerHeight) 1597{ 1598 IntPoint constrainedPosition = ScrollableArea::constrainScrollPositionForOverhang(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, headerHeight, footerHeight); 1599 1600 IntSize maxSize = totalContentsSize - visibleContentRect.size(); 1601 1602 float dragFactorX = (fixedElementsLayoutRelativeToFrame || !maxSize.width()) ? 1 : (totalContentsSize.width() - visibleContentRect.width() * frameScaleFactor) / maxSize.width(); 1603 float dragFactorY = (fixedElementsLayoutRelativeToFrame || !maxSize.height()) ? 1 : (totalContentsSize.height() - visibleContentRect.height() * frameScaleFactor) / maxSize.height(); 1604 1605 return IntSize(constrainedPosition.x() * dragFactorX / frameScaleFactor, constrainedPosition.y() * dragFactorY / frameScaleFactor); 1606} 1607 1608IntSize FrameView::scrollOffsetForFixedPosition() const 1609{ 1610 IntRect visibleContentRect = this->visibleContentRect(); 1611 IntSize totalContentsSize = this->totalContentsSize(); 1612 IntPoint scrollPosition = this->scrollPosition(); 1613 IntPoint scrollOrigin = this->scrollOrigin(); 1614 float frameScaleFactor = m_frame ? m_frame->frameScaleFactor() : 1; 1615 return scrollOffsetForFixedPosition(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, frameScaleFactor, fixedElementsLayoutRelativeToFrame(), headerHeight(), footerHeight()); 1616} 1617 1618IntPoint FrameView::minimumScrollPosition() const 1619{ 1620 IntPoint minimumPosition(ScrollView::minimumScrollPosition()); 1621 1622 if (!m_frame || !m_frame->page()) 1623 return minimumPosition; 1624 1625 if (m_frame == m_frame->page()->mainFrame() && m_scrollPinningBehavior == PinToBottom) 1626 minimumPosition.setY(maximumScrollPosition().y()); 1627 1628 return minimumPosition; 1629} 1630 1631IntPoint FrameView::maximumScrollPosition() const 1632{ 1633 IntPoint maximumOffset(contentsWidth() - visibleWidth() - scrollOrigin().x(), totalContentsSize().height() - visibleHeight() - scrollOrigin().y()); 1634 1635 maximumOffset.clampNegativeToZero(); 1636 1637 if (!m_frame || !m_frame->page()) 1638 return maximumOffset; 1639 1640 if (m_frame == m_frame->page()->mainFrame() && m_scrollPinningBehavior == PinToTop) 1641 maximumOffset.setY(minimumScrollPosition().y()); 1642 1643 return maximumOffset; 1644} 1645 1646bool FrameView::fixedElementsLayoutRelativeToFrame() const 1647{ 1648 ASSERT(m_frame); 1649 if (!m_frame->settings()) 1650 return false; 1651 1652 return m_frame->settings()->fixedElementsLayoutRelativeToFrame(); 1653} 1654 1655IntPoint FrameView::lastKnownMousePosition() const 1656{ 1657 return m_frame ? m_frame->eventHandler()->lastKnownMousePosition() : IntPoint(); 1658} 1659 1660bool FrameView::isHandlingWheelEvent() const 1661{ 1662 return m_frame ? m_frame->eventHandler()->isHandlingWheelEvent() : false; 1663} 1664 1665bool FrameView::shouldSetCursor() const 1666{ 1667 Page* page = frame()->page(); 1668 return page && page->isOnscreen() && page->focusController()->isActive(); 1669} 1670 1671bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) 1672{ 1673 if (!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty()) { 1674 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect); 1675 return true; 1676 } 1677 1678 const bool isCompositedContentLayer = contentsInCompositedLayer(); 1679 1680 // Get the rects of the fixed objects visible in the rectToScroll 1681 Region regionToUpdate; 1682 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end(); 1683 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) { 1684 RenderObject* renderer = *it; 1685 if (!renderer->style()->hasViewportConstrainedPosition()) 1686 continue; 1687#if USE(ACCELERATED_COMPOSITING) 1688 if (renderer->isComposited()) 1689 continue; 1690#endif 1691 1692 // Fixed items should always have layers. 1693 ASSERT(renderer->hasLayer()); 1694 RenderLayer* layer = toRenderBoxModelObject(renderer)->layer(); 1695 1696#if USE(ACCELERATED_COMPOSITING) 1697 if (layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForBoundsOutOfView 1698 || layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForNoVisibleContent) { 1699 // Don't invalidate for invisible fixed layers. 1700 continue; 1701 } 1702#endif 1703 1704#if ENABLE(CSS_FILTERS) 1705 if (layer->hasAncestorWithFilterOutsets()) { 1706 // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot 1707 // scroll using the fast path, otherwise the outsets of the filter will be moved around the page. 1708 return false; 1709 } 1710#endif 1711 IntRect updateRect = pixelSnappedIntRect(layer->repaintRectIncludingNonCompositingDescendants()); 1712 updateRect = contentsToRootView(updateRect); 1713 if (!isCompositedContentLayer && clipsRepaints()) 1714 updateRect.intersect(rectToScroll); 1715 if (!updateRect.isEmpty()) 1716 regionToUpdate.unite(updateRect); 1717 } 1718 1719 // 1) scroll 1720 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect); 1721 1722 // 2) update the area of fixed objects that has been invalidated 1723 Vector<IntRect> subRectsToUpdate = regionToUpdate.rects(); 1724 size_t viewportConstrainedObjectsCount = subRectsToUpdate.size(); 1725 for (size_t i = 0; i < viewportConstrainedObjectsCount; ++i) { 1726 IntRect updateRect = subRectsToUpdate[i]; 1727 IntRect scrolledRect = updateRect; 1728 scrolledRect.move(scrollDelta); 1729 updateRect.unite(scrolledRect); 1730#if USE(ACCELERATED_COMPOSITING) 1731 if (isCompositedContentLayer) { 1732 updateRect = rootViewToContents(updateRect); 1733 ASSERT(renderView()); 1734 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect); 1735 continue; 1736 } 1737#endif 1738 if (clipsRepaints()) 1739 updateRect.intersect(rectToScroll); 1740 hostWindow()->invalidateContentsAndRootView(updateRect, false); 1741 } 1742 1743 return true; 1744} 1745 1746void FrameView::scrollContentsSlowPath(const IntRect& updateRect) 1747{ 1748#if USE(ACCELERATED_COMPOSITING) 1749 if (contentsInCompositedLayer()) { 1750 IntRect updateRect = visibleContentRect(); 1751 1752 // Make sure to "apply" the scale factor here since we're converting from frame view 1753 // coordinates to layer backing coordinates. 1754 updateRect.scale(1 / m_frame->frameScaleFactor()); 1755 1756 ASSERT(renderView()); 1757 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect); 1758 } 1759 1760 repaintSlowRepaintObjects(); 1761 1762 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) { 1763 if (isEnclosedInCompositingLayer()) { 1764 LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(), 1765 frameRenderer->borderTop() + frameRenderer->paddingTop(), 1766 visibleWidth(), visibleHeight()); 1767 frameRenderer->repaintRectangle(rect); 1768 return; 1769 } 1770 } 1771#endif 1772 1773 ScrollView::scrollContentsSlowPath(updateRect); 1774} 1775 1776void FrameView::repaintSlowRepaintObjects() 1777{ 1778 if (!m_slowRepaintObjects) 1779 return; 1780 1781 // Renderers with fixed backgrounds may be in compositing layers, so we need to explicitly 1782 // repaint them after scrolling. 1783 RenderObjectSet::const_iterator end = m_slowRepaintObjects->end(); 1784 for (RenderObjectSet::const_iterator it = m_slowRepaintObjects->begin(); it != end; ++it) { 1785 RenderObject* renderer = *it; 1786 renderer->repaint(); 1787 } 1788} 1789 1790// Note that this gets called at painting time. 1791void FrameView::setIsOverlapped(bool isOverlapped) 1792{ 1793 if (isOverlapped == m_isOverlapped) 1794 return; 1795 1796 m_isOverlapped = isOverlapped; 1797 updateCanBlitOnScrollRecursively(); 1798 1799#if USE(ACCELERATED_COMPOSITING) 1800 if (hasCompositedContentIncludingDescendants()) { 1801 // Overlap can affect compositing tests, so if it changes, we need to trigger 1802 // a layer update in the parent document. 1803 if (Frame* parentFrame = m_frame->tree()->parent()) { 1804 if (RenderView* parentView = parentFrame->contentRenderer()) { 1805 RenderLayerCompositor* compositor = parentView->compositor(); 1806 compositor->setCompositingLayersNeedRebuild(); 1807 compositor->scheduleCompositingLayerUpdate(); 1808 } 1809 } 1810 1811 if (RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) { 1812 // We also need to trigger reevaluation for this and all descendant frames, 1813 // since a frame uses compositing if any ancestor is compositing. 1814 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 1815 if (RenderView* view = frame->contentRenderer()) { 1816 RenderLayerCompositor* compositor = view->compositor(); 1817 compositor->setCompositingLayersNeedRebuild(); 1818 compositor->scheduleCompositingLayerUpdate(); 1819 } 1820 } 1821 } 1822 } 1823#endif 1824} 1825 1826bool FrameView::isOverlappedIncludingAncestors() const 1827{ 1828 if (isOverlapped()) 1829 return true; 1830 1831 if (FrameView* parentView = parentFrameView()) { 1832 if (parentView->isOverlapped()) 1833 return true; 1834 } 1835 1836 return false; 1837} 1838 1839void FrameView::setContentIsOpaque(bool contentIsOpaque) 1840{ 1841 if (contentIsOpaque == m_contentIsOpaque) 1842 return; 1843 1844 m_contentIsOpaque = contentIsOpaque; 1845 updateCanBlitOnScrollRecursively(); 1846} 1847 1848void FrameView::restoreScrollbar() 1849{ 1850 setScrollbarsSuppressed(false); 1851} 1852 1853bool FrameView::scrollToFragment(const KURL& url) 1854{ 1855 // If our URL has no ref, then we have no place we need to jump to. 1856 // OTOH If CSS target was set previously, we want to set it to 0, recalc 1857 // and possibly repaint because :target pseudo class may have been 1858 // set (see bug 11321). 1859 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget()) 1860 return false; 1861 1862 String fragmentIdentifier = url.fragmentIdentifier(); 1863 if (scrollToAnchor(fragmentIdentifier)) 1864 return true; 1865 1866 // Try again after decoding the ref, based on the document's encoding. 1867 if (TextResourceDecoder* decoder = m_frame->document()->decoder()) 1868 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding())); 1869 1870 return false; 1871} 1872 1873bool FrameView::scrollToAnchor(const String& name) 1874{ 1875 ASSERT(m_frame->document()); 1876 1877 if (!m_frame->document()->haveStylesheetsLoaded()) { 1878 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true); 1879 return false; 1880 } 1881 1882 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false); 1883 1884 Element* anchorElement = m_frame->document()->findAnchor(name); 1885 1886 // Setting to null will clear the current target. 1887 m_frame->document()->setCSSTarget(anchorElement); 1888 1889#if ENABLE(SVG) 1890 if (m_frame->document()->isSVGDocument()) { 1891 if (SVGSVGElement* svg = toSVGDocument(m_frame->document())->rootElement()) { 1892 svg->setupInitialView(name, anchorElement); 1893 if (!anchorElement) 1894 return true; 1895 } 1896 } 1897#endif 1898 1899 // Implement the rule that "" and "top" both mean top of page as in other browsers. 1900 if (!anchorElement && !(name.isEmpty() || equalIgnoringCase(name, "top"))) 1901 return false; 1902 1903 maintainScrollPositionAtAnchor(anchorElement ? static_cast<Node*>(anchorElement) : m_frame->document()); 1904 1905 // If the anchor accepts keyboard focus, move focus there to aid users relying on keyboard navigation. 1906 if (anchorElement && anchorElement->isFocusable()) 1907 m_frame->document()->setFocusedElement(anchorElement); 1908 1909 return true; 1910} 1911 1912void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode) 1913{ 1914 m_maintainScrollPositionAnchor = anchorNode; 1915 if (!m_maintainScrollPositionAnchor) 1916 return; 1917 1918 // We need to update the layout before scrolling, otherwise we could 1919 // really mess things up if an anchor scroll comes at a bad moment. 1920 m_frame->document()->updateStyleIfNeeded(); 1921 // Only do a layout if changes have occurred that make it necessary. 1922 RenderView* renderView = this->renderView(); 1923 if (renderView && renderView->needsLayout()) 1924 layout(); 1925 else 1926 scrollToAnchor(); 1927} 1928 1929void FrameView::scrollElementToRect(Element* element, const IntRect& rect) 1930{ 1931 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 1932 1933 LayoutRect bounds = element->boundingBox(); 1934 int centeringOffsetX = (rect.width() - bounds.width()) / 2; 1935 int centeringOffsetY = (rect.height() - bounds.height()) / 2; 1936 setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y())); 1937} 1938 1939void FrameView::setScrollPosition(const IntPoint& scrollPoint) 1940{ 1941 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true); 1942 m_maintainScrollPositionAnchor = 0; 1943 ScrollView::setScrollPosition(scrollPoint); 1944} 1945 1946void FrameView::delegatesScrollingDidChange() 1947{ 1948#if USE(ACCELERATED_COMPOSITING) 1949 // When we switch to delgatesScrolling mode, we should destroy the scrolling/clipping layers in RenderLayerCompositor. 1950 if (hasCompositedContent()) 1951 clearBackingStores(); 1952#endif 1953} 1954 1955void FrameView::setFixedVisibleContentRect(const IntRect& visibleContentRect) 1956{ 1957 bool visibleContentSizeDidChange = false; 1958 if (visibleContentRect.size() != this->fixedVisibleContentRect().size()) { 1959 // When the viewport size changes or the content is scaled, we need to 1960 // reposition the fixed and sticky positioned elements. 1961 setViewportConstrainedObjectsNeedLayout(); 1962 visibleContentSizeDidChange = true; 1963 } 1964 1965 IntSize offset = scrollOffset(); 1966 ScrollView::setFixedVisibleContentRect(visibleContentRect); 1967 if (offset != scrollOffset()) { 1968 repaintFixedElementsAfterScrolling(); 1969 if (m_frame->page()->settings()->acceleratedCompositingForFixedPositionEnabled()) 1970 updateFixedElementsAfterScrolling(); 1971 scrollAnimator()->setCurrentPosition(scrollPosition()); 1972 scrollPositionChanged(); 1973 } 1974 if (visibleContentSizeDidChange) { 1975 // Update the scroll-bars to calculate new page-step size. 1976 updateScrollbars(scrollOffset()); 1977 } 1978 frame()->loader()->client()->didChangeScrollOffset(); 1979} 1980 1981void FrameView::setViewportConstrainedObjectsNeedLayout() 1982{ 1983 if (!hasViewportConstrainedObjects()) 1984 return; 1985 1986 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end(); 1987 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) { 1988 RenderObject* renderer = *it; 1989 renderer->setNeedsLayout(true); 1990 } 1991} 1992 1993void FrameView::scrollPositionChangedViaPlatformWidget() 1994{ 1995 repaintFixedElementsAfterScrolling(); 1996 updateFixedElementsAfterScrolling(); 1997 repaintSlowRepaintObjects(); 1998 scrollPositionChanged(); 1999} 2000 2001void FrameView::scrollPositionChanged() 2002{ 2003 frame()->eventHandler()->sendScrollEvent(); 2004 frame()->eventHandler()->dispatchFakeMouseMoveEventSoon(); 2005 2006#if USE(ACCELERATED_COMPOSITING) 2007 if (RenderView* renderView = this->renderView()) { 2008 if (renderView->usesCompositing()) 2009 renderView->compositor()->frameViewDidScroll(); 2010 } 2011#endif 2012} 2013 2014// FIXME: this function is misnamed; its primary purpose is to update RenderLayer positions. 2015void FrameView::repaintFixedElementsAfterScrolling() 2016{ 2017 // For fixed position elements, update widget positions and compositing layers after scrolling, 2018 // but only if we're not inside of layout. 2019 if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) { 2020 if (RenderView* renderView = this->renderView()) { 2021 renderView->updateWidgetPositions(); 2022 renderView->layer()->updateLayerPositionsAfterDocumentScroll(); 2023 } 2024 } 2025} 2026 2027bool FrameView::shouldUpdateFixedElementsAfterScrolling() 2028{ 2029#if ENABLE(THREADED_SCROLLING) 2030 Page* page = m_frame->page(); 2031 if (!page) 2032 return true; 2033 2034 // If the scrolling thread is updating the fixed elements, then the FrameView should not update them as well. 2035 if (page->mainFrame() != m_frame) 2036 return true; 2037 2038 ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator(); 2039 if (!scrollingCoordinator) 2040 return true; 2041 2042 if (!scrollingCoordinator->supportsFixedPositionLayers()) 2043 return true; 2044 2045 if (scrollingCoordinator->shouldUpdateScrollLayerPositionOnMainThread()) 2046 return true; 2047 2048 if (inProgrammaticScroll()) 2049 return true; 2050 2051 return false; 2052#endif 2053 return true; 2054} 2055 2056void FrameView::updateFixedElementsAfterScrolling() 2057{ 2058#if USE(ACCELERATED_COMPOSITING) 2059 if (!shouldUpdateFixedElementsAfterScrolling()) 2060 return; 2061 2062 if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) { 2063 if (RenderView* renderView = this->renderView()) 2064 renderView->compositor()->updateCompositingLayers(CompositingUpdateOnScroll); 2065 } 2066#endif 2067} 2068 2069bool FrameView::shouldRubberBandInDirection(ScrollDirection direction) const 2070{ 2071 Page* page = frame() ? frame()->page() : 0; 2072 if (!page) 2073 return ScrollView::shouldRubberBandInDirection(direction); 2074 return page->chrome().client()->shouldRubberBandInDirection(direction); 2075} 2076 2077bool FrameView::isRubberBandInProgress() const 2078{ 2079 if (scrollbarsSuppressed()) 2080 return false; 2081 2082 // If the scrolling thread updates the scroll position for this FrameView, then we should return 2083 // ScrollingCoordinator::isRubberBandInProgress(). 2084 if (Page* page = m_frame->page()) { 2085 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) { 2086 if (!scrollingCoordinator->shouldUpdateScrollLayerPositionOnMainThread()) 2087 return scrollingCoordinator->isRubberBandInProgress(); 2088 } 2089 } 2090 2091 // If the main thread updates the scroll position for this FrameView, we should return 2092 // ScrollAnimator::isRubberBandInProgress(). 2093 if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) 2094 return scrollAnimator->isRubberBandInProgress(); 2095 2096 return false; 2097} 2098 2099bool FrameView::requestScrollPositionUpdate(const IntPoint& position) 2100{ 2101#if ENABLE(THREADED_SCROLLING) 2102 if (TiledBacking* tiledBacking = this->tiledBacking()) { 2103 IntRect visibleRect = visibleContentRect(); 2104 visibleRect.setLocation(position); 2105 tiledBacking->prepopulateRect(visibleRect); 2106 } 2107 2108 if (Page* page = m_frame->page()) { 2109 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) 2110 return scrollingCoordinator->requestScrollPositionUpdate(this, position); 2111 } 2112#else 2113 UNUSED_PARAM(position); 2114#endif 2115 2116 return false; 2117} 2118 2119HostWindow* FrameView::hostWindow() const 2120{ 2121 Page* page = frame() ? frame()->page() : 0; 2122 if (!page) 2123 return 0; 2124 return &page->chrome(); 2125} 2126 2127const unsigned cRepaintRectUnionThreshold = 25; 2128 2129void FrameView::repaintContentRectangle(const IntRect& r, bool immediate) 2130{ 2131 ASSERT(!m_frame->ownerElement()); 2132 2133 if (m_isTrackingRepaints) { 2134 IntRect repaintRect = r; 2135 repaintRect.move(-scrollOffset()); 2136 m_trackedRepaintRects.append(repaintRect); 2137 } 2138 2139 double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay(); 2140 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) { 2141 IntRect paintRect = r; 2142 if (clipsRepaints() && !paintsEntireContents()) 2143 paintRect.intersect(visibleContentRect()); 2144 if (paintRect.isEmpty()) 2145 return; 2146 if (m_repaintCount == cRepaintRectUnionThreshold) { 2147 IntRect unionedRect; 2148 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i) 2149 unionedRect.unite(pixelSnappedIntRect(m_repaintRects[i])); 2150 m_repaintRects.clear(); 2151 m_repaintRects.append(unionedRect); 2152 } 2153 if (m_repaintCount < cRepaintRectUnionThreshold) 2154 m_repaintRects.append(paintRect); 2155 else 2156 m_repaintRects[0].unite(paintRect); 2157 m_repaintCount++; 2158 2159 if (!m_deferringRepaints) 2160 startDeferredRepaintTimer(delay); 2161 2162 return; 2163 } 2164 2165 if (!shouldUpdate(immediate)) 2166 return; 2167 2168#if USE(TILED_BACKING_STORE) 2169 if (frame()->tiledBackingStore()) { 2170 frame()->tiledBackingStore()->invalidate(r); 2171 return; 2172 } 2173#endif 2174 ScrollView::repaintContentRectangle(r, immediate); 2175} 2176 2177void FrameView::contentsResized() 2178{ 2179 ScrollView::contentsResized(); 2180 setNeedsLayout(); 2181} 2182 2183void FrameView::visibleContentsResized() 2184{ 2185 // We check to make sure the view is attached to a frame() as this method can 2186 // be triggered before the view is attached by Frame::createView(...) setting 2187 // various values such as setScrollBarModes(...) for example. An ASSERT is 2188 // triggered when a view is layout before being attached to a frame(). 2189 if (!frame()->view()) 2190 return; 2191 2192 if (!useFixedLayout() && needsLayout()) 2193 layout(); 2194 2195#if USE(ACCELERATED_COMPOSITING) 2196 if (RenderView* renderView = this->renderView()) { 2197 if (renderView->usesCompositing()) 2198 renderView->compositor()->frameViewDidChangeSize(); 2199 } 2200#endif 2201} 2202 2203void FrameView::beginDeferredRepaints() 2204{ 2205 Page* page = m_frame->page(); 2206 if (page->mainFrame() != m_frame) { 2207 page->mainFrame()->view()->beginDeferredRepaints(); 2208 return; 2209 } 2210 2211 m_deferringRepaints++; 2212} 2213 2214void FrameView::endDeferredRepaints() 2215{ 2216 Page* page = m_frame->page(); 2217 if (page->mainFrame() != m_frame) { 2218 page->mainFrame()->view()->endDeferredRepaints(); 2219 return; 2220 } 2221 2222 ASSERT(m_deferringRepaints > 0); 2223 2224 if (--m_deferringRepaints) 2225 return; 2226 2227 if (m_deferredRepaintTimer.isActive()) 2228 return; 2229 2230 if (double delay = adjustedDeferredRepaintDelay()) { 2231 startDeferredRepaintTimer(delay); 2232 return; 2233 } 2234 2235 doDeferredRepaints(); 2236} 2237 2238void FrameView::startDeferredRepaintTimer(double delay) 2239{ 2240 if (m_deferredRepaintTimer.isActive()) 2241 return; 2242 2243 if (m_disableRepaints) 2244 return; 2245 2246 m_deferredRepaintTimer.startOneShot(delay); 2247} 2248 2249void FrameView::handleLoadCompleted() 2250{ 2251 // Once loading has completed, allow autoSize one last opportunity to 2252 // reduce the size of the frame. 2253 autoSizeIfEnabled(); 2254 if (shouldUseLoadTimeDeferredRepaintDelay()) 2255 return; 2256 m_deferredRepaintDelay = s_normalDeferredRepaintDelay; 2257 flushDeferredRepaints(); 2258} 2259 2260void FrameView::flushDeferredRepaints() 2261{ 2262 if (!m_deferredRepaintTimer.isActive()) 2263 return; 2264 m_deferredRepaintTimer.stop(); 2265 doDeferredRepaints(); 2266} 2267 2268void FrameView::doDeferredRepaints() 2269{ 2270 if (m_disableRepaints) 2271 return; 2272 2273 ASSERT(!m_deferringRepaints); 2274 if (!shouldUpdate()) { 2275 m_repaintRects.clear(); 2276 m_repaintCount = 0; 2277 return; 2278 } 2279 unsigned size = m_repaintRects.size(); 2280 for (unsigned i = 0; i < size; i++) { 2281#if USE(TILED_BACKING_STORE) 2282 if (frame()->tiledBackingStore()) { 2283 frame()->tiledBackingStore()->invalidate(pixelSnappedIntRect(m_repaintRects[i])); 2284 continue; 2285 } 2286#endif 2287 ScrollView::repaintContentRectangle(pixelSnappedIntRect(m_repaintRects[i]), false); 2288 } 2289 m_repaintRects.clear(); 2290 m_repaintCount = 0; 2291 2292 updateDeferredRepaintDelayAfterRepaint(); 2293} 2294 2295bool FrameView::shouldUseLoadTimeDeferredRepaintDelay() const 2296{ 2297 // Don't defer after the initial load of the page has been completed. 2298 if (m_frame->tree()->top()->loader()->isComplete()) 2299 return false; 2300 Document* document = m_frame->document(); 2301 if (!document) 2302 return false; 2303 if (document->parsing()) 2304 return true; 2305 if (document->cachedResourceLoader()->requestCount()) 2306 return true; 2307 return false; 2308} 2309 2310void FrameView::updateDeferredRepaintDelayAfterRepaint() 2311{ 2312 if (!shouldUseLoadTimeDeferredRepaintDelay()) { 2313 m_deferredRepaintDelay = s_normalDeferredRepaintDelay; 2314 return; 2315 } 2316 double incrementedRepaintDelay = m_deferredRepaintDelay + s_deferredRepaintDelayIncrementDuringLoading; 2317 m_deferredRepaintDelay = std::min(incrementedRepaintDelay, s_maxDeferredRepaintDelayDuringLoading); 2318} 2319 2320void FrameView::resetDeferredRepaintDelay() 2321{ 2322 m_deferredRepaintDelay = 0; 2323 if (m_deferredRepaintTimer.isActive()) { 2324 m_deferredRepaintTimer.stop(); 2325 if (!m_deferringRepaints) 2326 doDeferredRepaints(); 2327 } 2328#if USE(ACCELERATED_COMPOSITING) 2329 if (RenderView* view = renderView()) 2330 view->compositor()->disableLayerFlushThrottlingTemporarilyForInteraction(); 2331#endif 2332} 2333 2334double FrameView::adjustedDeferredRepaintDelay() const 2335{ 2336 ASSERT(!m_deferringRepaints); 2337 if (!m_deferredRepaintDelay) 2338 return 0; 2339 double timeSinceLastPaint = currentTime() - m_lastPaintTime; 2340 return max(0., m_deferredRepaintDelay - timeSinceLastPaint); 2341} 2342 2343void FrameView::deferredRepaintTimerFired(Timer<FrameView>*) 2344{ 2345 doDeferredRepaints(); 2346} 2347 2348void FrameView::beginDisableRepaints() 2349{ 2350 m_disableRepaints++; 2351} 2352 2353void FrameView::endDisableRepaints() 2354{ 2355 ASSERT(m_disableRepaints > 0); 2356 m_disableRepaints--; 2357} 2358 2359void FrameView::updateLayerFlushThrottlingInAllFrames() 2360{ 2361#if USE(ACCELERATED_COMPOSITING) 2362 bool isMainLoadProgressing = m_frame->page()->progress()->isMainLoadProgressing(); 2363 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 2364 if (RenderView* renderView = frame->contentRenderer()) 2365 renderView->compositor()->setLayerFlushThrottlingEnabled(isMainLoadProgressing); 2366 } 2367#endif 2368} 2369 2370void FrameView::adjustTiledBackingCoverage() 2371{ 2372#if USE(ACCELERATED_COMPOSITING) 2373 RenderView* renderView = this->renderView(); 2374 if (renderView && renderView->layer()->backing()) 2375 renderView->layer()->backing()->adjustTiledBackingCoverage(); 2376#endif 2377} 2378 2379void FrameView::layoutTimerFired(Timer<FrameView>*) 2380{ 2381#ifdef INSTRUMENT_LAYOUT_SCHEDULING 2382 if (!m_frame->document()->ownerElement()) 2383 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime()); 2384#endif 2385 layout(); 2386} 2387 2388void FrameView::scheduleRelayout() 2389{ 2390 // FIXME: We should assert the page is not in the page cache, but that is causing 2391 // too many false assertions. See <rdar://problem/7218118>. 2392 ASSERT(m_frame->view() == this); 2393 2394 if (m_layoutRoot) { 2395 m_layoutRoot->markContainingBlocksForLayout(false); 2396 m_layoutRoot = 0; 2397 } 2398 if (!m_layoutSchedulingEnabled) 2399 return; 2400 if (!needsLayout()) 2401 return; 2402 if (!m_frame->document()->shouldScheduleLayout()) 2403 return; 2404 InspectorInstrumentation::didInvalidateLayout(m_frame.get()); 2405 // When frame flattening is enabled, the contents of the frame could affect the layout of the parent frames. 2406 // Also invalidate parent frame starting from the owner element of this frame. 2407 if (m_frame->ownerRenderer() && isInChildFrameWithFrameFlattening()) 2408 m_frame->ownerRenderer()->setNeedsLayout(true, MarkContainingBlockChain); 2409 2410 int delay = m_frame->document()->minimumLayoutDelay(); 2411 if (m_layoutTimer.isActive() && m_delayedLayout && !delay) 2412 unscheduleRelayout(); 2413 if (m_layoutTimer.isActive()) 2414 return; 2415 2416 m_delayedLayout = delay != 0; 2417 2418#ifdef INSTRUMENT_LAYOUT_SCHEDULING 2419 if (!m_frame->document()->ownerElement()) 2420 printf("Scheduling layout for %d\n", delay); 2421#endif 2422 2423 m_layoutTimer.startOneShot(delay * 0.001); 2424} 2425 2426static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant) 2427{ 2428 for (RenderObject* r = descendant; r; r = r->container()) { 2429 if (r == ancestor) 2430 return true; 2431 } 2432 return false; 2433} 2434 2435void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot) 2436{ 2437 ASSERT(m_frame->view() == this); 2438 2439 RenderView* renderView = this->renderView(); 2440 if (renderView && renderView->needsLayout()) { 2441 if (relayoutRoot) 2442 relayoutRoot->markContainingBlocksForLayout(false); 2443 return; 2444 } 2445 2446 if (layoutPending() || !m_layoutSchedulingEnabled) { 2447 if (m_layoutRoot != relayoutRoot) { 2448 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) { 2449 // Keep the current root 2450 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot); 2451 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout()); 2452 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) { 2453 // Re-root at relayoutRoot 2454 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot); 2455 m_layoutRoot = relayoutRoot; 2456 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout()); 2457 InspectorInstrumentation::didInvalidateLayout(m_frame.get()); 2458 } else { 2459 // Just do a full relayout 2460 if (m_layoutRoot) 2461 m_layoutRoot->markContainingBlocksForLayout(false); 2462 m_layoutRoot = 0; 2463 relayoutRoot->markContainingBlocksForLayout(false); 2464 InspectorInstrumentation::didInvalidateLayout(m_frame.get()); 2465 } 2466 } 2467 } else if (m_layoutSchedulingEnabled) { 2468 int delay = m_frame->document()->minimumLayoutDelay(); 2469 m_layoutRoot = relayoutRoot; 2470 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout()); 2471 InspectorInstrumentation::didInvalidateLayout(m_frame.get()); 2472 m_delayedLayout = delay != 0; 2473 m_layoutTimer.startOneShot(delay * 0.001); 2474 } 2475} 2476 2477bool FrameView::layoutPending() const 2478{ 2479 return m_layoutTimer.isActive(); 2480} 2481 2482bool FrameView::needsLayout() const 2483{ 2484 // This can return true in cases where the document does not have a body yet. 2485 // Document::shouldScheduleLayout takes care of preventing us from scheduling 2486 // layout in that case. 2487 if (!m_frame) 2488 return false; 2489 2490 RenderView* renderView = this->renderView(); 2491 return layoutPending() 2492 || (renderView && renderView->needsLayout()) 2493 || m_layoutRoot 2494 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred); 2495} 2496 2497void FrameView::setNeedsLayout() 2498{ 2499 if (m_deferSetNeedsLayouts) { 2500 m_setNeedsLayoutWasDeferred = true; 2501 return; 2502 } 2503 2504 if (RenderView* renderView = this->renderView()) 2505 renderView->setNeedsLayout(true); 2506} 2507 2508void FrameView::unscheduleRelayout() 2509{ 2510 if (!m_layoutTimer.isActive()) 2511 return; 2512 2513#ifdef INSTRUMENT_LAYOUT_SCHEDULING 2514 if (!m_frame->document()->ownerElement()) 2515 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime()); 2516#endif 2517 2518 m_layoutTimer.stop(); 2519 m_delayedLayout = false; 2520} 2521 2522#if ENABLE(REQUEST_ANIMATION_FRAME) 2523void FrameView::serviceScriptedAnimations(double monotonicAnimationStartTime) 2524{ 2525 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext()) { 2526 frame->view()->serviceScrollAnimations(); 2527 frame->animation()->serviceAnimations(); 2528 } 2529 2530 Vector<RefPtr<Document> > documents; 2531 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext()) 2532 documents.append(frame->document()); 2533 2534 for (size_t i = 0; i < documents.size(); ++i) 2535 documents[i]->serviceScriptedAnimations(monotonicAnimationStartTime); 2536} 2537#endif 2538 2539bool FrameView::isTransparent() const 2540{ 2541 return m_isTransparent; 2542} 2543 2544void FrameView::setTransparent(bool isTransparent) 2545{ 2546 m_isTransparent = isTransparent; 2547} 2548 2549bool FrameView::hasOpaqueBackground() const 2550{ 2551 return !m_isTransparent && !m_baseBackgroundColor.hasAlpha(); 2552} 2553 2554Color FrameView::baseBackgroundColor() const 2555{ 2556 return m_baseBackgroundColor; 2557} 2558 2559void FrameView::setBaseBackgroundColor(const Color& backgroundColor) 2560{ 2561 if (!backgroundColor.isValid()) 2562 m_baseBackgroundColor = Color::white; 2563 else 2564 m_baseBackgroundColor = backgroundColor; 2565 2566 recalculateScrollbarOverlayStyle(); 2567} 2568 2569void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent) 2570{ 2571 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 2572 if (FrameView* view = frame->view()) { 2573 view->setTransparent(transparent); 2574 view->setBaseBackgroundColor(backgroundColor); 2575 } 2576 } 2577} 2578 2579bool FrameView::shouldUpdateWhileOffscreen() const 2580{ 2581 return m_shouldUpdateWhileOffscreen; 2582} 2583 2584void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen) 2585{ 2586 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen; 2587} 2588 2589bool FrameView::shouldUpdate(bool immediateRequested) const 2590{ 2591 if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen()) 2592 return false; 2593 return true; 2594} 2595 2596void FrameView::scrollToAnchor() 2597{ 2598 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor; 2599 if (!anchorNode) 2600 return; 2601 2602 if (!anchorNode->renderer()) 2603 return; 2604 2605 LayoutRect rect; 2606 if (anchorNode != m_frame->document()) 2607 rect = anchorNode->boundingBox(); 2608 2609 // Scroll nested layers and frames to reveal the anchor. 2610 // Align to the top and to the closest side (this matches other browsers). 2611 anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways); 2612 2613 if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache()) 2614 cache->handleScrolledToAnchor(anchorNode.get()); 2615 2616 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor. 2617 m_maintainScrollPositionAnchor = anchorNode; 2618} 2619 2620void FrameView::updateWidget(RenderObject* object) 2621{ 2622 ASSERT(!object->node() || object->node()->isElementNode()); 2623 Element* ownerElement = toElement(object->node()); 2624 // The object may have already been destroyed (thus node cleared), 2625 // but FrameView holds a manual ref, so it won't have been deleted. 2626 ASSERT(m_widgetUpdateSet->contains(object)); 2627 if (!ownerElement) 2628 return; 2629 2630 if (object->isEmbeddedObject()) { 2631 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object); 2632 // No need to update if it's already crashed or known to be missing. 2633 if (embeddedObject->isPluginUnavailable()) 2634 return; 2635 2636 if (object->isSnapshottedPlugIn()) { 2637 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag)) { 2638 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement); 2639 pluginElement->checkSnapshotStatus(); 2640 } 2641 return; 2642 } 2643 2644 // FIXME: This could turn into a real virtual dispatch if we defined 2645 // updateWidget(PluginCreationOption) on HTMLElement. 2646 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag) || ownerElement->hasTagName(appletTag)) { 2647 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement); 2648 if (pluginElement->needsCheckForSizeChange()) { 2649 pluginElement->checkSnapshotStatus(); 2650 return; 2651 } 2652 if (pluginElement->needsWidgetUpdate()) 2653 pluginElement->updateWidget(CreateAnyWidgetType); 2654 } 2655 // FIXME: It is not clear that Media elements need or want this updateWidget() call. 2656#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) 2657 else if (ownerElement->isMediaElement()) 2658 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(CreateAnyWidgetType); 2659#endif 2660 else 2661 ASSERT_NOT_REACHED(); 2662 2663 // Caution: it's possible the object was destroyed again, since loading a 2664 // plugin may run any arbitrary JavaScript. 2665 embeddedObject->updateWidgetPosition(); 2666 } 2667} 2668 2669bool FrameView::updateWidgets() 2670{ 2671 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty()) 2672 return true; 2673 2674 size_t size = m_widgetUpdateSet->size(); 2675 2676 Vector<RenderObject*> objects; 2677 objects.reserveInitialCapacity(size); 2678 // Protect RendereArena from getting wiped out, when Document is detached during updateWidget(). 2679 RefPtr<RenderArena> protectedArena = m_frame->document()->renderArena(); 2680 2681 RenderObjectSet::const_iterator end = m_widgetUpdateSet->end(); 2682 for (RenderObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) { 2683 RenderObject* object = *it; 2684 objects.uncheckedAppend(object); 2685 if (object->isEmbeddedObject()) { 2686 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object); 2687 embeddedObject->ref(); 2688 } 2689 } 2690 2691 for (size_t i = 0; i < size; ++i) { 2692 RenderObject* object = objects[i]; 2693 updateWidget(object); 2694 m_widgetUpdateSet->remove(object); 2695 } 2696 2697 for (size_t i = 0; i < size; ++i) { 2698 RenderObject* object = objects[i]; 2699 if (object->isEmbeddedObject()) { 2700 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object); 2701 embeddedObject->deref(protectedArena.get()); 2702 } 2703 } 2704 2705 return m_widgetUpdateSet->isEmpty(); 2706} 2707 2708void FrameView::updateEmbeddedObjectsTimerFired(Timer<FrameView>*) 2709{ 2710 RefPtr<FrameView> protect(this); 2711 m_updateEmbeddedObjectsTimer.stop(); 2712 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) { 2713 if (updateWidgets()) 2714 break; 2715 } 2716} 2717 2718void FrameView::flushAnyPendingPostLayoutTasks() 2719{ 2720 if (m_postLayoutTasksTimer.isActive()) 2721 performPostLayoutTasks(); 2722 if (m_updateEmbeddedObjectsTimer.isActive()) 2723 updateEmbeddedObjectsTimerFired(nullptr); 2724} 2725 2726void FrameView::performPostLayoutTasks() 2727{ 2728 // FIXME: We should not run any JavaScript code in this function. 2729 2730 m_postLayoutTasksTimer.stop(); 2731 2732 m_frame->selection()->setCaretRectNeedsUpdate(); 2733 m_frame->selection()->updateAppearance(); 2734 2735 LayoutMilestones requestedMilestones = 0; 2736 LayoutMilestones milestonesAchieved = 0; 2737 Page* page = m_frame->page(); 2738 if (page) 2739 requestedMilestones = page->requestedLayoutMilestones(); 2740 2741 if (m_nestedLayoutCount <= 1) { 2742 if (m_firstLayoutCallbackPending) { 2743 m_firstLayoutCallbackPending = false; 2744 m_frame->loader()->didFirstLayout(); 2745 if (requestedMilestones & DidFirstLayout) 2746 milestonesAchieved |= DidFirstLayout; 2747 if (page) { 2748 if (page->mainFrame() == m_frame) 2749 page->startCountingRelevantRepaintedObjects(); 2750 } 2751 } 2752 2753 // Ensure that we always send this eventually. 2754 if (!m_frame->document()->parsing() && m_frame->loader()->stateMachine()->committedFirstRealDocumentLoad()) 2755 m_isVisuallyNonEmpty = true; 2756 2757 // If the layout was done with pending sheets, we are not in fact visually non-empty yet. 2758 if (m_isVisuallyNonEmpty && !m_frame->document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) { 2759 m_firstVisuallyNonEmptyLayoutCallbackPending = false; 2760 if (requestedMilestones & DidFirstVisuallyNonEmptyLayout) 2761 milestonesAchieved |= DidFirstVisuallyNonEmptyLayout; 2762 } 2763 } 2764 2765 if (milestonesAchieved) 2766 m_frame->loader()->didLayout(milestonesAchieved); 2767#if ENABLE(FONT_LOAD_EVENTS) 2768 if (RuntimeEnabledFeatures::fontLoadEventsEnabled()) 2769 m_frame->document()->fontloader()->didLayout(); 2770#endif 2771 2772 // FIXME: We should consider adding DidLayout as a LayoutMilestone. That would let us merge this 2773 // with didLayout(LayoutMilestones). 2774 m_frame->loader()->client()->dispatchDidLayout(); 2775 2776 if (RenderView* renderView = this->renderView()) 2777 renderView->updateWidgetPositions(); 2778 2779 // layout() protects FrameView, but it still can get destroyed when updateWidgets() 2780 // is called through the post layout timer. 2781 2782 RefPtr<FrameView> protector(this); 2783 m_updateEmbeddedObjectsTimer.startOneShot(0); 2784 2785 if (page) { 2786 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) 2787 scrollingCoordinator->frameViewLayoutUpdated(this); 2788 } 2789 2790#if USE(ACCELERATED_COMPOSITING) 2791 if (RenderView* renderView = this->renderView()) { 2792 if (renderView->usesCompositing()) 2793 renderView->compositor()->frameViewDidLayout(); 2794 } 2795#endif 2796 2797 scrollToAnchor(); 2798 2799 sendResizeEventIfNeeded(); 2800} 2801 2802void FrameView::sendResizeEventIfNeeded() 2803{ 2804 ASSERT(m_frame); 2805 2806 RenderView* renderView = this->renderView(); 2807 if (!renderView || renderView->printing()) 2808 return; 2809 2810 Page* page = m_frame->page(); 2811 IntSize currentSize; 2812 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling()) 2813 currentSize = fixedLayoutSize(); 2814 else 2815 currentSize = visibleContentRect(IncludeScrollbars).size(); 2816 2817 float currentZoomFactor = renderView->style()->zoom(); 2818 bool shouldSendResizeEvent = !m_firstLayout && (currentSize != m_lastViewportSize || currentZoomFactor != m_lastZoomFactor); 2819 2820 m_lastViewportSize = currentSize; 2821 m_lastZoomFactor = currentZoomFactor; 2822 2823 if (!shouldSendResizeEvent) 2824 return; 2825 2826 bool isMainFrame = page && page->mainFrame() == m_frame; 2827 bool canSendResizeEventSynchronously = !m_shouldAutoSize && isMainFrame && !isInLayout(); 2828 2829 // If we resized during layout, queue up a resize event for later, otherwise fire it right away. 2830 RefPtr<Event> resizeEvent = Event::create(eventNames().resizeEvent, false, false); 2831 if (canSendResizeEventSynchronously) 2832 m_frame->document()->dispatchWindowEvent(resizeEvent.release(), m_frame->document()->domWindow()); 2833 else 2834 m_frame->document()->enqueueWindowEvent(resizeEvent.release()); 2835 2836#if ENABLE(INSPECTOR) 2837 if (InspectorInstrumentation::hasFrontends() && isMainFrame) { 2838 if (InspectorClient* inspectorClient = page ? page->inspectorController()->inspectorClient() : 0) 2839 inspectorClient->didResizeMainFrame(m_frame.get()); 2840 } 2841#endif 2842} 2843 2844void FrameView::willStartLiveResize() 2845{ 2846 ScrollView::willStartLiveResize(); 2847 adjustTiledBackingCoverage(); 2848} 2849 2850void FrameView::willEndLiveResize() 2851{ 2852 ScrollView::willEndLiveResize(); 2853 adjustTiledBackingCoverage(); 2854} 2855 2856void FrameView::postLayoutTimerFired(Timer<FrameView>*) 2857{ 2858 performPostLayoutTasks(); 2859} 2860 2861void FrameView::autoSizeIfEnabled() 2862{ 2863 if (!m_shouldAutoSize) 2864 return; 2865 2866 if (m_inAutoSize) 2867 return; 2868 2869 TemporaryChange<bool> changeInAutoSize(m_inAutoSize, true); 2870 2871 Document* document = frame()->document(); 2872 if (!document) 2873 return; 2874 2875 RenderView* documentView = document->renderView(); 2876 Element* documentElement = document->documentElement(); 2877 if (!documentView || !documentElement) 2878 return; 2879 2880 // Start from the minimum size and allow it to grow. 2881 resize(m_minAutoSize.width(), m_minAutoSize.height()); 2882 2883 IntSize size = frameRect().size(); 2884 2885 // Do the resizing twice. The first time is basically a rough calculation using the preferred width 2886 // which may result in a height change during the second iteration. 2887 for (int i = 0; i < 2; i++) { 2888 // Update various sizes including contentsSize, scrollHeight, etc. 2889 document->updateLayoutIgnorePendingStylesheets(); 2890 int width = documentView->minPreferredLogicalWidth(); 2891 int height = documentView->documentRect().height(); 2892 IntSize newSize(width, height); 2893 2894 // Check to see if a scrollbar is needed for a given dimension and 2895 // if so, increase the other dimension to account for the scrollbar. 2896 // Since the dimensions are only for the view rectangle, once a 2897 // dimension exceeds the maximum, there is no need to increase it further. 2898 if (newSize.width() > m_maxAutoSize.width()) { 2899 RefPtr<Scrollbar> localHorizontalScrollbar = horizontalScrollbar(); 2900 if (!localHorizontalScrollbar) 2901 localHorizontalScrollbar = createScrollbar(HorizontalScrollbar); 2902 if (!localHorizontalScrollbar->isOverlayScrollbar()) 2903 newSize.setHeight(newSize.height() + localHorizontalScrollbar->height()); 2904 2905 // Don't bother checking for a vertical scrollbar because the width is at 2906 // already greater the maximum. 2907 } else if (newSize.height() > m_maxAutoSize.height()) { 2908 RefPtr<Scrollbar> localVerticalScrollbar = verticalScrollbar(); 2909 if (!localVerticalScrollbar) 2910 localVerticalScrollbar = createScrollbar(VerticalScrollbar); 2911 if (!localVerticalScrollbar->isOverlayScrollbar()) 2912 newSize.setWidth(newSize.width() + localVerticalScrollbar->width()); 2913 2914 // Don't bother checking for a horizontal scrollbar because the height is 2915 // already greater the maximum. 2916 } 2917 2918 // Ensure the size is at least the min bounds. 2919 newSize = newSize.expandedTo(m_minAutoSize); 2920 2921 // Bound the dimensions by the max bounds and determine what scrollbars to show. 2922 ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff; 2923 if (newSize.width() > m_maxAutoSize.width()) { 2924 newSize.setWidth(m_maxAutoSize.width()); 2925 horizonalScrollbarMode = ScrollbarAlwaysOn; 2926 } 2927 ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff; 2928 if (newSize.height() > m_maxAutoSize.height()) { 2929 newSize.setHeight(m_maxAutoSize.height()); 2930 verticalScrollbarMode = ScrollbarAlwaysOn; 2931 } 2932 2933 if (newSize == size) 2934 continue; 2935 2936 // While loading only allow the size to increase (to avoid twitching during intermediate smaller states) 2937 // unless autoresize has just been turned on or the maximum size is smaller than the current size. 2938 if (m_didRunAutosize && size.height() <= m_maxAutoSize.height() && size.width() <= m_maxAutoSize.width() 2939 && !frame()->loader()->isComplete() && (newSize.height() < size.height() || newSize.width() < size.width())) 2940 break; 2941 2942 resize(newSize.width(), newSize.height()); 2943 // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example, 2944 // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed). 2945 setVerticalScrollbarLock(false); 2946 setHorizontalScrollbarLock(false); 2947 setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true); 2948 } 2949 2950 m_autoSizeContentSize = contentsSize(); 2951 2952 if (m_autoSizeFixedMinimumHeight) { 2953 resize(m_autoSizeContentSize.width(), max(m_autoSizeFixedMinimumHeight, m_autoSizeContentSize.height())); 2954 document->updateLayoutIgnorePendingStylesheets(); 2955 } 2956 2957 m_didRunAutosize = true; 2958} 2959 2960void FrameView::setAutoSizeFixedMinimumHeight(int fixedMinimumHeight) 2961{ 2962 if (m_autoSizeFixedMinimumHeight == fixedMinimumHeight) 2963 return; 2964 2965 m_autoSizeFixedMinimumHeight = fixedMinimumHeight; 2966 2967 setNeedsLayout(); 2968} 2969 2970void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow) 2971{ 2972 if (!m_viewportRenderer) 2973 return; 2974 2975 if (m_overflowStatusDirty) { 2976 m_horizontalOverflow = horizontalOverflow; 2977 m_verticalOverflow = verticalOverflow; 2978 m_overflowStatusDirty = false; 2979 return; 2980 } 2981 2982 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow); 2983 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow); 2984 2985 if (horizontalOverflowChanged || verticalOverflowChanged) { 2986 m_horizontalOverflow = horizontalOverflow; 2987 m_verticalOverflow = verticalOverflow; 2988 2989 RefPtr<OverflowEvent> overflowEvent = OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, 2990 verticalOverflowChanged, verticalOverflow); 2991 overflowEvent->setTarget(m_viewportRenderer->node()); 2992 2993 frame()->document()->enqueueOverflowEvent(overflowEvent); 2994 } 2995 2996} 2997 2998const Pagination& FrameView::pagination() const 2999{ 3000 if (m_pagination != Pagination()) 3001 return m_pagination; 3002 3003 if (Page* page = m_frame->page()) { 3004 if (page->mainFrame() == m_frame) 3005 return page->pagination(); 3006 } 3007 3008 return m_pagination; 3009} 3010 3011void FrameView::setPagination(const Pagination& pagination) 3012{ 3013 if (m_pagination == pagination) 3014 return; 3015 3016 m_pagination = pagination; 3017 3018 if (m_frame) 3019 m_frame->document()->styleResolverChanged(DeferRecalcStyle); 3020} 3021 3022IntRect FrameView::windowClipRect(bool clipToContents) const 3023{ 3024 ASSERT(m_frame->view() == this); 3025 3026 if (paintsEntireContents()) 3027 return IntRect(IntPoint(), totalContentsSize()); 3028 3029 // Set our clip rect to be our contents. 3030 IntRect clipRect = contentsToWindow(visibleContentRect(clipToContents ? ExcludeScrollbars : IncludeScrollbars)); 3031 if (!m_frame || !m_frame->ownerElement()) 3032 return clipRect; 3033 3034 // Take our owner element and get its clip rect. 3035 HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement(); 3036 FrameView* parentView = ownerElement->document()->view(); 3037 if (parentView) 3038 clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement, true)); 3039 return clipRect; 3040} 3041 3042IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement, bool clipToLayerContents) const 3043{ 3044 // The renderer can sometimes be null when style="display:none" interacts 3045 // with external content and plugins. 3046 if (!ownerElement->renderer()) 3047 return windowClipRect(); 3048 3049 // If we have no layer, just return our window clip rect. 3050 const RenderLayer* enclosingLayer = ownerElement->renderer()->enclosingLayer(); 3051 if (!enclosingLayer) 3052 return windowClipRect(); 3053 3054 // Apply the clip from the layer. 3055 IntRect clipRect; 3056 if (clipToLayerContents) 3057 clipRect = pixelSnappedIntRect(enclosingLayer->childrenClipRect()); 3058 else 3059 clipRect = pixelSnappedIntRect(enclosingLayer->selfClipRect()); 3060 clipRect = contentsToWindow(clipRect); 3061 return intersection(clipRect, windowClipRect()); 3062} 3063 3064bool FrameView::isActive() const 3065{ 3066 Page* page = frame()->page(); 3067 return page && page->focusController()->isActive(); 3068} 3069 3070void FrameView::scrollTo(const IntSize& newOffset) 3071{ 3072 LayoutSize offset = scrollOffset(); 3073 ScrollView::scrollTo(newOffset); 3074 if (offset != scrollOffset()) 3075 scrollPositionChanged(); 3076 frame()->loader()->client()->didChangeScrollOffset(); 3077} 3078 3079void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect) 3080{ 3081 // Add in our offset within the FrameView. 3082 IntRect dirtyRect = rect; 3083 dirtyRect.moveBy(scrollbar->location()); 3084 invalidateRect(dirtyRect); 3085} 3086 3087void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const 3088{ 3089 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch); 3090} 3091 3092IntRect FrameView::windowResizerRect() const 3093{ 3094 Page* page = frame() ? frame()->page() : 0; 3095 if (!page) 3096 return IntRect(); 3097 return page->chrome().windowResizerRect(); 3098} 3099 3100float FrameView::visibleContentScaleFactor() const 3101{ 3102 if (!m_frame || !m_frame->page()) 3103 return 1; 3104 3105 if (!m_frame->settings()->applyPageScaleFactorInCompositor() || m_frame != m_frame->page()->mainFrame()) 3106 return 1; 3107 3108 return m_frame->page()->pageScaleFactor(); 3109} 3110 3111void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb) 3112{ 3113 Page* page = m_frame->page(); 3114 if (!page) 3115 return; 3116 if (page->mainFrame() != m_frame) 3117 return; 3118 page->chrome().client()->notifyScrollerThumbIsVisibleInRect(scrollerThumb); 3119} 3120 3121bool FrameView::scrollbarsCanBeActive() const 3122{ 3123 if (!m_frame) 3124 return false; 3125 3126 if (m_frame->view() != this) 3127 return false; 3128 3129 if (Page* page = m_frame->page()) { 3130 if (page->shouldSuppressScrollbarAnimations()) 3131 return false; 3132 } 3133 3134 if (Document* document = m_frame->document()) 3135 return !document->inPageCache(); 3136 3137 return false; 3138} 3139 3140ScrollableArea* FrameView::enclosingScrollableArea() const 3141{ 3142 // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer. 3143 return 0; 3144} 3145 3146IntRect FrameView::scrollableAreaBoundingBox() const 3147{ 3148 RenderPart* ownerRenderer = frame()->ownerRenderer(); 3149 if (!ownerRenderer) 3150 return frameRect(); 3151 3152 return ownerRenderer->absoluteContentQuad().enclosingBoundingBox(); 3153} 3154 3155bool FrameView::isScrollable() 3156{ 3157 // Check for: 3158 // 1) If there an actual overflow. 3159 // 2) display:none or visibility:hidden set to self or inherited. 3160 // 3) overflow{-x,-y}: hidden; 3161 // 4) scrolling: no; 3162 3163 // Covers #1 3164 IntSize totalContentsSize = this->totalContentsSize(); 3165 IntSize visibleContentSize = visibleContentRect().size(); 3166 if ((totalContentsSize.height() <= visibleContentSize.height() && totalContentsSize.width() <= visibleContentSize.width())) 3167 return false; 3168 3169 // Covers #2. 3170 HTMLFrameOwnerElement* owner = m_frame->ownerElement(); 3171 if (owner && (!owner->renderer() || !owner->renderer()->visibleToHitTesting())) 3172 return false; 3173 3174 // Cover #3 and #4. 3175 ScrollbarMode horizontalMode; 3176 ScrollbarMode verticalMode; 3177 calculateScrollbarModesForLayout(horizontalMode, verticalMode, RulesFromWebContentOnly); 3178 if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff) 3179 return false; 3180 3181 return true; 3182} 3183 3184void FrameView::updateScrollableAreaSet() 3185{ 3186 // That ensures that only inner frames are cached. 3187 FrameView* parentFrameView = this->parentFrameView(); 3188 if (!parentFrameView) 3189 return; 3190 3191 if (!isScrollable()) { 3192 parentFrameView->removeScrollableArea(this); 3193 return; 3194 } 3195 3196 parentFrameView->addScrollableArea(this); 3197} 3198 3199bool FrameView::shouldSuspendScrollAnimations() const 3200{ 3201 return m_frame->loader()->state() != FrameStateComplete; 3202} 3203 3204void FrameView::scrollbarStyleChanged(int newStyle, bool forceUpdate) 3205{ 3206 Page* page = m_frame->page(); 3207 if (!page) 3208 return; 3209 if (page->mainFrame() != m_frame) 3210 return; 3211 page->chrome().client()->recommendedScrollbarStyleDidChange(newStyle); 3212 3213 if (forceUpdate) 3214 ScrollView::scrollbarStyleChanged(newStyle, forceUpdate); 3215} 3216 3217void FrameView::setAnimatorsAreActive() 3218{ 3219 Page* page = m_frame->page(); 3220 if (!page) 3221 return; 3222 3223 if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) 3224 scrollAnimator->setIsActive(); 3225 3226 if (!m_scrollableAreas) 3227 return; 3228 3229 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) { 3230 ScrollableArea* scrollableArea = *it; 3231 3232 ASSERT(scrollableArea->scrollbarsCanBeActive()); 3233 scrollableArea->scrollAnimator()->setIsActive(); 3234 } 3235} 3236 3237void FrameView::notifyPageThatContentAreaWillPaint() const 3238{ 3239 Page* page = m_frame->page(); 3240 if (!page) 3241 return; 3242 3243 contentAreaWillPaint(); 3244 3245 if (!m_scrollableAreas) 3246 return; 3247 3248 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) { 3249 ScrollableArea* scrollableArea = *it; 3250 3251 if (!scrollableArea->scrollbarsCanBeActive()) 3252 continue; 3253 3254 scrollableArea->contentAreaWillPaint(); 3255 } 3256} 3257 3258bool FrameView::scrollAnimatorEnabled() const 3259{ 3260#if ENABLE(SMOOTH_SCROLLING) 3261 if (Page* page = m_frame->page()) 3262 return page->settings()->scrollAnimatorEnabled(); 3263#endif 3264 3265 return false; 3266} 3267 3268#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION) 3269void FrameView::updateAnnotatedRegions() 3270{ 3271 Document* document = m_frame->document(); 3272 if (!document->hasAnnotatedRegions()) 3273 return; 3274 Vector<AnnotatedRegionValue> newRegions; 3275 document->renderBox()->collectAnnotatedRegions(newRegions); 3276 if (newRegions == document->annotatedRegions()) 3277 return; 3278 document->setAnnotatedRegions(newRegions); 3279 Page* page = m_frame->page(); 3280 if (!page) 3281 return; 3282 page->chrome().client()->annotatedRegionsChanged(); 3283} 3284#endif 3285 3286void FrameView::updateScrollCorner() 3287{ 3288 RenderObject* renderer = 0; 3289 RefPtr<RenderStyle> cornerStyle; 3290 IntRect cornerRect = scrollCornerRect(); 3291 3292 if (!cornerRect.isEmpty()) { 3293 // Try the <body> element first as a scroll corner source. 3294 Document* doc = m_frame->document(); 3295 Element* body = doc ? doc->body() : 0; 3296 if (body && body->renderer()) { 3297 renderer = body->renderer(); 3298 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style()); 3299 } 3300 3301 if (!cornerStyle) { 3302 // If the <body> didn't have a custom style, then the root element might. 3303 Element* docElement = doc ? doc->documentElement() : 0; 3304 if (docElement && docElement->renderer()) { 3305 renderer = docElement->renderer(); 3306 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style()); 3307 } 3308 } 3309 3310 if (!cornerStyle) { 3311 // If we have an owning iframe/frame element, then it can set the custom scrollbar also. 3312 if (RenderPart* renderer = m_frame->ownerRenderer()) 3313 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style()); 3314 } 3315 } 3316 3317 if (cornerStyle) { 3318 if (!m_scrollCorner) 3319 m_scrollCorner = RenderScrollbarPart::createAnonymous(renderer->document()); 3320 m_scrollCorner->setStyle(cornerStyle.release()); 3321 invalidateScrollCorner(cornerRect); 3322 } else if (m_scrollCorner) { 3323 m_scrollCorner->destroy(); 3324 m_scrollCorner = 0; 3325 } 3326 3327 ScrollView::updateScrollCorner(); 3328} 3329 3330void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect) 3331{ 3332 if (context->updatingControlTints()) { 3333 updateScrollCorner(); 3334 return; 3335 } 3336 3337 if (m_scrollCorner) { 3338 bool needsBackgorund = m_frame->page() && m_frame->page()->mainFrame() == m_frame; 3339 if (needsBackgorund) 3340 context->fillRect(cornerRect, baseBackgroundColor(), ColorSpaceDeviceRGB); 3341 m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect); 3342 return; 3343 } 3344 3345 ScrollView::paintScrollCorner(context, cornerRect); 3346} 3347 3348void FrameView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect) 3349{ 3350 bool needsBackgorund = bar->isCustomScrollbar() && (m_frame->page() && m_frame->page()->mainFrame() == m_frame); 3351 if (needsBackgorund) { 3352 IntRect toFill = bar->frameRect(); 3353 toFill.intersect(rect); 3354 context->fillRect(toFill, baseBackgroundColor(), ColorSpaceDeviceRGB); 3355 } 3356 3357 ScrollView::paintScrollbar(context, bar, rect); 3358} 3359 3360Color FrameView::documentBackgroundColor() const 3361{ 3362 // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of 3363 // the document and the body against the base background color of the frame view. 3364 // Background images are unfortunately impractical to include. 3365 3366 // Return invalid Color objects whenever there is insufficient information. 3367 if (!frame()->document()) 3368 return Color(); 3369 3370 Element* htmlElement = frame()->document()->documentElement(); 3371 Element* bodyElement = frame()->document()->body(); 3372 3373 // Start with invalid colors. 3374 Color htmlBackgroundColor; 3375 Color bodyBackgroundColor; 3376 if (htmlElement && htmlElement->renderer()) 3377 htmlBackgroundColor = htmlElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor); 3378 if (bodyElement && bodyElement->renderer()) 3379 bodyBackgroundColor = bodyElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor); 3380 3381 if (!bodyBackgroundColor.isValid()) { 3382 if (!htmlBackgroundColor.isValid()) 3383 return Color(); 3384 return baseBackgroundColor().blend(htmlBackgroundColor); 3385 } 3386 3387 if (!htmlBackgroundColor.isValid()) 3388 return baseBackgroundColor().blend(bodyBackgroundColor); 3389 3390 // We take the aggregate of the base background color 3391 // the <html> background color, and the <body> 3392 // background color to find the document color. The 3393 // addition of the base background color is not 3394 // technically part of the document background, but it 3395 // otherwise poses problems when the aggregate is not 3396 // fully opaque. 3397 return baseBackgroundColor().blend(htmlBackgroundColor).blend(bodyBackgroundColor); 3398} 3399 3400bool FrameView::hasCustomScrollbars() const 3401{ 3402 const HashSet<RefPtr<Widget> >* viewChildren = children(); 3403 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end(); 3404 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) { 3405 Widget* widget = current->get(); 3406 if (widget->isFrameView()) { 3407 if (toFrameView(widget)->hasCustomScrollbars()) 3408 return true; 3409 } else if (widget->isScrollbar()) { 3410 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget); 3411 if (scrollbar->isCustomScrollbar()) 3412 return true; 3413 } 3414 } 3415 3416 return false; 3417} 3418 3419FrameView* FrameView::parentFrameView() const 3420{ 3421 if (!parent()) 3422 return 0; 3423 3424 if (Frame* parentFrame = m_frame->tree()->parent()) 3425 return parentFrame->view(); 3426 3427 return 0; 3428} 3429 3430bool FrameView::isInChildFrameWithFrameFlattening() const 3431{ 3432 if (!parent() || !m_frame->ownerElement()) 3433 return false; 3434 3435 // Frame flattening applies when the owner element is either in a frameset or 3436 // an iframe with flattening parameters. 3437 if (m_frame->ownerElement()->hasTagName(iframeTag)) { 3438 RenderIFrame* iframeRenderer = toRenderIFrame(m_frame->ownerElement()->renderPart()); 3439 if (iframeRenderer->flattenFrame() || iframeRenderer->isSeamless()) 3440 return true; 3441 } 3442 3443 if (!frameFlatteningEnabled(frame())) 3444 return false; 3445 3446 if (m_frame->ownerElement()->hasTagName(frameTag)) 3447 return true; 3448 3449 return false; 3450} 3451 3452bool FrameView::doLayoutWithFrameFlattening(bool allowSubtree) 3453{ 3454 // Try initiating layout from the topmost parent. 3455 FrameView* parentView = parentFrameView(); 3456 3457 if (!parentView) 3458 return false; 3459 3460 // In the middle of parent layout, no need to restart from topmost. 3461 if (parentView->m_nestedLayoutCount) 3462 return false; 3463 3464 // Parent tree is clean. Starting layout from it would have no effect. 3465 if (!parentView->needsLayout()) 3466 return false; 3467 3468 while (parentView->parentFrameView()) 3469 parentView = parentView->parentFrameView(); 3470 3471 parentView->layout(allowSubtree); 3472 3473 RenderObject* root = m_layoutRoot ? m_layoutRoot : m_frame->document()->renderer(); 3474 ASSERT_UNUSED(root, !root->needsLayout()); 3475 3476 return true; 3477} 3478 3479void FrameView::updateControlTints() 3480{ 3481 // This is called when control tints are changed from aqua/graphite to clear and vice versa. 3482 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate. 3483 // This is only done if the theme supports control tinting. It's up to the theme and platform 3484 // to define when controls get the tint and to call this function when that changes. 3485 3486 // Optimize the common case where we bring a window to the front while it's still empty. 3487 if (!m_frame || m_frame->document()->url().isEmpty()) 3488 return; 3489 3490 RenderView* renderView = this->renderView(); 3491 if ((renderView && renderView->theme()->supportsControlTints()) || hasCustomScrollbars()) 3492 paintControlTints(); 3493} 3494 3495void FrameView::paintControlTints() 3496{ 3497 if (needsLayout()) 3498 layout(); 3499 PlatformGraphicsContext* const noContext = 0; 3500 GraphicsContext context(noContext); 3501 context.setUpdatingControlTints(true); 3502 if (platformWidget()) 3503 paintContents(&context, visibleContentRect()); 3504 else 3505 paint(&context, frameRect()); 3506} 3507 3508bool FrameView::wasScrolledByUser() const 3509{ 3510 return m_wasScrolledByUser; 3511} 3512 3513void FrameView::setWasScrolledByUser(bool wasScrolledByUser) 3514{ 3515 if (m_inProgrammaticScroll) 3516 return; 3517 m_maintainScrollPositionAnchor = 0; 3518 if (m_wasScrolledByUser == wasScrolledByUser) 3519 return; 3520 m_wasScrolledByUser = wasScrolledByUser; 3521 adjustTiledBackingCoverage(); 3522} 3523 3524void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) 3525{ 3526 if (!frame()) 3527 return; 3528 3529 Document* document = m_frame->document(); 3530 3531#ifndef NDEBUG 3532 bool fillWithRed; 3533 if (document->printing()) 3534 fillWithRed = false; // Printing, don't fill with red (can't remember why). 3535 else if (m_frame->ownerElement()) 3536 fillWithRed = false; // Subframe, don't fill with red. 3537 else if (isTransparent()) 3538 fillWithRed = false; // Transparent, don't fill with red. 3539 else if (m_paintBehavior & PaintBehaviorSelectionOnly) 3540 fillWithRed = false; // Selections are transparent, don't fill with red. 3541 else if (m_nodeToDraw) 3542 fillWithRed = false; // Element images are transparent, don't fill with red. 3543 else 3544 fillWithRed = true; 3545 3546 if (fillWithRed) 3547 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB); 3548#endif 3549 3550 RenderView* renderView = this->renderView(); 3551 if (!renderView) { 3552 LOG_ERROR("called FrameView::paint with nil renderer"); 3553 return; 3554 } 3555 3556 ASSERT(!needsLayout()); 3557 if (needsLayout()) 3558 return; 3559 3560 if (!p->paintingDisabled()) 3561 InspectorInstrumentation::willPaint(renderView); 3562 3563 bool isTopLevelPainter = !sCurrentPaintTimeStamp; 3564 if (isTopLevelPainter) 3565 sCurrentPaintTimeStamp = currentTime(); 3566 3567 FontCachePurgePreventer fontCachePurgePreventer; 3568 3569#if USE(ACCELERATED_COMPOSITING) 3570 if (!p->paintingDisabled() && !document->printing()) 3571 flushCompositingStateForThisFrame(m_frame.get()); 3572#endif 3573 3574 PaintBehavior oldPaintBehavior = m_paintBehavior; 3575 3576 if (FrameView* parentView = parentFrameView()) { 3577 if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers) 3578 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers; 3579 } 3580 3581 if (m_paintBehavior == PaintBehaviorNormal) 3582 document->markers()->invalidateRenderedRectsForMarkersInRect(rect); 3583 3584 if (document->printing()) 3585 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers; 3586 3587 bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers; 3588 bool isRootFrame = !m_frame->ownerElement(); 3589 if (flatteningPaint && isRootFrame) 3590 notifyWidgetsInAllFrames(WillPaintFlattened); 3591 3592 ASSERT(!m_isPainting); 3593 m_isPainting = true; 3594 3595 // m_nodeToDraw is used to draw only one element (and its descendants) 3596 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0; 3597 RenderLayer* rootLayer = renderView->layer(); 3598 3599#ifndef NDEBUG 3600 RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(rootLayer->renderer()); 3601#endif 3602 3603 rootLayer->paint(p, rect, m_paintBehavior, eltRenderer); 3604 3605 if (rootLayer->containsDirtyOverlayScrollbars()) 3606 rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer); 3607 3608 m_isPainting = false; 3609 3610 if (flatteningPaint && isRootFrame) 3611 notifyWidgetsInAllFrames(DidPaintFlattened); 3612 3613 m_paintBehavior = oldPaintBehavior; 3614 m_lastPaintTime = currentTime(); 3615 3616 // Regions may have changed as a result of the visibility/z-index of element changing. 3617#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION) 3618 if (document->annotatedRegionsDirty()) 3619 updateAnnotatedRegions(); 3620#endif 3621 3622 if (isTopLevelPainter) 3623 sCurrentPaintTimeStamp = 0; 3624 3625 if (!p->paintingDisabled()) { 3626 InspectorInstrumentation::didPaint(renderView, p, rect); 3627 // FIXME: should probably not fire milestones for snapshot painting. https://bugs.webkit.org/show_bug.cgi?id=117623 3628 firePaintRelatedMilestones(); 3629 } 3630} 3631 3632void FrameView::setPaintBehavior(PaintBehavior behavior) 3633{ 3634 m_paintBehavior = behavior; 3635} 3636 3637PaintBehavior FrameView::paintBehavior() const 3638{ 3639 return m_paintBehavior; 3640} 3641 3642bool FrameView::isPainting() const 3643{ 3644 return m_isPainting; 3645} 3646 3647// FIXME: change this to use the subtreePaint terminology. 3648void FrameView::setNodeToDraw(Node* node) 3649{ 3650 m_nodeToDraw = node; 3651} 3652 3653void FrameView::paintContentsForSnapshot(GraphicsContext* context, const IntRect& imageRect, SelectionInSnaphot shouldPaintSelection, CoordinateSpaceForSnapshot coordinateSpace) 3654{ 3655 updateLayoutAndStyleIfNeededRecursive(); 3656 3657 // Cache paint behavior and set a new behavior appropriate for snapshots. 3658 PaintBehavior oldBehavior = paintBehavior(); 3659 setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers); 3660 3661 // If the snapshot should exclude selection, then we'll clear the current selection 3662 // in the render tree only. This will allow us to restore the selection from the DOM 3663 // after we paint the snapshot. 3664 if (shouldPaintSelection == ExcludeSelection) { 3665 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 3666 if (RenderView* root = frame->contentRenderer()) 3667 root->clearSelection(); 3668 } 3669 } 3670 3671 if (coordinateSpace == DocumentCoordinates) 3672 paintContents(context, imageRect); 3673 else { 3674 // A snapshot in ViewCoordinates will include a scrollbar, and the snapshot will contain 3675 // whatever content the document is currently scrolled to. 3676 paint(context, imageRect); 3677 } 3678 3679 // Restore selection. 3680 if (shouldPaintSelection == ExcludeSelection) { 3681 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) 3682 frame->selection()->updateAppearance(); 3683 } 3684 3685 // Restore cached paint behavior. 3686 setPaintBehavior(oldBehavior); 3687} 3688 3689void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect) 3690{ 3691 if (context->paintingDisabled()) 3692 return; 3693 3694 if (m_frame->document()->printing()) 3695 return; 3696 3697 Page* page = m_frame->page(); 3698 if (page->mainFrame() == m_frame) { 3699 if (page->chrome().client()->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect)) 3700 return; 3701 } 3702 3703 ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect); 3704} 3705 3706void FrameView::updateLayoutAndStyleIfNeededRecursive() 3707{ 3708 // We have to crawl our entire tree looking for any FrameViews that need 3709 // layout and make sure they are up to date. 3710 // Mac actually tests for intersection with the dirty region and tries not to 3711 // update layout for frames that are outside the dirty region. Not only does this seem 3712 // pointless (since those frames will have set a zero timer to layout anyway), but 3713 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty 3714 // region but then become included later by the second frame adding rects to the dirty region 3715 // when it lays out. 3716 3717 m_frame->document()->updateStyleIfNeeded(); 3718 3719 if (needsLayout()) 3720 layout(); 3721 3722 // Grab a copy of the children() set, as it may be mutated by the following updateLayoutAndStyleIfNeededRecursive 3723 // calls, as they can potentially re-enter a layout of the parent frame view, which may add/remove scrollbars 3724 // and thus mutates the children() set. 3725 Vector<RefPtr<FrameView> > frameViews; 3726 collectFrameViewChildren(this, frameViews); 3727 3728 const Vector<RefPtr<FrameView> >::iterator end = frameViews.end(); 3729 for (Vector<RefPtr<FrameView> >::iterator it = frameViews.begin(); it != end; ++it) 3730 (*it)->updateLayoutAndStyleIfNeededRecursive(); 3731 3732 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before 3733 // painting, so we need to flush out any deferred repaints too. 3734 flushDeferredRepaints(); 3735 3736 // When frame flattening is on, child frame can mark parent frame dirty. In such case, child frame 3737 // needs to call layout on parent frame recursively. 3738 // This assert ensures that parent frames are clean, when child frames finished updating layout and style. 3739 ASSERT(!needsLayout()); 3740} 3741 3742void FrameView::setIsVisuallyNonEmpty() 3743{ 3744 m_isVisuallyNonEmpty = true; 3745 adjustTiledBackingCoverage(); 3746} 3747 3748void FrameView::enableAutoSizeMode(bool enable, const IntSize& minSize, const IntSize& maxSize) 3749{ 3750 ASSERT(!enable || !minSize.isEmpty()); 3751 ASSERT(minSize.width() <= maxSize.width()); 3752 ASSERT(minSize.height() <= maxSize.height()); 3753 3754 if (m_shouldAutoSize == enable && m_minAutoSize == minSize && m_maxAutoSize == maxSize) 3755 return; 3756 3757 m_shouldAutoSize = enable; 3758 m_minAutoSize = minSize; 3759 m_maxAutoSize = maxSize; 3760 m_didRunAutosize = false; 3761 3762 setNeedsLayout(); 3763 scheduleRelayout(); 3764 if (m_shouldAutoSize) 3765 return; 3766 3767 // Since autosize mode forces the scrollbar mode, change them to being auto. 3768 setVerticalScrollbarLock(false); 3769 setHorizontalScrollbarLock(false); 3770 setScrollbarModes(ScrollbarAuto, ScrollbarAuto); 3771} 3772 3773void FrameView::forceLayout(bool allowSubtree) 3774{ 3775 layout(allowSubtree); 3776} 3777 3778void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor, AdjustViewSizeOrNot shouldAdjustViewSize) 3779{ 3780 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see 3781 // the state of things before and after the layout 3782 if (RenderView* renderView = this->renderView()) { 3783 float pageLogicalWidth = renderView->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height(); 3784 float pageLogicalHeight = renderView->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width(); 3785 3786 LayoutUnit flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth); 3787 LayoutUnit flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight); 3788 renderView->setLogicalWidth(flooredPageLogicalWidth); 3789 renderView->setPageLogicalHeight(flooredPageLogicalHeight); 3790 renderView->setNeedsLayoutAndPrefWidthsRecalc(); 3791 forceLayout(); 3792 3793 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the 3794 // page width when shrunk, we will lay out at maximum shrink and clip extra content. 3795 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping 3796 // implementation should not do this! 3797 bool horizontalWritingMode = renderView->style()->isHorizontalWritingMode(); 3798 const LayoutRect& documentRect = renderView->documentRect(); 3799 LayoutUnit docLogicalWidth = horizontalWritingMode ? documentRect.width() : documentRect.height(); 3800 if (docLogicalWidth > pageLogicalWidth) { 3801 int expectedPageWidth = std::min<float>(documentRect.width(), pageSize.width() * maximumShrinkFactor); 3802 int expectedPageHeight = std::min<float>(documentRect.height(), pageSize.height() * maximumShrinkFactor); 3803 FloatSize maxPageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(originalPageSize.width(), originalPageSize.height()), FloatSize(expectedPageWidth, expectedPageHeight)); 3804 pageLogicalWidth = horizontalWritingMode ? maxPageSize.width() : maxPageSize.height(); 3805 pageLogicalHeight = horizontalWritingMode ? maxPageSize.height() : maxPageSize.width(); 3806 3807 flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth); 3808 flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight); 3809 renderView->setLogicalWidth(flooredPageLogicalWidth); 3810 renderView->setPageLogicalHeight(flooredPageLogicalHeight); 3811 renderView->setNeedsLayoutAndPrefWidthsRecalc(); 3812 forceLayout(); 3813 3814 const LayoutRect& updatedDocumentRect = renderView->documentRect(); 3815 LayoutUnit docLogicalHeight = horizontalWritingMode ? updatedDocumentRect.height() : updatedDocumentRect.width(); 3816 LayoutUnit docLogicalTop = horizontalWritingMode ? updatedDocumentRect.y() : updatedDocumentRect.x(); 3817 LayoutUnit docLogicalRight = horizontalWritingMode ? updatedDocumentRect.maxX() : updatedDocumentRect.maxY(); 3818 LayoutUnit clippedLogicalLeft = 0; 3819 if (!renderView->style()->isLeftToRightDirection()) 3820 clippedLogicalLeft = docLogicalRight - pageLogicalWidth; 3821 LayoutRect overflow(clippedLogicalLeft, docLogicalTop, pageLogicalWidth, docLogicalHeight); 3822 3823 if (!horizontalWritingMode) 3824 overflow = overflow.transposedRect(); 3825 renderView->clearLayoutOverflow(); 3826 renderView->addLayoutOverflow(overflow); // This is how we clip in case we overflow again. 3827 } 3828 } 3829 3830 if (shouldAdjustViewSize) 3831 adjustViewSize(); 3832} 3833 3834void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/) 3835{ 3836 RenderView* renderView = this->renderView(); 3837 if (!renderView) { 3838 *newBottom = oldBottom; 3839 return; 3840 3841 } 3842 // Use a context with painting disabled. 3843 GraphicsContext context((PlatformGraphicsContext*)0); 3844 renderView->setTruncatedAt(static_cast<int>(floorf(oldBottom))); 3845 IntRect dirtyRect(0, static_cast<int>(floorf(oldTop)), renderView->layoutOverflowRect().maxX(), static_cast<int>(ceilf(oldBottom - oldTop))); 3846 renderView->setPrintRect(dirtyRect); 3847 renderView->layer()->paint(&context, dirtyRect); 3848 *newBottom = renderView->bestTruncatedAt(); 3849 if (!*newBottom) 3850 *newBottom = oldBottom; 3851 renderView->setPrintRect(IntRect()); 3852} 3853 3854IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const 3855{ 3856 IntRect rect = pixelSnappedIntRect(enclosingLayoutRect(renderer->localToAbsoluteQuad(FloatRect(rendererRect)).boundingBox())); 3857 3858 // Convert from page ("absolute") to FrameView coordinates. 3859 if (!delegatesScrolling()) 3860 rect.moveBy(-scrollPosition() + IntPoint(0, headerHeight())); 3861 3862 return rect; 3863} 3864 3865IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const 3866{ 3867 IntRect rect = viewRect; 3868 3869 // Convert from FrameView coords into page ("absolute") coordinates. 3870 if (!delegatesScrolling()) 3871 rect.moveBy(scrollPositionRelativeToDocument()); 3872 3873 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just 3874 // move the rect for now. 3875 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), UseTransforms))); 3876 return rect; 3877} 3878 3879IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const 3880{ 3881 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, UseTransforms)); 3882 3883 // Convert from page ("absolute") to FrameView coordinates. 3884 if (!delegatesScrolling()) 3885 point.moveBy(-scrollPosition() + IntPoint(0, headerHeight())); 3886 return point; 3887} 3888 3889IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const 3890{ 3891 IntPoint point = viewPoint; 3892 3893 // Convert from FrameView coords into page ("absolute") coordinates. 3894 if (!delegatesScrolling()) 3895 point = point + scrollPositionRelativeToDocument(); 3896 3897 return roundedIntPoint(renderer->absoluteToLocal(point, UseTransforms)); 3898} 3899 3900IntRect FrameView::convertToContainingView(const IntRect& localRect) const 3901{ 3902 if (const ScrollView* parentScrollView = parent()) { 3903 if (parentScrollView->isFrameView()) { 3904 const FrameView* parentView = toFrameView(parentScrollView); 3905 // Get our renderer in the parent view 3906 RenderPart* renderer = m_frame->ownerRenderer(); 3907 if (!renderer) 3908 return localRect; 3909 3910 IntRect rect(localRect); 3911 // Add borders and padding?? 3912 rect.move(renderer->borderLeft() + renderer->paddingLeft(), 3913 renderer->borderTop() + renderer->paddingTop()); 3914 return parentView->convertFromRenderer(renderer, rect); 3915 } 3916 3917 return Widget::convertToContainingView(localRect); 3918 } 3919 3920 return localRect; 3921} 3922 3923IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const 3924{ 3925 if (const ScrollView* parentScrollView = parent()) { 3926 if (parentScrollView->isFrameView()) { 3927 const FrameView* parentView = toFrameView(parentScrollView); 3928 3929 // Get our renderer in the parent view 3930 RenderPart* renderer = m_frame->ownerRenderer(); 3931 if (!renderer) 3932 return parentRect; 3933 3934 IntRect rect = parentView->convertToRenderer(renderer, parentRect); 3935 // Subtract borders and padding 3936 rect.move(-renderer->borderLeft() - renderer->paddingLeft(), 3937 -renderer->borderTop() - renderer->paddingTop()); 3938 return rect; 3939 } 3940 3941 return Widget::convertFromContainingView(parentRect); 3942 } 3943 3944 return parentRect; 3945} 3946 3947IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const 3948{ 3949 if (const ScrollView* parentScrollView = parent()) { 3950 if (parentScrollView->isFrameView()) { 3951 const FrameView* parentView = toFrameView(parentScrollView); 3952 3953 // Get our renderer in the parent view 3954 RenderPart* renderer = m_frame->ownerRenderer(); 3955 if (!renderer) 3956 return localPoint; 3957 3958 IntPoint point(localPoint); 3959 3960 // Add borders and padding 3961 point.move(renderer->borderLeft() + renderer->paddingLeft(), 3962 renderer->borderTop() + renderer->paddingTop()); 3963 return parentView->convertFromRenderer(renderer, point); 3964 } 3965 3966 return Widget::convertToContainingView(localPoint); 3967 } 3968 3969 return localPoint; 3970} 3971 3972IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const 3973{ 3974 if (const ScrollView* parentScrollView = parent()) { 3975 if (parentScrollView->isFrameView()) { 3976 const FrameView* parentView = toFrameView(parentScrollView); 3977 3978 // Get our renderer in the parent view 3979 RenderPart* renderer = m_frame->ownerRenderer(); 3980 if (!renderer) 3981 return parentPoint; 3982 3983 IntPoint point = parentView->convertToRenderer(renderer, parentPoint); 3984 // Subtract borders and padding 3985 point.move(-renderer->borderLeft() - renderer->paddingLeft(), 3986 -renderer->borderTop() - renderer->paddingTop()); 3987 return point; 3988 } 3989 3990 return Widget::convertFromContainingView(parentPoint); 3991 } 3992 3993 return parentPoint; 3994} 3995 3996PlatformDisplayID FrameView::windowDisplayID() const 3997{ 3998 if (Page* page = m_frame->page()) 3999 return page->displayID(); 4000 4001 return Widget::windowDisplayID(); 4002} 4003 4004// Normal delay 4005void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p) 4006{ 4007 s_normalDeferredRepaintDelay = p; 4008} 4009 4010// Negative value would mean that first few repaints happen without a delay 4011void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p) 4012{ 4013 s_initialDeferredRepaintDelayDuringLoading = p; 4014} 4015 4016// The delay grows on each repaint to this maximum value 4017void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p) 4018{ 4019 s_maxDeferredRepaintDelayDuringLoading = p; 4020} 4021 4022// On each repaint the delay increases by this amount 4023void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p) 4024{ 4025 s_deferredRepaintDelayIncrementDuringLoading = p; 4026} 4027 4028void FrameView::setTracksRepaints(bool trackRepaints) 4029{ 4030 if (trackRepaints == m_isTrackingRepaints) 4031 return; 4032 4033 // Force layout to flush out any pending repaints. 4034 if (trackRepaints) { 4035 if (frame() && frame()->document()) 4036 frame()->document()->updateLayout(); 4037 } 4038 4039#if USE(ACCELERATED_COMPOSITING) 4040 for (Frame* frame = m_frame->tree()->top(); frame; frame = frame->tree()->traverseNext()) { 4041 if (RenderView* renderView = frame->contentRenderer()) 4042 renderView->compositor()->setTracksRepaints(trackRepaints); 4043 } 4044#endif 4045 4046 resetTrackedRepaints(); 4047 m_isTrackingRepaints = trackRepaints; 4048} 4049 4050void FrameView::resetTrackedRepaints() 4051{ 4052 m_trackedRepaintRects.clear(); 4053#if USE(ACCELERATED_COMPOSITING) 4054 if (RenderView* renderView = this->renderView()) 4055 renderView->compositor()->resetTrackedRepaintRects(); 4056#endif 4057} 4058 4059String FrameView::trackedRepaintRectsAsText() const 4060{ 4061 if (frame() && frame()->document()) 4062 frame()->document()->updateLayout(); 4063 4064 TextStream ts; 4065 if (!m_trackedRepaintRects.isEmpty()) { 4066 ts << "(repaint rects\n"; 4067 for (size_t i = 0; i < m_trackedRepaintRects.size(); ++i) 4068 ts << " (rect " << m_trackedRepaintRects[i].x() << " " << m_trackedRepaintRects[i].y() << " " << m_trackedRepaintRects[i].width() << " " << m_trackedRepaintRects[i].height() << ")\n"; 4069 ts << ")\n"; 4070 } 4071 return ts.release(); 4072} 4073 4074bool FrameView::addScrollableArea(ScrollableArea* scrollableArea) 4075{ 4076 if (!m_scrollableAreas) 4077 m_scrollableAreas = adoptPtr(new ScrollableAreaSet); 4078 return m_scrollableAreas->add(scrollableArea).isNewEntry; 4079} 4080 4081bool FrameView::removeScrollableArea(ScrollableArea* scrollableArea) 4082{ 4083 if (!m_scrollableAreas) 4084 return false; 4085 4086 ScrollableAreaSet::iterator it = m_scrollableAreas->find(scrollableArea); 4087 if (it == m_scrollableAreas->end()) 4088 return false; 4089 4090 m_scrollableAreas->remove(it); 4091 return true; 4092} 4093 4094bool FrameView::containsScrollableArea(ScrollableArea* scrollableArea) const 4095{ 4096 if (!m_scrollableAreas) 4097 return false; 4098 return m_scrollableAreas->contains(scrollableArea); 4099} 4100 4101void FrameView::removeChild(Widget* widget) 4102{ 4103 if (widget->isFrameView()) 4104 removeScrollableArea(toFrameView(widget)); 4105 4106 ScrollView::removeChild(widget); 4107} 4108 4109bool FrameView::wheelEvent(const PlatformWheelEvent& wheelEvent) 4110{ 4111 // Note that to allow for rubber-band over-scroll behavior, even non-scrollable views 4112 // should handle wheel events. 4113#if !ENABLE(RUBBER_BANDING) 4114 if (!isScrollable()) 4115 return false; 4116#endif 4117 4118 if (delegatesScrolling()) { 4119 IntSize offset = scrollOffset(); 4120 IntSize newOffset = IntSize(offset.width() - wheelEvent.deltaX(), offset.height() - wheelEvent.deltaY()); 4121 if (offset != newOffset) { 4122 ScrollView::scrollTo(newOffset); 4123 scrollPositionChanged(); 4124 frame()->loader()->client()->didChangeScrollOffset(); 4125 } 4126 return true; 4127 } 4128 4129 // We don't allow mouse wheeling to happen in a ScrollView that has had its scrollbars explicitly disabled. 4130 if (!canHaveScrollbars()) 4131 return false; 4132 4133 if (platformWidget()) 4134 return false; 4135 4136#if ENABLE(THREADED_SCROLLING) 4137 if (Page* page = m_frame->page()) { 4138 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) { 4139 if (scrollingCoordinator->coordinatesScrollingForFrameView(this)) 4140 return scrollingCoordinator->handleWheelEvent(this, wheelEvent); 4141 } 4142 } 4143#endif 4144 4145 return ScrollableArea::handleWheelEvent(wheelEvent); 4146} 4147 4148 4149bool FrameView::isVerticalDocument() const 4150{ 4151 RenderView* renderView = this->renderView(); 4152 if (!renderView) 4153 return true; 4154 4155 return renderView->style()->isHorizontalWritingMode(); 4156} 4157 4158bool FrameView::isFlippedDocument() const 4159{ 4160 RenderView* renderView = this->renderView(); 4161 if (!renderView) 4162 return false; 4163 4164 return renderView->style()->isFlippedBlocksWritingMode(); 4165} 4166 4167void FrameView::notifyWidgetsInAllFrames(WidgetNotification notification) 4168{ 4169 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 4170 if (RenderView* root = frame->contentRenderer()) 4171 root->notifyWidgets(notification); 4172 } 4173} 4174 4175AXObjectCache* FrameView::axObjectCache() const 4176{ 4177 if (frame() && frame()->document()) 4178 return frame()->document()->existingAXObjectCache(); 4179 return 0; 4180} 4181 4182void FrameView::setScrollingPerformanceLoggingEnabled(bool flag) 4183{ 4184#if USE(ACCELERATED_COMPOSITING) 4185 if (TiledBacking* tiledBacking = this->tiledBacking()) 4186 tiledBacking->setScrollingPerformanceLoggingEnabled(flag); 4187#else 4188 UNUSED_PARAM(flag); 4189#endif 4190} 4191 4192void FrameView::didAddScrollbar(Scrollbar* scrollbar, ScrollbarOrientation orientation) 4193{ 4194 ScrollableArea::didAddScrollbar(scrollbar, orientation); 4195 if (AXObjectCache* cache = axObjectCache()) 4196 cache->handleScrollbarUpdate(this); 4197} 4198 4199void FrameView::willRemoveScrollbar(Scrollbar* scrollbar, ScrollbarOrientation orientation) 4200{ 4201 ScrollableArea::willRemoveScrollbar(scrollbar, orientation); 4202 if (AXObjectCache* cache = axObjectCache()) { 4203 cache->remove(scrollbar); 4204 cache->handleScrollbarUpdate(this); 4205 } 4206} 4207 4208void FrameView::addPaintPendingMilestones(LayoutMilestones milestones) 4209{ 4210 m_milestonesPendingPaint |= milestones; 4211} 4212 4213void FrameView::firePaintRelatedMilestones() 4214{ 4215 Page* page = m_frame->page(); 4216 if (!page) 4217 return; 4218 4219 LayoutMilestones milestonesAchieved = 0; 4220 4221 // Make sure the pending paint milestones have actually been requested before we send them. 4222 if (m_milestonesPendingPaint & DidFirstFlushForHeaderLayer) { 4223 if (page->requestedLayoutMilestones() & DidFirstFlushForHeaderLayer) 4224 milestonesAchieved |= DidFirstFlushForHeaderLayer; 4225 } 4226 4227 if (m_milestonesPendingPaint & DidFirstPaintAfterSuppressedIncrementalRendering) { 4228 if (page->requestedLayoutMilestones() & DidFirstPaintAfterSuppressedIncrementalRendering) 4229 milestonesAchieved |= DidFirstPaintAfterSuppressedIncrementalRendering; 4230 } 4231 4232 m_milestonesPendingPaint = 0; 4233 4234 if (milestonesAchieved) { 4235 if (Frame* frame = page->mainFrame()) 4236 frame->loader()->didLayout(milestonesAchieved); 4237 } 4238} 4239 4240void FrameView::setVisualUpdatesAllowedByClient(bool visualUpdatesAllowed) 4241{ 4242 if (m_visualUpdatesAllowedByClient == visualUpdatesAllowed) 4243 return; 4244 4245 m_visualUpdatesAllowedByClient = visualUpdatesAllowed; 4246 4247 m_frame->document()->setVisualUpdatesAllowedByClient(visualUpdatesAllowed); 4248} 4249 4250void FrameView::setScrollPinningBehavior(ScrollPinningBehavior pinning) 4251{ 4252 m_scrollPinningBehavior = pinning; 4253 4254 if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator()) 4255 scrollingCoordinator->setScrollPinningBehavior(pinning); 4256 4257 updateScrollbars(scrollOffset()); 4258} 4259 4260} // namespace WebCore 4261