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 "FrameView.h" 29 30 #include "AXObjectCache.h" 31 #include "CSSStyleSelector.h" 32 #include "CachedResourceLoader.h" 33 #include "Chrome.h" 34 #include "ChromeClient.h" 35 #include "DocumentMarkerController.h" 36 #include "EventHandler.h" 37 #include "FloatRect.h" 38 #include "FocusController.h" 39 #include "Frame.h" 40 #include "FrameActionScheduler.h" 41 #include "FrameLoader.h" 42 #include "FrameLoaderClient.h" 43 #include "FrameTree.h" 44 #include "GraphicsContext.h" 45 #include "HTMLDocument.h" 46 #include "HTMLFrameElement.h" 47 #include "HTMLFrameSetElement.h" 48 #include "HTMLNames.h" 49 #include "HTMLPlugInImageElement.h" 50 #include "InspectorInstrumentation.h" 51 #include "OverflowEvent.h" 52 #include "RenderEmbeddedObject.h" 53 #include "RenderFullScreen.h" 54 #include "RenderLayer.h" 55 #include "RenderPart.h" 56 #include "RenderScrollbar.h" 57 #include "RenderScrollbarPart.h" 58 #include "RenderTheme.h" 59 #include "RenderView.h" 60 #include "ScrollAnimator.h" 61 #include "Settings.h" 62 #include "TextResourceDecoder.h" 63 #include <wtf/CurrentTime.h> 64 65 #ifdef ANDROID_INSTRUMENT 66 #include "FrameTree.h" 67 #include "TimeCounter.h" 68 #endif 69 70 #if USE(ACCELERATED_COMPOSITING) 71 #include "RenderLayerCompositor.h" 72 #endif 73 74 #if ENABLE(SVG) 75 #include "SVGDocument.h" 76 #include "SVGLocatable.h" 77 #include "SVGNames.h" 78 #include "SVGPreserveAspectRatio.h" 79 #include "SVGSVGElement.h" 80 #include "SVGViewElement.h" 81 #include "SVGViewSpec.h" 82 #endif 83 84 #if ENABLE(TILED_BACKING_STORE) 85 #include "TiledBackingStore.h" 86 #endif 87 88 #if PLATFORM(ANDROID) 89 #include "WebCoreFrameBridge.h" 90 #endif 91 92 namespace WebCore { 93 94 using namespace HTMLNames; 95 96 double FrameView::sCurrentPaintTimeStamp = 0.0; 97 98 // REPAINT_THROTTLING now chooses default values for throttling parameters. 99 // Should be removed when applications start using runtime configuration. 100 #if ENABLE(REPAINT_THROTTLING) 101 // Normal delay 102 double FrameView::s_deferredRepaintDelay = 0.025; 103 // Negative value would mean that first few repaints happen without a delay 104 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0; 105 // The delay grows on each repaint to this maximum value 106 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5; 107 // On each repaint the delay increses by this amount 108 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5; 109 #else 110 // FIXME: Repaint throttling could be good to have on all platform. 111 // The balance between CPU use and repaint frequency will need some tuning for desktop. 112 // More hooks may be needed to reset the delay on things like GIF and CSS animations. 113 double FrameView::s_deferredRepaintDelay = 0; 114 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0; 115 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0; 116 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0; 117 #endif 118 119 // The maximum number of updateWidgets iterations that should be done before returning. 120 static const unsigned maxUpdateWidgetsIterations = 2; 121 122 FrameView::FrameView(Frame* frame) 123 : m_frame(frame) 124 , m_canHaveScrollbars(true) 125 , m_slowRepaintObjectCount(0) 126 , m_fixedObjectCount(0) 127 , m_layoutTimer(this, &FrameView::layoutTimerFired) 128 , m_layoutRoot(0) 129 , m_hasPendingPostLayoutTasks(false) 130 , m_inSynchronousPostLayout(false) 131 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired) 132 , m_isTransparent(false) 133 , m_baseBackgroundColor(Color::white) 134 , m_mediaType("screen") 135 , m_actionScheduler(new FrameActionScheduler()) 136 , m_overflowStatusDirty(true) 137 , m_viewportRenderer(0) 138 , m_wasScrolledByUser(false) 139 , m_inProgrammaticScroll(false) 140 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired) 141 , m_shouldUpdateWhileOffscreen(true) 142 , m_deferSetNeedsLayouts(0) 143 , m_setNeedsLayoutWasDeferred(false) 144 , m_scrollCorner(0) 145 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 146 , m_hasOverflowScroll(false) 147 #endif 148 { 149 init(); 150 151 if (m_frame) { 152 if (Page* page = m_frame->page()) { 153 m_page = page; 154 m_page->addScrollableArea(this); 155 156 if (m_frame == m_page->mainFrame()) { 157 ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed); 158 ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed); 159 } 160 } 161 } 162 } 163 164 PassRefPtr<FrameView> FrameView::create(Frame* frame) 165 { 166 RefPtr<FrameView> view = adoptRef(new FrameView(frame)); 167 view->show(); 168 return view.release(); 169 } 170 171 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize) 172 { 173 RefPtr<FrameView> view = adoptRef(new FrameView(frame)); 174 view->Widget::setFrameRect(IntRect(view->pos(), initialSize)); 175 view->setInitialBoundsSize(initialSize); 176 view->show(); 177 return view.release(); 178 } 179 180 FrameView::~FrameView() 181 { 182 if (m_hasPendingPostLayoutTasks) { 183 m_postLayoutTasksTimer.stop(); 184 m_actionScheduler->clear(); 185 } 186 187 if (AXObjectCache::accessibilityEnabled() && axObjectCache()) 188 axObjectCache()->remove(this); 189 190 resetScrollbars(); 191 192 // Custom scrollbars should already be destroyed at this point 193 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar()); 194 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar()); 195 196 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow. 197 setHasVerticalScrollbar(false); 198 199 ASSERT(!m_scrollCorner); 200 ASSERT(m_actionScheduler->isEmpty()); 201 202 if (m_page) 203 m_page->removeScrollableArea(this); 204 205 if (m_frame) { 206 ASSERT(m_frame->view() != this || !m_frame->contentRenderer()); 207 RenderPart* renderer = m_frame->ownerRenderer(); 208 if (renderer && renderer->widget() == this) 209 renderer->setWidget(0); 210 } 211 } 212 213 void FrameView::reset() 214 { 215 m_useSlowRepaints = false; 216 m_isOverlapped = false; 217 m_contentIsOpaque = false; 218 m_borderX = 30; 219 m_borderY = 30; 220 m_layoutTimer.stop(); 221 m_layoutRoot = 0; 222 m_delayedLayout = false; 223 m_doFullRepaint = true; 224 m_layoutSchedulingEnabled = true; 225 m_inLayout = false; 226 m_inSynchronousPostLayout = false; 227 m_hasPendingPostLayoutTasks = false; 228 m_layoutCount = 0; 229 m_nestedLayoutCount = 0; 230 m_postLayoutTasksTimer.stop(); 231 m_firstLayout = true; 232 m_firstLayoutCallbackPending = false; 233 m_wasScrolledByUser = false; 234 m_lastLayoutSize = IntSize(); 235 m_lastZoomFactor = 1.0f; 236 m_deferringRepaints = 0; 237 m_repaintCount = 0; 238 m_repaintRects.clear(); 239 m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading; 240 m_deferredRepaintTimer.stop(); 241 m_lastPaintTime = 0; 242 m_paintBehavior = PaintBehaviorNormal; 243 m_isPainting = false; 244 m_isVisuallyNonEmpty = false; 245 m_firstVisuallyNonEmptyLayoutCallbackPending = true; 246 m_maintainScrollPositionAnchor = 0; 247 } 248 249 bool FrameView::isFrameView() const 250 { 251 return true; 252 } 253 254 void FrameView::clearFrame() 255 { 256 m_frame = 0; 257 } 258 259 void FrameView::resetScrollbars() 260 { 261 // Reset the document's scrollbars back to our defaults before we yield the floor. 262 m_firstLayout = true; 263 setScrollbarsSuppressed(true); 264 if (m_canHaveScrollbars) 265 setScrollbarModes(ScrollbarAuto, ScrollbarAuto); 266 else 267 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); 268 setScrollbarsSuppressed(false); 269 } 270 271 void FrameView::resetScrollbarsAndClearContentsSize() 272 { 273 // Since the contents size is being cleared, the scroll position will lost as a consequence. 274 // Cache the scroll position so it can be restored by the page cache if necessary. 275 cacheCurrentScrollPosition(); 276 277 resetScrollbars(); 278 279 setScrollbarsSuppressed(true); 280 setContentsSize(IntSize()); 281 setScrollbarsSuppressed(false); 282 } 283 284 void FrameView::init() 285 { 286 reset(); 287 288 m_margins = IntSize(-1, -1); // undefined 289 m_size = IntSize(); 290 291 // Propagate the marginwidth/height and scrolling modes to the view. 292 Element* ownerElement = m_frame ? m_frame->ownerElement() : 0; 293 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) { 294 HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement); 295 if (frameElt->scrollingMode() == ScrollbarAlwaysOff) 296 setCanHaveScrollbars(false); 297 int marginWidth = frameElt->marginWidth(); 298 int marginHeight = frameElt->marginHeight(); 299 if (marginWidth != -1) 300 setMarginWidth(marginWidth); 301 if (marginHeight != -1) 302 setMarginHeight(marginHeight); 303 } 304 } 305 306 void FrameView::detachCustomScrollbars() 307 { 308 if (!m_frame) 309 return; 310 311 Scrollbar* horizontalBar = horizontalScrollbar(); 312 if (horizontalBar && horizontalBar->isCustomScrollbar()) 313 setHasHorizontalScrollbar(false); 314 315 Scrollbar* verticalBar = verticalScrollbar(); 316 if (verticalBar && verticalBar->isCustomScrollbar()) 317 setHasVerticalScrollbar(false); 318 319 if (m_scrollCorner) { 320 m_scrollCorner->destroy(); 321 m_scrollCorner = 0; 322 } 323 } 324 325 void FrameView::clear() 326 { 327 setCanBlitOnScroll(true); 328 329 reset(); 330 331 if (m_frame) { 332 if (RenderPart* renderer = m_frame->ownerRenderer()) 333 renderer->viewCleared(); 334 } 335 336 setScrollbarsSuppressed(true); 337 } 338 339 bool FrameView::didFirstLayout() const 340 { 341 return !m_firstLayout; 342 } 343 344 void FrameView::invalidateRect(const IntRect& rect) 345 { 346 if (!parent()) { 347 if (hostWindow()) 348 hostWindow()->invalidateContentsAndWindow(rect, false /*immediate*/); 349 return; 350 } 351 352 if (!m_frame) 353 return; 354 355 RenderPart* renderer = m_frame->ownerRenderer(); 356 if (!renderer) 357 return; 358 359 IntRect repaintRect = rect; 360 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(), 361 renderer->borderTop() + renderer->paddingTop()); 362 renderer->repaintRectangle(repaintRect); 363 } 364 365 void FrameView::setFrameRect(const IntRect& newRect) 366 { 367 IntRect oldRect = frameRect(); 368 if (newRect == oldRect) 369 return; 370 371 ScrollView::setFrameRect(newRect); 372 373 #if USE(ACCELERATED_COMPOSITING) 374 if (RenderView* root = m_frame->contentRenderer()) { 375 if (root->usesCompositing()) 376 root->compositor()->frameViewDidChangeSize(); 377 } 378 #endif 379 } 380 381 #if ENABLE(REQUEST_ANIMATION_FRAME) 382 void FrameView::scheduleAnimation() 383 { 384 if (hostWindow()) 385 hostWindow()->scheduleAnimation(); 386 } 387 #endif 388 389 void FrameView::setMarginWidth(int w) 390 { 391 // make it update the rendering area when set 392 m_margins.setWidth(w); 393 } 394 395 void FrameView::setMarginHeight(int h) 396 { 397 // make it update the rendering area when set 398 m_margins.setHeight(h); 399 } 400 401 bool FrameView::avoidScrollbarCreation() const 402 { 403 ASSERT(m_frame); 404 405 // with frame flattening no subframe can have scrollbars 406 // but we also cannot turn scrollbars of as we determine 407 // our flattening policy using that. 408 409 if (!m_frame->ownerElement()) 410 return false; 411 412 if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled()) 413 return true; 414 415 return false; 416 } 417 418 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars) 419 { 420 m_canHaveScrollbars = canHaveScrollbars; 421 ScrollView::setCanHaveScrollbars(canHaveScrollbars); 422 } 423 424 void FrameView::updateCanHaveScrollbars() 425 { 426 ScrollbarMode hMode; 427 ScrollbarMode vMode; 428 scrollbarModes(hMode, vMode); 429 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff) 430 setCanHaveScrollbars(false); 431 else 432 setCanHaveScrollbars(true); 433 } 434 435 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation) 436 { 437 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles). 438 Document* doc = m_frame->document(); 439 440 // Try the <body> element first as a scrollbar source. 441 Element* body = doc ? doc->body() : 0; 442 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR)) 443 return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderer()->enclosingBox()); 444 445 // If the <body> didn't have a custom style, then the root element might. 446 Element* docElement = doc ? doc->documentElement() : 0; 447 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR)) 448 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox()); 449 450 // If we have an owning iframe/frame element, then it can set the custom scrollbar also. 451 RenderPart* frameRenderer = m_frame->ownerRenderer(); 452 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR)) 453 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get()); 454 455 // Nobody set a custom style, so we just use a native scrollbar. 456 return ScrollView::createScrollbar(orientation); 457 } 458 459 void FrameView::setContentsSize(const IntSize& size) 460 { 461 if (size == contentsSize()) 462 return; 463 464 m_deferSetNeedsLayouts++; 465 466 ScrollView::setContentsSize(size); 467 scrollAnimator()->contentsResized(); 468 469 Page* page = frame() ? frame()->page() : 0; 470 if (!page) 471 return; 472 473 page->chrome()->contentsSizeChanged(frame(), size); //notify only 474 475 m_deferSetNeedsLayouts--; 476 477 if (!m_deferSetNeedsLayouts) 478 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen. 479 } 480 481 void FrameView::adjustViewSize() 482 { 483 ASSERT(m_frame->view() == this); 484 RenderView* root = m_frame->contentRenderer(); 485 if (!root) 486 return; 487 488 IntSize size = IntSize(root->docWidth(), root->docHeight()); 489 490 ScrollView::setScrollOrigin(IntPoint(-root->docLeft(), -root->docTop()), !m_frame->document()->printing(), size == contentsSize()); 491 492 setContentsSize(size); 493 } 494 495 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode) 496 { 497 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats 498 // overflow:hidden and overflow:scroll on <body> as applying to the document's 499 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should 500 // use the root element. 501 switch (o->style()->overflowX()) { 502 case OHIDDEN: 503 hMode = ScrollbarAlwaysOff; 504 break; 505 case OSCROLL: 506 hMode = ScrollbarAlwaysOn; 507 break; 508 case OAUTO: 509 hMode = ScrollbarAuto; 510 break; 511 default: 512 // Don't set it at all. 513 ; 514 } 515 516 switch (o->style()->overflowY()) { 517 case OHIDDEN: 518 vMode = ScrollbarAlwaysOff; 519 break; 520 case OSCROLL: 521 vMode = ScrollbarAlwaysOn; 522 break; 523 case OAUTO: 524 vMode = ScrollbarAuto; 525 break; 526 default: 527 // Don't set it at all. 528 ; 529 } 530 531 m_viewportRenderer = o; 532 } 533 534 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode) 535 { 536 m_viewportRenderer = 0; 537 538 const HTMLFrameOwnerElement* owner = m_frame->ownerElement(); 539 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) { 540 hMode = ScrollbarAlwaysOff; 541 vMode = ScrollbarAlwaysOff; 542 return; 543 } 544 545 if (m_canHaveScrollbars) { 546 hMode = ScrollbarAuto; 547 vMode = ScrollbarAuto; 548 } else { 549 hMode = ScrollbarAlwaysOff; 550 vMode = ScrollbarAlwaysOff; 551 } 552 553 if (!m_layoutRoot) { 554 Document* document = m_frame->document(); 555 Node* documentElement = document->documentElement(); 556 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0; 557 Node* body = document->body(); 558 if (body && body->renderer()) { 559 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) { 560 vMode = ScrollbarAlwaysOff; 561 hMode = ScrollbarAlwaysOff; 562 } else if (body->hasTagName(bodyTag)) { 563 // It's sufficient to just check the X overflow, 564 // since it's illegal to have visible in only one direction. 565 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer; 566 applyOverflowToViewport(o, hMode, vMode); 567 } 568 } else if (rootRenderer) { 569 #if ENABLE(SVG) 570 if (!documentElement->isSVGElement()) 571 applyOverflowToViewport(rootRenderer, hMode, vMode); 572 #else 573 applyOverflowToViewport(rootRenderer, hMode, vMode); 574 #endif 575 } 576 } 577 } 578 579 #if ENABLE(FULLSCREEN_API) && USE(ACCELERATED_COMPOSITING) 580 static bool isDocumentRunningFullScreenAnimation(Document* document) 581 { 582 return document->webkitIsFullScreen() && document->fullScreenRenderer() && document->fullScreenRenderer()->isAnimating(); 583 } 584 #endif 585 586 #if USE(ACCELERATED_COMPOSITING) 587 void FrameView::updateCompositingLayers() 588 { 589 RenderView* view = m_frame->contentRenderer(); 590 if (!view) 591 return; 592 593 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref 594 view->compositor()->cacheAcceleratedCompositingFlags(); 595 view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange); 596 597 #if ENABLE(FULLSCREEN_API) 598 Document* document = m_frame->document(); 599 if (isDocumentRunningFullScreenAnimation(document)) 600 view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange, document->fullScreenRenderer()->layer()); 601 #endif 602 } 603 604 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const 605 { 606 RenderView* view = m_frame->contentRenderer(); 607 if (!view) 608 return 0; 609 return view->compositor()->layerForHorizontalScrollbar(); 610 } 611 612 GraphicsLayer* FrameView::layerForVerticalScrollbar() const 613 { 614 RenderView* view = m_frame->contentRenderer(); 615 if (!view) 616 return 0; 617 return view->compositor()->layerForVerticalScrollbar(); 618 } 619 620 GraphicsLayer* FrameView::layerForScrollCorner() const 621 { 622 RenderView* view = m_frame->contentRenderer(); 623 if (!view) 624 return 0; 625 return view->compositor()->layerForScrollCorner(); 626 } 627 628 bool FrameView::syncCompositingStateForThisFrame() 629 { 630 ASSERT(m_frame->view() == this); 631 RenderView* view = m_frame->contentRenderer(); 632 if (!view) 633 return true; // We don't want to keep trying to update layers if we have no renderer. 634 635 // If we sync compositing layers when a layout is pending, we may cause painting of compositing 636 // layer content to occur before layout has happened, which will cause paintContents() to bail. 637 if (needsLayout()) 638 return false; 639 640 if (GraphicsLayer* graphicsLayer = view->compositor()->layerForHorizontalScrollbar()) 641 graphicsLayer->syncCompositingStateForThisLayerOnly(); 642 if (GraphicsLayer* graphicsLayer = view->compositor()->layerForVerticalScrollbar()) 643 graphicsLayer->syncCompositingStateForThisLayerOnly(); 644 if (GraphicsLayer* graphicsLayer = view->compositor()->layerForScrollCorner()) 645 graphicsLayer->syncCompositingStateForThisLayerOnly(); 646 647 view->compositor()->flushPendingLayerChanges(); 648 649 #if ENABLE(FULLSCREEN_API) 650 // The fullScreenRenderer's graphicsLayer has been re-parented, and the above recursive syncCompositingState 651 // call will not cause the subtree under it to repaint. Explicitly call the syncCompositingState on 652 // the fullScreenRenderer's graphicsLayer here: 653 Document* document = m_frame->document(); 654 if (isDocumentRunningFullScreenAnimation(document)) { 655 #if PLATFORM(ANDROID) 656 // We don't create an extra layer for the full screen video. 657 if (!document->fullScreenRenderer()->layer() 658 || !document->fullScreenRenderer()->layer()->backing()) 659 return true; 660 #endif 661 RenderLayerBacking* backing = document->fullScreenRenderer()->layer()->backing(); 662 if (GraphicsLayer* fullScreenLayer = backing->graphicsLayer()) 663 fullScreenLayer->syncCompositingState(); 664 } 665 #endif 666 return true; 667 } 668 669 void FrameView::setNeedsOneShotDrawingSynchronization() 670 { 671 Page* page = frame() ? frame()->page() : 0; 672 if (page) 673 page->chrome()->client()->setNeedsOneShotDrawingSynchronization(); 674 } 675 676 #endif // USE(ACCELERATED_COMPOSITING) 677 678 bool FrameView::hasCompositedContent() const 679 { 680 #if USE(ACCELERATED_COMPOSITING) 681 if (RenderView* view = m_frame->contentRenderer()) 682 return view->compositor()->inCompositingMode(); 683 #endif 684 return false; 685 } 686 687 bool FrameView::hasCompositedContentIncludingDescendants() const 688 { 689 #if USE(ACCELERATED_COMPOSITING) 690 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 691 RenderView* renderView = frame->contentRenderer(); 692 RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0; 693 if (compositor) { 694 if (compositor->inCompositingMode()) 695 return true; 696 697 if (!RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) 698 break; 699 } 700 } 701 #endif 702 return false; 703 } 704 705 bool FrameView::hasCompositingAncestor() const 706 { 707 #if USE(ACCELERATED_COMPOSITING) 708 for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) { 709 if (FrameView* view = frame->view()) { 710 if (view->hasCompositedContent()) 711 return true; 712 } 713 } 714 #endif 715 return false; 716 } 717 718 // Sometimes (for plug-ins) we need to eagerly go into compositing mode. 719 void FrameView::enterCompositingMode() 720 { 721 #if USE(ACCELERATED_COMPOSITING) 722 if (RenderView* view = m_frame->contentRenderer()) { 723 view->compositor()->enableCompositingMode(); 724 if (!needsLayout()) 725 view->compositor()->scheduleCompositingLayerUpdate(); 726 } 727 #endif 728 } 729 730 bool FrameView::isEnclosedInCompositingLayer() const 731 { 732 #if USE(ACCELERATED_COMPOSITING) 733 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer(); 734 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint()) 735 return true; 736 737 if (FrameView* parentView = parentFrameView()) 738 return parentView->isEnclosedInCompositingLayer(); 739 #endif 740 return false; 741 } 742 743 bool FrameView::syncCompositingStateIncludingSubframes() 744 { 745 #if USE(ACCELERATED_COMPOSITING) 746 bool allFramesSynced = syncCompositingStateForThisFrame(); 747 748 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame.get())) { 749 bool synced = child->view()->syncCompositingStateForThisFrame(); 750 allFramesSynced &= synced; 751 } 752 return allFramesSynced; 753 #else // USE(ACCELERATED_COMPOSITING) 754 return true; 755 #endif 756 } 757 758 bool FrameView::isSoftwareRenderable() const 759 { 760 #if USE(ACCELERATED_COMPOSITING) 761 RenderView* view = m_frame->contentRenderer(); 762 if (!view) 763 return true; 764 765 return !view->compositor()->has3DContent(); 766 #else 767 return true; 768 #endif 769 } 770 771 void FrameView::didMoveOnscreen() 772 { 773 RenderView* view = m_frame->contentRenderer(); 774 if (view) 775 view->didMoveOnscreen(); 776 scrollAnimator()->contentAreaDidShow(); 777 } 778 779 void FrameView::willMoveOffscreen() 780 { 781 RenderView* view = m_frame->contentRenderer(); 782 if (view) 783 view->willMoveOffscreen(); 784 scrollAnimator()->contentAreaDidHide(); 785 } 786 787 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const 788 { 789 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot; 790 } 791 792 void FrameView::layout(bool allowSubtree) 793 { 794 if (m_inLayout) 795 return; 796 797 bool inSubframeLayoutWithFrameFlattening = parent() && m_frame->settings() && m_frame->settings()->frameFlatteningEnabled(); 798 799 if (inSubframeLayoutWithFrameFlattening) { 800 if (parent()->isFrameView()) { 801 FrameView* parentView = static_cast<FrameView*>(parent()); 802 if (!parentView->m_nestedLayoutCount) { 803 while (parentView->parent() && parentView->parent()->isFrameView()) 804 parentView = static_cast<FrameView*>(parentView->parent()); 805 parentView->layout(allowSubtree); 806 return; 807 } 808 } 809 } 810 811 m_layoutTimer.stop(); 812 m_delayedLayout = false; 813 m_setNeedsLayoutWasDeferred = false; 814 815 // Protect the view from being deleted during layout (in recalcStyle) 816 RefPtr<FrameView> protector(this); 817 818 if (!m_frame) { 819 // FIXME: Do we need to set m_size.width here? 820 // FIXME: Should we set m_size.height here too? 821 m_size.setWidth(layoutWidth()); 822 return; 823 } 824 825 // we shouldn't enter layout() while painting 826 ASSERT(!isPainting()); 827 if (isPainting()) 828 return; 829 830 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get()); 831 832 if (!allowSubtree && m_layoutRoot) { 833 m_layoutRoot->markContainingBlocksForLayout(false); 834 m_layoutRoot = 0; 835 } 836 837 ASSERT(m_frame->view() == this); 838 839 Document* document = m_frame->document(); 840 841 m_layoutSchedulingEnabled = false; 842 843 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_hasPendingPostLayoutTasks && !inSubframeLayoutWithFrameFlattening) { 844 // This is a new top-level layout. If there are any remaining tasks from the previous 845 // layout, finish them now. 846 m_inSynchronousPostLayout = true; 847 m_postLayoutTasksTimer.stop(); 848 performPostLayoutTasks(); 849 m_inSynchronousPostLayout = false; 850 } 851 852 // Viewport-dependent media queries may cause us to need completely different style information. 853 // Check that here. 854 if (document->styleSelector()->affectedByViewportChange()) 855 document->styleSelectorChanged(RecalcStyleImmediately); 856 857 // Always ensure our style info is up-to-date. This can happen in situations where 858 // the layout beats any sort of style recalc update that needs to occur. 859 document->updateStyleIfNeeded(); 860 861 bool subtree = m_layoutRoot; 862 863 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit, 864 // so there's no point to continuing to layout 865 if (protector->hasOneRef()) 866 return; 867 868 RenderObject* root = subtree ? m_layoutRoot : document->renderer(); 869 if (!root) { 870 // FIXME: Do we need to set m_size here? 871 m_layoutSchedulingEnabled = true; 872 return; 873 } 874 875 #ifdef ANDROID_INSTRUMENT 876 if (!m_frame->tree() || !m_frame->tree()->parent()) 877 android::TimeCounter::start(android::TimeCounter::LayoutTimeCounter); 878 #endif 879 880 m_nestedLayoutCount++; 881 882 if (!m_layoutRoot) { 883 Document* document = m_frame->document(); 884 Node* documentElement = document->documentElement(); 885 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0; 886 Node* body = document->body(); 887 if (body && body->renderer()) { 888 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) { 889 body->renderer()->setChildNeedsLayout(true); 890 } else if (body->hasTagName(bodyTag)) { 891 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport()) 892 body->renderer()->setChildNeedsLayout(true); 893 } 894 } else if (rootRenderer) { 895 #if ENABLE(SVG) 896 if (documentElement->isSVGElement()) { 897 if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight())) 898 rootRenderer->setChildNeedsLayout(true); 899 } 900 #endif 901 } 902 903 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 904 if (m_firstLayout && !m_frame->ownerElement()) 905 printf("Elapsed time before first layout: %d\n", document->elapsedTime()); 906 #endif 907 } 908 909 ScrollbarMode hMode; 910 ScrollbarMode vMode; 911 calculateScrollbarModesForLayout(hMode, vMode); 912 913 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing()); 914 915 if (!subtree) { 916 // Now set our scrollbar state for the layout. 917 ScrollbarMode currentHMode = horizontalScrollbarMode(); 918 ScrollbarMode currentVMode = verticalScrollbarMode(); 919 920 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) { 921 if (m_firstLayout) { 922 setScrollbarsSuppressed(true); 923 924 m_firstLayout = false; 925 m_firstLayoutCallbackPending = true; 926 m_lastLayoutSize = IntSize(width(), height()); 927 m_lastZoomFactor = root->style()->zoom(); 928 929 // Set the initial vMode to AlwaysOn if we're auto. 930 if (vMode == ScrollbarAuto) 931 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear. 932 // Set the initial hMode to AlwaysOff if we're auto. 933 if (hMode == ScrollbarAuto) 934 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear. 935 936 setScrollbarModes(hMode, vMode); 937 setScrollbarsSuppressed(false, true); 938 } else 939 setScrollbarModes(hMode, vMode); 940 } 941 942 IntSize oldSize = m_size; 943 944 m_size = IntSize(layoutWidth(), layoutHeight()); 945 946 if (oldSize != m_size) { 947 m_doFullRepaint = true; 948 if (!m_firstLayout) { 949 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0; 950 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0; 951 if (bodyRenderer && bodyRenderer->stretchesToViewport()) 952 bodyRenderer->setChildNeedsLayout(true); 953 else if (rootRenderer && rootRenderer->stretchesToViewport()) 954 rootRenderer->setChildNeedsLayout(true); 955 } 956 } 957 } 958 959 RenderLayer* layer = root->enclosingLayer(); 960 961 m_actionScheduler->pause(); 962 963 bool disableLayoutState = false; 964 if (subtree) { 965 RenderView* view = root->view(); 966 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root); 967 view->pushLayoutState(root); 968 if (disableLayoutState) 969 view->disableLayoutState(); 970 } 971 972 m_inLayout = true; 973 beginDeferredRepaints(); 974 root->layout(); 975 endDeferredRepaints(); 976 m_inLayout = false; 977 978 if (subtree) { 979 RenderView* view = root->view(); 980 view->popLayoutState(root); 981 if (disableLayoutState) 982 view->enableLayoutState(); 983 } 984 m_layoutRoot = 0; 985 986 m_layoutSchedulingEnabled = true; 987 988 if (!subtree && !toRenderView(root)->printing()) 989 adjustViewSize(); 990 991 // Now update the positions of all layers. 992 beginDeferredRepaints(); 993 IntPoint cachedOffset; 994 if (m_doFullRepaint) 995 root->view()->repaint(); // FIXME: This isn't really right, since the RenderView doesn't fully encompass the visibleContentRect(). It just happens 996 // to work out most of the time, since first layouts and printing don't have you scrolled anywhere. 997 layer->updateLayerPositions((m_doFullRepaint ? 0 : RenderLayer::CheckForRepaint) 998 | RenderLayer::IsCompositingUpdateRoot 999 | RenderLayer::UpdateCompositingLayers, 1000 subtree ? 0 : &cachedOffset); 1001 endDeferredRepaints(); 1002 1003 #if USE(ACCELERATED_COMPOSITING) 1004 updateCompositingLayers(); 1005 #endif 1006 1007 m_layoutCount++; 1008 1009 #if PLATFORM(MAC) || PLATFORM(CHROMIUM) 1010 if (AXObjectCache::accessibilityEnabled()) 1011 root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true); 1012 #endif 1013 #if ENABLE(DASHBOARD_SUPPORT) 1014 updateDashboardRegions(); 1015 #endif 1016 1017 #ifdef ANDROID_INSTRUMENT 1018 if (!m_frame->tree()->parent()) 1019 android::TimeCounter::record(android::TimeCounter::LayoutTimeCounter, __FUNCTION__); 1020 #endif 1021 ASSERT(!root->needsLayout()); 1022 1023 updateCanBlitOnScrollRecursively(); 1024 1025 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER)) 1026 updateOverflowStatus(layoutWidth() < contentsWidth(), 1027 layoutHeight() < contentsHeight()); 1028 1029 if (!m_hasPendingPostLayoutTasks) { 1030 if (!m_inSynchronousPostLayout && !inSubframeLayoutWithFrameFlattening) { 1031 m_inSynchronousPostLayout = true; 1032 // Calls resumeScheduledEvents() 1033 performPostLayoutTasks(); 1034 m_inSynchronousPostLayout = false; 1035 } 1036 1037 if (!m_hasPendingPostLayoutTasks && (needsLayout() || m_inSynchronousPostLayout || inSubframeLayoutWithFrameFlattening)) { 1038 // If we need layout or are already in a synchronous call to postLayoutTasks(), 1039 // defer widget updates and event dispatch until after we return. postLayoutTasks() 1040 // can make us need to update again, and we can get stuck in a nasty cycle unless 1041 // we call it through the timer here. 1042 m_hasPendingPostLayoutTasks = true; 1043 m_postLayoutTasksTimer.startOneShot(0); 1044 if (needsLayout()) { 1045 m_actionScheduler->pause(); 1046 layout(); 1047 } 1048 } 1049 } else { 1050 m_actionScheduler->resume(); 1051 } 1052 1053 InspectorInstrumentation::didLayout(cookie); 1054 1055 m_nestedLayoutCount--; 1056 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 1057 // Reset to false each time we layout in case the overflow status changed. 1058 bool hasOverflowScroll = false; 1059 RenderObject* ownerRenderer = m_frame->ownerRenderer(); 1060 if (ownerRenderer && ownerRenderer->isRenderIFrame()) { 1061 RenderLayer* layer = ownerRenderer->enclosingLayer(); 1062 if (layer) { 1063 // Some sites use tiny iframes for loading so don't composite those. 1064 if (canHaveScrollbars() && layoutWidth() > 1 && layoutHeight() > 1) 1065 hasOverflowScroll = layoutWidth() < contentsWidth() || layoutHeight() < contentsHeight(); 1066 } 1067 } 1068 if (RenderView* view = m_frame->contentRenderer()) { 1069 if (hasOverflowScroll != m_hasOverflowScroll) { 1070 if (hasOverflowScroll) 1071 enterCompositingMode(); 1072 else 1073 // We are leaving overflow mode so we need to update the layer 1074 // tree in case that is the reason we were composited. 1075 view->compositor()->scheduleCompositingLayerUpdate(); 1076 } 1077 } 1078 m_hasOverflowScroll = hasOverflowScroll; 1079 #endif 1080 } 1081 1082 void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object) 1083 { 1084 if (!m_widgetUpdateSet) 1085 m_widgetUpdateSet.set(new RenderEmbeddedObjectSet); 1086 1087 m_widgetUpdateSet->add(object); 1088 } 1089 1090 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object) 1091 { 1092 if (!m_widgetUpdateSet) 1093 return; 1094 1095 m_widgetUpdateSet->remove(object); 1096 } 1097 1098 void FrameView::setMediaType(const String& mediaType) 1099 { 1100 m_mediaType = mediaType; 1101 } 1102 1103 String FrameView::mediaType() const 1104 { 1105 // See if we have an override type. 1106 String overrideType = m_frame->loader()->client()->overrideMediaType(); 1107 if (!overrideType.isNull()) 1108 return overrideType; 1109 return m_mediaType; 1110 } 1111 1112 void FrameView::adjustMediaTypeForPrinting(bool printing) 1113 { 1114 if (printing) { 1115 if (m_mediaTypeWhenNotPrinting.isNull()) 1116 m_mediaTypeWhenNotPrinting = mediaType(); 1117 setMediaType("print"); 1118 } else { 1119 if (!m_mediaTypeWhenNotPrinting.isNull()) 1120 setMediaType(m_mediaTypeWhenNotPrinting); 1121 m_mediaTypeWhenNotPrinting = String(); 1122 } 1123 } 1124 1125 bool FrameView::useSlowRepaints() const 1126 { 1127 if (m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || m_isOverlapped || !m_contentIsOpaque) 1128 return true; 1129 1130 if (FrameView* parentView = parentFrameView()) 1131 return parentView->useSlowRepaints(); 1132 1133 return false; 1134 } 1135 1136 bool FrameView::useSlowRepaintsIfNotOverlapped() const 1137 { 1138 if (m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || !m_contentIsOpaque) 1139 return true; 1140 1141 if (FrameView* parentView = parentFrameView()) 1142 return parentView->useSlowRepaintsIfNotOverlapped(); 1143 1144 return false; 1145 } 1146 1147 void FrameView::updateCanBlitOnScrollRecursively() 1148 { 1149 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 1150 if (FrameView* view = frame->view()) 1151 view->setCanBlitOnScroll(!view->useSlowRepaints()); 1152 } 1153 } 1154 1155 void FrameView::setUseSlowRepaints() 1156 { 1157 m_useSlowRepaints = true; 1158 updateCanBlitOnScrollRecursively(); 1159 } 1160 1161 void FrameView::addSlowRepaintObject() 1162 { 1163 if (!m_slowRepaintObjectCount) 1164 updateCanBlitOnScrollRecursively(); 1165 m_slowRepaintObjectCount++; 1166 } 1167 1168 void FrameView::removeSlowRepaintObject() 1169 { 1170 ASSERT(m_slowRepaintObjectCount > 0); 1171 m_slowRepaintObjectCount--; 1172 if (!m_slowRepaintObjectCount) 1173 updateCanBlitOnScrollRecursively(); 1174 } 1175 1176 void FrameView::addFixedObject() 1177 { 1178 if (!m_fixedObjectCount && platformWidget()) 1179 updateCanBlitOnScrollRecursively(); 1180 ++m_fixedObjectCount; 1181 } 1182 1183 void FrameView::removeFixedObject() 1184 { 1185 ASSERT(m_fixedObjectCount > 0); 1186 --m_fixedObjectCount; 1187 if (!m_fixedObjectCount) 1188 updateCanBlitOnScrollRecursively(); 1189 } 1190 1191 #if PLATFORM(ANDROID) 1192 // When the screen size change, fixed positioned element should be updated. 1193 void FrameView::updatePositionedObjects() 1194 { 1195 RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0; 1196 if (RenderView* root = m_frame->contentRenderer()) 1197 positionedObjects = root->positionedObjects(); 1198 1199 if (!positionedObjects || positionedObjects->isEmpty()) 1200 return; 1201 1202 RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end(); 1203 for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) { 1204 RenderBox* renderBox = *it; 1205 if (renderBox->style()->position() != FixedPosition) 1206 continue; 1207 1208 renderBox->computeLogicalWidth(); 1209 renderBox->computeLogicalHeight(); 1210 } 1211 } 1212 #endif 1213 1214 int FrameView::scrollXForFixedPosition() const 1215 { 1216 int visibleContentWidth = visibleContentRect().width(); 1217 int maxX = contentsWidth() - visibleContentWidth; 1218 1219 if (maxX == 0) 1220 return 0; 1221 1222 int x = scrollX(); 1223 1224 if (x < 0) 1225 x = 0; 1226 else if (x > maxX) 1227 x = maxX; 1228 1229 if (!m_frame) 1230 return x; 1231 1232 float pageScaleFactor = m_frame->pageScaleFactor(); 1233 1234 // When the page is scaled, the scaled "viewport" with respect to which fixed object are positioned 1235 // doesn't move as fast as the content view, so that when the content is scrolled all the way to the 1236 // end, the bottom of the scaled "viewport" touches the bottom of the real viewport. 1237 float dragFactor = (contentsWidth() - visibleContentWidth * pageScaleFactor) / maxX; 1238 1239 return x * dragFactor / pageScaleFactor; 1240 } 1241 1242 int FrameView::scrollYForFixedPosition() const 1243 { 1244 int visibleContentHeight = visibleContentRect().height(); 1245 1246 int maxY = contentsHeight() - visibleContentHeight; 1247 if (maxY == 0) 1248 return 0; 1249 1250 int y = scrollY(); 1251 1252 if (y < 0) 1253 y = 0; 1254 else if (y > maxY) 1255 y = maxY; 1256 1257 if (!m_frame) 1258 return y; 1259 1260 float pageScaleFactor = m_frame->pageScaleFactor(); 1261 float dragFactor = (contentsHeight() - visibleContentHeight * pageScaleFactor) / maxY; 1262 1263 return y * dragFactor / pageScaleFactor; 1264 } 1265 1266 IntSize FrameView::scrollOffsetForFixedPosition() const 1267 { 1268 return IntSize(scrollXForFixedPosition(), scrollYForFixedPosition()); 1269 } 1270 1271 IntPoint FrameView::currentMousePosition() const 1272 { 1273 return m_frame ? m_frame->eventHandler()->currentMousePosition() : IntPoint(); 1274 } 1275 1276 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) 1277 { 1278 const size_t fixedObjectThreshold = 5; 1279 1280 RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0; 1281 if (RenderView* root = m_frame->contentRenderer()) 1282 positionedObjects = root->positionedObjects(); 1283 1284 if (!positionedObjects || positionedObjects->isEmpty()) { 1285 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect); 1286 return true; 1287 } 1288 1289 // Get the rects of the fixed objects visible in the rectToScroll 1290 Vector<IntRect, fixedObjectThreshold> subRectToUpdate; 1291 bool updateInvalidatedSubRect = true; 1292 RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end(); 1293 for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) { 1294 RenderBox* renderBox = *it; 1295 if (renderBox->style()->position() != FixedPosition) 1296 continue; 1297 IntRect updateRect = renderBox->layer()->repaintRectIncludingDescendants(); 1298 updateRect = contentsToWindow(updateRect); 1299 if (clipsRepaints()) 1300 updateRect.intersect(rectToScroll); 1301 if (!updateRect.isEmpty()) { 1302 if (subRectToUpdate.size() >= fixedObjectThreshold) { 1303 updateInvalidatedSubRect = false; 1304 break; 1305 } 1306 subRectToUpdate.append(updateRect); 1307 } 1308 } 1309 1310 // Scroll the view 1311 if (updateInvalidatedSubRect) { 1312 // 1) scroll 1313 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect); 1314 1315 // 2) update the area of fixed objects that has been invalidated 1316 size_t fixObjectsCount = subRectToUpdate.size(); 1317 for (size_t i = 0; i < fixObjectsCount; ++i) { 1318 IntRect updateRect = subRectToUpdate[i]; 1319 IntRect scrolledRect = updateRect; 1320 scrolledRect.move(scrollDelta); 1321 updateRect.unite(scrolledRect); 1322 if (clipsRepaints()) 1323 updateRect.intersect(rectToScroll); 1324 hostWindow()->invalidateContentsAndWindow(updateRect, false); 1325 } 1326 return true; 1327 } 1328 1329 // the number of fixed objects exceed the threshold, we cannot use the fast path 1330 return false; 1331 } 1332 1333 void FrameView::scrollContentsSlowPath(const IntRect& updateRect) 1334 { 1335 #if USE(ACCELERATED_COMPOSITING) 1336 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) { 1337 if (frameRenderer->containerForRepaint()) { 1338 IntRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(), 1339 frameRenderer->borderTop() + frameRenderer->paddingTop(), 1340 visibleWidth(), visibleHeight()); 1341 frameRenderer->repaintRectangle(rect); 1342 return; 1343 } 1344 } 1345 #endif 1346 1347 ScrollView::scrollContentsSlowPath(updateRect); 1348 } 1349 1350 // Note that this gets called at painting time. 1351 void FrameView::setIsOverlapped(bool isOverlapped) 1352 { 1353 if (isOverlapped == m_isOverlapped) 1354 return; 1355 1356 m_isOverlapped = isOverlapped; 1357 updateCanBlitOnScrollRecursively(); 1358 1359 #if USE(ACCELERATED_COMPOSITING) 1360 if (hasCompositedContentIncludingDescendants()) { 1361 // Overlap can affect compositing tests, so if it changes, we need to trigger 1362 // a layer update in the parent document. 1363 if (Frame* parentFrame = m_frame->tree()->parent()) { 1364 if (RenderView* parentView = parentFrame->contentRenderer()) { 1365 RenderLayerCompositor* compositor = parentView->compositor(); 1366 compositor->setCompositingLayersNeedRebuild(); 1367 compositor->scheduleCompositingLayerUpdate(); 1368 } 1369 } 1370 1371 if (RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) { 1372 // We also need to trigger reevaluation for this and all descendant frames, 1373 // since a frame uses compositing if any ancestor is compositing. 1374 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 1375 if (RenderView* view = frame->contentRenderer()) { 1376 RenderLayerCompositor* compositor = view->compositor(); 1377 compositor->setCompositingLayersNeedRebuild(); 1378 compositor->scheduleCompositingLayerUpdate(); 1379 } 1380 } 1381 } 1382 } 1383 #endif 1384 } 1385 1386 bool FrameView::isOverlappedIncludingAncestors() const 1387 { 1388 if (isOverlapped()) 1389 return true; 1390 1391 if (FrameView* parentView = parentFrameView()) { 1392 if (parentView->isOverlapped()) 1393 return true; 1394 } 1395 1396 return false; 1397 } 1398 1399 void FrameView::setContentIsOpaque(bool contentIsOpaque) 1400 { 1401 if (contentIsOpaque == m_contentIsOpaque) 1402 return; 1403 1404 m_contentIsOpaque = contentIsOpaque; 1405 updateCanBlitOnScrollRecursively(); 1406 } 1407 1408 void FrameView::restoreScrollbar() 1409 { 1410 setScrollbarsSuppressed(false); 1411 } 1412 1413 bool FrameView::scrollToFragment(const KURL& url) 1414 { 1415 // If our URL has no ref, then we have no place we need to jump to. 1416 // OTOH If CSS target was set previously, we want to set it to 0, recalc 1417 // and possibly repaint because :target pseudo class may have been 1418 // set (see bug 11321). 1419 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget()) 1420 return false; 1421 1422 String fragmentIdentifier = url.fragmentIdentifier(); 1423 if (scrollToAnchor(fragmentIdentifier)) 1424 return true; 1425 1426 // Try again after decoding the ref, based on the document's encoding. 1427 if (TextResourceDecoder* decoder = m_frame->document()->decoder()) 1428 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding())); 1429 1430 return false; 1431 } 1432 1433 bool FrameView::scrollToAnchor(const String& name) 1434 { 1435 ASSERT(m_frame->document()); 1436 1437 if (!m_frame->document()->haveStylesheetsLoaded()) { 1438 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true); 1439 return false; 1440 } 1441 1442 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false); 1443 1444 Element* anchorNode = m_frame->document()->findAnchor(name); 1445 1446 #if ENABLE(SVG) 1447 if (m_frame->document()->isSVGDocument()) { 1448 if (name.startsWith("xpointer(")) { 1449 // We need to parse the xpointer reference here 1450 } else if (name.startsWith("svgView(")) { 1451 RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement(); 1452 if (!svg->currentView()->parseViewSpec(name)) 1453 return false; 1454 svg->setUseCurrentView(true); 1455 } else { 1456 if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) { 1457 RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0; 1458 if (viewElement.get()) { 1459 SVGElement* element = SVGLocatable::nearestViewportElement(viewElement.get()); 1460 if (element->hasTagName(SVGNames::svgTag)) { 1461 RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(element); 1462 svg->inheritViewAttributes(viewElement.get()); 1463 } 1464 } 1465 } 1466 } 1467 // FIXME: need to decide which <svg> to focus on, and zoom to that one 1468 // FIXME: need to actually "highlight" the viewTarget(s) 1469 } 1470 #endif 1471 1472 m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target. 1473 1474 // Implement the rule that "" and "top" both mean top of page as in other browsers. 1475 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top"))) 1476 return false; 1477 1478 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document()); 1479 return true; 1480 } 1481 1482 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode) 1483 { 1484 m_maintainScrollPositionAnchor = anchorNode; 1485 if (!m_maintainScrollPositionAnchor) 1486 return; 1487 1488 // We need to update the layout before scrolling, otherwise we could 1489 // really mess things up if an anchor scroll comes at a bad moment. 1490 m_frame->document()->updateStyleIfNeeded(); 1491 // Only do a layout if changes have occurred that make it necessary. 1492 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) 1493 layout(); 1494 else 1495 scrollToAnchor(); 1496 } 1497 1498 void FrameView::setScrollPosition(const IntPoint& scrollPoint) 1499 { 1500 bool wasInProgrammaticScroll = m_inProgrammaticScroll; 1501 m_inProgrammaticScroll = true; 1502 m_maintainScrollPositionAnchor = 0; 1503 ScrollView::setScrollPosition(scrollPoint); 1504 m_inProgrammaticScroll = wasInProgrammaticScroll; 1505 } 1506 1507 void FrameView::scrollPositionChangedViaPlatformWidget() 1508 { 1509 repaintFixedElementsAfterScrolling(); 1510 scrollPositionChanged(); 1511 } 1512 1513 void FrameView::scrollPositionChanged() 1514 { 1515 frame()->eventHandler()->sendScrollEvent(); 1516 1517 #if USE(ACCELERATED_COMPOSITING) 1518 if (RenderView* root = m_frame->contentRenderer()) { 1519 if (root->usesCompositing()) 1520 root->compositor()->frameViewDidScroll(scrollPosition()); 1521 } 1522 #endif 1523 } 1524 1525 void FrameView::repaintFixedElementsAfterScrolling() 1526 { 1527 // For fixed position elements, update widget positions and compositing layers after scrolling, 1528 // but only if we're not inside of layout. 1529 if (!m_nestedLayoutCount && hasFixedObjects()) { 1530 if (RenderView* root = m_frame->contentRenderer()) { 1531 root->updateWidgetPositions(); 1532 root->layer()->updateRepaintRectsAfterScroll(); 1533 #if USE(ACCELERATED_COMPOSITING) 1534 root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll); 1535 #endif 1536 } 1537 } 1538 } 1539 1540 HostWindow* FrameView::hostWindow() const 1541 { 1542 Page* page = frame() ? frame()->page() : 0; 1543 if (!page) 1544 return 0; 1545 return page->chrome(); 1546 } 1547 1548 const unsigned cRepaintRectUnionThreshold = 25; 1549 1550 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate) 1551 { 1552 ASSERT(!m_frame->ownerElement()); 1553 1554 double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay(); 1555 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) { 1556 IntRect paintRect = r; 1557 if (clipsRepaints() && !paintsEntireContents()) 1558 paintRect.intersect(visibleContentRect()); 1559 #ifdef ANDROID_CAPTURE_OFFSCREEN_PAINTS 1560 if (r != paintRect) 1561 ScrollView::platformOffscreenContentRectangle(visibleContentRect(), r); 1562 #endif 1563 if (paintRect.isEmpty()) 1564 return; 1565 if (m_repaintCount == cRepaintRectUnionThreshold) { 1566 IntRect unionedRect; 1567 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i) 1568 unionedRect.unite(m_repaintRects[i]); 1569 m_repaintRects.clear(); 1570 m_repaintRects.append(unionedRect); 1571 } 1572 if (m_repaintCount < cRepaintRectUnionThreshold) 1573 m_repaintRects.append(paintRect); 1574 else 1575 m_repaintRects[0].unite(paintRect); 1576 m_repaintCount++; 1577 1578 if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive()) 1579 m_deferredRepaintTimer.startOneShot(delay); 1580 return; 1581 } 1582 1583 if (!shouldUpdate(immediate)) 1584 return; 1585 1586 #if ENABLE(TILED_BACKING_STORE) 1587 if (frame()->tiledBackingStore()) { 1588 frame()->tiledBackingStore()->invalidate(r); 1589 return; 1590 } 1591 #endif 1592 ScrollView::repaintContentRectangle(r, immediate); 1593 } 1594 1595 void FrameView::contentsResized() 1596 { 1597 scrollAnimator()->contentsResized(); 1598 setNeedsLayout(); 1599 } 1600 1601 void FrameView::visibleContentsResized() 1602 { 1603 // We check to make sure the view is attached to a frame() as this method can 1604 // be triggered before the view is attached by Frame::createView(...) setting 1605 // various values such as setScrollBarModes(...) for example. An ASSERT is 1606 // triggered when a view is layout before being attached to a frame(). 1607 if (!frame()->view()) 1608 return; 1609 1610 if (needsLayout()) 1611 layout(); 1612 1613 #if USE(ACCELERATED_COMPOSITING) 1614 if (RenderView* root = m_frame->contentRenderer()) { 1615 if (root->usesCompositing()) 1616 root->compositor()->frameViewDidChangeSize(); 1617 } 1618 #endif 1619 } 1620 1621 void FrameView::beginDeferredRepaints() 1622 { 1623 Page* page = m_frame->page(); 1624 if (page->mainFrame() != m_frame) 1625 return page->mainFrame()->view()->beginDeferredRepaints(); 1626 1627 m_deferringRepaints++; 1628 } 1629 1630 1631 void FrameView::endDeferredRepaints() 1632 { 1633 Page* page = m_frame->page(); 1634 if (page->mainFrame() != m_frame) 1635 return page->mainFrame()->view()->endDeferredRepaints(); 1636 1637 ASSERT(m_deferringRepaints > 0); 1638 1639 if (--m_deferringRepaints) 1640 return; 1641 1642 if (m_deferredRepaintTimer.isActive()) 1643 return; 1644 1645 if (double delay = adjustedDeferredRepaintDelay()) { 1646 m_deferredRepaintTimer.startOneShot(delay); 1647 return; 1648 } 1649 1650 doDeferredRepaints(); 1651 } 1652 1653 void FrameView::checkStopDelayingDeferredRepaints() 1654 { 1655 if (!m_deferredRepaintTimer.isActive()) 1656 return; 1657 1658 Document* document = m_frame->document(); 1659 if (document && (document->parsing() || document->cachedResourceLoader()->requestCount())) 1660 return; 1661 1662 m_deferredRepaintTimer.stop(); 1663 1664 doDeferredRepaints(); 1665 } 1666 1667 void FrameView::doDeferredRepaints() 1668 { 1669 ASSERT(!m_deferringRepaints); 1670 if (!shouldUpdate()) { 1671 m_repaintRects.clear(); 1672 m_repaintCount = 0; 1673 return; 1674 } 1675 unsigned size = m_repaintRects.size(); 1676 for (unsigned i = 0; i < size; i++) { 1677 #if ENABLE(TILED_BACKING_STORE) 1678 if (frame()->tiledBackingStore()) { 1679 frame()->tiledBackingStore()->invalidate(m_repaintRects[i]); 1680 continue; 1681 } 1682 #endif 1683 ScrollView::repaintContentRectangle(m_repaintRects[i], false); 1684 } 1685 m_repaintRects.clear(); 1686 m_repaintCount = 0; 1687 1688 updateDeferredRepaintDelay(); 1689 } 1690 1691 void FrameView::updateDeferredRepaintDelay() 1692 { 1693 Document* document = m_frame->document(); 1694 if (!document || (!document->parsing() && !document->cachedResourceLoader()->requestCount())) { 1695 m_deferredRepaintDelay = s_deferredRepaintDelay; 1696 return; 1697 } 1698 if (m_deferredRepaintDelay < s_maxDeferredRepaintDelayDuringLoading) { 1699 m_deferredRepaintDelay += s_deferredRepaintDelayIncrementDuringLoading; 1700 if (m_deferredRepaintDelay > s_maxDeferredRepaintDelayDuringLoading) 1701 m_deferredRepaintDelay = s_maxDeferredRepaintDelayDuringLoading; 1702 } 1703 } 1704 1705 void FrameView::resetDeferredRepaintDelay() 1706 { 1707 m_deferredRepaintDelay = 0; 1708 if (m_deferredRepaintTimer.isActive()) { 1709 m_deferredRepaintTimer.stop(); 1710 if (!m_deferringRepaints) 1711 doDeferredRepaints(); 1712 } 1713 } 1714 1715 double FrameView::adjustedDeferredRepaintDelay() const 1716 { 1717 ASSERT(!m_deferringRepaints); 1718 if (!m_deferredRepaintDelay) 1719 return 0; 1720 double timeSinceLastPaint = currentTime() - m_lastPaintTime; 1721 return max(0., m_deferredRepaintDelay - timeSinceLastPaint); 1722 } 1723 1724 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*) 1725 { 1726 doDeferredRepaints(); 1727 } 1728 1729 void FrameView::layoutTimerFired(Timer<FrameView>*) 1730 { 1731 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1732 if (!m_frame->document()->ownerElement()) 1733 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime()); 1734 #endif 1735 layout(); 1736 } 1737 1738 void FrameView::scheduleRelayout() 1739 { 1740 // FIXME: We should assert the page is not in the page cache, but that is causing 1741 // too many false assertions. See <rdar://problem/7218118>. 1742 ASSERT(m_frame->view() == this); 1743 1744 if (m_layoutRoot) { 1745 m_layoutRoot->markContainingBlocksForLayout(false); 1746 m_layoutRoot = 0; 1747 } 1748 if (!m_layoutSchedulingEnabled) 1749 return; 1750 if (!needsLayout()) 1751 return; 1752 if (!m_frame->document()->shouldScheduleLayout()) 1753 return; 1754 1755 #ifdef ANDROID_FLATTEN_FRAMESET 1756 if (m_frame->ownerRenderer()) 1757 m_frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc(); 1758 #endif 1759 1760 // When frame flattening is enabled, the contents of the frame affects layout of the parent frames. 1761 // Also invalidate parent frame starting from the owner element of this frame. 1762 if (m_frame->settings() && m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) { 1763 if (m_frame->ownerElement()->hasTagName(iframeTag) || m_frame->ownerElement()->hasTagName(frameTag)) 1764 m_frame->ownerRenderer()->setNeedsLayout(true, true); 1765 } 1766 1767 int delay = m_frame->document()->minimumLayoutDelay(); 1768 if (m_layoutTimer.isActive() && m_delayedLayout && !delay) 1769 unscheduleRelayout(); 1770 if (m_layoutTimer.isActive()) 1771 return; 1772 1773 m_delayedLayout = delay != 0; 1774 1775 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1776 if (!m_frame->document()->ownerElement()) 1777 printf("Scheduling layout for %d\n", delay); 1778 #endif 1779 1780 m_layoutTimer.startOneShot(delay * 0.001); 1781 } 1782 1783 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant) 1784 { 1785 for (RenderObject* r = descendant; r; r = r->container()) { 1786 if (r == ancestor) 1787 return true; 1788 } 1789 return false; 1790 } 1791 1792 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot) 1793 { 1794 ASSERT(m_frame->view() == this); 1795 1796 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) { 1797 if (relayoutRoot) 1798 relayoutRoot->markContainingBlocksForLayout(false); 1799 return; 1800 } 1801 1802 if (layoutPending() || !m_layoutSchedulingEnabled) { 1803 if (m_layoutRoot != relayoutRoot) { 1804 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) { 1805 // Keep the current root 1806 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot); 1807 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout()); 1808 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) { 1809 // Re-root at relayoutRoot 1810 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot); 1811 m_layoutRoot = relayoutRoot; 1812 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout()); 1813 } else { 1814 // Just do a full relayout 1815 if (m_layoutRoot) 1816 m_layoutRoot->markContainingBlocksForLayout(false); 1817 m_layoutRoot = 0; 1818 relayoutRoot->markContainingBlocksForLayout(false); 1819 } 1820 } 1821 } else if (m_layoutSchedulingEnabled) { 1822 int delay = m_frame->document()->minimumLayoutDelay(); 1823 m_layoutRoot = relayoutRoot; 1824 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout()); 1825 m_delayedLayout = delay != 0; 1826 m_layoutTimer.startOneShot(delay * 0.001); 1827 } 1828 } 1829 1830 bool FrameView::layoutPending() const 1831 { 1832 return m_layoutTimer.isActive(); 1833 } 1834 1835 bool FrameView::needsLayout() const 1836 { 1837 // This can return true in cases where the document does not have a body yet. 1838 // Document::shouldScheduleLayout takes care of preventing us from scheduling 1839 // layout in that case. 1840 if (!m_frame) 1841 return false; 1842 RenderView* root = m_frame->contentRenderer(); 1843 return layoutPending() 1844 || (root && root->needsLayout()) 1845 || m_layoutRoot 1846 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred); 1847 } 1848 1849 void FrameView::setNeedsLayout() 1850 { 1851 if (m_deferSetNeedsLayouts) { 1852 m_setNeedsLayoutWasDeferred = true; 1853 return; 1854 } 1855 RenderView* root = m_frame->contentRenderer(); 1856 if (root) 1857 root->setNeedsLayout(true); 1858 } 1859 1860 void FrameView::unscheduleRelayout() 1861 { 1862 m_postLayoutTasksTimer.stop(); 1863 1864 if (!m_layoutTimer.isActive()) 1865 return; 1866 1867 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1868 if (!m_frame->document()->ownerElement()) 1869 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime()); 1870 #endif 1871 1872 m_layoutTimer.stop(); 1873 m_delayedLayout = false; 1874 } 1875 1876 #if ENABLE(REQUEST_ANIMATION_FRAME) 1877 void FrameView::serviceScriptedAnimations(DOMTimeStamp time) 1878 { 1879 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext()) 1880 frame->document()->serviceScriptedAnimations(time); 1881 } 1882 #endif 1883 1884 bool FrameView::isTransparent() const 1885 { 1886 return m_isTransparent; 1887 } 1888 1889 void FrameView::setTransparent(bool isTransparent) 1890 { 1891 m_isTransparent = isTransparent; 1892 } 1893 1894 Color FrameView::baseBackgroundColor() const 1895 { 1896 return m_baseBackgroundColor; 1897 } 1898 1899 void FrameView::setBaseBackgroundColor(const Color& backgroundColor) 1900 { 1901 if (!backgroundColor.isValid()) 1902 m_baseBackgroundColor = Color::white; 1903 else 1904 m_baseBackgroundColor = backgroundColor; 1905 } 1906 1907 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent) 1908 { 1909 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 1910 if (FrameView* view = frame->view()) { 1911 view->setTransparent(transparent); 1912 view->setBaseBackgroundColor(backgroundColor); 1913 } 1914 } 1915 } 1916 1917 bool FrameView::shouldUpdateWhileOffscreen() const 1918 { 1919 return m_shouldUpdateWhileOffscreen; 1920 } 1921 1922 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen) 1923 { 1924 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen; 1925 } 1926 1927 bool FrameView::shouldUpdate(bool immediateRequested) const 1928 { 1929 if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen()) 1930 return false; 1931 return true; 1932 } 1933 1934 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget) 1935 { 1936 m_actionScheduler->scheduleEvent(event, eventTarget); 1937 } 1938 1939 void FrameView::pauseScheduledEvents() 1940 { 1941 m_actionScheduler->pause(); 1942 } 1943 1944 void FrameView::resumeScheduledEvents() 1945 { 1946 m_actionScheduler->resume(); 1947 } 1948 1949 void FrameView::scrollToAnchor() 1950 { 1951 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor; 1952 if (!anchorNode) 1953 return; 1954 1955 if (!anchorNode->renderer()) 1956 return; 1957 1958 IntRect rect; 1959 if (anchorNode != m_frame->document()) 1960 rect = anchorNode->getRect(); 1961 1962 // Scroll nested layers and frames to reveal the anchor. 1963 // Align to the top and to the closest side (this matches other browsers). 1964 anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways); 1965 1966 if (AXObjectCache::accessibilityEnabled()) 1967 m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get()); 1968 1969 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor. 1970 m_maintainScrollPositionAnchor = anchorNode; 1971 } 1972 1973 void FrameView::updateWidget(RenderEmbeddedObject* object) 1974 { 1975 ASSERT(!object->node() || object->node()->isElementNode()); 1976 Element* ownerElement = static_cast<Element*>(object->node()); 1977 // The object may have already been destroyed (thus node cleared), 1978 // but FrameView holds a manual ref, so it won't have been deleted. 1979 ASSERT(m_widgetUpdateSet->contains(object)); 1980 if (!ownerElement) 1981 return; 1982 1983 // No need to update if it's already crashed or known to be missing. 1984 if (object->pluginCrashedOrWasMissing()) 1985 return; 1986 1987 // FIXME: This could turn into a real virtual dispatch if we defined 1988 // updateWidget(bool) on HTMLElement. 1989 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag)) 1990 static_cast<HTMLPlugInImageElement*>(ownerElement)->updateWidget(CreateAnyWidgetType); 1991 // FIXME: It is not clear that Media elements need or want this updateWidget() call. 1992 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) 1993 else if (ownerElement->hasTagName(videoTag) || ownerElement->hasTagName(audioTag)) 1994 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(CreateAnyWidgetType); 1995 #endif 1996 else 1997 ASSERT_NOT_REACHED(); 1998 1999 // Caution: it's possible the object was destroyed again, since loading a 2000 // plugin may run any arbitrary javascript. 2001 object->updateWidgetPosition(); 2002 } 2003 2004 bool FrameView::updateWidgets() 2005 { 2006 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty()) 2007 return true; 2008 2009 size_t size = m_widgetUpdateSet->size(); 2010 2011 Vector<RenderEmbeddedObject*> objects; 2012 objects.reserveCapacity(size); 2013 2014 RenderEmbeddedObjectSet::const_iterator end = m_widgetUpdateSet->end(); 2015 for (RenderEmbeddedObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) { 2016 objects.uncheckedAppend(*it); 2017 (*it)->ref(); 2018 } 2019 2020 for (size_t i = 0; i < size; ++i) { 2021 RenderEmbeddedObject* object = objects[i]; 2022 updateWidget(object); 2023 m_widgetUpdateSet->remove(object); 2024 } 2025 2026 RenderArena* arena = m_frame->document()->renderArena(); 2027 for (size_t i = 0; i < size; ++i) 2028 objects[i]->deref(arena); 2029 2030 return m_widgetUpdateSet->isEmpty(); 2031 } 2032 2033 void FrameView::flushAnyPendingPostLayoutTasks() 2034 { 2035 if (!m_hasPendingPostLayoutTasks) 2036 return; 2037 2038 m_postLayoutTasksTimer.stop(); 2039 performPostLayoutTasks(); 2040 } 2041 2042 void FrameView::performPostLayoutTasks() 2043 { 2044 m_hasPendingPostLayoutTasks = false; 2045 2046 m_frame->selection()->setCaretRectNeedsUpdate(); 2047 m_frame->selection()->updateAppearance(); 2048 2049 if (m_nestedLayoutCount <= 1) { 2050 if (m_firstLayoutCallbackPending) { 2051 m_firstLayoutCallbackPending = false; 2052 m_frame->loader()->didFirstLayout(); 2053 } 2054 2055 if (m_isVisuallyNonEmpty && m_firstVisuallyNonEmptyLayoutCallbackPending) { 2056 m_firstVisuallyNonEmptyLayoutCallbackPending = false; 2057 m_frame->loader()->didFirstVisuallyNonEmptyLayout(); 2058 } 2059 } 2060 2061 RenderView* root = m_frame->contentRenderer(); 2062 2063 root->updateWidgetPositions(); 2064 2065 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) { 2066 if (updateWidgets()) 2067 break; 2068 } 2069 2070 scrollToAnchor(); 2071 2072 m_actionScheduler->resume(); 2073 2074 if (!root->printing()) { 2075 IntSize currentSize = IntSize(width(), height()); 2076 float currentZoomFactor = root->style()->zoom(); 2077 bool resized = !m_firstLayout && (currentSize != m_lastLayoutSize || currentZoomFactor != m_lastZoomFactor); 2078 m_lastLayoutSize = currentSize; 2079 m_lastZoomFactor = currentZoomFactor; 2080 if (resized) 2081 m_frame->eventHandler()->sendResizeEvent(); 2082 } 2083 } 2084 2085 void FrameView::postLayoutTimerFired(Timer<FrameView>*) 2086 { 2087 performPostLayoutTasks(); 2088 } 2089 2090 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow) 2091 { 2092 if (!m_viewportRenderer) 2093 return; 2094 2095 if (m_overflowStatusDirty) { 2096 m_horizontalOverflow = horizontalOverflow; 2097 m_verticalOverflow = verticalOverflow; 2098 m_overflowStatusDirty = false; 2099 return; 2100 } 2101 2102 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow); 2103 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow); 2104 2105 if (horizontalOverflowChanged || verticalOverflowChanged) { 2106 m_horizontalOverflow = horizontalOverflow; 2107 m_verticalOverflow = verticalOverflow; 2108 2109 m_actionScheduler->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, 2110 verticalOverflowChanged, verticalOverflow), 2111 m_viewportRenderer->node()); 2112 } 2113 2114 } 2115 2116 IntRect FrameView::windowClipRect(bool clipToContents) const 2117 { 2118 ASSERT(m_frame->view() == this); 2119 2120 if (paintsEntireContents()) 2121 return IntRect(IntPoint(0, 0), contentsSize()); 2122 2123 // Set our clip rect to be our contents. 2124 IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents)); 2125 if (!m_frame || !m_frame->ownerElement()) 2126 return clipRect; 2127 2128 // Take our owner element and get the clip rect from the enclosing layer. 2129 Element* elt = m_frame->ownerElement(); 2130 RenderLayer* layer = elt->renderer()->enclosingLayer(); 2131 // FIXME: layer should never be null, but sometimes seems to be anyway. 2132 if (!layer) 2133 return clipRect; 2134 FrameView* parentView = elt->document()->view(); 2135 clipRect.intersect(parentView->windowClipRectForLayer(layer, true)); 2136 return clipRect; 2137 } 2138 2139 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const 2140 { 2141 // If we have no layer, just return our window clip rect. 2142 if (!layer) 2143 return windowClipRect(); 2144 2145 // Apply the clip from the layer. 2146 IntRect clipRect; 2147 if (clipToLayerContents) 2148 clipRect = layer->childrenClipRect(); 2149 else 2150 clipRect = layer->selfClipRect(); 2151 clipRect = contentsToWindow(clipRect); 2152 return intersection(clipRect, windowClipRect()); 2153 } 2154 2155 bool FrameView::isActive() const 2156 { 2157 Page* page = frame()->page(); 2158 return page && page->focusController()->isActive(); 2159 } 2160 2161 void FrameView::scrollTo(const IntSize& newOffset) 2162 { 2163 IntSize offset = scrollOffset(); 2164 ScrollView::scrollTo(newOffset); 2165 if (offset != scrollOffset()) 2166 scrollPositionChanged(); 2167 frame()->loader()->client()->didChangeScrollOffset(); 2168 } 2169 2170 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect) 2171 { 2172 // Add in our offset within the FrameView. 2173 IntRect dirtyRect = rect; 2174 dirtyRect.move(scrollbar->x(), scrollbar->y()); 2175 invalidateRect(dirtyRect); 2176 } 2177 2178 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const 2179 { 2180 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch); 2181 } 2182 2183 IntRect FrameView::windowResizerRect() const 2184 { 2185 Page* page = frame() ? frame()->page() : 0; 2186 if (!page) 2187 return IntRect(); 2188 return page->chrome()->windowResizerRect(); 2189 } 2190 2191 void FrameView::didCompleteRubberBand(const IntSize& initialOverhang) const 2192 { 2193 Page* page = m_frame->page(); 2194 if (page->mainFrame() != m_frame) 2195 return; 2196 return page->chrome()->client()->didCompleteRubberBandForMainFrame(initialOverhang); 2197 } 2198 2199 void FrameView::scrollbarStyleChanged() 2200 { 2201 Page* page = m_frame->page(); 2202 ASSERT(page); 2203 if (!page) 2204 return; 2205 page->setNeedsRecalcStyleInAllFrames(); 2206 } 2207 2208 bool FrameView::shouldSuspendScrollAnimations() const 2209 { 2210 return m_frame->loader()->state() != FrameStateComplete; 2211 } 2212 2213 void FrameView::notifyPageThatContentAreaWillPaint() const 2214 { 2215 Page* page = m_frame->page(); 2216 const HashSet<ScrollableArea*>* scrollableAreas = page->scrollableAreaSet(); 2217 if (!scrollableAreas) 2218 return; 2219 2220 HashSet<ScrollableArea*>::const_iterator end = scrollableAreas->end(); 2221 for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(); it != end; ++it) 2222 (*it)->scrollAnimator()->contentAreaWillPaint(); 2223 } 2224 2225 #if ENABLE(DASHBOARD_SUPPORT) 2226 void FrameView::updateDashboardRegions() 2227 { 2228 Document* document = m_frame->document(); 2229 if (!document->hasDashboardRegions()) 2230 return; 2231 Vector<DashboardRegionValue> newRegions; 2232 document->renderBox()->collectDashboardRegions(newRegions); 2233 if (newRegions == document->dashboardRegions()) 2234 return; 2235 document->setDashboardRegions(newRegions); 2236 Page* page = m_frame->page(); 2237 if (!page) 2238 return; 2239 page->chrome()->client()->dashboardRegionsChanged(); 2240 } 2241 #endif 2242 2243 void FrameView::updateScrollCorner() 2244 { 2245 RenderObject* renderer = 0; 2246 RefPtr<RenderStyle> cornerStyle; 2247 2248 if (!scrollCornerRect().isEmpty()) { 2249 // Try the <body> element first as a scroll corner source. 2250 Document* doc = m_frame->document(); 2251 Element* body = doc ? doc->body() : 0; 2252 if (body && body->renderer()) { 2253 renderer = body->renderer(); 2254 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style()); 2255 } 2256 2257 if (!cornerStyle) { 2258 // If the <body> didn't have a custom style, then the root element might. 2259 Element* docElement = doc ? doc->documentElement() : 0; 2260 if (docElement && docElement->renderer()) { 2261 renderer = docElement->renderer(); 2262 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style()); 2263 } 2264 } 2265 2266 if (!cornerStyle) { 2267 // If we have an owning iframe/frame element, then it can set the custom scrollbar also. 2268 if (RenderPart* renderer = m_frame->ownerRenderer()) 2269 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style()); 2270 } 2271 } 2272 2273 if (cornerStyle) { 2274 if (!m_scrollCorner) 2275 m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document()); 2276 m_scrollCorner->setStyle(cornerStyle.release()); 2277 invalidateScrollCorner(); 2278 } else if (m_scrollCorner) { 2279 m_scrollCorner->destroy(); 2280 m_scrollCorner = 0; 2281 } 2282 2283 ScrollView::updateScrollCorner(); 2284 } 2285 2286 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect) 2287 { 2288 if (context->updatingControlTints()) { 2289 updateScrollCorner(); 2290 return; 2291 } 2292 2293 if (m_scrollCorner) { 2294 m_scrollCorner->paintIntoRect(context, cornerRect.x(), cornerRect.y(), cornerRect); 2295 return; 2296 } 2297 2298 ScrollView::paintScrollCorner(context, cornerRect); 2299 } 2300 2301 bool FrameView::hasCustomScrollbars() const 2302 { 2303 const HashSet<RefPtr<Widget> >* viewChildren = children(); 2304 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end(); 2305 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) { 2306 Widget* widget = current->get(); 2307 if (widget->isFrameView()) { 2308 if (static_cast<FrameView*>(widget)->hasCustomScrollbars()) 2309 return true; 2310 } else if (widget->isScrollbar()) { 2311 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget); 2312 if (scrollbar->isCustomScrollbar()) 2313 return true; 2314 } 2315 } 2316 2317 return false; 2318 } 2319 2320 FrameView* FrameView::parentFrameView() const 2321 { 2322 if (Widget* parentView = parent()) { 2323 if (parentView->isFrameView()) 2324 return static_cast<FrameView*>(parentView); 2325 } 2326 return 0; 2327 } 2328 2329 void FrameView::updateControlTints() 2330 { 2331 // This is called when control tints are changed from aqua/graphite to clear and vice versa. 2332 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate. 2333 // This is only done if the theme supports control tinting. It's up to the theme and platform 2334 // to define when controls get the tint and to call this function when that changes. 2335 2336 // Optimize the common case where we bring a window to the front while it's still empty. 2337 if (!m_frame || m_frame->document()->url().isEmpty()) 2338 return; 2339 2340 if ((m_frame->contentRenderer() && m_frame->contentRenderer()->theme()->supportsControlTints()) || hasCustomScrollbars()) { 2341 if (needsLayout()) 2342 layout(); 2343 PlatformGraphicsContext* const noContext = 0; 2344 GraphicsContext context(noContext); 2345 context.setUpdatingControlTints(true); 2346 if (platformWidget()) 2347 paintContents(&context, visibleContentRect()); 2348 else 2349 paint(&context, frameRect()); 2350 } 2351 } 2352 2353 bool FrameView::wasScrolledByUser() const 2354 { 2355 return m_wasScrolledByUser; 2356 } 2357 2358 void FrameView::setWasScrolledByUser(bool wasScrolledByUser) 2359 { 2360 if (m_inProgrammaticScroll) 2361 return; 2362 m_maintainScrollPositionAnchor = 0; 2363 m_wasScrolledByUser = wasScrolledByUser; 2364 } 2365 2366 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) 2367 { 2368 if (!frame()) 2369 return; 2370 2371 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get(), rect); 2372 2373 Document* document = m_frame->document(); 2374 2375 #ifndef NDEBUG 2376 bool fillWithRed; 2377 if (document->printing()) 2378 fillWithRed = false; // Printing, don't fill with red (can't remember why). 2379 else if (m_frame->ownerElement()) 2380 fillWithRed = false; // Subframe, don't fill with red. 2381 else if (isTransparent()) 2382 fillWithRed = false; // Transparent, don't fill with red. 2383 else if (m_paintBehavior & PaintBehaviorSelectionOnly) 2384 fillWithRed = false; // Selections are transparent, don't fill with red. 2385 else if (m_nodeToDraw) 2386 fillWithRed = false; // Element images are transparent, don't fill with red. 2387 else 2388 fillWithRed = true; 2389 2390 if (fillWithRed) 2391 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB); 2392 #endif 2393 2394 bool isTopLevelPainter = !sCurrentPaintTimeStamp; 2395 if (isTopLevelPainter) 2396 sCurrentPaintTimeStamp = currentTime(); 2397 2398 RenderView* contentRenderer = frame()->contentRenderer(); 2399 if (!contentRenderer) { 2400 LOG_ERROR("called FrameView::paint with nil renderer"); 2401 return; 2402 } 2403 2404 ASSERT(!needsLayout()); 2405 if (needsLayout()) 2406 return; 2407 2408 #if USE(ACCELERATED_COMPOSITING) 2409 if (!p->paintingDisabled()) 2410 syncCompositingStateForThisFrame(); 2411 #endif 2412 2413 PaintBehavior oldPaintBehavior = m_paintBehavior; 2414 2415 if (FrameView* parentView = parentFrameView()) { 2416 if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers) 2417 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers; 2418 } 2419 2420 if (m_paintBehavior == PaintBehaviorNormal) 2421 document->markers()->invalidateRenderedRectsForMarkersInRect(rect); 2422 2423 if (document->printing()) 2424 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers; 2425 2426 bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers; 2427 bool isRootFrame = !m_frame->ownerElement(); 2428 if (flatteningPaint && isRootFrame) 2429 notifyWidgetsInAllFrames(WillPaintFlattened); 2430 2431 ASSERT(!m_isPainting); 2432 m_isPainting = true; 2433 2434 // m_nodeToDraw is used to draw only one element (and its descendants) 2435 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0; 2436 RenderLayer* rootLayer = contentRenderer->layer(); 2437 2438 rootLayer->paint(p, rect, m_paintBehavior, eltRenderer); 2439 2440 if (rootLayer->containsDirtyOverlayScrollbars()) 2441 rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer); 2442 2443 m_isPainting = false; 2444 2445 if (flatteningPaint && isRootFrame) 2446 notifyWidgetsInAllFrames(DidPaintFlattened); 2447 2448 m_paintBehavior = oldPaintBehavior; 2449 m_lastPaintTime = currentTime(); 2450 2451 #if ENABLE(DASHBOARD_SUPPORT) 2452 // Regions may have changed as a result of the visibility/z-index of element changing. 2453 if (document->dashboardRegionsDirty()) 2454 updateDashboardRegions(); 2455 #endif 2456 2457 if (isTopLevelPainter) 2458 sCurrentPaintTimeStamp = 0; 2459 2460 InspectorInstrumentation::didPaint(cookie); 2461 } 2462 2463 void FrameView::setPaintBehavior(PaintBehavior behavior) 2464 { 2465 m_paintBehavior = behavior; 2466 } 2467 2468 PaintBehavior FrameView::paintBehavior() const 2469 { 2470 return m_paintBehavior; 2471 } 2472 2473 bool FrameView::isPainting() const 2474 { 2475 return m_isPainting; 2476 } 2477 2478 void FrameView::setNodeToDraw(Node* node) 2479 { 2480 m_nodeToDraw = node; 2481 } 2482 2483 void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect) 2484 { 2485 if (context->paintingDisabled()) 2486 return; 2487 2488 if (m_frame->document()->printing()) 2489 return; 2490 2491 Page* page = m_frame->page(); 2492 if (page->mainFrame() == m_frame) { 2493 if (page->chrome()->client()->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect)) 2494 return; 2495 } 2496 2497 return ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect); 2498 } 2499 2500 void FrameView::updateLayoutAndStyleIfNeededRecursive() 2501 { 2502 // We have to crawl our entire tree looking for any FrameViews that need 2503 // layout and make sure they are up to date. 2504 // Mac actually tests for intersection with the dirty region and tries not to 2505 // update layout for frames that are outside the dirty region. Not only does this seem 2506 // pointless (since those frames will have set a zero timer to layout anyway), but 2507 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty 2508 // region but then become included later by the second frame adding rects to the dirty region 2509 // when it lays out. 2510 2511 m_frame->document()->updateStyleIfNeeded(); 2512 2513 if (needsLayout()) 2514 layout(); 2515 2516 const HashSet<RefPtr<Widget> >* viewChildren = children(); 2517 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end(); 2518 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) { 2519 Widget* widget = (*current).get(); 2520 if (widget->isFrameView()) 2521 static_cast<FrameView*>(widget)->updateLayoutAndStyleIfNeededRecursive(); 2522 } 2523 2524 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before 2525 // painting, so we need to flush out any deferred repaints too. 2526 flushDeferredRepaints(); 2527 } 2528 2529 void FrameView::flushDeferredRepaints() 2530 { 2531 if (!m_deferredRepaintTimer.isActive()) 2532 return; 2533 m_deferredRepaintTimer.stop(); 2534 doDeferredRepaints(); 2535 } 2536 2537 void FrameView::forceLayout(bool allowSubtree) 2538 { 2539 layout(allowSubtree); 2540 } 2541 2542 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximumShrinkFactor, Frame::AdjustViewSizeOrNot shouldAdjustViewSize) 2543 { 2544 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see 2545 // the state of things before and after the layout 2546 RenderView *root = toRenderView(m_frame->document()->renderer()); 2547 if (root) { 2548 float pageLogicalWidth = root->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height(); 2549 float pageLogicalHeight = root->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width(); 2550 2551 int flooredPageLogicalWidth = static_cast<int>(pageLogicalWidth); 2552 root->setLogicalWidth(flooredPageLogicalWidth); 2553 root->setPageLogicalHeight(pageLogicalHeight); 2554 root->setNeedsLayoutAndPrefWidthsRecalc(); 2555 forceLayout(); 2556 2557 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the 2558 // page width when shrunk, we will lay out at maximum shrink and clip extra content. 2559 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping 2560 // implementation should not do this! 2561 int docLogicalWidth = root->style()->isHorizontalWritingMode() ? root->docWidth() : root->docHeight(); 2562 if (docLogicalWidth > pageLogicalWidth) { 2563 flooredPageLogicalWidth = std::min<int>(docLogicalWidth, pageLogicalWidth * maximumShrinkFactor); 2564 if (pageLogicalHeight) 2565 root->setPageLogicalHeight(flooredPageLogicalWidth / pageSize.width() * pageSize.height()); 2566 root->setLogicalWidth(flooredPageLogicalWidth); 2567 root->setNeedsLayoutAndPrefWidthsRecalc(); 2568 forceLayout(); 2569 int docLogicalHeight = root->style()->isHorizontalWritingMode() ? root->docHeight() : root->docWidth(); 2570 int docLogicalTop = root->style()->isHorizontalWritingMode() ? root->docTop() : root->docLeft(); 2571 int docLogicalRight = root->style()->isHorizontalWritingMode() ? root->docRight() : root->docBottom(); 2572 int clippedLogicalLeft = 0; 2573 if (!root->style()->isLeftToRightDirection()) 2574 clippedLogicalLeft = docLogicalRight - flooredPageLogicalWidth; 2575 IntRect overflow(clippedLogicalLeft, docLogicalTop, flooredPageLogicalWidth, docLogicalHeight); 2576 if (!root->style()->isHorizontalWritingMode()) 2577 overflow = overflow.transposedRect(); 2578 root->clearLayoutOverflow(); 2579 root->addLayoutOverflow(overflow); // This is how we clip in case we overflow again. 2580 } 2581 } 2582 2583 if (shouldAdjustViewSize) 2584 adjustViewSize(); 2585 } 2586 2587 void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/) 2588 { 2589 RenderView* root = m_frame->contentRenderer(); 2590 if (root) { 2591 // Use a context with painting disabled. 2592 GraphicsContext context((PlatformGraphicsContext*)0); 2593 root->setTruncatedAt((int)floorf(oldBottom)); 2594 IntRect dirtyRect(0, (int)floorf(oldTop), root->maxXLayoutOverflow(), (int)ceilf(oldBottom - oldTop)); 2595 root->setPrintRect(dirtyRect); 2596 root->layer()->paint(&context, dirtyRect); 2597 *newBottom = root->bestTruncatedAt(); 2598 if (*newBottom == 0) 2599 *newBottom = oldBottom; 2600 root->setPrintRect(IntRect()); 2601 } else 2602 *newBottom = oldBottom; 2603 } 2604 2605 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const 2606 { 2607 IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox(); 2608 2609 // Convert from page ("absolute") to FrameView coordinates. 2610 rect.move(-scrollX(), -scrollY()); 2611 2612 return rect; 2613 } 2614 2615 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const 2616 { 2617 IntRect rect = viewRect; 2618 2619 // Convert from FrameView coords into page ("absolute") coordinates. 2620 rect.move(scrollX(), scrollY()); 2621 2622 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just 2623 // move the rect for now. 2624 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */))); 2625 return rect; 2626 } 2627 2628 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const 2629 { 2630 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */)); 2631 2632 // Convert from page ("absolute") to FrameView coordinates. 2633 point.move(-scrollX(), -scrollY()); 2634 return point; 2635 } 2636 2637 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const 2638 { 2639 IntPoint point = viewPoint; 2640 2641 // Convert from FrameView coords into page ("absolute") coordinates. 2642 point += IntSize(scrollX(), scrollY()); 2643 2644 return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */)); 2645 } 2646 2647 IntRect FrameView::convertToContainingView(const IntRect& localRect) const 2648 { 2649 if (const ScrollView* parentScrollView = parent()) { 2650 if (parentScrollView->isFrameView()) { 2651 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView); 2652 // Get our renderer in the parent view 2653 RenderPart* renderer = m_frame->ownerRenderer(); 2654 if (!renderer) 2655 return localRect; 2656 2657 IntRect rect(localRect); 2658 // Add borders and padding?? 2659 rect.move(renderer->borderLeft() + renderer->paddingLeft(), 2660 renderer->borderTop() + renderer->paddingTop()); 2661 return parentView->convertFromRenderer(renderer, rect); 2662 } 2663 2664 return Widget::convertToContainingView(localRect); 2665 } 2666 2667 return localRect; 2668 } 2669 2670 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const 2671 { 2672 if (const ScrollView* parentScrollView = parent()) { 2673 if (parentScrollView->isFrameView()) { 2674 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView); 2675 2676 // Get our renderer in the parent view 2677 RenderPart* renderer = m_frame->ownerRenderer(); 2678 if (!renderer) 2679 return parentRect; 2680 2681 IntRect rect = parentView->convertToRenderer(renderer, parentRect); 2682 // Subtract borders and padding 2683 rect.move(-renderer->borderLeft() - renderer->paddingLeft(), 2684 -renderer->borderTop() - renderer->paddingTop()); 2685 return rect; 2686 } 2687 2688 return Widget::convertFromContainingView(parentRect); 2689 } 2690 2691 return parentRect; 2692 } 2693 2694 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const 2695 { 2696 if (const ScrollView* parentScrollView = parent()) { 2697 if (parentScrollView->isFrameView()) { 2698 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView); 2699 2700 // Get our renderer in the parent view 2701 RenderPart* renderer = m_frame->ownerRenderer(); 2702 if (!renderer) 2703 return localPoint; 2704 2705 IntPoint point(localPoint); 2706 2707 // Add borders and padding 2708 point.move(renderer->borderLeft() + renderer->paddingLeft(), 2709 renderer->borderTop() + renderer->paddingTop()); 2710 return parentView->convertFromRenderer(renderer, point); 2711 } 2712 2713 return Widget::convertToContainingView(localPoint); 2714 } 2715 2716 return localPoint; 2717 } 2718 2719 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const 2720 { 2721 if (const ScrollView* parentScrollView = parent()) { 2722 if (parentScrollView->isFrameView()) { 2723 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView); 2724 2725 // Get our renderer in the parent view 2726 RenderPart* renderer = m_frame->ownerRenderer(); 2727 if (!renderer) 2728 return parentPoint; 2729 2730 IntPoint point = parentView->convertToRenderer(renderer, parentPoint); 2731 // Subtract borders and padding 2732 point.move(-renderer->borderLeft() - renderer->paddingLeft(), 2733 -renderer->borderTop() - renderer->paddingTop()); 2734 return point; 2735 } 2736 2737 return Widget::convertFromContainingView(parentPoint); 2738 } 2739 2740 return parentPoint; 2741 } 2742 2743 // Normal delay 2744 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p) 2745 { 2746 s_deferredRepaintDelay = p; 2747 } 2748 2749 // Negative value would mean that first few repaints happen without a delay 2750 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p) 2751 { 2752 s_initialDeferredRepaintDelayDuringLoading = p; 2753 } 2754 2755 // The delay grows on each repaint to this maximum value 2756 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p) 2757 { 2758 s_maxDeferredRepaintDelayDuringLoading = p; 2759 } 2760 2761 // On each repaint the delay increases by this amount 2762 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p) 2763 { 2764 s_deferredRepaintDelayIncrementDuringLoading = p; 2765 } 2766 2767 bool FrameView::isVerticalDocument() const 2768 { 2769 if (!m_frame) 2770 return true; 2771 Document* doc = m_frame->document(); 2772 if (!doc) 2773 return true; 2774 RenderObject* renderView = doc->renderer(); 2775 if (!renderView) 2776 return true; 2777 return renderView->style()->isHorizontalWritingMode(); 2778 } 2779 2780 bool FrameView::isFlippedDocument() const 2781 { 2782 if (!m_frame) 2783 return false; 2784 Document* doc = m_frame->document(); 2785 if (!doc) 2786 return false; 2787 RenderObject* renderView = doc->renderer(); 2788 if (!renderView) 2789 return false; 2790 return renderView->style()->isFlippedBlocksWritingMode(); 2791 } 2792 2793 void FrameView::notifyWidgetsInAllFrames(WidgetNotification notification) 2794 { 2795 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 2796 if (RenderView* root = frame->contentRenderer()) 2797 root->notifyWidgets(notification); 2798 } 2799 } 2800 2801 AXObjectCache* FrameView::axObjectCache() const 2802 { 2803 if (frame() && frame()->document() && frame()->document()->axObjectCacheExists()) 2804 return frame()->document()->axObjectCache(); 2805 return 0; 2806 } 2807 2808 } // namespace WebCore 2809