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