1 /* 2 * Copyright (C) 1998, 1999 Torben Weis <weis (at) kde.org> 3 * 1999 Lars Knoll <knoll (at) kde.org> 4 * 1999 Antti Koivisto <koivisto (at) kde.org> 5 * 2000 Dirk Mueller <mueller (at) kde.org> 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 7 * (C) 2006 Graham Dennis (graham.dennis (at) gmail.com) 8 * (C) 2006 Alexey Proskuryakov (ap (at) 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 "core/page/FrameView.h" 29 30 #include "HTMLNames.h" 31 #include "RuntimeEnabledFeatures.h" 32 #include "core/accessibility/AXObjectCache.h" 33 #include "core/animation/DocumentTimeline.h" 34 #include "core/css/FontLoader.h" 35 #include "core/css/resolver/StyleResolver.h" 36 #include "core/dom/DocumentMarkerController.h" 37 #include "core/dom/OverflowEvent.h" 38 #include "core/editing/FrameSelection.h" 39 #include "core/html/HTMLFrameElement.h" 40 #include "core/html/HTMLHtmlElement.h" 41 #include "core/html/HTMLPlugInImageElement.h" 42 #include "core/inspector/InspectorInstrumentation.h" 43 #include "core/loader/FrameLoader.h" 44 #include "core/loader/FrameLoaderClient.h" 45 #include "core/loader/TextResourceDecoder.h" 46 #include "core/loader/cache/ResourceFetcher.h" 47 #include "core/page/Chrome.h" 48 #include "core/page/ChromeClient.h" 49 #include "core/page/EventHandler.h" 50 #include "core/page/FocusController.h" 51 #include "core/page/Frame.h" 52 #include "core/page/FrameActionScheduler.h" 53 #include "core/page/FrameTree.h" 54 #include "core/page/Settings.h" 55 #include "core/page/animation/AnimationController.h" 56 #include "core/page/scrolling/ScrollingCoordinator.h" 57 #include "core/platform/ScrollAnimator.h" 58 #include "core/platform/graphics/FloatRect.h" 59 #include "core/platform/graphics/FontCache.h" 60 #include "core/platform/graphics/GraphicsContext.h" 61 #include "core/platform/text/TextStream.h" 62 #include "core/rendering/RenderEmbeddedObject.h" 63 #include "core/rendering/RenderLayer.h" 64 #include "core/rendering/RenderLayerBacking.h" 65 #include "core/rendering/RenderLayerCompositor.h" 66 #include "core/rendering/RenderLazyBlock.h" 67 #include "core/rendering/RenderPart.h" 68 #include "core/rendering/RenderScrollbar.h" 69 #include "core/rendering/RenderScrollbarPart.h" 70 #include "core/rendering/RenderTheme.h" 71 #include "core/rendering/RenderView.h" 72 #include "core/rendering/TextAutosizer.h" 73 #include "core/rendering/style/RenderStyle.h" 74 #include "core/rendering/svg/RenderSVGRoot.h" 75 #include "core/svg/SVGDocument.h" 76 #include "core/svg/SVGSVGElement.h" 77 78 #include "wtf/CurrentTime.h" 79 #include "wtf/TemporaryChange.h" 80 81 #include "core/platform/chromium/TraceEvent.h" 82 83 namespace WebCore { 84 85 using namespace HTMLNames; 86 87 double FrameView::sCurrentPaintTimeStamp = 0.0; 88 89 90 // REPAINT_THROTTLING now chooses default values for throttling parameters. 91 // Should be removed when applications start using runtime configuration. 92 #if ENABLE(REPAINT_THROTTLING) 93 // Normal delay 94 double FrameView::s_normalDeferredRepaintDelay = 0.016; 95 // Negative value would mean that first few repaints happen without a delay 96 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0; 97 // The delay grows on each repaint to this maximum value 98 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5; 99 // On each repaint the delay increses by this amount 100 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5; 101 #else 102 // FIXME: Repaint throttling could be good to have on all platform. 103 // The balance between CPU use and repaint frequency will need some tuning for desktop. 104 // More hooks may be needed to reset the delay on things like GIF and CSS animations. 105 double FrameView::s_normalDeferredRepaintDelay = 0; 106 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0; 107 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0; 108 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0; 109 #endif 110 111 // The maximum number of updateWidgets iterations that should be done before returning. 112 static const unsigned maxUpdateWidgetsIterations = 2; 113 114 static RenderLayer::UpdateLayerPositionsFlags updateLayerPositionFlags(RenderLayer* layer, bool isRelayoutingSubtree, bool didFullRepaint) 115 { 116 RenderLayer::UpdateLayerPositionsFlags flags = RenderLayer::defaultFlags; 117 if (didFullRepaint) { 118 flags &= ~RenderLayer::CheckForRepaint; 119 flags |= RenderLayer::NeedsFullRepaintInBacking; 120 } 121 if (isRelayoutingSubtree && layer->isPaginated()) 122 flags |= RenderLayer::UpdatePagination; 123 return flags; 124 } 125 126 Pagination::Mode paginationModeForRenderStyle(RenderStyle* style) 127 { 128 EOverflow overflow = style->overflowY(); 129 if (overflow != OPAGEDX && overflow != OPAGEDY) 130 return Pagination::Unpaginated; 131 132 bool isHorizontalWritingMode = style->isHorizontalWritingMode(); 133 TextDirection textDirection = style->direction(); 134 WritingMode writingMode = style->writingMode(); 135 136 // paged-x always corresponds to LeftToRightPaginated or RightToLeftPaginated. If the WritingMode 137 // is horizontal, then we use TextDirection to choose between those options. If the WritingMode 138 // is vertical, then the direction of the verticality dictates the choice. 139 if (overflow == OPAGEDX) { 140 if ((isHorizontalWritingMode && textDirection == LTR) || writingMode == LeftToRightWritingMode) 141 return Pagination::LeftToRightPaginated; 142 return Pagination::RightToLeftPaginated; 143 } 144 145 // paged-y always corresponds to TopToBottomPaginated or BottomToTopPaginated. If the WritingMode 146 // is horizontal, then the direction of the horizontality dictates the choice. If the WritingMode 147 // is vertical, then we use TextDirection to choose between those options. 148 if (writingMode == TopToBottomWritingMode || (!isHorizontalWritingMode && textDirection == RTL)) 149 return Pagination::TopToBottomPaginated; 150 return Pagination::BottomToTopPaginated; 151 } 152 153 FrameView::FrameView(Frame* frame) 154 : m_frame(frame) 155 , m_canHaveScrollbars(true) 156 , m_slowRepaintObjectCount(0) 157 , m_layoutTimer(this, &FrameView::layoutTimerFired) 158 , m_layoutRoot(0) 159 , m_inSynchronousPostLayout(false) 160 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired) 161 , m_isTransparent(false) 162 , m_baseBackgroundColor(Color::white) 163 , m_mediaType("screen") 164 , m_actionScheduler(adoptPtr(new FrameActionScheduler)) 165 , m_overflowStatusDirty(true) 166 , m_viewportRenderer(0) 167 , m_wasScrolledByUser(false) 168 , m_inProgrammaticScroll(false) 169 , m_safeToPropagateScrollToParent(true) 170 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired) 171 , m_disableRepaints(0) 172 , m_isTrackingRepaints(false) 173 , m_shouldUpdateWhileOffscreen(true) 174 , m_deferSetNeedsLayouts(0) 175 , m_setNeedsLayoutWasDeferred(false) 176 , m_scrollCorner(0) 177 , m_shouldAutoSize(false) 178 , m_inAutoSize(false) 179 , m_didRunAutosize(false) 180 , m_hasSoftwareFilters(false) 181 , m_visibleContentScaleFactor(1) 182 { 183 init(); 184 185 // FIXME: Can m_frame ever be null here? 186 if (!m_frame) 187 return; 188 189 Page* page = m_frame->page(); 190 if (!page) 191 return; 192 193 if (m_frame == page->mainFrame()) { 194 ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed); 195 ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed); 196 } 197 } 198 199 PassRefPtr<FrameView> FrameView::create(Frame* frame) 200 { 201 RefPtr<FrameView> view = adoptRef(new FrameView(frame)); 202 view->show(); 203 return view.release(); 204 } 205 206 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize) 207 { 208 RefPtr<FrameView> view = adoptRef(new FrameView(frame)); 209 view->Widget::setFrameRect(IntRect(view->location(), initialSize)); 210 view->show(); 211 return view.release(); 212 } 213 214 FrameView::~FrameView() 215 { 216 if (m_postLayoutTasksTimer.isActive()) { 217 m_postLayoutTasksTimer.stop(); 218 m_actionScheduler->clear(); 219 } 220 221 removeFromAXObjectCache(); 222 resetScrollbars(); 223 224 // Custom scrollbars should already be destroyed at this point 225 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar()); 226 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar()); 227 228 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow. 229 setHasVerticalScrollbar(false); 230 231 ASSERT(!m_scrollCorner); 232 ASSERT(m_actionScheduler->isEmpty()); 233 234 if (m_frame) { 235 ASSERT(m_frame->view() != this || !m_frame->contentRenderer()); 236 RenderPart* renderer = m_frame->ownerRenderer(); 237 if (renderer && renderer->widget() == this) 238 renderer->setWidget(0); 239 } 240 } 241 242 void FrameView::reset() 243 { 244 m_cannotBlitToWindow = false; 245 m_isOverlapped = false; 246 m_contentIsOpaque = false; 247 m_borderX = 30; 248 m_borderY = 30; 249 m_layoutTimer.stop(); 250 m_layoutRoot = 0; 251 m_delayedLayout = false; 252 m_doFullRepaint = true; 253 m_layoutSchedulingEnabled = true; 254 m_inLayout = false; 255 m_doingPreLayoutStyleUpdate = false; 256 m_inSynchronousPostLayout = false; 257 m_layoutCount = 0; 258 m_nestedLayoutCount = 0; 259 m_postLayoutTasksTimer.stop(); 260 m_firstLayout = true; 261 m_firstLayoutCallbackPending = false; 262 m_wasScrolledByUser = false; 263 m_safeToPropagateScrollToParent = true; 264 m_lastViewportSize = IntSize(); 265 m_lastZoomFactor = 1.0f; 266 m_deferringRepaints = 0; 267 m_repaintCount = 0; 268 m_repaintRects.clear(); 269 m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading; 270 m_deferredRepaintTimer.stop(); 271 m_isTrackingRepaints = false; 272 m_trackedRepaintRects.clear(); 273 m_lastPaintTime = 0; 274 m_paintBehavior = PaintBehaviorNormal; 275 m_isPainting = false; 276 m_visuallyNonEmptyCharacterCount = 0; 277 m_visuallyNonEmptyPixelCount = 0; 278 m_isVisuallyNonEmpty = false; 279 m_firstVisuallyNonEmptyLayoutCallbackPending = true; 280 m_maintainScrollPositionAnchor = 0; 281 m_disableRepaints = 0; 282 } 283 284 void FrameView::removeFromAXObjectCache() 285 { 286 if (AXObjectCache* cache = axObjectCache()) 287 cache->remove(this); 288 } 289 290 void FrameView::clearFrame() 291 { 292 RELEASE_ASSERT(!isInLayout()); 293 m_frame = 0; 294 } 295 296 void FrameView::resetScrollbars() 297 { 298 // Reset the document's scrollbars back to our defaults before we yield the floor. 299 m_firstLayout = true; 300 setScrollbarsSuppressed(true); 301 if (m_canHaveScrollbars) 302 setScrollbarModes(ScrollbarAuto, ScrollbarAuto); 303 else 304 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); 305 setScrollbarsSuppressed(false); 306 } 307 308 void FrameView::init() 309 { 310 reset(); 311 312 m_margins = LayoutSize(-1, -1); // undefined 313 m_size = LayoutSize(); 314 315 // Propagate the marginwidth/height and scrolling modes to the view. 316 Element* ownerElement = m_frame ? m_frame->ownerElement() : 0; 317 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) { 318 HTMLFrameElementBase* frameElt = static_cast<HTMLFrameElementBase*>(ownerElement); 319 if (frameElt->scrollingMode() == ScrollbarAlwaysOff) 320 setCanHaveScrollbars(false); 321 LayoutUnit marginWidth = frameElt->marginWidth(); 322 LayoutUnit marginHeight = frameElt->marginHeight(); 323 if (marginWidth != -1) 324 setMarginWidth(marginWidth); 325 if (marginHeight != -1) 326 setMarginHeight(marginHeight); 327 } 328 } 329 330 void FrameView::prepareForDetach() 331 { 332 RELEASE_ASSERT(!isInLayout()); 333 334 if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) 335 scrollAnimator->cancelAnimations(); 336 337 detachCustomScrollbars(); 338 // When the view is no longer associated with a frame, it needs to be removed from the ax object cache 339 // right now, otherwise it won't be able to reach the topDocument()'s axObject cache later. 340 removeFromAXObjectCache(); 341 342 if (m_frame && m_frame->page()) { 343 if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator()) 344 scrollingCoordinator->willDestroyScrollableArea(this); 345 } 346 } 347 348 void FrameView::detachCustomScrollbars() 349 { 350 Scrollbar* horizontalBar = horizontalScrollbar(); 351 if (horizontalBar && horizontalBar->isCustomScrollbar()) 352 setHasHorizontalScrollbar(false); 353 354 Scrollbar* verticalBar = verticalScrollbar(); 355 if (verticalBar && verticalBar->isCustomScrollbar()) 356 setHasVerticalScrollbar(false); 357 358 if (m_scrollCorner) { 359 m_scrollCorner->destroy(); 360 m_scrollCorner = 0; 361 } 362 } 363 364 void FrameView::recalculateScrollbarOverlayStyle() 365 { 366 ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle(); 367 ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault; 368 369 StyleColor backgroundColor = documentBackgroundColor(); 370 if (backgroundColor.isValid()) { 371 // Reduce the background color from RGB to a lightness value 372 // and determine which scrollbar style to use based on a lightness 373 // heuristic. 374 double hue, saturation, lightness; 375 backgroundColor.color().getHSL(hue, saturation, lightness); 376 if (lightness <= .5) 377 overlayStyle = ScrollbarOverlayStyleLight; 378 } 379 380 if (oldOverlayStyle != overlayStyle) 381 setScrollbarOverlayStyle(overlayStyle); 382 } 383 384 void FrameView::clear() 385 { 386 setCanBlitOnScroll(true); 387 388 reset(); 389 390 if (m_frame) { 391 if (RenderPart* renderer = m_frame->ownerRenderer()) 392 renderer->viewCleared(); 393 } 394 395 setScrollbarsSuppressed(true); 396 } 397 398 bool FrameView::didFirstLayout() const 399 { 400 return !m_firstLayout; 401 } 402 403 void FrameView::invalidateRect(const IntRect& rect) 404 { 405 if (!parent()) { 406 if (HostWindow* window = hostWindow()) 407 window->invalidateContentsAndRootView(rect); 408 return; 409 } 410 411 if (!m_frame) 412 return; 413 414 RenderPart* renderer = m_frame->ownerRenderer(); 415 if (!renderer) 416 return; 417 418 IntRect repaintRect = rect; 419 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(), 420 renderer->borderTop() + renderer->paddingTop()); 421 renderer->repaintRectangle(repaintRect); 422 } 423 424 void FrameView::setFrameRect(const IntRect& newRect) 425 { 426 IntRect oldRect = frameRect(); 427 if (newRect == oldRect) 428 return; 429 430 // Autosized font sizes depend on the width of the viewing area. 431 if (newRect.width() != oldRect.width()) { 432 Page* page = m_frame ? m_frame->page() : 0; 433 if (page && page->mainFrame() == m_frame && page->settings()->textAutosizingEnabled()) { 434 for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) 435 m_frame->document()->textAutosizer()->recalculateMultipliers(); 436 } 437 } 438 439 ScrollView::setFrameRect(newRect); 440 441 updateScrollableAreaSet(); 442 443 if (RenderView* renderView = this->renderView()) { 444 if (renderView->usesCompositing()) 445 renderView->compositor()->frameViewDidChangeSize(); 446 } 447 } 448 449 bool FrameView::scheduleAnimation() 450 { 451 if (HostWindow* window = hostWindow()) { 452 window->scheduleAnimation(); 453 return true; 454 } 455 return false; 456 } 457 458 void FrameView::setMarginWidth(LayoutUnit w) 459 { 460 // make it update the rendering area when set 461 m_margins.setWidth(w); 462 } 463 464 void FrameView::setMarginHeight(LayoutUnit h) 465 { 466 // make it update the rendering area when set 467 m_margins.setHeight(h); 468 } 469 470 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars) 471 { 472 m_canHaveScrollbars = canHaveScrollbars; 473 ScrollView::setCanHaveScrollbars(canHaveScrollbars); 474 } 475 476 void FrameView::updateCanHaveScrollbars() 477 { 478 ScrollbarMode hMode; 479 ScrollbarMode vMode; 480 scrollbarModes(hMode, vMode); 481 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff) 482 setCanHaveScrollbars(false); 483 else 484 setCanHaveScrollbars(true); 485 } 486 487 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation) 488 { 489 if (Settings* settings = m_frame->settings()) { 490 if (!settings->allowCustomScrollbarInMainFrame() && m_frame->page() && m_frame->page()->mainFrame() == m_frame) 491 return ScrollView::createScrollbar(orientation); 492 } 493 494 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles). 495 Document* doc = m_frame->document(); 496 497 // Try the <body> element first as a scrollbar source. 498 Element* body = doc ? doc->body() : 0; 499 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR)) 500 return RenderScrollbar::createCustomScrollbar(this, orientation, body); 501 502 // If the <body> didn't have a custom style, then the root element might. 503 Element* docElement = doc ? doc->documentElement() : 0; 504 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR)) 505 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement); 506 507 // If we have an owning iframe/frame element, then it can set the custom scrollbar also. 508 RenderPart* frameRenderer = m_frame->ownerRenderer(); 509 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR)) 510 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get()); 511 512 // Nobody set a custom style, so we just use a native scrollbar. 513 return ScrollView::createScrollbar(orientation); 514 } 515 516 void FrameView::setContentsSize(const IntSize& size) 517 { 518 if (size == contentsSize()) 519 return; 520 521 m_deferSetNeedsLayouts++; 522 523 ScrollView::setContentsSize(size); 524 ScrollView::contentsResized(); 525 526 Page* page = frame() ? frame()->page() : 0; 527 if (!page) 528 return; 529 530 updateScrollableAreaSet(); 531 532 page->chrome().contentsSizeChanged(frame(), size); // Notify only. 533 534 m_deferSetNeedsLayouts--; 535 536 if (!m_deferSetNeedsLayouts) 537 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen. 538 } 539 540 void FrameView::adjustViewSize() 541 { 542 RenderView* renderView = this->renderView(); 543 if (!renderView) 544 return; 545 546 ASSERT(m_frame->view() == this); 547 548 const IntRect rect = renderView->documentRect(); 549 const IntSize& size = rect.size(); 550 ScrollView::setScrollOrigin(IntPoint(-rect.x(), -rect.y()), !m_frame->document()->printing(), size == contentsSize()); 551 552 setContentsSize(size); 553 } 554 555 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode) 556 { 557 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats 558 // overflow:hidden and overflow:scroll on <body> as applying to the document's 559 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should 560 // use the root element. 561 562 EOverflow overflowX = o->style()->overflowX(); 563 EOverflow overflowY = o->style()->overflowY(); 564 565 if (o->isSVGRoot()) { 566 // overflow is ignored in stand-alone SVG documents. 567 if (!toRenderSVGRoot(o)->isEmbeddedThroughFrameContainingSVGDocument()) 568 return; 569 overflowX = OHIDDEN; 570 overflowY = OHIDDEN; 571 } 572 573 bool ignoreOverflowHidden = false; 574 if (m_frame->page()->settings()->ignoreMainFrameOverflowHiddenQuirk() && m_frame->page()->mainFrame() == m_frame) 575 ignoreOverflowHidden = true; 576 577 switch (overflowX) { 578 case OHIDDEN: 579 if (!ignoreOverflowHidden) 580 hMode = ScrollbarAlwaysOff; 581 break; 582 case OSCROLL: 583 hMode = ScrollbarAlwaysOn; 584 break; 585 case OAUTO: 586 hMode = ScrollbarAuto; 587 break; 588 default: 589 // Don't set it at all. 590 ; 591 } 592 593 switch (overflowY) { 594 case OHIDDEN: 595 if (!ignoreOverflowHidden) 596 vMode = ScrollbarAlwaysOff; 597 break; 598 case OSCROLL: 599 vMode = ScrollbarAlwaysOn; 600 break; 601 case OAUTO: 602 vMode = ScrollbarAuto; 603 break; 604 default: 605 // Don't set it at all. Values of OPAGEDX and OPAGEDY are handled by applyPaginationToViewPort(). 606 ; 607 } 608 609 m_viewportRenderer = o; 610 } 611 612 void FrameView::applyPaginationToViewport() 613 { 614 Document* document = m_frame->document(); 615 Node* documentElement = document->documentElement(); 616 RenderObject* documentRenderer = documentElement ? documentElement->renderer() : 0; 617 RenderObject* documentOrBodyRenderer = documentRenderer; 618 Node* body = document->body(); 619 if (body && body->renderer()) { 620 if (body->hasTagName(bodyTag)) 621 documentOrBodyRenderer = documentRenderer->style()->overflowX() == OVISIBLE && isHTMLHtmlElement(documentElement) ? body->renderer() : documentRenderer; 622 } 623 624 Pagination pagination; 625 626 if (!documentOrBodyRenderer) { 627 setPagination(pagination); 628 return; 629 } 630 631 EOverflow overflowY = documentOrBodyRenderer->style()->overflowY(); 632 if (overflowY == OPAGEDX || overflowY == OPAGEDY) { 633 pagination.mode = WebCore::paginationModeForRenderStyle(documentOrBodyRenderer->style()); 634 pagination.gap = static_cast<unsigned>(documentOrBodyRenderer->style()->columnGap()); 635 } 636 637 setPagination(pagination); 638 } 639 640 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy) 641 { 642 m_viewportRenderer = 0; 643 644 const HTMLFrameOwnerElement* owner = m_frame->ownerElement(); 645 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) { 646 hMode = ScrollbarAlwaysOff; 647 vMode = ScrollbarAlwaysOff; 648 return; 649 } 650 651 if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) { 652 hMode = ScrollbarAuto; 653 // Seamless documents begin with heights of 0; we special case that here 654 // to correctly render documents that don't need scrollbars. 655 IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size(); 656 bool isSeamlessDocument = frame() && frame()->document() && frame()->document()->shouldDisplaySeamlesslyWithParent(); 657 vMode = (isSeamlessDocument && !fullVisibleSize.height()) ? ScrollbarAlwaysOff : ScrollbarAuto; 658 } else { 659 hMode = ScrollbarAlwaysOff; 660 vMode = ScrollbarAlwaysOff; 661 } 662 663 if (!m_layoutRoot) { 664 Document* document = m_frame->document(); 665 Node* documentElement = document->documentElement(); 666 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0; 667 Node* body = document->body(); 668 if (body && body->renderer()) { 669 if (body->hasTagName(framesetTag)) { 670 vMode = ScrollbarAlwaysOff; 671 hMode = ScrollbarAlwaysOff; 672 } else if (body->hasTagName(bodyTag)) { 673 // It's sufficient to just check the X overflow, 674 // since it's illegal to have visible in only one direction. 675 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && isHTMLHtmlElement(document->documentElement()) ? body->renderer() : rootRenderer; 676 applyOverflowToViewport(o, hMode, vMode); 677 } 678 } else if (rootRenderer) 679 applyOverflowToViewport(rootRenderer, hMode, vMode); 680 } 681 } 682 683 void FrameView::updateCompositingLayersAfterStyleChange() 684 { 685 RenderView* renderView = this->renderView(); 686 if (!renderView) 687 return; 688 689 // If we expect to update compositing after an incipient layout, don't do so here. 690 if (m_doingPreLayoutStyleUpdate || layoutPending() || renderView->needsLayout()) 691 return; 692 693 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref 694 renderView->compositor()->cacheAcceleratedCompositingFlags(); 695 696 // Sometimes we will change a property (for example, z-index) that will not 697 // cause a layout, but will require us to update compositing state. We only 698 // need to do this if a layout is not already scheduled. 699 if (!needsLayout()) 700 renderView->compositor()->updateCompositingRequirementsState(); 701 702 renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterStyleChange); 703 } 704 705 void FrameView::updateCompositingLayersAfterLayout() 706 { 707 RenderView* renderView = this->renderView(); 708 if (!renderView) 709 return; 710 711 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref 712 renderView->compositor()->cacheAcceleratedCompositingFlags(); 713 renderView->compositor()->updateCompositingRequirementsState(); 714 renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterLayout); 715 } 716 717 bool FrameView::usesCompositedScrolling() const 718 { 719 RenderView* renderView = this->renderView(); 720 if (!renderView) 721 return false; 722 if (m_frame->settings() && m_frame->settings()->compositedScrollingForFramesEnabled()) 723 return renderView->compositor()->inForcedCompositingMode(); 724 return false; 725 } 726 727 GraphicsLayer* FrameView::layerForScrolling() const 728 { 729 RenderView* renderView = this->renderView(); 730 if (!renderView) 731 return 0; 732 return renderView->compositor()->scrollLayer(); 733 } 734 735 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const 736 { 737 RenderView* renderView = this->renderView(); 738 if (!renderView) 739 return 0; 740 return renderView->compositor()->layerForHorizontalScrollbar(); 741 } 742 743 GraphicsLayer* FrameView::layerForVerticalScrollbar() const 744 { 745 RenderView* renderView = this->renderView(); 746 if (!renderView) 747 return 0; 748 return renderView->compositor()->layerForVerticalScrollbar(); 749 } 750 751 GraphicsLayer* FrameView::layerForScrollCorner() const 752 { 753 RenderView* renderView = this->renderView(); 754 if (!renderView) 755 return 0; 756 return renderView->compositor()->layerForScrollCorner(); 757 } 758 759 #if ENABLE(RUBBER_BANDING) 760 GraphicsLayer* FrameView::layerForOverhangAreas() const 761 { 762 RenderView* renderView = this->renderView(); 763 if (!renderView) 764 return 0; 765 return renderView->compositor()->layerForOverhangAreas(); 766 } 767 #endif // ENABLE(RUBBER_BANDING) 768 769 bool FrameView::hasCompositedContent() const 770 { 771 if (RenderView* renderView = this->renderView()) 772 return renderView->compositor()->inCompositingMode(); 773 return false; 774 } 775 776 bool FrameView::isEnclosedInCompositingLayer() const 777 { 778 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer(); 779 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint()) 780 return true; 781 782 if (FrameView* parentView = parentFrameView()) 783 return parentView->isEnclosedInCompositingLayer(); 784 785 return false; 786 } 787 788 bool FrameView::isSoftwareRenderable() const 789 { 790 RenderView* renderView = this->renderView(); 791 return !renderView || !renderView->compositor()->has3DContent(); 792 } 793 794 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const 795 { 796 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot; 797 } 798 799 static inline void collectFrameViewChildren(FrameView* frameView, Vector<RefPtr<FrameView> >& frameViews) 800 { 801 const HashSet<RefPtr<Widget> >* viewChildren = frameView->children(); 802 ASSERT(viewChildren); 803 804 const HashSet<RefPtr<Widget> >::iterator end = viewChildren->end(); 805 for (HashSet<RefPtr<Widget> >::iterator current = viewChildren->begin(); current != end; ++current) { 806 Widget* widget = (*current).get(); 807 if (widget->isFrameView()) 808 frameViews.append(toFrameView(widget)); 809 } 810 } 811 812 inline void FrameView::forceLayoutParentViewIfNeeded() 813 { 814 RenderPart* ownerRenderer = m_frame->ownerRenderer(); 815 if (!ownerRenderer || !ownerRenderer->frame()) 816 return; 817 818 RenderBox* contentBox = embeddedContentBox(); 819 if (!contentBox) 820 return; 821 822 RenderSVGRoot* svgRoot = toRenderSVGRoot(contentBox); 823 if (svgRoot->everHadLayout() && !svgRoot->needsLayout()) 824 return; 825 826 // If the embedded SVG document appears the first time, the ownerRenderer has already finished 827 // layout without knowing about the existence of the embedded SVG document, because RenderReplaced 828 // embeddedContentBox() returns 0, as long as the embedded document isn't loaded yet. Before 829 // bothering to lay out the SVG document, mark the ownerRenderer needing layout and ask its 830 // FrameView for a layout. After that the RenderEmbeddedObject (ownerRenderer) carries the 831 // correct size, which RenderSVGRoot::computeReplacedLogicalWidth/Height rely on, when laying 832 // out for the first time, or when the RenderSVGRoot size has changed dynamically (eg. via <script>). 833 RefPtr<FrameView> frameView = ownerRenderer->frame()->view(); 834 835 // Mark the owner renderer as needing layout. 836 ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc(); 837 838 // Synchronously enter layout, to layout the view containing the host object/embed/iframe. 839 ASSERT(frameView); 840 frameView->layout(); 841 } 842 843 void FrameView::layout(bool allowSubtree) 844 { 845 // We should never layout a Document which is not in a Frame. 846 ASSERT(m_frame); 847 ASSERT(m_frame->view() == this); 848 ASSERT(m_frame->page()); 849 850 if (m_inLayout) 851 return; 852 853 TRACE_EVENT0("webkit", "FrameView::layout"); 854 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "Layout"); 855 856 // Protect the view from being deleted during layout (in recalcStyle) 857 RefPtr<FrameView> protector(this); 858 859 // Every scroll that happens during layout is programmatic. 860 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true); 861 862 m_layoutTimer.stop(); 863 m_delayedLayout = false; 864 m_setNeedsLayoutWasDeferred = false; 865 866 // we shouldn't enter layout() while painting 867 ASSERT(!isPainting()); 868 if (isPainting()) 869 return; 870 871 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get()); 872 873 if (!allowSubtree && m_layoutRoot) { 874 m_layoutRoot->markContainingBlocksForLayout(false); 875 m_layoutRoot = 0; 876 } 877 878 Document* document = m_frame->document(); 879 bool inSubtreeLayout = false; 880 RenderObject* rootForThisLayout = 0; 881 882 { 883 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false); 884 885 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_postLayoutTasksTimer.isActive() && !frame()->document()->shouldDisplaySeamlesslyWithParent()) { 886 // This is a new top-level layout. If there are any remaining tasks from the previous layout, finish them now. 887 m_inSynchronousPostLayout = true; 888 performPostLayoutTasks(); 889 m_inSynchronousPostLayout = false; 890 } 891 892 // Viewport-dependent media queries may cause us to need completely different style information. 893 if (!document->styleResolverIfExists() || document->styleResolverIfExists()->affectedByViewportChange()) { 894 document->styleResolverChanged(DeferRecalcStyle); 895 // FIXME: This instrumentation event is not strictly accurate since cached media query results 896 // do not persist across StyleResolver rebuilds. 897 InspectorInstrumentation::mediaQueryResultChanged(document); 898 } else { 899 document->evaluateMediaQueryList(); 900 } 901 902 // If there is any pagination to apply, it will affect the RenderView's style, so we should 903 // take care of that now. 904 applyPaginationToViewport(); 905 906 // Always ensure our style info is up-to-date. This can happen in situations where 907 // the layout beats any sort of style recalc update that needs to occur. 908 TemporaryChange<bool> changeDoingPreLayoutStyleUpdate(m_doingPreLayoutStyleUpdate, true); 909 document->updateStyleIfNeeded(); 910 911 inSubtreeLayout = m_layoutRoot; 912 913 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit, 914 // so there's no point to continuing to layout 915 if (protector->hasOneRef()) 916 return; 917 918 rootForThisLayout = inSubtreeLayout ? m_layoutRoot : document->renderer(); 919 if (!rootForThisLayout) { 920 // FIXME: Do we need to set m_size here? 921 return; 922 } 923 } // Reset m_layoutSchedulingEnabled to its previous value. 924 // The only reason the scoping was closed here is allow fontCachePurgePreventer 925 // to outlive the change and reset of m_layoutSchedulingEnabled. 926 927 FontCachePurgePreventer fontCachePurgePreventer; 928 RenderLayer* layer; 929 { 930 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false); 931 932 m_nestedLayoutCount++; 933 934 autoSizeIfEnabled(); 935 936 ScrollbarMode hMode; 937 ScrollbarMode vMode; 938 calculateScrollbarModesForLayout(hMode, vMode); 939 940 m_doFullRepaint = !inSubtreeLayout && (m_firstLayout || toRenderView(rootForThisLayout)->printing()); 941 942 if (!inSubtreeLayout) { 943 // Now set our scrollbar state for the layout. 944 ScrollbarMode currentHMode = horizontalScrollbarMode(); 945 ScrollbarMode currentVMode = verticalScrollbarMode(); 946 947 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) { 948 if (m_firstLayout) { 949 setScrollbarsSuppressed(true); 950 951 m_firstLayout = false; 952 m_firstLayoutCallbackPending = true; 953 m_lastViewportSize = layoutSize(IncludeScrollbars); 954 m_lastZoomFactor = rootForThisLayout->style()->zoom(); 955 956 // Set the initial vMode to AlwaysOn if we're auto. 957 if (vMode == ScrollbarAuto) 958 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear. 959 // Set the initial hMode to AlwaysOff if we're auto. 960 if (hMode == ScrollbarAuto) 961 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear. 962 963 setScrollbarModes(hMode, vMode); 964 setScrollbarsSuppressed(false, true); 965 } else 966 setScrollbarModes(hMode, vMode); 967 } 968 969 LayoutSize oldSize = m_size; 970 971 m_size = LayoutSize(layoutWidth(), layoutHeight()); 972 973 if (oldSize != m_size) { 974 m_doFullRepaint = true; 975 if (!m_firstLayout) { 976 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0; 977 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0; 978 if (bodyRenderer && bodyRenderer->stretchesToViewport()) 979 bodyRenderer->setChildNeedsLayout(); 980 else if (rootRenderer && rootRenderer->stretchesToViewport()) 981 rootRenderer->setChildNeedsLayout(); 982 } 983 } 984 } 985 986 layer = rootForThisLayout->enclosingLayer(); 987 988 m_actionScheduler->pause(); 989 990 { 991 bool disableLayoutState = false; 992 if (inSubtreeLayout) { 993 RenderView* view = rootForThisLayout->view(); 994 disableLayoutState = view->shouldDisableLayoutStateForSubtree(rootForThisLayout); 995 view->pushLayoutState(rootForThisLayout); 996 } 997 LayoutStateDisabler layoutStateDisabler(disableLayoutState ? rootForThisLayout->view() : 0); 998 999 m_inLayout = true; 1000 beginDeferredRepaints(); 1001 forceLayoutParentViewIfNeeded(); 1002 rootForThisLayout->layout(); 1003 1004 bool autosized = document->textAutosizer()->processSubtree(rootForThisLayout); 1005 if (autosized && rootForThisLayout->needsLayout()) { 1006 TRACE_EVENT0("webkit", "2nd layout due to Text Autosizing"); 1007 rootForThisLayout->layout(); 1008 } 1009 1010 endDeferredRepaints(); 1011 m_inLayout = false; 1012 1013 if (inSubtreeLayout) 1014 rootForThisLayout->view()->popLayoutState(rootForThisLayout); 1015 } 1016 m_layoutRoot = 0; 1017 } // Reset m_layoutSchedulingEnabled to its previous value. 1018 1019 bool neededFullRepaint = m_doFullRepaint; 1020 1021 if (!inSubtreeLayout && !toRenderView(rootForThisLayout)->printing()) 1022 adjustViewSize(); 1023 1024 m_doFullRepaint = neededFullRepaint; 1025 1026 // Now update the positions of all layers. 1027 beginDeferredRepaints(); 1028 if (m_doFullRepaint) 1029 rootForThisLayout->view()->repaint(); // FIXME: This isn't really right, since the RenderView doesn't fully encompass the visibleContentRect(). It just happens 1030 // to work out most of the time, since first layouts and printing don't have you scrolled anywhere. 1031 1032 layer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPositionFlags(layer, inSubtreeLayout, m_doFullRepaint)); 1033 1034 endDeferredRepaints(); 1035 1036 updateCompositingLayersAfterLayout(); 1037 1038 m_layoutCount++; 1039 1040 if (AXObjectCache* cache = rootForThisLayout->document()->existingAXObjectCache()) 1041 cache->postNotification(rootForThisLayout, AXObjectCache::AXLayoutComplete, true); 1042 updateAnnotatedRegions(); 1043 1044 layoutLazyBlocks(); 1045 1046 ASSERT(!rootForThisLayout->needsLayout()); 1047 1048 updateCanBlitOnScrollRecursively(); 1049 1050 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER)) 1051 updateOverflowStatus(layoutWidth() < contentsWidth(), layoutHeight() < contentsHeight()); 1052 1053 if (!m_postLayoutTasksTimer.isActive()) { 1054 if (!m_inSynchronousPostLayout) { 1055 if (frame()->document()->shouldDisplaySeamlesslyWithParent()) { 1056 if (RenderView* renderView = this->renderView()) 1057 renderView->updateWidgetPositions(); 1058 } else { 1059 m_inSynchronousPostLayout = true; 1060 // Calls resumeScheduledEvents() 1061 performPostLayoutTasks(); 1062 m_inSynchronousPostLayout = false; 1063 } 1064 } 1065 1066 if (!m_postLayoutTasksTimer.isActive() && (needsLayout() || m_inSynchronousPostLayout || frame()->document()->shouldDisplaySeamlesslyWithParent())) { 1067 // If we need layout or are already in a synchronous call to postLayoutTasks(), 1068 // defer widget updates and event dispatch until after we return. postLayoutTasks() 1069 // can make us need to update again, and we can get stuck in a nasty cycle unless 1070 // we call it through the timer here. 1071 m_postLayoutTasksTimer.startOneShot(0); 1072 if (needsLayout()) { 1073 m_actionScheduler->pause(); 1074 layout(); 1075 } 1076 } 1077 } else { 1078 m_actionScheduler->resume(); 1079 } 1080 1081 InspectorInstrumentation::didLayout(cookie, rootForThisLayout); 1082 1083 m_nestedLayoutCount--; 1084 if (m_nestedLayoutCount) 1085 return; 1086 1087 #ifndef NDEBUG 1088 // Post-layout assert that nobody was re-marked as needing layout during layout. 1089 for (RenderObject* renderer = document->renderer(); renderer; renderer = renderer->nextInPreOrder()) 1090 ASSERT(!renderer->needsLayout()); 1091 #endif 1092 1093 // FIXME: It should be not possible to remove the FrameView from the frame/page during layout 1094 // however m_inLayout is not set for most of this function, so none of our RELEASE_ASSERTS 1095 // in Frame/Page will fire. One of the post-layout tasks is disconnecting the Frame from 1096 // the page in fast/frames/crash-remove-iframe-during-object-beforeload-2.html 1097 // necessitating this check here. 1098 ASSERT(frame()); 1099 // ASSERT(frame()->page()); 1100 if (frame() && frame()->page()) 1101 frame()->page()->chrome().client()->layoutUpdated(frame()); 1102 } 1103 1104 void FrameView::layoutLazyBlocks() 1105 { 1106 // FIXME: This infinite recursion protection would seem to break plugins 1107 // doing things that require lazy blocks to layout. 1108 if (m_nestedLayoutCount != 1) 1109 return; 1110 1111 if (!renderView()->firstLazyBlock()) 1112 return; 1113 1114 // First mark all lazy blocks as needing layout and perform another layout. 1115 for (RenderLazyBlock* block = renderView()->firstLazyBlock(); block; block = block->next()) 1116 block->markForNestedLayout(); 1117 1118 layout(); 1119 1120 // FIXME: This is pretty awful if you start nesting lazy blocks, we should 1121 // signal to the nested blocks to avoid doing work until the second pass. 1122 1123 // Next walk all lazy blocks and find nested ones, these need another layout 1124 // since the first one would not have placed them correctly inside the viewport. 1125 for (RenderLazyBlock* block = renderView()->firstLazyBlock(); block; block = block->next()) { 1126 if (!block->isNested()) 1127 continue; 1128 block->setNeedsLayout(); 1129 layout(); 1130 } 1131 } 1132 1133 RenderBox* FrameView::embeddedContentBox() const 1134 { 1135 RenderView* renderView = this->renderView(); 1136 if (!renderView) 1137 return 0; 1138 1139 RenderObject* firstChild = renderView->firstChild(); 1140 if (!firstChild || !firstChild->isBox()) 1141 return 0; 1142 1143 // Curently only embedded SVG documents participate in the size-negotiation logic. 1144 if (firstChild->isSVGRoot()) 1145 return toRenderBox(firstChild); 1146 1147 return 0; 1148 } 1149 1150 void FrameView::addWidgetToUpdate(RenderObject* object) 1151 { 1152 if (!m_widgetUpdateSet) 1153 m_widgetUpdateSet = adoptPtr(new RenderObjectSet); 1154 1155 // Tell the DOM element that it needs a widget update. 1156 Node* node = object->node(); 1157 if (node->hasTagName(objectTag) || node->hasTagName(embedTag)) { 1158 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(node); 1159 pluginElement->setNeedsWidgetUpdate(true); 1160 } 1161 1162 m_widgetUpdateSet->add(object); 1163 } 1164 1165 void FrameView::removeWidgetToUpdate(RenderObject* object) 1166 { 1167 if (!m_widgetUpdateSet) 1168 return; 1169 1170 m_widgetUpdateSet->remove(object); 1171 } 1172 1173 void FrameView::setMediaType(const AtomicString& mediaType) 1174 { 1175 m_mediaType = mediaType; 1176 } 1177 1178 AtomicString FrameView::mediaType() const 1179 { 1180 // See if we have an override type. 1181 String overrideType; 1182 InspectorInstrumentation::applyEmulatedMedia(m_frame.get(), &overrideType); 1183 if (!overrideType.isNull()) 1184 return overrideType; 1185 return m_mediaType; 1186 } 1187 1188 void FrameView::adjustMediaTypeForPrinting(bool printing) 1189 { 1190 if (printing) { 1191 if (m_mediaTypeWhenNotPrinting.isNull()) 1192 m_mediaTypeWhenNotPrinting = mediaType(); 1193 setMediaType("print"); 1194 } else { 1195 if (!m_mediaTypeWhenNotPrinting.isNull()) 1196 setMediaType(m_mediaTypeWhenNotPrinting); 1197 m_mediaTypeWhenNotPrinting = nullAtom; 1198 } 1199 } 1200 1201 bool FrameView::useSlowRepaints(bool considerOverlap) const 1202 { 1203 bool mustBeSlow = m_slowRepaintObjectCount > 0; 1204 1205 if (contentsInCompositedLayer()) 1206 return mustBeSlow; 1207 1208 // The chromium compositor does not support scrolling a non-composited frame within a composited page through 1209 // the fast scrolling path, so force slow scrolling in that case. 1210 if (m_frame->ownerElement() && !hasCompositedContent() && m_frame->page() && m_frame->page()->mainFrame()->view()->hasCompositedContent()) 1211 return true; 1212 1213 bool isOverlapped = m_isOverlapped && considerOverlap; 1214 1215 if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque) 1216 return true; 1217 1218 if (FrameView* parentView = parentFrameView()) 1219 return parentView->useSlowRepaints(considerOverlap); 1220 1221 return false; 1222 } 1223 1224 bool FrameView::useSlowRepaintsIfNotOverlapped() const 1225 { 1226 return useSlowRepaints(false); 1227 } 1228 1229 void FrameView::updateCanBlitOnScrollRecursively() 1230 { 1231 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 1232 if (FrameView* view = frame->view()) 1233 view->setCanBlitOnScroll(!view->useSlowRepaints()); 1234 } 1235 } 1236 1237 bool FrameView::contentsInCompositedLayer() const 1238 { 1239 RenderView* renderView = this->renderView(); 1240 if (renderView && renderView->isComposited()) { 1241 GraphicsLayer* layer = renderView->layer()->backing()->graphicsLayer(); 1242 if (layer && layer->drawsContent()) 1243 return true; 1244 } 1245 1246 return false; 1247 } 1248 1249 void FrameView::setCannotBlitToWindow() 1250 { 1251 m_cannotBlitToWindow = true; 1252 updateCanBlitOnScrollRecursively(); 1253 } 1254 1255 void FrameView::addSlowRepaintObject() 1256 { 1257 if (!m_slowRepaintObjectCount++) { 1258 updateCanBlitOnScrollRecursively(); 1259 1260 if (Page* page = m_frame->page()) { 1261 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) 1262 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this); 1263 } 1264 } 1265 } 1266 1267 void FrameView::removeSlowRepaintObject() 1268 { 1269 ASSERT(m_slowRepaintObjectCount > 0); 1270 m_slowRepaintObjectCount--; 1271 if (!m_slowRepaintObjectCount) { 1272 updateCanBlitOnScrollRecursively(); 1273 1274 if (Page* page = m_frame->page()) { 1275 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) 1276 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this); 1277 } 1278 } 1279 } 1280 1281 void FrameView::addViewportConstrainedObject(RenderObject* object) 1282 { 1283 if (!m_viewportConstrainedObjects) 1284 m_viewportConstrainedObjects = adoptPtr(new ViewportConstrainedObjectSet); 1285 1286 if (!m_viewportConstrainedObjects->contains(object)) { 1287 m_viewportConstrainedObjects->add(object); 1288 1289 if (Page* page = m_frame->page()) { 1290 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) 1291 scrollingCoordinator->frameViewFixedObjectsDidChange(this); 1292 } 1293 } 1294 } 1295 1296 void FrameView::removeViewportConstrainedObject(RenderObject* object) 1297 { 1298 if (m_viewportConstrainedObjects && m_viewportConstrainedObjects->contains(object)) { 1299 m_viewportConstrainedObjects->remove(object); 1300 if (Page* page = m_frame->page()) { 1301 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) 1302 scrollingCoordinator->frameViewFixedObjectsDidChange(this); 1303 } 1304 1305 // FIXME: In addFixedObject() we only call this if there's a platform widget, 1306 // why isn't the same check being made here? 1307 updateCanBlitOnScrollRecursively(); 1308 } 1309 } 1310 1311 LayoutRect FrameView::viewportConstrainedVisibleContentRect() const 1312 { 1313 LayoutRect viewportRect = visibleContentRect(); 1314 // Ignore overhang. No-op when not using rubber banding. 1315 viewportRect.setLocation(clampScrollPosition(scrollPosition())); 1316 return viewportRect; 1317 } 1318 1319 1320 IntSize FrameView::scrollOffsetForFixedPosition() const 1321 { 1322 return toIntSize(clampScrollPosition(scrollPosition())); 1323 } 1324 1325 IntPoint FrameView::lastKnownMousePosition() const 1326 { 1327 return m_frame ? m_frame->eventHandler()->lastKnownMousePosition() : IntPoint(); 1328 } 1329 1330 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) 1331 { 1332 if (!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty()) { 1333 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect); 1334 return true; 1335 } 1336 1337 const bool isCompositedContentLayer = contentsInCompositedLayer(); 1338 1339 // Get the rects of the fixed objects visible in the rectToScroll 1340 Region regionToUpdate; 1341 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end(); 1342 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) { 1343 RenderObject* renderer = *it; 1344 if (!renderer->style()->hasViewportConstrainedPosition()) 1345 continue; 1346 1347 if (renderer->isComposited()) 1348 continue; 1349 1350 // Fixed items should always have layers. 1351 ASSERT(renderer->hasLayer()); 1352 RenderLayer* layer = toRenderBoxModelObject(renderer)->layer(); 1353 1354 if (layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForBoundsOutOfView 1355 || layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForNoVisibleContent) { 1356 // Don't invalidate for invisible fixed layers. 1357 continue; 1358 } 1359 1360 if (layer->hasAncestorWithFilterOutsets()) { 1361 // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot 1362 // scroll using the fast path, otherwise the outsets of the filter will be moved around the page. 1363 return false; 1364 } 1365 IntRect updateRect = pixelSnappedIntRect(layer->repaintRectIncludingNonCompositingDescendants()); 1366 updateRect = contentsToRootView(updateRect); 1367 if (!isCompositedContentLayer && clipsRepaints()) 1368 updateRect.intersect(rectToScroll); 1369 if (!updateRect.isEmpty()) 1370 regionToUpdate.unite(updateRect); 1371 } 1372 1373 // 1) scroll 1374 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect); 1375 1376 // 2) update the area of fixed objects that has been invalidated 1377 Vector<IntRect> subRectsToUpdate = regionToUpdate.rects(); 1378 size_t viewportConstrainedObjectsCount = subRectsToUpdate.size(); 1379 for (size_t i = 0; i < viewportConstrainedObjectsCount; ++i) { 1380 IntRect updateRect = subRectsToUpdate[i]; 1381 IntRect scrolledRect = updateRect; 1382 scrolledRect.move(scrollDelta); 1383 updateRect.unite(scrolledRect); 1384 if (isCompositedContentLayer) { 1385 updateRect = rootViewToContents(updateRect); 1386 ASSERT(renderView()); 1387 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect); 1388 continue; 1389 } 1390 if (clipsRepaints()) 1391 updateRect.intersect(rectToScroll); 1392 hostWindow()->invalidateContentsAndRootView(updateRect); 1393 } 1394 1395 return true; 1396 } 1397 1398 void FrameView::scrollContentsSlowPath(const IntRect& updateRect) 1399 { 1400 if (contentsInCompositedLayer()) { 1401 IntRect updateRect = visibleContentRect(); 1402 ASSERT(renderView()); 1403 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect); 1404 } 1405 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) { 1406 if (isEnclosedInCompositingLayer()) { 1407 LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(), 1408 frameRenderer->borderTop() + frameRenderer->paddingTop(), 1409 visibleWidth(), visibleHeight()); 1410 frameRenderer->repaintRectangle(rect); 1411 return; 1412 } 1413 } 1414 1415 ScrollView::scrollContentsSlowPath(updateRect); 1416 } 1417 1418 // Note that this gets called at painting time. 1419 void FrameView::setIsOverlapped(bool isOverlapped) 1420 { 1421 if (isOverlapped == m_isOverlapped) 1422 return; 1423 1424 m_isOverlapped = isOverlapped; 1425 updateCanBlitOnScrollRecursively(); 1426 } 1427 1428 bool FrameView::isOverlappedIncludingAncestors() const 1429 { 1430 if (isOverlapped()) 1431 return true; 1432 1433 if (FrameView* parentView = parentFrameView()) { 1434 if (parentView->isOverlapped()) 1435 return true; 1436 } 1437 1438 return false; 1439 } 1440 1441 void FrameView::setContentIsOpaque(bool contentIsOpaque) 1442 { 1443 if (contentIsOpaque == m_contentIsOpaque) 1444 return; 1445 1446 m_contentIsOpaque = contentIsOpaque; 1447 updateCanBlitOnScrollRecursively(); 1448 } 1449 1450 void FrameView::restoreScrollbar() 1451 { 1452 setScrollbarsSuppressed(false); 1453 } 1454 1455 bool FrameView::scrollToFragment(const KURL& url) 1456 { 1457 // If our URL has no ref, then we have no place we need to jump to. 1458 // OTOH If CSS target was set previously, we want to set it to 0, recalc 1459 // and possibly repaint because :target pseudo class may have been 1460 // set (see bug 11321). 1461 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget()) 1462 return false; 1463 1464 String fragmentIdentifier = url.fragmentIdentifier(); 1465 if (scrollToAnchor(fragmentIdentifier)) 1466 return true; 1467 1468 // Try again after decoding the ref, based on the document's encoding. 1469 if (TextResourceDecoder* decoder = m_frame->document()->decoder()) 1470 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding())); 1471 1472 return false; 1473 } 1474 1475 bool FrameView::scrollToAnchor(const String& name) 1476 { 1477 ASSERT(m_frame->document()); 1478 1479 if (!m_frame->document()->haveStylesheetsLoaded()) { 1480 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true); 1481 return false; 1482 } 1483 1484 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false); 1485 1486 Element* anchorNode = m_frame->document()->findAnchor(name); 1487 1488 // Setting to null will clear the current target. 1489 m_frame->document()->setCSSTarget(anchorNode); 1490 1491 if (m_frame->document()->isSVGDocument()) { 1492 if (SVGSVGElement* svg = toSVGDocument(m_frame->document())->rootElement()) { 1493 svg->setupInitialView(name, anchorNode); 1494 if (!anchorNode) 1495 return true; 1496 } 1497 } 1498 1499 // Implement the rule that "" and "top" both mean top of page as in other browsers. 1500 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top"))) 1501 return false; 1502 1503 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document()); 1504 1505 // If the anchor accepts keyboard focus, move focus there to aid users relying on keyboard navigation. 1506 if (anchorNode && anchorNode->isFocusable()) 1507 m_frame->document()->setFocusedElement(anchorNode); 1508 1509 return true; 1510 } 1511 1512 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode) 1513 { 1514 m_maintainScrollPositionAnchor = anchorNode; 1515 if (!m_maintainScrollPositionAnchor) 1516 return; 1517 1518 // We need to update the layout before scrolling, otherwise we could 1519 // really mess things up if an anchor scroll comes at a bad moment. 1520 m_frame->document()->updateStyleIfNeeded(); 1521 // Only do a layout if changes have occurred that make it necessary. 1522 RenderView* renderView = this->renderView(); 1523 if (renderView && renderView->needsLayout()) 1524 layout(); 1525 else 1526 scrollToAnchor(); 1527 } 1528 1529 void FrameView::scrollElementToRect(Element* element, const IntRect& rect) 1530 { 1531 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 1532 1533 LayoutRect bounds = element->boundingBox(); 1534 int centeringOffsetX = (rect.width() - bounds.width()) / 2; 1535 int centeringOffsetY = (rect.height() - bounds.height()) / 2; 1536 setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y())); 1537 } 1538 1539 void FrameView::setScrollPosition(const IntPoint& scrollPoint) 1540 { 1541 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true); 1542 m_maintainScrollPositionAnchor = 0; 1543 1544 IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint); 1545 1546 if (newScrollPosition == scrollPosition()) 1547 return; 1548 1549 Page* page = m_frame->page(); 1550 if (page && RuntimeEnabledFeatures::programmaticScrollNotificationsEnabled()) 1551 page->chrome().client()->didProgrammaticallyScroll(m_frame.get(), newScrollPosition); 1552 1553 if (requestScrollPositionUpdate(newScrollPosition)) 1554 return; 1555 1556 ScrollView::setScrollPosition(newScrollPosition); 1557 } 1558 1559 void FrameView::setScrollPositionNonProgrammatically(const IntPoint& scrollPoint) 1560 { 1561 IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint); 1562 1563 if (newScrollPosition == scrollPosition()) 1564 return; 1565 1566 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, false); 1567 notifyScrollPositionChanged(newScrollPosition); 1568 } 1569 1570 void FrameView::setViewportConstrainedObjectsNeedLayout() 1571 { 1572 if (!hasViewportConstrainedObjects()) 1573 return; 1574 1575 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end(); 1576 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) { 1577 RenderObject* renderer = *it; 1578 renderer->setNeedsLayout(); 1579 } 1580 } 1581 1582 1583 void FrameView::scrollPositionChanged() 1584 { 1585 frame()->eventHandler()->sendScrollEvent(); 1586 frame()->eventHandler()->dispatchFakeMouseMoveEventSoon(); 1587 1588 if (RenderView* renderView = this->renderView()) { 1589 if (renderView->usesCompositing()) 1590 renderView->compositor()->frameViewDidScroll(); 1591 1592 renderView->markLazyBlocksForLayout(); 1593 } 1594 } 1595 1596 void FrameView::repaintFixedElementsAfterScrolling() 1597 { 1598 // For fixed position elements, update widget positions and compositing layers after scrolling, 1599 // but only if we're not inside of layout. 1600 if (!m_nestedLayoutCount && hasViewportConstrainedObjects()) { 1601 if (RenderView* renderView = this->renderView()) { 1602 renderView->updateWidgetPositions(); 1603 renderView->layer()->updateLayerPositionsAfterDocumentScroll(); 1604 } 1605 } 1606 } 1607 1608 void FrameView::updateFixedElementsAfterScrolling() 1609 { 1610 if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) { 1611 if (RenderView* renderView = this->renderView()) 1612 renderView->compositor()->updateCompositingLayers(CompositingUpdateOnScroll); 1613 } 1614 } 1615 1616 bool FrameView::shouldRubberBandInDirection(ScrollDirection direction) const 1617 { 1618 Page* page = frame() ? frame()->page() : 0; 1619 if (!page) 1620 return ScrollView::shouldRubberBandInDirection(direction); 1621 return page->chrome().client()->shouldRubberBandInDirection(direction); 1622 } 1623 1624 bool FrameView::isRubberBandInProgress() const 1625 { 1626 if (scrollbarsSuppressed()) 1627 return false; 1628 1629 // If the main thread updates the scroll position for this FrameView, we should return 1630 // ScrollAnimator::isRubberBandInProgress(). 1631 if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) 1632 return scrollAnimator->isRubberBandInProgress(); 1633 1634 return false; 1635 } 1636 1637 bool FrameView::requestScrollPositionUpdate(const IntPoint& position) 1638 { 1639 return false; 1640 } 1641 1642 HostWindow* FrameView::hostWindow() const 1643 { 1644 Page* page = frame() ? frame()->page() : 0; 1645 if (!page) 1646 return 0; 1647 return &page->chrome(); 1648 } 1649 1650 const unsigned cRepaintRectUnionThreshold = 25; 1651 1652 void FrameView::repaintContentRectangle(const IntRect& r) 1653 { 1654 ASSERT(!m_frame->ownerElement()); 1655 1656 if (m_isTrackingRepaints) { 1657 IntRect repaintRect = r; 1658 repaintRect.move(-scrollOffset()); 1659 m_trackedRepaintRects.append(repaintRect); 1660 } 1661 1662 double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay(); 1663 if (m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) { 1664 IntRect paintRect = r; 1665 if (clipsRepaints() && !paintsEntireContents()) 1666 paintRect.intersect(visibleContentRect()); 1667 if (paintRect.isEmpty()) 1668 return; 1669 if (m_repaintCount == cRepaintRectUnionThreshold) { 1670 IntRect unionedRect; 1671 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i) 1672 unionedRect.unite(pixelSnappedIntRect(m_repaintRects[i])); 1673 m_repaintRects.clear(); 1674 m_repaintRects.append(unionedRect); 1675 } 1676 if (m_repaintCount < cRepaintRectUnionThreshold) 1677 m_repaintRects.append(paintRect); 1678 else 1679 m_repaintRects[0].unite(paintRect); 1680 m_repaintCount++; 1681 1682 if (!m_deferringRepaints) 1683 startDeferredRepaintTimer(delay); 1684 1685 return; 1686 } 1687 1688 if (!shouldUpdate()) 1689 return; 1690 1691 ScrollView::repaintContentRectangle(r); 1692 } 1693 1694 void FrameView::contentsResized() 1695 { 1696 ScrollView::contentsResized(); 1697 setNeedsLayout(); 1698 } 1699 1700 void FrameView::visibleContentsResized() 1701 { 1702 // We check to make sure the view is attached to a frame() as this method can 1703 // be triggered before the view is attached by Frame::createView(...) setting 1704 // various values such as setScrollBarModes(...) for example. An ASSERT is 1705 // triggered when a view is layout before being attached to a frame(). 1706 if (!frame()->view()) 1707 return; 1708 1709 if (!useFixedLayout() && needsLayout()) 1710 layout(); 1711 1712 if (RenderView* renderView = this->renderView()) { 1713 if (renderView->usesCompositing()) 1714 renderView->compositor()->frameViewDidChangeSize(); 1715 } 1716 } 1717 1718 void FrameView::beginDeferredRepaints() 1719 { 1720 Page* page = m_frame->page(); 1721 if (page->mainFrame() != m_frame) { 1722 page->mainFrame()->view()->beginDeferredRepaints(); 1723 return; 1724 } 1725 1726 m_deferringRepaints++; 1727 } 1728 1729 void FrameView::endDeferredRepaints() 1730 { 1731 Page* page = m_frame->page(); 1732 if (page->mainFrame() != m_frame) { 1733 page->mainFrame()->view()->endDeferredRepaints(); 1734 return; 1735 } 1736 1737 ASSERT(m_deferringRepaints > 0); 1738 1739 if (--m_deferringRepaints) 1740 return; 1741 1742 if (m_deferredRepaintTimer.isActive()) 1743 return; 1744 1745 if (double delay = adjustedDeferredRepaintDelay()) { 1746 startDeferredRepaintTimer(delay); 1747 return; 1748 } 1749 1750 doDeferredRepaints(); 1751 } 1752 1753 void FrameView::startDeferredRepaintTimer(double delay) 1754 { 1755 if (m_deferredRepaintTimer.isActive()) 1756 return; 1757 1758 if (m_disableRepaints) 1759 return; 1760 1761 m_deferredRepaintTimer.startOneShot(delay); 1762 } 1763 1764 void FrameView::handleLoadCompleted() 1765 { 1766 // Once loading has completed, allow autoSize one last opportunity to 1767 // reduce the size of the frame. 1768 autoSizeIfEnabled(); 1769 if (shouldUseLoadTimeDeferredRepaintDelay()) 1770 return; 1771 m_deferredRepaintDelay = s_normalDeferredRepaintDelay; 1772 flushDeferredRepaints(); 1773 } 1774 1775 void FrameView::flushDeferredRepaints() 1776 { 1777 if (!m_deferredRepaintTimer.isActive()) 1778 return; 1779 m_deferredRepaintTimer.stop(); 1780 doDeferredRepaints(); 1781 } 1782 1783 void FrameView::doDeferredRepaints() 1784 { 1785 if (m_disableRepaints) 1786 return; 1787 1788 ASSERT(!m_deferringRepaints); 1789 if (!shouldUpdate()) { 1790 m_repaintRects.clear(); 1791 m_repaintCount = 0; 1792 return; 1793 } 1794 unsigned size = m_repaintRects.size(); 1795 for (unsigned i = 0; i < size; i++) { 1796 ScrollView::repaintContentRectangle(pixelSnappedIntRect(m_repaintRects[i])); 1797 } 1798 m_repaintRects.clear(); 1799 m_repaintCount = 0; 1800 1801 updateDeferredRepaintDelayAfterRepaint(); 1802 } 1803 1804 bool FrameView::shouldUseLoadTimeDeferredRepaintDelay() const 1805 { 1806 // Don't defer after the initial load of the page has been completed. 1807 if (m_frame->tree()->top()->loader()->isComplete()) 1808 return false; 1809 Document* document = m_frame->document(); 1810 if (!document) 1811 return false; 1812 if (document->parsing()) 1813 return true; 1814 if (document->fetcher()->requestCount()) 1815 return true; 1816 return false; 1817 } 1818 1819 void FrameView::updateDeferredRepaintDelayAfterRepaint() 1820 { 1821 if (!shouldUseLoadTimeDeferredRepaintDelay()) { 1822 m_deferredRepaintDelay = s_normalDeferredRepaintDelay; 1823 return; 1824 } 1825 double incrementedRepaintDelay = m_deferredRepaintDelay + s_deferredRepaintDelayIncrementDuringLoading; 1826 m_deferredRepaintDelay = std::min(incrementedRepaintDelay, s_maxDeferredRepaintDelayDuringLoading); 1827 } 1828 1829 void FrameView::resetDeferredRepaintDelay() 1830 { 1831 m_deferredRepaintDelay = 0; 1832 if (m_deferredRepaintTimer.isActive()) { 1833 m_deferredRepaintTimer.stop(); 1834 if (!m_deferringRepaints) 1835 doDeferredRepaints(); 1836 } 1837 } 1838 1839 double FrameView::adjustedDeferredRepaintDelay() const 1840 { 1841 ASSERT(!m_deferringRepaints); 1842 if (!m_deferredRepaintDelay) 1843 return 0; 1844 double timeSinceLastPaint = currentTime() - m_lastPaintTime; 1845 return max(0., m_deferredRepaintDelay - timeSinceLastPaint); 1846 } 1847 1848 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*) 1849 { 1850 doDeferredRepaints(); 1851 } 1852 1853 void FrameView::beginDisableRepaints() 1854 { 1855 m_disableRepaints++; 1856 } 1857 1858 void FrameView::endDisableRepaints() 1859 { 1860 ASSERT(m_disableRepaints > 0); 1861 m_disableRepaints--; 1862 } 1863 1864 void FrameView::layoutTimerFired(Timer<FrameView>*) 1865 { 1866 layout(); 1867 } 1868 1869 void FrameView::scheduleRelayout() 1870 { 1871 ASSERT(m_frame->view() == this); 1872 1873 if (m_layoutRoot) { 1874 m_layoutRoot->markContainingBlocksForLayout(false); 1875 m_layoutRoot = 0; 1876 } 1877 if (!m_layoutSchedulingEnabled) 1878 return; 1879 if (!needsLayout()) 1880 return; 1881 if (!m_frame->document()->shouldScheduleLayout()) 1882 return; 1883 InspectorInstrumentation::didInvalidateLayout(m_frame.get()); 1884 1885 // When frame seamless is enabled, the contents of the frame could affect the layout of the parent frames. 1886 // Also invalidate parent frame starting from the owner element of this frame. 1887 if (m_frame->ownerRenderer() && frame()->document()->shouldDisplaySeamlesslyWithParent()) 1888 m_frame->ownerRenderer()->setNeedsLayout(MarkContainingBlockChain); 1889 1890 int delay = m_frame->document()->minimumLayoutDelay(); 1891 if (m_layoutTimer.isActive() && m_delayedLayout && !delay) 1892 unscheduleRelayout(); 1893 if (m_layoutTimer.isActive()) 1894 return; 1895 1896 m_delayedLayout = delay != 0; 1897 m_layoutTimer.startOneShot(delay * 0.001); 1898 } 1899 1900 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant) 1901 { 1902 for (RenderObject* r = descendant; r; r = r->container()) { 1903 if (r == ancestor) 1904 return true; 1905 } 1906 return false; 1907 } 1908 1909 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot) 1910 { 1911 ASSERT(m_frame->view() == this); 1912 1913 RenderView* renderView = this->renderView(); 1914 if (renderView && renderView->needsLayout()) { 1915 if (relayoutRoot) 1916 relayoutRoot->markContainingBlocksForLayout(false); 1917 return; 1918 } 1919 1920 if (layoutPending() || !m_layoutSchedulingEnabled) { 1921 if (m_layoutRoot != relayoutRoot) { 1922 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) { 1923 // Keep the current root 1924 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot); 1925 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout()); 1926 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) { 1927 // Re-root at relayoutRoot 1928 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot); 1929 m_layoutRoot = relayoutRoot; 1930 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout()); 1931 InspectorInstrumentation::didInvalidateLayout(m_frame.get()); 1932 } else { 1933 // Just do a full relayout 1934 if (m_layoutRoot) 1935 m_layoutRoot->markContainingBlocksForLayout(false); 1936 m_layoutRoot = 0; 1937 relayoutRoot->markContainingBlocksForLayout(false); 1938 InspectorInstrumentation::didInvalidateLayout(m_frame.get()); 1939 } 1940 } 1941 } else if (m_layoutSchedulingEnabled) { 1942 int delay = m_frame->document()->minimumLayoutDelay(); 1943 m_layoutRoot = relayoutRoot; 1944 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout()); 1945 InspectorInstrumentation::didInvalidateLayout(m_frame.get()); 1946 m_delayedLayout = delay != 0; 1947 m_layoutTimer.startOneShot(delay * 0.001); 1948 } 1949 } 1950 1951 bool FrameView::layoutPending() const 1952 { 1953 return m_layoutTimer.isActive(); 1954 } 1955 1956 bool FrameView::needsLayout() const 1957 { 1958 // This can return true in cases where the document does not have a body yet. 1959 // Document::shouldScheduleLayout takes care of preventing us from scheduling 1960 // layout in that case. 1961 if (!m_frame) 1962 return false; 1963 1964 RenderView* renderView = this->renderView(); 1965 return layoutPending() 1966 || (renderView && renderView->needsLayout()) 1967 || m_layoutRoot 1968 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred); 1969 } 1970 1971 void FrameView::setNeedsLayout() 1972 { 1973 if (m_deferSetNeedsLayouts) { 1974 m_setNeedsLayoutWasDeferred = true; 1975 return; 1976 } 1977 1978 if (RenderView* renderView = this->renderView()) 1979 renderView->setNeedsLayout(); 1980 } 1981 1982 void FrameView::unscheduleRelayout() 1983 { 1984 if (!m_layoutTimer.isActive()) 1985 return; 1986 1987 m_layoutTimer.stop(); 1988 m_delayedLayout = false; 1989 } 1990 1991 void FrameView::serviceScriptedAnimations(double monotonicAnimationStartTime) 1992 { 1993 for (RefPtr<Frame> frame = m_frame; frame; frame = frame->tree()->traverseNext()) { 1994 frame->view()->serviceScrollAnimations(); 1995 if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled()) 1996 frame->animation()->serviceAnimations(); 1997 if (RuntimeEnabledFeatures::webAnimationsEnabled()) 1998 frame->document()->timeline()->serviceAnimations(monotonicAnimationStartTime); 1999 } 2000 2001 Vector<RefPtr<Document> > documents; 2002 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext()) 2003 documents.append(frame->document()); 2004 2005 for (size_t i = 0; i < documents.size(); ++i) 2006 documents[i]->serviceScriptedAnimations(monotonicAnimationStartTime); 2007 } 2008 2009 bool FrameView::isTransparent() const 2010 { 2011 return m_isTransparent; 2012 } 2013 2014 void FrameView::setTransparent(bool isTransparent) 2015 { 2016 m_isTransparent = isTransparent; 2017 if (renderView() && renderView()->layer()->backing()) 2018 renderView()->layer()->backing()->updateContentsOpaque(); 2019 } 2020 2021 bool FrameView::hasOpaqueBackground() const 2022 { 2023 return !m_isTransparent && !m_baseBackgroundColor.hasAlpha(); 2024 } 2025 2026 Color FrameView::baseBackgroundColor() const 2027 { 2028 return m_baseBackgroundColor; 2029 } 2030 2031 void FrameView::setBaseBackgroundColor(const StyleColor& backgroundColor) 2032 { 2033 if (!backgroundColor.isValid()) 2034 m_baseBackgroundColor = Color::white; 2035 else 2036 m_baseBackgroundColor = backgroundColor.color(); 2037 2038 if (RenderLayerBacking* backing = renderView() ? renderView()->layer()->backing() : 0) { 2039 backing->updateContentsOpaque(); 2040 if (backing->graphicsLayer()) 2041 backing->graphicsLayer()->setNeedsDisplay(); 2042 } 2043 recalculateScrollbarOverlayStyle(); 2044 } 2045 2046 void FrameView::updateBackgroundRecursively(const StyleColor& backgroundColor, bool transparent) 2047 { 2048 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 2049 if (FrameView* view = frame->view()) { 2050 view->setTransparent(transparent); 2051 view->setBaseBackgroundColor(backgroundColor); 2052 } 2053 } 2054 } 2055 2056 bool FrameView::shouldUpdateWhileOffscreen() const 2057 { 2058 return m_shouldUpdateWhileOffscreen; 2059 } 2060 2061 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen) 2062 { 2063 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen; 2064 } 2065 2066 bool FrameView::shouldUpdate() const 2067 { 2068 if (isOffscreen() && !shouldUpdateWhileOffscreen()) 2069 return false; 2070 return true; 2071 } 2072 2073 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget) 2074 { 2075 m_actionScheduler->scheduleEvent(event, eventTarget); 2076 } 2077 2078 void FrameView::pauseScheduledEvents() 2079 { 2080 m_actionScheduler->pause(); 2081 } 2082 2083 void FrameView::resumeScheduledEvents() 2084 { 2085 m_actionScheduler->resume(); 2086 } 2087 2088 void FrameView::scrollToAnchor() 2089 { 2090 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor; 2091 if (!anchorNode) 2092 return; 2093 2094 if (!anchorNode->renderer()) 2095 return; 2096 2097 LayoutRect rect; 2098 if (anchorNode != m_frame->document()) 2099 rect = anchorNode->boundingBox(); 2100 2101 // Scroll nested layers and frames to reveal the anchor. 2102 // Align to the top and to the closest side (this matches other browsers). 2103 anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways); 2104 2105 if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache()) 2106 cache->handleScrolledToAnchor(anchorNode.get()); 2107 2108 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor. 2109 m_maintainScrollPositionAnchor = anchorNode; 2110 } 2111 2112 void FrameView::updateWidget(RenderObject* object) 2113 { 2114 ASSERT(!object->node() || object->node()->isElementNode()); 2115 Element* ownerElement = toElement(object->node()); 2116 // The object may have already been destroyed (thus node cleared), 2117 // but FrameView holds a manual ref, so it won't have been deleted. 2118 ASSERT(m_widgetUpdateSet->contains(object)); 2119 if (!ownerElement) 2120 return; 2121 2122 if (object->isEmbeddedObject()) { 2123 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object); 2124 // No need to update if it's already crashed or known to be missing. 2125 if (embeddedObject->showsUnavailablePluginIndicator()) 2126 return; 2127 2128 // FIXME: This could turn into a real virtual dispatch if we defined 2129 // updateWidget(PluginCreationOption) on HTMLElement. 2130 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag) || ownerElement->hasTagName(appletTag)) { 2131 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement); 2132 if (pluginElement->needsWidgetUpdate()) 2133 pluginElement->updateWidget(CreateAnyWidgetType); 2134 } else 2135 ASSERT_NOT_REACHED(); 2136 2137 // Caution: it's possible the object was destroyed again, since loading a 2138 // plugin may run any arbitrary JavaScript. 2139 embeddedObject->updateWidgetPosition(); 2140 } 2141 } 2142 2143 bool FrameView::updateWidgets() 2144 { 2145 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty()) 2146 return true; 2147 2148 size_t size = m_widgetUpdateSet->size(); 2149 2150 Vector<RenderObject*> objects; 2151 objects.reserveInitialCapacity(size); 2152 2153 RenderObjectSet::const_iterator end = m_widgetUpdateSet->end(); 2154 for (RenderObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) { 2155 RenderObject* object = *it; 2156 objects.uncheckedAppend(object); 2157 if (object->isEmbeddedObject()) { 2158 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object); 2159 embeddedObject->ref(); 2160 } 2161 } 2162 2163 for (size_t i = 0; i < size; ++i) { 2164 RenderObject* object = objects[i]; 2165 updateWidget(object); 2166 m_widgetUpdateSet->remove(object); 2167 } 2168 2169 for (size_t i = 0; i < size; ++i) { 2170 RenderObject* object = objects[i]; 2171 if (object->isEmbeddedObject()) { 2172 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object); 2173 embeddedObject->deref(); 2174 } 2175 } 2176 2177 return m_widgetUpdateSet->isEmpty(); 2178 } 2179 2180 void FrameView::flushAnyPendingPostLayoutTasks() 2181 { 2182 if (!m_postLayoutTasksTimer.isActive()) 2183 return; 2184 2185 performPostLayoutTasks(); 2186 } 2187 2188 void FrameView::performPostLayoutTasks() 2189 { 2190 // updateWidgets() call below can blow us away from underneath. 2191 RefPtr<FrameView> protect(this); 2192 2193 m_postLayoutTasksTimer.stop(); 2194 2195 m_frame->selection()->setCaretRectNeedsUpdate(); 2196 m_frame->selection()->updateAppearance(); 2197 2198 LayoutMilestones milestonesOfInterest = 0; 2199 LayoutMilestones milestonesAchieved = 0; 2200 Page* page = m_frame->page(); 2201 if (page) 2202 milestonesOfInterest = page->layoutMilestones(); 2203 2204 if (m_nestedLayoutCount <= 1) { 2205 if (m_firstLayoutCallbackPending) { 2206 m_firstLayoutCallbackPending = false; 2207 m_frame->loader()->didFirstLayout(); 2208 if (milestonesOfInterest & DidFirstLayout) 2209 milestonesAchieved |= DidFirstLayout; 2210 if (page) { 2211 if (page->mainFrame() == m_frame) 2212 page->startCountingRelevantRepaintedObjects(); 2213 } 2214 } 2215 2216 // Ensure that we always send this eventually. 2217 if (!m_frame->document()->parsing() && m_frame->loader()->stateMachine()->committedFirstRealDocumentLoad()) 2218 m_isVisuallyNonEmpty = true; 2219 2220 // If the layout was done with pending sheets, we are not in fact visually non-empty yet. 2221 if (m_isVisuallyNonEmpty && !m_frame->document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) { 2222 m_firstVisuallyNonEmptyLayoutCallbackPending = false; 2223 if (milestonesOfInterest & DidFirstVisuallyNonEmptyLayout) 2224 milestonesAchieved |= DidFirstVisuallyNonEmptyLayout; 2225 } 2226 } 2227 2228 m_frame->loader()->didLayout(milestonesAchieved); 2229 m_frame->document()->fontloader()->didLayout(); 2230 2231 RenderView* renderView = this->renderView(); 2232 if (renderView) 2233 renderView->updateWidgetPositions(); 2234 2235 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) { 2236 if (updateWidgets()) 2237 break; 2238 } 2239 2240 if (page) { 2241 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) 2242 scrollingCoordinator->frameViewLayoutUpdated(this); 2243 } 2244 2245 scrollToAnchor(); 2246 2247 m_actionScheduler->resume(); 2248 2249 // Refetch render view since it can be destroyed by updateWidget() call above. 2250 renderView = this->renderView(); 2251 if (renderView && !renderView->printing()) { 2252 IntSize currentSize = layoutSize(IncludeScrollbars); 2253 float currentZoomFactor = renderView->style()->zoom(); 2254 bool resized = !m_firstLayout && (currentSize != m_lastViewportSize || currentZoomFactor != m_lastZoomFactor); 2255 m_lastViewportSize = currentSize; 2256 m_lastZoomFactor = currentZoomFactor; 2257 if (resized) { 2258 m_frame->eventHandler()->sendResizeEvent(); 2259 if (page && page->mainFrame() == m_frame) 2260 InspectorInstrumentation::didResizeMainFrame(page); 2261 } 2262 } 2263 } 2264 2265 void FrameView::postLayoutTimerFired(Timer<FrameView>*) 2266 { 2267 performPostLayoutTasks(); 2268 } 2269 2270 void FrameView::autoSizeIfEnabled() 2271 { 2272 if (!m_shouldAutoSize) 2273 return; 2274 2275 if (m_inAutoSize) 2276 return; 2277 2278 TemporaryChange<bool> changeInAutoSize(m_inAutoSize, true); 2279 2280 Document* document = frame()->document(); 2281 if (!document) 2282 return; 2283 2284 RenderView* documentView = document->renderView(); 2285 Element* documentElement = document->documentElement(); 2286 if (!documentView || !documentElement) 2287 return; 2288 2289 RenderBox* documentRenderBox = documentElement->renderBox(); 2290 if (!documentRenderBox) 2291 return; 2292 2293 // If this is the first time we run autosize, start from small height and 2294 // allow it to grow. 2295 if (!m_didRunAutosize) 2296 resize(frameRect().width(), m_minAutoSize.height()); 2297 2298 IntSize size = frameRect().size(); 2299 2300 // Do the resizing twice. The first time is basically a rough calculation using the preferred width 2301 // which may result in a height change during the second iteration. 2302 for (int i = 0; i < 2; i++) { 2303 // Update various sizes including contentsSize, scrollHeight, etc. 2304 document->updateLayoutIgnorePendingStylesheets(); 2305 int width = documentView->minPreferredLogicalWidth(); 2306 int height = documentRenderBox->scrollHeight(); 2307 IntSize newSize(width, height); 2308 2309 // Check to see if a scrollbar is needed for a given dimension and 2310 // if so, increase the other dimension to account for the scrollbar. 2311 // Since the dimensions are only for the view rectangle, once a 2312 // dimension exceeds the maximum, there is no need to increase it further. 2313 if (newSize.width() > m_maxAutoSize.width()) { 2314 RefPtr<Scrollbar> localHorizontalScrollbar = horizontalScrollbar(); 2315 if (!localHorizontalScrollbar) 2316 localHorizontalScrollbar = createScrollbar(HorizontalScrollbar); 2317 if (!localHorizontalScrollbar->isOverlayScrollbar()) 2318 newSize.setHeight(newSize.height() + localHorizontalScrollbar->height()); 2319 2320 // Don't bother checking for a vertical scrollbar because the width is at 2321 // already greater the maximum. 2322 } else if (newSize.height() > m_maxAutoSize.height()) { 2323 RefPtr<Scrollbar> localVerticalScrollbar = verticalScrollbar(); 2324 if (!localVerticalScrollbar) 2325 localVerticalScrollbar = createScrollbar(VerticalScrollbar); 2326 if (!localVerticalScrollbar->isOverlayScrollbar()) 2327 newSize.setWidth(newSize.width() + localVerticalScrollbar->width()); 2328 2329 // Don't bother checking for a horizontal scrollbar because the height is 2330 // already greater the maximum. 2331 } 2332 2333 // Ensure the size is at least the min bounds. 2334 newSize = newSize.expandedTo(m_minAutoSize); 2335 2336 // Bound the dimensions by the max bounds and determine what scrollbars to show. 2337 ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff; 2338 if (newSize.width() > m_maxAutoSize.width()) { 2339 newSize.setWidth(m_maxAutoSize.width()); 2340 horizonalScrollbarMode = ScrollbarAlwaysOn; 2341 } 2342 ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff; 2343 if (newSize.height() > m_maxAutoSize.height()) { 2344 newSize.setHeight(m_maxAutoSize.height()); 2345 verticalScrollbarMode = ScrollbarAlwaysOn; 2346 } 2347 2348 if (newSize == size) 2349 continue; 2350 2351 // While loading only allow the size to increase (to avoid twitching during intermediate smaller states) 2352 // unless autoresize has just been turned on or the maximum size is smaller than the current size. 2353 if (m_didRunAutosize && size.height() <= m_maxAutoSize.height() && size.width() <= m_maxAutoSize.width() 2354 && !frame()->loader()->isComplete() && (newSize.height() < size.height() || newSize.width() < size.width())) 2355 break; 2356 2357 resize(newSize.width(), newSize.height()); 2358 // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example, 2359 // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed). 2360 setVerticalScrollbarLock(false); 2361 setHorizontalScrollbarLock(false); 2362 setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true); 2363 } 2364 m_didRunAutosize = true; 2365 } 2366 2367 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow) 2368 { 2369 if (!m_viewportRenderer) 2370 return; 2371 2372 if (m_overflowStatusDirty) { 2373 m_horizontalOverflow = horizontalOverflow; 2374 m_verticalOverflow = verticalOverflow; 2375 m_overflowStatusDirty = false; 2376 return; 2377 } 2378 2379 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow); 2380 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow); 2381 2382 if (horizontalOverflowChanged || verticalOverflowChanged) { 2383 m_horizontalOverflow = horizontalOverflow; 2384 m_verticalOverflow = verticalOverflow; 2385 2386 m_actionScheduler->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, 2387 verticalOverflowChanged, verticalOverflow), 2388 m_viewportRenderer->node()); 2389 } 2390 2391 } 2392 2393 const Pagination& FrameView::pagination() const 2394 { 2395 if (m_pagination != Pagination()) 2396 return m_pagination; 2397 2398 if (Page* page = m_frame->page()) { 2399 if (page->mainFrame() == m_frame) 2400 return page->pagination(); 2401 } 2402 2403 return m_pagination; 2404 } 2405 2406 void FrameView::setPagination(const Pagination& pagination) 2407 { 2408 if (m_pagination == pagination) 2409 return; 2410 2411 m_pagination = pagination; 2412 2413 if (m_frame) 2414 m_frame->document()->styleResolverChanged(DeferRecalcStyle); 2415 } 2416 2417 IntRect FrameView::windowClipRect(bool clipToContents) const 2418 { 2419 ASSERT(m_frame->view() == this); 2420 2421 if (paintsEntireContents()) 2422 return IntRect(IntPoint(), contentsSize()); 2423 2424 // Set our clip rect to be our contents. 2425 IntRect clipRect = contentsToWindow(visibleContentRect(clipToContents ? ExcludeScrollbars : IncludeScrollbars)); 2426 if (!m_frame || !m_frame->ownerElement()) 2427 return clipRect; 2428 2429 // Take our owner element and get its clip rect. 2430 HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement(); 2431 FrameView* parentView = ownerElement->document()->view(); 2432 if (parentView) 2433 clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement, true)); 2434 return clipRect; 2435 } 2436 2437 IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement, bool clipToLayerContents) const 2438 { 2439 // The renderer can sometimes be null when style="display:none" interacts 2440 // with external content and plugins. 2441 if (!ownerElement->renderer()) 2442 return windowClipRect(); 2443 2444 // If we have no layer, just return our window clip rect. 2445 const RenderLayer* enclosingLayer = ownerElement->renderer()->enclosingLayer(); 2446 if (!enclosingLayer) 2447 return windowClipRect(); 2448 2449 // Apply the clip from the layer. 2450 IntRect clipRect; 2451 if (clipToLayerContents) 2452 clipRect = pixelSnappedIntRect(enclosingLayer->childrenClipRect()); 2453 else 2454 clipRect = pixelSnappedIntRect(enclosingLayer->selfClipRect()); 2455 clipRect = contentsToWindow(clipRect); 2456 return intersection(clipRect, windowClipRect()); 2457 } 2458 2459 bool FrameView::isActive() const 2460 { 2461 Page* page = frame()->page(); 2462 return page && page->focusController().isActive(); 2463 } 2464 2465 void FrameView::scrollTo(const IntSize& newOffset) 2466 { 2467 LayoutSize offset = scrollOffset(); 2468 ScrollView::scrollTo(newOffset); 2469 if (offset != scrollOffset()) 2470 scrollPositionChanged(); 2471 frame()->loader()->client()->didChangeScrollOffset(); 2472 } 2473 2474 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect) 2475 { 2476 // Add in our offset within the FrameView. 2477 IntRect dirtyRect = rect; 2478 dirtyRect.moveBy(scrollbar->location()); 2479 invalidateRect(dirtyRect); 2480 } 2481 2482 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const 2483 { 2484 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch); 2485 } 2486 2487 IntRect FrameView::windowResizerRect() const 2488 { 2489 Page* page = frame() ? frame()->page() : 0; 2490 if (!page) 2491 return IntRect(); 2492 return page->chrome().windowResizerRect(); 2493 } 2494 2495 void FrameView::setVisibleContentScaleFactor(float visibleContentScaleFactor) 2496 { 2497 if (m_visibleContentScaleFactor == visibleContentScaleFactor) 2498 return; 2499 2500 m_visibleContentScaleFactor = visibleContentScaleFactor; 2501 updateScrollbars(scrollOffset()); 2502 } 2503 2504 bool FrameView::scrollbarsCanBeActive() const 2505 { 2506 if (!m_frame) 2507 return false; 2508 2509 if (m_frame->view() != this) 2510 return false; 2511 2512 return !!m_frame->document(); 2513 } 2514 2515 ScrollableArea* FrameView::enclosingScrollableArea() const 2516 { 2517 // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer. 2518 return 0; 2519 } 2520 2521 IntRect FrameView::scrollableAreaBoundingBox() const 2522 { 2523 RenderPart* ownerRenderer = frame()->ownerRenderer(); 2524 if (!ownerRenderer) 2525 return frameRect(); 2526 2527 return ownerRenderer->absoluteContentQuad().enclosingBoundingBox(); 2528 } 2529 2530 bool FrameView::isScrollable() 2531 { 2532 // Check for: 2533 // 1) If there an actual overflow. 2534 // 2) display:none or visibility:hidden set to self or inherited. 2535 // 3) overflow{-x,-y}: hidden; 2536 // 4) scrolling: no; 2537 2538 // Covers #1 2539 IntSize contentsSize = this->contentsSize(); 2540 IntSize visibleContentSize = visibleContentRect().size(); 2541 if ((contentsSize.height() <= visibleContentSize.height() && contentsSize.width() <= visibleContentSize.width())) 2542 return false; 2543 2544 // Covers #2. 2545 HTMLFrameOwnerElement* owner = m_frame->ownerElement(); 2546 if (owner && (!owner->renderer() || !owner->renderer()->visibleToHitTesting())) 2547 return false; 2548 2549 // Cover #3 and #4. 2550 ScrollbarMode horizontalMode; 2551 ScrollbarMode verticalMode; 2552 calculateScrollbarModesForLayout(horizontalMode, verticalMode, RulesFromWebContentOnly); 2553 if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff) 2554 return false; 2555 2556 return true; 2557 } 2558 2559 void FrameView::updateScrollableAreaSet() 2560 { 2561 // That ensures that only inner frames are cached. 2562 FrameView* parentFrameView = this->parentFrameView(); 2563 if (!parentFrameView) 2564 return; 2565 2566 if (!isScrollable()) { 2567 parentFrameView->removeScrollableArea(this); 2568 return; 2569 } 2570 2571 parentFrameView->addScrollableArea(this); 2572 } 2573 2574 bool FrameView::shouldSuspendScrollAnimations() const 2575 { 2576 return m_frame->loader()->state() != FrameStateComplete; 2577 } 2578 2579 void FrameView::scrollbarStyleChanged(int newStyle, bool forceUpdate) 2580 { 2581 Page* page = m_frame->page(); 2582 if (!page) 2583 return; 2584 if (page->mainFrame() != m_frame) 2585 return; 2586 2587 if (forceUpdate) 2588 ScrollView::scrollbarStyleChanged(newStyle, forceUpdate); 2589 } 2590 2591 void FrameView::setAnimatorsAreActive() 2592 { 2593 Page* page = m_frame->page(); 2594 if (!page) 2595 return; 2596 2597 if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) 2598 scrollAnimator->setIsActive(); 2599 2600 if (!m_scrollableAreas) 2601 return; 2602 2603 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) { 2604 ScrollableArea* scrollableArea = *it; 2605 2606 ASSERT(scrollableArea->scrollbarsCanBeActive()); 2607 scrollableArea->scrollAnimator()->setIsActive(); 2608 } 2609 } 2610 2611 void FrameView::notifyPageThatContentAreaWillPaint() const 2612 { 2613 Page* page = m_frame->page(); 2614 if (!page) 2615 return; 2616 2617 contentAreaWillPaint(); 2618 2619 if (!m_scrollableAreas) 2620 return; 2621 2622 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) { 2623 ScrollableArea* scrollableArea = *it; 2624 2625 if (!scrollableArea->scrollbarsCanBeActive()) 2626 continue; 2627 2628 scrollableArea->contentAreaWillPaint(); 2629 } 2630 } 2631 2632 bool FrameView::scrollAnimatorEnabled() const 2633 { 2634 if (Page* page = m_frame->page()) 2635 return page->settings()->scrollAnimatorEnabled(); 2636 return false; 2637 } 2638 2639 void FrameView::updateAnnotatedRegions() 2640 { 2641 Document* document = m_frame->document(); 2642 if (!document->hasAnnotatedRegions()) 2643 return; 2644 Vector<AnnotatedRegionValue> newRegions; 2645 document->renderBox()->collectAnnotatedRegions(newRegions); 2646 if (newRegions == document->annotatedRegions()) 2647 return; 2648 document->setAnnotatedRegions(newRegions); 2649 Page* page = m_frame->page(); 2650 if (!page) 2651 return; 2652 page->chrome().client()->annotatedRegionsChanged(); 2653 } 2654 2655 void FrameView::updateScrollCorner() 2656 { 2657 RefPtr<RenderStyle> cornerStyle; 2658 IntRect cornerRect = scrollCornerRect(); 2659 Document* doc = m_frame->document(); 2660 2661 if (doc && !cornerRect.isEmpty()) { 2662 // Try the <body> element first as a scroll corner source. 2663 if (Element* body = doc->body()) { 2664 if (RenderObject* renderer = body->renderer()) 2665 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style()); 2666 } 2667 2668 if (!cornerStyle) { 2669 // If the <body> didn't have a custom style, then the root element might. 2670 if (Element* docElement = doc->documentElement()) { 2671 if (RenderObject* renderer = docElement->renderer()) 2672 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style()); 2673 } 2674 } 2675 2676 if (!cornerStyle) { 2677 // If we have an owning iframe/frame element, then it can set the custom scrollbar also. 2678 if (RenderPart* renderer = m_frame->ownerRenderer()) 2679 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style()); 2680 } 2681 } 2682 2683 if (cornerStyle) { 2684 if (!m_scrollCorner) 2685 m_scrollCorner = RenderScrollbarPart::createAnonymous(doc); 2686 m_scrollCorner->setStyle(cornerStyle.release()); 2687 invalidateScrollCorner(cornerRect); 2688 } else if (m_scrollCorner) { 2689 m_scrollCorner->destroy(); 2690 m_scrollCorner = 0; 2691 } 2692 2693 ScrollView::updateScrollCorner(); 2694 } 2695 2696 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect) 2697 { 2698 if (context->updatingControlTints()) { 2699 updateScrollCorner(); 2700 return; 2701 } 2702 2703 if (m_scrollCorner) { 2704 bool needsBackgorund = m_frame->page() && m_frame->page()->mainFrame() == m_frame; 2705 if (needsBackgorund) 2706 context->fillRect(cornerRect, baseBackgroundColor()); 2707 m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect); 2708 return; 2709 } 2710 2711 ScrollView::paintScrollCorner(context, cornerRect); 2712 } 2713 2714 void FrameView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect) 2715 { 2716 bool needsBackgorund = bar->isCustomScrollbar() && (m_frame->page() && m_frame->page()->mainFrame() == m_frame); 2717 if (needsBackgorund) { 2718 IntRect toFill = bar->frameRect(); 2719 toFill.intersect(rect); 2720 context->fillRect(toFill, baseBackgroundColor()); 2721 } 2722 2723 ScrollView::paintScrollbar(context, bar, rect); 2724 } 2725 2726 StyleColor FrameView::documentBackgroundColor() const 2727 { 2728 // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of 2729 // the document and the body against the base background color of the frame view. 2730 // Background images are unfortunately impractical to include. 2731 2732 // Return invalid Color objects whenever there is insufficient information. 2733 if (!frame()->document()) 2734 return Color(); 2735 2736 Element* htmlElement = frame()->document()->documentElement(); 2737 Element* bodyElement = frame()->document()->body(); 2738 2739 // Start with invalid colors. 2740 StyleColor htmlBackgroundColor; 2741 StyleColor bodyBackgroundColor; 2742 if (htmlElement && htmlElement->renderer()) 2743 htmlBackgroundColor = htmlElement->renderer()->resolveStyleColor(CSSPropertyBackgroundColor); 2744 if (bodyElement && bodyElement->renderer()) 2745 bodyBackgroundColor = bodyElement->renderer()->resolveStyleColor(CSSPropertyBackgroundColor); 2746 2747 if (!bodyBackgroundColor.isValid()) { 2748 if (!htmlBackgroundColor.isValid()) 2749 return StyleColor(); 2750 return baseBackgroundColor().blend(htmlBackgroundColor.color()); 2751 } 2752 2753 if (!htmlBackgroundColor.isValid()) 2754 return baseBackgroundColor().blend(bodyBackgroundColor.color()); 2755 2756 // We take the aggregate of the base background color 2757 // the <html> background color, and the <body> 2758 // background color to find the document color. The 2759 // addition of the base background color is not 2760 // technically part of the document background, but it 2761 // otherwise poses problems when the aggregate is not 2762 // fully opaque. 2763 return baseBackgroundColor().blend(htmlBackgroundColor.color()).blend(bodyBackgroundColor.color()); 2764 } 2765 2766 bool FrameView::hasCustomScrollbars() const 2767 { 2768 const HashSet<RefPtr<Widget> >* viewChildren = children(); 2769 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end(); 2770 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) { 2771 Widget* widget = current->get(); 2772 if (widget->isFrameView()) { 2773 if (toFrameView(widget)->hasCustomScrollbars()) 2774 return true; 2775 } else if (widget->isScrollbar()) { 2776 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget); 2777 if (scrollbar->isCustomScrollbar()) 2778 return true; 2779 } 2780 } 2781 2782 return false; 2783 } 2784 2785 FrameView* FrameView::parentFrameView() const 2786 { 2787 if (!parent()) 2788 return 0; 2789 2790 if (Frame* parentFrame = m_frame->tree()->parent()) 2791 return parentFrame->view(); 2792 2793 return 0; 2794 } 2795 2796 void FrameView::updateControlTints() 2797 { 2798 // This is called when control tints are changed from aqua/graphite to clear and vice versa. 2799 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate. 2800 // This is only done if the theme supports control tinting. It's up to the theme and platform 2801 // to define when controls get the tint and to call this function when that changes. 2802 2803 // Optimize the common case where we bring a window to the front while it's still empty. 2804 if (!m_frame || m_frame->document()->url().isEmpty()) 2805 return; 2806 2807 RenderView* renderView = this->renderView(); 2808 if ((renderView && renderView->theme()->supportsControlTints()) || hasCustomScrollbars()) 2809 paintControlTints(); 2810 } 2811 2812 void FrameView::paintControlTints() 2813 { 2814 if (needsLayout()) 2815 layout(); 2816 // FIXME: The use of paint seems like overkill: crbug.com/236892 2817 GraphicsContext context(0); // NULL canvas to get a non-painting context. 2818 context.setUpdatingControlTints(true); 2819 paint(&context, frameRect()); 2820 } 2821 2822 bool FrameView::wasScrolledByUser() const 2823 { 2824 return m_wasScrolledByUser; 2825 } 2826 2827 void FrameView::setWasScrolledByUser(bool wasScrolledByUser) 2828 { 2829 if (m_inProgrammaticScroll) 2830 return; 2831 m_maintainScrollPositionAnchor = 0; 2832 m_wasScrolledByUser = wasScrolledByUser; 2833 } 2834 2835 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) 2836 { 2837 if (!frame()) 2838 return; 2839 2840 Document* document = m_frame->document(); 2841 2842 #ifndef NDEBUG 2843 bool fillWithRed; 2844 if (document->printing()) 2845 fillWithRed = false; // Printing, don't fill with red (can't remember why). 2846 else if (m_frame->ownerElement()) 2847 fillWithRed = false; // Subframe, don't fill with red. 2848 else if (isTransparent()) 2849 fillWithRed = false; // Transparent, don't fill with red. 2850 else if (m_paintBehavior & PaintBehaviorSelectionOnly) 2851 fillWithRed = false; // Selections are transparent, don't fill with red. 2852 else if (m_nodeToDraw) 2853 fillWithRed = false; // Element images are transparent, don't fill with red. 2854 else 2855 fillWithRed = true; 2856 2857 if (fillWithRed) 2858 p->fillRect(rect, Color(0xFF, 0, 0)); 2859 #endif 2860 2861 RenderView* renderView = this->renderView(); 2862 if (!renderView) { 2863 LOG_ERROR("called FrameView::paint with nil renderer"); 2864 return; 2865 } 2866 2867 ASSERT(!needsLayout()); 2868 if (needsLayout()) 2869 return; 2870 2871 InspectorInstrumentation::willPaint(renderView); 2872 2873 bool isTopLevelPainter = !sCurrentPaintTimeStamp; 2874 if (isTopLevelPainter) 2875 sCurrentPaintTimeStamp = currentTime(); 2876 2877 FontCachePurgePreventer fontCachePurgePreventer; 2878 2879 PaintBehavior oldPaintBehavior = m_paintBehavior; 2880 2881 if (FrameView* parentView = parentFrameView()) { 2882 if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers) 2883 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers; 2884 } 2885 2886 if (m_paintBehavior == PaintBehaviorNormal) 2887 document->markers()->invalidateRenderedRectsForMarkersInRect(rect); 2888 2889 if (document->printing()) 2890 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers; 2891 2892 ASSERT(!m_isPainting); 2893 m_isPainting = true; 2894 2895 // m_nodeToDraw is used to draw only one element (and its descendants) 2896 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0; 2897 RenderLayer* rootLayer = renderView->layer(); 2898 2899 #ifndef NDEBUG 2900 RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(rootLayer->renderer()); 2901 #endif 2902 2903 rootLayer->paint(p, rect, m_paintBehavior, eltRenderer); 2904 2905 if (rootLayer->containsDirtyOverlayScrollbars()) 2906 rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer); 2907 2908 m_isPainting = false; 2909 2910 m_paintBehavior = oldPaintBehavior; 2911 m_lastPaintTime = currentTime(); 2912 2913 // Regions may have changed as a result of the visibility/z-index of element changing. 2914 if (document->annotatedRegionsDirty()) 2915 updateAnnotatedRegions(); 2916 2917 if (isTopLevelPainter) 2918 sCurrentPaintTimeStamp = 0; 2919 2920 InspectorInstrumentation::didPaint(renderView, p, rect); 2921 } 2922 2923 void FrameView::setPaintBehavior(PaintBehavior behavior) 2924 { 2925 m_paintBehavior = behavior; 2926 } 2927 2928 PaintBehavior FrameView::paintBehavior() const 2929 { 2930 return m_paintBehavior; 2931 } 2932 2933 bool FrameView::isPainting() const 2934 { 2935 return m_isPainting; 2936 } 2937 2938 void FrameView::setNodeToDraw(Node* node) 2939 { 2940 m_nodeToDraw = node; 2941 } 2942 2943 void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect) 2944 { 2945 if (context->paintingDisabled()) 2946 return; 2947 2948 if (m_frame->document()->printing()) 2949 return; 2950 2951 Page* page = m_frame->page(); 2952 if (page->mainFrame() == m_frame) { 2953 if (page->chrome().client()->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect)) 2954 return; 2955 } 2956 2957 ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect); 2958 } 2959 2960 void FrameView::updateLayoutAndStyleIfNeededRecursive() 2961 { 2962 // We have to crawl our entire tree looking for any FrameViews that need 2963 // layout and make sure they are up to date. 2964 // Mac actually tests for intersection with the dirty region and tries not to 2965 // update layout for frames that are outside the dirty region. Not only does this seem 2966 // pointless (since those frames will have set a zero timer to layout anyway), but 2967 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty 2968 // region but then become included later by the second frame adding rects to the dirty region 2969 // when it lays out. 2970 2971 m_frame->document()->updateStyleIfNeeded(); 2972 2973 if (needsLayout()) 2974 layout(); 2975 2976 // Grab a copy of the children() set, as it may be mutated by the following updateLayoutAndStyleIfNeededRecursive 2977 // calls, as they can potentially re-enter a layout of the parent frame view, which may add/remove scrollbars 2978 // and thus mutates the children() set. 2979 Vector<RefPtr<FrameView> > frameViews; 2980 collectFrameViewChildren(this, frameViews); 2981 2982 const Vector<RefPtr<FrameView> >::iterator end = frameViews.end(); 2983 for (Vector<RefPtr<FrameView> >::iterator it = frameViews.begin(); it != end; ++it) 2984 (*it)->updateLayoutAndStyleIfNeededRecursive(); 2985 2986 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before 2987 // painting, so we need to flush out any deferred repaints too. 2988 flushDeferredRepaints(); 2989 2990 // When seamless is on, child frame can mark parent frame dirty. In such case, child frame 2991 // needs to call layout on parent frame recursively. 2992 // This assert ensures that parent frames are clean, when child frames finished updating layout and style. 2993 ASSERT(!needsLayout()); 2994 } 2995 2996 void FrameView::enableAutoSizeMode(bool enable, const IntSize& minSize, const IntSize& maxSize) 2997 { 2998 ASSERT(!enable || !minSize.isEmpty()); 2999 ASSERT(minSize.width() <= maxSize.width()); 3000 ASSERT(minSize.height() <= maxSize.height()); 3001 3002 if (m_shouldAutoSize == enable && m_minAutoSize == minSize && m_maxAutoSize == maxSize) 3003 return; 3004 3005 m_shouldAutoSize = enable; 3006 m_minAutoSize = minSize; 3007 m_maxAutoSize = maxSize; 3008 m_didRunAutosize = false; 3009 3010 setNeedsLayout(); 3011 scheduleRelayout(); 3012 if (m_shouldAutoSize) 3013 return; 3014 3015 // Since autosize mode forces the scrollbar mode, change them to being auto. 3016 setVerticalScrollbarLock(false); 3017 setHorizontalScrollbarLock(false); 3018 setScrollbarModes(ScrollbarAuto, ScrollbarAuto); 3019 } 3020 3021 void FrameView::forceLayout(bool allowSubtree) 3022 { 3023 layout(allowSubtree); 3024 } 3025 3026 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor, AdjustViewSizeOrNot shouldAdjustViewSize) 3027 { 3028 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see 3029 // the state of things before and after the layout 3030 if (RenderView* renderView = this->renderView()) { 3031 float pageLogicalWidth = renderView->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height(); 3032 float pageLogicalHeight = renderView->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width(); 3033 3034 LayoutUnit flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth); 3035 LayoutUnit flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight); 3036 renderView->setLogicalWidth(flooredPageLogicalWidth); 3037 renderView->setPageLogicalHeight(flooredPageLogicalHeight); 3038 renderView->setNeedsLayoutAndPrefWidthsRecalc(); 3039 forceLayout(); 3040 3041 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the 3042 // page width when shrunk, we will lay out at maximum shrink and clip extra content. 3043 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping 3044 // implementation should not do this! 3045 bool horizontalWritingMode = renderView->style()->isHorizontalWritingMode(); 3046 const LayoutRect& documentRect = renderView->documentRect(); 3047 LayoutUnit docLogicalWidth = horizontalWritingMode ? documentRect.width() : documentRect.height(); 3048 if (docLogicalWidth > pageLogicalWidth) { 3049 int expectedPageWidth = std::min<float>(documentRect.width(), pageSize.width() * maximumShrinkFactor); 3050 int expectedPageHeight = std::min<float>(documentRect.height(), pageSize.height() * maximumShrinkFactor); 3051 FloatSize maxPageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(originalPageSize.width(), originalPageSize.height()), FloatSize(expectedPageWidth, expectedPageHeight)); 3052 pageLogicalWidth = horizontalWritingMode ? maxPageSize.width() : maxPageSize.height(); 3053 pageLogicalHeight = horizontalWritingMode ? maxPageSize.height() : maxPageSize.width(); 3054 3055 flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth); 3056 flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight); 3057 renderView->setLogicalWidth(flooredPageLogicalWidth); 3058 renderView->setPageLogicalHeight(flooredPageLogicalHeight); 3059 renderView->setNeedsLayoutAndPrefWidthsRecalc(); 3060 forceLayout(); 3061 3062 const LayoutRect& updatedDocumentRect = renderView->documentRect(); 3063 LayoutUnit docLogicalHeight = horizontalWritingMode ? updatedDocumentRect.height() : updatedDocumentRect.width(); 3064 LayoutUnit docLogicalTop = horizontalWritingMode ? updatedDocumentRect.y() : updatedDocumentRect.x(); 3065 LayoutUnit docLogicalRight = horizontalWritingMode ? updatedDocumentRect.maxX() : updatedDocumentRect.maxY(); 3066 LayoutUnit clippedLogicalLeft = 0; 3067 if (!renderView->style()->isLeftToRightDirection()) 3068 clippedLogicalLeft = docLogicalRight - pageLogicalWidth; 3069 LayoutRect overflow(clippedLogicalLeft, docLogicalTop, pageLogicalWidth, docLogicalHeight); 3070 3071 if (!horizontalWritingMode) 3072 overflow = overflow.transposedRect(); 3073 renderView->clearLayoutOverflow(); 3074 renderView->addLayoutOverflow(overflow); // This is how we clip in case we overflow again. 3075 } 3076 } 3077 3078 if (shouldAdjustViewSize) 3079 adjustViewSize(); 3080 } 3081 3082 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const 3083 { 3084 IntRect rect = pixelSnappedIntRect(enclosingLayoutRect(renderer->localToAbsoluteQuad(FloatRect(rendererRect)).boundingBox())); 3085 3086 // Convert from page ("absolute") to FrameView coordinates. 3087 rect.moveBy(-scrollPosition()); 3088 3089 return rect; 3090 } 3091 3092 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const 3093 { 3094 IntRect rect = viewRect; 3095 3096 // Convert from FrameView coords into page ("absolute") coordinates. 3097 rect.moveBy(scrollPosition()); 3098 3099 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just 3100 // move the rect for now. 3101 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), UseTransforms))); 3102 return rect; 3103 } 3104 3105 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const 3106 { 3107 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, UseTransforms)); 3108 3109 // Convert from page ("absolute") to FrameView coordinates. 3110 point.moveBy(-scrollPosition()); 3111 return point; 3112 } 3113 3114 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const 3115 { 3116 IntPoint point = viewPoint; 3117 3118 // Convert from FrameView coords into page ("absolute") coordinates. 3119 point += IntSize(scrollX(), scrollY()); 3120 3121 return roundedIntPoint(renderer->absoluteToLocal(point, UseTransforms)); 3122 } 3123 3124 IntRect FrameView::convertToContainingView(const IntRect& localRect) const 3125 { 3126 if (const ScrollView* parentScrollView = parent()) { 3127 if (parentScrollView->isFrameView()) { 3128 const FrameView* parentView = toFrameView(parentScrollView); 3129 // Get our renderer in the parent view 3130 RenderPart* renderer = m_frame->ownerRenderer(); 3131 if (!renderer) 3132 return localRect; 3133 3134 IntRect rect(localRect); 3135 // Add borders and padding?? 3136 rect.move(renderer->borderLeft() + renderer->paddingLeft(), 3137 renderer->borderTop() + renderer->paddingTop()); 3138 return parentView->convertFromRenderer(renderer, rect); 3139 } 3140 3141 return Widget::convertToContainingView(localRect); 3142 } 3143 3144 return localRect; 3145 } 3146 3147 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const 3148 { 3149 if (const ScrollView* parentScrollView = parent()) { 3150 if (parentScrollView->isFrameView()) { 3151 const FrameView* parentView = toFrameView(parentScrollView); 3152 3153 // Get our renderer in the parent view 3154 RenderPart* renderer = m_frame->ownerRenderer(); 3155 if (!renderer) 3156 return parentRect; 3157 3158 IntRect rect = parentView->convertToRenderer(renderer, parentRect); 3159 // Subtract borders and padding 3160 rect.move(-renderer->borderLeft() - renderer->paddingLeft(), 3161 -renderer->borderTop() - renderer->paddingTop()); 3162 return rect; 3163 } 3164 3165 return Widget::convertFromContainingView(parentRect); 3166 } 3167 3168 return parentRect; 3169 } 3170 3171 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const 3172 { 3173 if (const ScrollView* parentScrollView = parent()) { 3174 if (parentScrollView->isFrameView()) { 3175 const FrameView* parentView = toFrameView(parentScrollView); 3176 3177 // Get our renderer in the parent view 3178 RenderPart* renderer = m_frame->ownerRenderer(); 3179 if (!renderer) 3180 return localPoint; 3181 3182 IntPoint point(localPoint); 3183 3184 // Add borders and padding 3185 point.move(renderer->borderLeft() + renderer->paddingLeft(), 3186 renderer->borderTop() + renderer->paddingTop()); 3187 return parentView->convertFromRenderer(renderer, point); 3188 } 3189 3190 return Widget::convertToContainingView(localPoint); 3191 } 3192 3193 return localPoint; 3194 } 3195 3196 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const 3197 { 3198 if (const ScrollView* parentScrollView = parent()) { 3199 if (parentScrollView->isFrameView()) { 3200 const FrameView* parentView = toFrameView(parentScrollView); 3201 3202 // Get our renderer in the parent view 3203 RenderPart* renderer = m_frame->ownerRenderer(); 3204 if (!renderer) 3205 return parentPoint; 3206 3207 IntPoint point = parentView->convertToRenderer(renderer, parentPoint); 3208 // Subtract borders and padding 3209 point.move(-renderer->borderLeft() - renderer->paddingLeft(), 3210 -renderer->borderTop() - renderer->paddingTop()); 3211 return point; 3212 } 3213 3214 return Widget::convertFromContainingView(parentPoint); 3215 } 3216 3217 return parentPoint; 3218 } 3219 3220 // Normal delay 3221 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p) 3222 { 3223 s_normalDeferredRepaintDelay = p; 3224 } 3225 3226 // Negative value would mean that first few repaints happen without a delay 3227 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p) 3228 { 3229 s_initialDeferredRepaintDelayDuringLoading = p; 3230 } 3231 3232 // The delay grows on each repaint to this maximum value 3233 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p) 3234 { 3235 s_maxDeferredRepaintDelayDuringLoading = p; 3236 } 3237 3238 // On each repaint the delay increases by this amount 3239 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p) 3240 { 3241 s_deferredRepaintDelayIncrementDuringLoading = p; 3242 } 3243 3244 void FrameView::setTracksRepaints(bool trackRepaints) 3245 { 3246 if (trackRepaints == m_isTrackingRepaints) 3247 return; 3248 3249 for (Frame* frame = m_frame->tree()->top(); frame; frame = frame->tree()->traverseNext()) { 3250 if (RenderView* renderView = frame->contentRenderer()) 3251 renderView->compositor()->setTracksRepaints(trackRepaints); 3252 } 3253 3254 resetTrackedRepaints(); 3255 m_isTrackingRepaints = trackRepaints; 3256 } 3257 3258 void FrameView::resetTrackedRepaints() 3259 { 3260 m_trackedRepaintRects.clear(); 3261 if (RenderView* renderView = this->renderView()) 3262 renderView->compositor()->resetTrackedRepaintRects(); 3263 } 3264 3265 String FrameView::trackedRepaintRectsAsText() const 3266 { 3267 TextStream ts; 3268 if (!m_trackedRepaintRects.isEmpty()) { 3269 ts << "(repaint rects\n"; 3270 for (size_t i = 0; i < m_trackedRepaintRects.size(); ++i) 3271 ts << " (rect " << m_trackedRepaintRects[i].x() << " " << m_trackedRepaintRects[i].y() << " " << m_trackedRepaintRects[i].width() << " " << m_trackedRepaintRects[i].height() << ")\n"; 3272 ts << ")\n"; 3273 } 3274 return ts.release(); 3275 } 3276 3277 void FrameView::addResizerArea(RenderLayer* resizerLayer) 3278 { 3279 if (!m_resizerAreas) 3280 m_resizerAreas = adoptPtr(new ResizerAreaSet); 3281 m_resizerAreas->add(resizerLayer); 3282 } 3283 3284 void FrameView::removeResizerArea(RenderLayer* resizerLayer) 3285 { 3286 if (!m_resizerAreas) 3287 return; 3288 3289 ResizerAreaSet::iterator it = m_resizerAreas->find(resizerLayer); 3290 if (it != m_resizerAreas->end()) 3291 m_resizerAreas->remove(it); 3292 } 3293 3294 bool FrameView::addScrollableArea(ScrollableArea* scrollableArea) 3295 { 3296 if (!m_scrollableAreas) 3297 m_scrollableAreas = adoptPtr(new ScrollableAreaSet); 3298 return m_scrollableAreas->add(scrollableArea).isNewEntry; 3299 } 3300 3301 bool FrameView::removeScrollableArea(ScrollableArea* scrollableArea) 3302 { 3303 if (!m_scrollableAreas) 3304 return false; 3305 3306 ScrollableAreaSet::iterator it = m_scrollableAreas->find(scrollableArea); 3307 if (it == m_scrollableAreas->end()) 3308 return false; 3309 3310 m_scrollableAreas->remove(it); 3311 return true; 3312 } 3313 3314 bool FrameView::containsScrollableArea(ScrollableArea* scrollableArea) const 3315 { 3316 if (!m_scrollableAreas) 3317 return false; 3318 return m_scrollableAreas->contains(scrollableArea); 3319 } 3320 3321 void FrameView::removeChild(Widget* widget) 3322 { 3323 if (widget->isFrameView()) 3324 removeScrollableArea(toFrameView(widget)); 3325 3326 ScrollView::removeChild(widget); 3327 } 3328 3329 bool FrameView::wheelEvent(const PlatformWheelEvent& wheelEvent) 3330 { 3331 // Note that to allow for rubber-band over-scroll behavior, even non-scrollable views 3332 // should handle wheel events. 3333 #if !ENABLE(RUBBER_BANDING) 3334 if (!isScrollable()) 3335 return false; 3336 #endif 3337 3338 // We don't allow mouse wheeling to happen in a ScrollView that has had its scrollbars explicitly disabled. 3339 if (!canHaveScrollbars()) 3340 return false; 3341 3342 return ScrollableArea::handleWheelEvent(wheelEvent); 3343 } 3344 3345 3346 bool FrameView::isVerticalDocument() const 3347 { 3348 RenderView* renderView = this->renderView(); 3349 if (!renderView) 3350 return true; 3351 3352 return renderView->style()->isHorizontalWritingMode(); 3353 } 3354 3355 bool FrameView::isFlippedDocument() const 3356 { 3357 RenderView* renderView = this->renderView(); 3358 if (!renderView) 3359 return false; 3360 3361 return renderView->style()->isFlippedBlocksWritingMode(); 3362 } 3363 3364 AXObjectCache* FrameView::axObjectCache() const 3365 { 3366 if (frame() && frame()->document()) 3367 return frame()->document()->existingAXObjectCache(); 3368 return 0; 3369 } 3370 3371 } // namespace WebCore 3372