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 "Chrome.h" 33 #include "ChromeClient.h" 34 #include "DocLoader.h" 35 #include "EventHandler.h" 36 #include "FloatRect.h" 37 #include "FocusController.h" 38 #include "Frame.h" 39 #include "FrameLoader.h" 40 #include "FrameLoaderClient.h" 41 #include "FrameTree.h" 42 #include "GraphicsContext.h" 43 #include "HTMLDocument.h" 44 #include "HTMLFrameElement.h" 45 #include "HTMLFrameSetElement.h" 46 #include "HTMLNames.h" 47 #include "InspectorTimelineAgent.h" 48 #include "OverflowEvent.h" 49 #include "RenderEmbeddedObject.h" 50 #include "RenderPart.h" 51 #include "RenderScrollbar.h" 52 #include "RenderScrollbarPart.h" 53 #include "RenderTheme.h" 54 #include "RenderView.h" 55 #include "Settings.h" 56 #include "TextResourceDecoder.h" 57 #include <wtf/CurrentTime.h> 58 59 #ifdef ANDROID_INSTRUMENT 60 #include "FrameTree.h" 61 #include "TimeCounter.h" 62 #endif 63 64 #if USE(ACCELERATED_COMPOSITING) 65 #include "RenderLayerCompositor.h" 66 #endif 67 68 #if ENABLE(SVG) 69 #include "SVGDocument.h" 70 #include "SVGLocatable.h" 71 #include "SVGNames.h" 72 #include "SVGPreserveAspectRatio.h" 73 #include "SVGSVGElement.h" 74 #include "SVGViewElement.h" 75 #include "SVGViewSpec.h" 76 #endif 77 78 #if PLATFORM(ANDROID) 79 #include "WebCoreFrameBridge.h" 80 #endif 81 82 83 namespace WebCore { 84 85 using namespace HTMLNames; 86 87 double FrameView::sCurrentPaintTimeStamp = 0.0; 88 89 #if ENABLE(REPAINT_THROTTLING) 90 // Normal delay 91 static const double deferredRepaintDelay = 0.025; 92 // Negative value would mean that first few repaints happen without a delay 93 static const double initialDeferredRepaintDelayDuringLoading = 0; 94 // The delay grows on each repaint to this maximum value 95 static const double maxDeferredRepaintDelayDuringLoading = 2.5; 96 // On each repaint the delay increses by this amount 97 static const double deferredRepaintDelayIncrementDuringLoading = 0.5; 98 #else 99 // FIXME: Repaint throttling could be good to have on all platform. 100 // The balance between CPU use and repaint frequency will need some tuning for desktop. 101 // More hooks may be needed to reset the delay on things like GIF and CSS animations. 102 static const double deferredRepaintDelay = 0; 103 static const double initialDeferredRepaintDelayDuringLoading = 0; 104 static const double maxDeferredRepaintDelayDuringLoading = 0; 105 static const double deferredRepaintDelayIncrementDuringLoading = 0; 106 #endif 107 108 // The maximum number of updateWidgets iterations that should be done before returning. 109 static const unsigned maxUpdateWidgetsIterations = 2; 110 111 struct ScheduledEvent : Noncopyable { 112 RefPtr<Event> m_event; 113 RefPtr<Node> m_eventTarget; 114 }; 115 116 FrameView::FrameView(Frame* frame) 117 : m_frame(frame) 118 , m_canHaveScrollbars(true) 119 , m_slowRepaintObjectCount(0) 120 , m_layoutTimer(this, &FrameView::layoutTimerFired) 121 , m_layoutRoot(0) 122 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired) 123 , m_isTransparent(false) 124 , m_baseBackgroundColor(Color::white) 125 , m_mediaType("screen") 126 , m_enqueueEvents(0) 127 , m_overflowStatusDirty(true) 128 , m_viewportRenderer(0) 129 , m_wasScrolledByUser(false) 130 , m_inProgrammaticScroll(false) 131 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired) 132 , m_shouldUpdateWhileOffscreen(true) 133 , m_deferSetNeedsLayouts(0) 134 , m_setNeedsLayoutWasDeferred(false) 135 , m_scrollCorner(0) 136 { 137 init(); 138 } 139 140 PassRefPtr<FrameView> FrameView::create(Frame* frame) 141 { 142 RefPtr<FrameView> view = adoptRef(new FrameView(frame)); 143 view->show(); 144 return view.release(); 145 } 146 147 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize) 148 { 149 RefPtr<FrameView> view = adoptRef(new FrameView(frame)); 150 view->Widget::setFrameRect(IntRect(view->pos(), initialSize)); 151 view->show(); 152 return view.release(); 153 } 154 155 FrameView::~FrameView() 156 { 157 if (m_postLayoutTasksTimer.isActive()) { 158 m_postLayoutTasksTimer.stop(); 159 m_scheduledEvents.clear(); 160 m_enqueueEvents = 0; 161 } 162 163 resetScrollbars(); 164 165 // Custom scrollbars should already be destroyed at this point 166 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar()); 167 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar()); 168 169 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow. 170 setHasVerticalScrollbar(false); 171 172 ASSERT(!m_scrollCorner); 173 ASSERT(m_scheduledEvents.isEmpty()); 174 ASSERT(!m_enqueueEvents); 175 176 if (m_frame) { 177 ASSERT(m_frame->view() != this || !m_frame->contentRenderer()); 178 RenderPart* renderer = m_frame->ownerRenderer(); 179 if (renderer && renderer->widget() == this) 180 renderer->setWidget(0); 181 } 182 } 183 184 void FrameView::reset() 185 { 186 m_useSlowRepaints = false; 187 m_isOverlapped = false; 188 m_contentIsOpaque = false; 189 m_borderX = 30; 190 m_borderY = 30; 191 m_layoutTimer.stop(); 192 m_layoutRoot = 0; 193 m_delayedLayout = false; 194 m_doFullRepaint = true; 195 m_layoutSchedulingEnabled = true; 196 m_midLayout = false; 197 m_layoutCount = 0; 198 m_nestedLayoutCount = 0; 199 m_postLayoutTasksTimer.stop(); 200 m_firstLayout = true; 201 m_firstLayoutCallbackPending = false; 202 m_wasScrolledByUser = false; 203 m_lastLayoutSize = IntSize(); 204 m_lastZoomFactor = 1.0f; 205 m_deferringRepaints = 0; 206 m_repaintCount = 0; 207 m_repaintRects.clear(); 208 m_deferredRepaintDelay = initialDeferredRepaintDelayDuringLoading; 209 m_deferredRepaintTimer.stop(); 210 m_lastPaintTime = 0; 211 m_paintBehavior = PaintBehaviorNormal; 212 m_isPainting = false; 213 m_isVisuallyNonEmpty = false; 214 m_firstVisuallyNonEmptyLayoutCallbackPending = true; 215 m_maintainScrollPositionAnchor = 0; 216 } 217 218 bool FrameView::isFrameView() const 219 { 220 return true; 221 } 222 223 void FrameView::clearFrame() 224 { 225 m_frame = 0; 226 } 227 228 void FrameView::resetScrollbars() 229 { 230 // Reset the document's scrollbars back to our defaults before we yield the floor. 231 m_firstLayout = true; 232 setScrollbarsSuppressed(true); 233 if (m_canHaveScrollbars) 234 setScrollbarModes(ScrollbarAuto, ScrollbarAuto); 235 else 236 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); 237 setScrollbarsSuppressed(false); 238 } 239 240 void FrameView::init() 241 { 242 reset(); 243 244 m_margins = IntSize(-1, -1); // undefined 245 m_size = IntSize(); 246 247 // Propagate the marginwidth/height and scrolling modes to the view. 248 Element* ownerElement = m_frame && m_frame->document() ? m_frame->document()->ownerElement() : 0; 249 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) { 250 HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement); 251 if (frameElt->scrollingMode() == ScrollbarAlwaysOff) 252 setCanHaveScrollbars(false); 253 int marginWidth = frameElt->getMarginWidth(); 254 int marginHeight = frameElt->getMarginHeight(); 255 if (marginWidth != -1) 256 setMarginWidth(marginWidth); 257 if (marginHeight != -1) 258 setMarginHeight(marginHeight); 259 } 260 } 261 262 void FrameView::detachCustomScrollbars() 263 { 264 if (!m_frame) 265 return; 266 267 Scrollbar* horizontalBar = horizontalScrollbar(); 268 if (horizontalBar && horizontalBar->isCustomScrollbar() && !toRenderScrollbar(horizontalBar)->owningRenderer()->isRenderPart()) 269 setHasHorizontalScrollbar(false); 270 271 Scrollbar* verticalBar = verticalScrollbar(); 272 if (verticalBar && verticalBar->isCustomScrollbar() && !toRenderScrollbar(verticalBar)->owningRenderer()->isRenderPart()) 273 setHasVerticalScrollbar(false); 274 275 if (m_scrollCorner) { 276 m_scrollCorner->destroy(); 277 m_scrollCorner = 0; 278 } 279 } 280 281 void FrameView::clear() 282 { 283 setCanBlitOnScroll(true); 284 285 reset(); 286 287 if (m_frame) { 288 if (RenderPart* renderer = m_frame->ownerRenderer()) 289 renderer->viewCleared(); 290 } 291 292 setScrollbarsSuppressed(true); 293 } 294 295 bool FrameView::didFirstLayout() const 296 { 297 return !m_firstLayout; 298 } 299 300 void FrameView::invalidateRect(const IntRect& rect) 301 { 302 if (!parent()) { 303 if (hostWindow()) 304 hostWindow()->repaint(rect, true); 305 return; 306 } 307 308 if (!m_frame) 309 return; 310 311 RenderPart* renderer = m_frame->ownerRenderer(); 312 if (!renderer) 313 return; 314 315 IntRect repaintRect = rect; 316 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(), 317 renderer->borderTop() + renderer->paddingTop()); 318 renderer->repaintRectangle(repaintRect); 319 } 320 321 void FrameView::setMarginWidth(int w) 322 { 323 // make it update the rendering area when set 324 m_margins.setWidth(w); 325 } 326 327 void FrameView::setMarginHeight(int h) 328 { 329 // make it update the rendering area when set 330 m_margins.setHeight(h); 331 } 332 333 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars) 334 { 335 m_canHaveScrollbars = canHaveScrollbars; 336 ScrollView::setCanHaveScrollbars(canHaveScrollbars); 337 } 338 339 void FrameView::updateCanHaveScrollbars() 340 { 341 ScrollbarMode hMode; 342 ScrollbarMode vMode; 343 scrollbarModes(hMode, vMode); 344 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff) 345 m_canHaveScrollbars = false; 346 else 347 m_canHaveScrollbars = true; 348 } 349 350 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation) 351 { 352 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles). 353 Document* doc = m_frame->document(); 354 355 // Try the <body> element first as a scrollbar source. 356 Element* body = doc ? doc->body() : 0; 357 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR)) 358 return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderer()->enclosingBox()); 359 360 // If the <body> didn't have a custom style, then the root element might. 361 Element* docElement = doc ? doc->documentElement() : 0; 362 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR)) 363 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox()); 364 365 // If we have an owning iframe/frame element, then it can set the custom scrollbar also. 366 RenderPart* frameRenderer = m_frame->ownerRenderer(); 367 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR)) 368 return RenderScrollbar::createCustomScrollbar(this, orientation, frameRenderer); 369 370 // Nobody set a custom style, so we just use a native scrollbar. 371 return ScrollView::createScrollbar(orientation); 372 } 373 374 void FrameView::setContentsSize(const IntSize& size) 375 { 376 if (size == contentsSize()) 377 return; 378 379 m_deferSetNeedsLayouts++; 380 381 ScrollView::setContentsSize(size); 382 383 Page* page = frame() ? frame()->page() : 0; 384 if (!page) 385 return; 386 387 page->chrome()->contentsSizeChanged(frame(), size); //notify only 388 389 m_deferSetNeedsLayouts--; 390 391 if (!m_deferSetNeedsLayouts) 392 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen. 393 } 394 395 void FrameView::adjustViewSize() 396 { 397 ASSERT(m_frame->view() == this); 398 RenderView* root = m_frame->contentRenderer(); 399 if (!root) 400 return; 401 setContentsSize(IntSize(root->rightLayoutOverflow(), root->bottomLayoutOverflow())); 402 } 403 404 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode) 405 { 406 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats 407 // overflow:hidden and overflow:scroll on <body> as applying to the document's 408 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should 409 // use the root element. 410 switch (o->style()->overflowX()) { 411 case OHIDDEN: 412 hMode = ScrollbarAlwaysOff; 413 break; 414 case OSCROLL: 415 hMode = ScrollbarAlwaysOn; 416 break; 417 case OAUTO: 418 hMode = ScrollbarAuto; 419 break; 420 default: 421 // Don't set it at all. 422 ; 423 } 424 425 switch (o->style()->overflowY()) { 426 case OHIDDEN: 427 vMode = ScrollbarAlwaysOff; 428 break; 429 case OSCROLL: 430 vMode = ScrollbarAlwaysOn; 431 break; 432 case OAUTO: 433 vMode = ScrollbarAuto; 434 break; 435 default: 436 // Don't set it at all. 437 ; 438 } 439 440 m_viewportRenderer = o; 441 } 442 443 #if USE(ACCELERATED_COMPOSITING) 444 void FrameView::updateCompositingLayers() 445 { 446 RenderView* view = m_frame->contentRenderer(); 447 if (!view) 448 return; 449 450 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref 451 view->compositor()->cacheAcceleratedCompositingFlags(); 452 453 if (!view->usesCompositing()) 454 return; 455 456 view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange); 457 } 458 459 void FrameView::setNeedsOneShotDrawingSynchronization() 460 { 461 Page* page = frame() ? frame()->page() : 0; 462 if (page) 463 page->chrome()->client()->setNeedsOneShotDrawingSynchronization(); 464 } 465 #endif // USE(ACCELERATED_COMPOSITING) 466 467 bool FrameView::syncCompositingStateRecursive() 468 { 469 #if USE(ACCELERATED_COMPOSITING) 470 ASSERT(m_frame->view() == this); 471 RenderView* contentRenderer = m_frame->contentRenderer(); 472 if (!contentRenderer) 473 return true; // We don't want to keep trying to update layers if we have no renderer. 474 475 if (m_layoutTimer.isActive()) { 476 // Don't sync layers if there's a layout pending. 477 return false; 478 } 479 480 if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer()) 481 rootLayer->syncCompositingState(); 482 483 bool allSubframesSynced = true; 484 const HashSet<RefPtr<Widget> >* viewChildren = children(); 485 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end(); 486 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) { 487 Widget* widget = (*current).get(); 488 if (widget->isFrameView()) { 489 bool synced = static_cast<FrameView*>(widget)->syncCompositingStateRecursive(); 490 allSubframesSynced &= synced; 491 } 492 } 493 return allSubframesSynced; 494 #else // USE(ACCELERATED_COMPOSITING) 495 return true; 496 #endif 497 } 498 499 void FrameView::didMoveOnscreen() 500 { 501 RenderView* view = m_frame->contentRenderer(); 502 if (view) 503 view->didMoveOnscreen(); 504 } 505 506 void FrameView::willMoveOffscreen() 507 { 508 RenderView* view = m_frame->contentRenderer(); 509 if (view) 510 view->willMoveOffscreen(); 511 } 512 513 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const 514 { 515 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot; 516 } 517 518 void FrameView::layout(bool allowSubtree) 519 { 520 if (m_midLayout) 521 return; 522 523 m_layoutTimer.stop(); 524 m_delayedLayout = false; 525 m_setNeedsLayoutWasDeferred = false; 526 527 // Protect the view from being deleted during layout (in recalcStyle) 528 RefPtr<FrameView> protector(this); 529 530 if (!m_frame) { 531 // FIXME: Do we need to set m_size.width here? 532 // FIXME: Should we set m_size.height here too? 533 m_size.setWidth(layoutWidth()); 534 return; 535 } 536 537 // we shouldn't enter layout() while painting 538 ASSERT(!isPainting()); 539 if (isPainting()) 540 return; 541 542 #if ENABLE(INSPECTOR) 543 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent()) 544 timelineAgent->willLayout(); 545 #endif 546 547 if (!allowSubtree && m_layoutRoot) { 548 m_layoutRoot->markContainingBlocksForLayout(false); 549 m_layoutRoot = 0; 550 } 551 552 ASSERT(m_frame->view() == this); 553 // This early return should be removed when rdar://5598072 is resolved. In the meantime, there is a 554 // gigantic CrashTracer because of this issue, and the early return will hopefully cause graceful 555 // failure instead. 556 if (m_frame->view() != this) 557 return; 558 559 Document* document = m_frame->document(); 560 561 m_layoutSchedulingEnabled = false; 562 563 if (!m_nestedLayoutCount && m_postLayoutTasksTimer.isActive()) { 564 // This is a new top-level layout. If there are any remaining tasks from the previous 565 // layout, finish them now. 566 m_postLayoutTasksTimer.stop(); 567 performPostLayoutTasks(); 568 } 569 570 // Viewport-dependent media queries may cause us to need completely different style information. 571 // Check that here. 572 if (document->styleSelector()->affectedByViewportChange()) 573 document->updateStyleSelector(); 574 575 // Always ensure our style info is up-to-date. This can happen in situations where 576 // the layout beats any sort of style recalc update that needs to occur. 577 if (m_frame->needsReapplyStyles()) 578 m_frame->reapplyStyles(); 579 else if (document->childNeedsStyleRecalc()) 580 document->recalcStyle(); 581 582 bool subtree = m_layoutRoot; 583 584 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit, 585 // so there's no point to continuing to layout 586 if (protector->hasOneRef()) 587 return; 588 589 RenderObject* root = subtree ? m_layoutRoot : document->renderer(); 590 if (!root) { 591 // FIXME: Do we need to set m_size here? 592 m_layoutSchedulingEnabled = true; 593 return; 594 } 595 596 #ifdef ANDROID_INSTRUMENT 597 if (!m_frame->tree() || !m_frame->tree()->parent()) 598 android::TimeCounter::start(android::TimeCounter::LayoutTimeCounter); 599 #endif 600 601 m_nestedLayoutCount++; 602 603 ScrollbarMode hMode; 604 ScrollbarMode vMode; 605 if (m_canHaveScrollbars) { 606 hMode = ScrollbarAuto; 607 vMode = ScrollbarAuto; 608 } else { 609 hMode = ScrollbarAlwaysOff; 610 vMode = ScrollbarAlwaysOff; 611 } 612 613 if (!subtree) { 614 Node* documentElement = document->documentElement(); 615 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0; 616 Node* body = document->body(); 617 if (body && body->renderer()) { 618 if (body->hasTagName(framesetTag) && !m_frame->settings()->frameSetFlatteningEnabled()) { 619 body->renderer()->setChildNeedsLayout(true); 620 vMode = ScrollbarAlwaysOff; 621 hMode = ScrollbarAlwaysOff; 622 } else if (body->hasTagName(bodyTag)) { 623 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewHeight()) 624 body->renderer()->setChildNeedsLayout(true); 625 // It's sufficient to just check the X overflow, 626 // since it's illegal to have visible in only one direction. 627 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer; 628 applyOverflowToViewport(o, hMode, vMode); 629 } 630 } else if (rootRenderer) { 631 #if ENABLE(SVG) 632 if (documentElement->isSVGElement()) { 633 if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight())) 634 rootRenderer->setChildNeedsLayout(true); 635 } else 636 applyOverflowToViewport(rootRenderer, hMode, vMode); 637 #else 638 applyOverflowToViewport(rootRenderer, hMode, vMode); 639 #endif 640 } 641 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 642 if (m_firstLayout && !document->ownerElement()) 643 printf("Elapsed time before first layout: %d\n", document->elapsedTime()); 644 #endif 645 } 646 647 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing()); 648 649 if (!subtree) { 650 // Now set our scrollbar state for the layout. 651 ScrollbarMode currentHMode = horizontalScrollbarMode(); 652 ScrollbarMode currentVMode = verticalScrollbarMode(); 653 654 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) { 655 setScrollbarsSuppressed(true); 656 if (m_firstLayout) { 657 m_firstLayout = false; 658 m_firstLayoutCallbackPending = true; 659 m_lastLayoutSize = IntSize(width(), height()); 660 m_lastZoomFactor = root->style()->zoom(); 661 662 // Set the initial vMode to AlwaysOn if we're auto. 663 if (vMode == ScrollbarAuto) 664 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear. 665 // Set the initial hMode to AlwaysOff if we're auto. 666 if (hMode == ScrollbarAuto) 667 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear. 668 } 669 setScrollbarModes(hMode, vMode); 670 setScrollbarsSuppressed(false, true); 671 } 672 673 IntSize oldSize = m_size; 674 675 m_size = IntSize(layoutWidth(), layoutHeight()); 676 677 if (oldSize != m_size) 678 m_doFullRepaint = true; 679 } 680 681 RenderLayer* layer = root->enclosingLayer(); 682 683 pauseScheduledEvents(); 684 685 bool disableLayoutState = false; 686 if (subtree) { 687 RenderView* view = root->view(); 688 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root); 689 view->pushLayoutState(root); 690 if (disableLayoutState) 691 view->disableLayoutState(); 692 } 693 694 m_midLayout = true; 695 beginDeferredRepaints(); 696 root->layout(); 697 endDeferredRepaints(); 698 m_midLayout = false; 699 700 if (subtree) { 701 RenderView* view = root->view(); 702 view->popLayoutState(); 703 if (disableLayoutState) 704 view->enableLayoutState(); 705 } 706 m_layoutRoot = 0; 707 708 m_frame->selection()->setNeedsLayout(); 709 m_frame->selection()->updateAppearance(); 710 711 m_layoutSchedulingEnabled = true; 712 713 if (!subtree && !toRenderView(root)->printing()) 714 adjustViewSize(); 715 716 // Now update the positions of all layers. 717 beginDeferredRepaints(); 718 layer->updateLayerPositions((m_doFullRepaint ? RenderLayer::DoFullRepaint : 0) 719 | RenderLayer::CheckForRepaint 720 | RenderLayer::IsCompositingUpdateRoot 721 | RenderLayer::UpdateCompositingLayers); 722 endDeferredRepaints(); 723 724 #if USE(ACCELERATED_COMPOSITING) 725 updateCompositingLayers(); 726 #endif 727 728 m_layoutCount++; 729 730 #if PLATFORM(MAC) 731 if (AXObjectCache::accessibilityEnabled()) 732 root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true); 733 #endif 734 #if ENABLE(DASHBOARD_SUPPORT) 735 updateDashboardRegions(); 736 #endif 737 738 #ifdef ANDROID_INSTRUMENT 739 if (!m_frame->tree()->parent()) 740 android::TimeCounter::record(android::TimeCounter::LayoutTimeCounter, __FUNCTION__); 741 #endif 742 ASSERT(!root->needsLayout()); 743 744 setCanBlitOnScroll(!useSlowRepaints()); 745 746 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER)) 747 updateOverflowStatus(layoutWidth() < contentsWidth(), 748 layoutHeight() < contentsHeight()); 749 750 if (!m_postLayoutTasksTimer.isActive()) { 751 // Calls resumeScheduledEvents() 752 performPostLayoutTasks(); 753 754 if (!m_postLayoutTasksTimer.isActive() && needsLayout()) { 755 // Post-layout widget updates or an event handler made us need layout again. 756 // Lay out again, but this time defer widget updates and event dispatch until after 757 // we return. 758 m_postLayoutTasksTimer.startOneShot(0); 759 pauseScheduledEvents(); 760 layout(); 761 } 762 } else { 763 resumeScheduledEvents(); 764 ASSERT(m_enqueueEvents); 765 } 766 767 #if ENABLE(INSPECTOR) 768 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent()) 769 timelineAgent->didLayout(); 770 #endif 771 772 m_nestedLayoutCount--; 773 } 774 775 void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object) 776 { 777 if (!m_widgetUpdateSet) 778 m_widgetUpdateSet.set(new RenderEmbeddedObjectSet); 779 780 m_widgetUpdateSet->add(object); 781 } 782 783 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object) 784 { 785 if (!m_widgetUpdateSet) 786 return; 787 788 m_widgetUpdateSet->remove(object); 789 } 790 791 void FrameView::setMediaType(const String& mediaType) 792 { 793 m_mediaType = mediaType; 794 } 795 796 String FrameView::mediaType() const 797 { 798 // See if we have an override type. 799 String overrideType = m_frame->loader()->client()->overrideMediaType(); 800 if (!overrideType.isNull()) 801 return overrideType; 802 return m_mediaType; 803 } 804 805 bool FrameView::useSlowRepaints() const 806 { 807 return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || m_isOverlapped || !m_contentIsOpaque; 808 } 809 810 bool FrameView::useSlowRepaintsIfNotOverlapped() const 811 { 812 return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || !m_contentIsOpaque; 813 } 814 815 void FrameView::setUseSlowRepaints() 816 { 817 m_useSlowRepaints = true; 818 setCanBlitOnScroll(false); 819 } 820 821 void FrameView::addSlowRepaintObject() 822 { 823 if (!m_slowRepaintObjectCount) 824 setCanBlitOnScroll(false); 825 m_slowRepaintObjectCount++; 826 } 827 828 void FrameView::removeSlowRepaintObject() 829 { 830 ASSERT(m_slowRepaintObjectCount > 0); 831 m_slowRepaintObjectCount--; 832 if (!m_slowRepaintObjectCount) 833 setCanBlitOnScroll(!useSlowRepaints()); 834 } 835 836 void FrameView::setIsOverlapped(bool isOverlapped) 837 { 838 if (isOverlapped == m_isOverlapped) 839 return; 840 841 m_isOverlapped = isOverlapped; 842 setCanBlitOnScroll(!useSlowRepaints()); 843 } 844 845 void FrameView::setContentIsOpaque(bool contentIsOpaque) 846 { 847 if (contentIsOpaque == m_contentIsOpaque) 848 return; 849 850 m_contentIsOpaque = contentIsOpaque; 851 setCanBlitOnScroll(!useSlowRepaints()); 852 } 853 854 void FrameView::restoreScrollbar() 855 { 856 setScrollbarsSuppressed(false); 857 } 858 859 bool FrameView::scrollToFragment(const KURL& url) 860 { 861 // If our URL has no ref, then we have no place we need to jump to. 862 // OTOH If CSS target was set previously, we want to set it to 0, recalc 863 // and possibly repaint because :target pseudo class may have been 864 // set (see bug 11321). 865 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget()) 866 return false; 867 868 String fragmentIdentifier = url.fragmentIdentifier(); 869 if (scrollToAnchor(fragmentIdentifier)) 870 return true; 871 872 // Try again after decoding the ref, based on the document's encoding. 873 if (TextResourceDecoder* decoder = m_frame->document()->decoder()) 874 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding())); 875 876 return false; 877 } 878 879 bool FrameView::scrollToAnchor(const String& name) 880 { 881 ASSERT(m_frame->document()); 882 883 if (!m_frame->document()->haveStylesheetsLoaded()) { 884 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true); 885 return false; 886 } 887 888 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false); 889 890 Element* anchorNode = m_frame->document()->findAnchor(name); 891 892 #if ENABLE(SVG) 893 if (m_frame->document()->isSVGDocument()) { 894 if (name.startsWith("xpointer(")) { 895 // We need to parse the xpointer reference here 896 } else if (name.startsWith("svgView(")) { 897 RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement(); 898 if (!svg->currentView()->parseViewSpec(name)) 899 return false; 900 svg->setUseCurrentView(true); 901 } else { 902 if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) { 903 RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0; 904 if (viewElement.get()) { 905 RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(SVGLocatable::nearestViewportElement(viewElement.get())); 906 svg->inheritViewAttributes(viewElement.get()); 907 } 908 } 909 } 910 // FIXME: need to decide which <svg> to focus on, and zoom to that one 911 // FIXME: need to actually "highlight" the viewTarget(s) 912 } 913 #endif 914 915 m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target. 916 917 // Implement the rule that "" and "top" both mean top of page as in other browsers. 918 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top"))) 919 return false; 920 921 #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR 922 // TODO(andreip): check with Grace if this is correct. 923 android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedClick(true); 924 #endif 925 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document()); 926 #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR 927 android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedClick(false); 928 #endif 929 return true; 930 } 931 932 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode) 933 { 934 m_maintainScrollPositionAnchor = anchorNode; 935 if (!m_maintainScrollPositionAnchor) 936 return; 937 938 // We need to update the layout before scrolling, otherwise we could 939 // really mess things up if an anchor scroll comes at a bad moment. 940 m_frame->document()->updateStyleIfNeeded(); 941 // Only do a layout if changes have occurred that make it necessary. 942 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) 943 layout(); 944 else 945 scrollToAnchor(); 946 } 947 948 void FrameView::scrollRectIntoViewRecursively(const IntRect& r) 949 { 950 bool wasInProgrammaticScroll = m_inProgrammaticScroll; 951 m_inProgrammaticScroll = true; 952 m_maintainScrollPositionAnchor = 0; 953 ScrollView::scrollRectIntoViewRecursively(r); 954 m_inProgrammaticScroll = wasInProgrammaticScroll; 955 } 956 957 void FrameView::setScrollPosition(const IntPoint& scrollPoint) 958 { 959 bool wasInProgrammaticScroll = m_inProgrammaticScroll; 960 m_inProgrammaticScroll = true; 961 m_maintainScrollPositionAnchor = 0; 962 ScrollView::setScrollPosition(scrollPoint); 963 m_inProgrammaticScroll = wasInProgrammaticScroll; 964 } 965 966 void FrameView::scrollPositionChanged() 967 { 968 frame()->eventHandler()->sendScrollEvent(); 969 970 // For fixed position elements, update widget positions and compositing layers after scrolling, 971 // but only if we're not inside of layout. 972 // FIXME: we could skip this if we knew the page had no fixed position elements. 973 if (!m_nestedLayoutCount) { 974 if (RenderView* root = m_frame->contentRenderer()) { 975 root->updateWidgetPositions(); 976 #if USE(ACCELERATED_COMPOSITING) 977 if (root->usesCompositing()) 978 root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll); 979 #endif 980 } 981 } 982 } 983 984 HostWindow* FrameView::hostWindow() const 985 { 986 Page* page = frame() ? frame()->page() : 0; 987 if (!page) 988 return 0; 989 return page->chrome(); 990 } 991 992 const unsigned cRepaintRectUnionThreshold = 25; 993 994 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate) 995 { 996 ASSERT(!m_frame->document()->ownerElement()); 997 998 double delay = adjustedDeferredRepaintDelay(); 999 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) { 1000 IntRect paintRect = r; 1001 if (!paintsEntireContents()) 1002 paintRect.intersect(visibleContentRect()); 1003 #ifdef ANDROID_CAPTURE_OFFSCREEN_PAINTS 1004 if (r != paintRect) 1005 ScrollView::platformOffscreenContentRectangle(visibleContentRect(), r); 1006 #endif 1007 if (paintRect.isEmpty()) 1008 return; 1009 if (m_repaintCount == cRepaintRectUnionThreshold) { 1010 IntRect unionedRect; 1011 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i) 1012 unionedRect.unite(m_repaintRects[i]); 1013 m_repaintRects.clear(); 1014 m_repaintRects.append(unionedRect); 1015 } 1016 if (m_repaintCount < cRepaintRectUnionThreshold) 1017 m_repaintRects.append(paintRect); 1018 else 1019 m_repaintRects[0].unite(paintRect); 1020 m_repaintCount++; 1021 1022 if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive()) 1023 m_deferredRepaintTimer.startOneShot(delay); 1024 return; 1025 } 1026 1027 if (!immediate && isOffscreen() && !shouldUpdateWhileOffscreen()) 1028 return; 1029 1030 ScrollView::repaintContentRectangle(r, immediate); 1031 } 1032 1033 void FrameView::visibleContentsResized() 1034 { 1035 // We check to make sure the view is attached to a frame() as this method can 1036 // be triggered before the view is attached by Frame::createView(...) setting 1037 // various values such as setScrollBarModes(...) for example. An ASSERT is 1038 // triggered when a view is layout before being attached to a frame(). 1039 if (!frame()->view()) 1040 return; 1041 1042 if (needsLayout()) 1043 layout(); 1044 } 1045 1046 void FrameView::beginDeferredRepaints() 1047 { 1048 Page* page = m_frame->page(); 1049 if (page->mainFrame() != m_frame) 1050 return page->mainFrame()->view()->beginDeferredRepaints(); 1051 1052 m_deferringRepaints++; 1053 } 1054 1055 1056 void FrameView::endDeferredRepaints() 1057 { 1058 Page* page = m_frame->page(); 1059 if (page->mainFrame() != m_frame) 1060 return page->mainFrame()->view()->endDeferredRepaints(); 1061 1062 ASSERT(m_deferringRepaints > 0); 1063 1064 if (--m_deferringRepaints) 1065 return; 1066 1067 if (m_deferredRepaintTimer.isActive()) 1068 return; 1069 1070 if (double delay = adjustedDeferredRepaintDelay()) { 1071 m_deferredRepaintTimer.startOneShot(delay); 1072 return; 1073 } 1074 1075 doDeferredRepaints(); 1076 } 1077 1078 void FrameView::checkStopDelayingDeferredRepaints() 1079 { 1080 if (!m_deferredRepaintTimer.isActive()) 1081 return; 1082 1083 Document* document = m_frame->document(); 1084 if (document && (document->parsing() || document->docLoader()->requestCount())) 1085 return; 1086 1087 m_deferredRepaintTimer.stop(); 1088 1089 doDeferredRepaints(); 1090 } 1091 1092 void FrameView::doDeferredRepaints() 1093 { 1094 ASSERT(!m_deferringRepaints); 1095 if (isOffscreen() && !shouldUpdateWhileOffscreen()) { 1096 m_repaintRects.clear(); 1097 m_repaintCount = 0; 1098 return; 1099 } 1100 unsigned size = m_repaintRects.size(); 1101 for (unsigned i = 0; i < size; i++) 1102 ScrollView::repaintContentRectangle(m_repaintRects[i], false); 1103 m_repaintRects.clear(); 1104 m_repaintCount = 0; 1105 1106 updateDeferredRepaintDelay(); 1107 } 1108 1109 void FrameView::updateDeferredRepaintDelay() 1110 { 1111 Document* document = m_frame->document(); 1112 if (!document || (!document->parsing() && !document->docLoader()->requestCount())) { 1113 m_deferredRepaintDelay = deferredRepaintDelay; 1114 return; 1115 } 1116 if (m_deferredRepaintDelay < maxDeferredRepaintDelayDuringLoading) { 1117 m_deferredRepaintDelay += deferredRepaintDelayIncrementDuringLoading; 1118 if (m_deferredRepaintDelay > maxDeferredRepaintDelayDuringLoading) 1119 m_deferredRepaintDelay = maxDeferredRepaintDelayDuringLoading; 1120 } 1121 } 1122 1123 void FrameView::resetDeferredRepaintDelay() 1124 { 1125 m_deferredRepaintDelay = 0; 1126 if (m_deferredRepaintTimer.isActive()) { 1127 m_deferredRepaintTimer.stop(); 1128 if (!m_deferringRepaints) 1129 doDeferredRepaints(); 1130 } 1131 } 1132 1133 double FrameView::adjustedDeferredRepaintDelay() const 1134 { 1135 if (!m_deferredRepaintDelay) 1136 return 0; 1137 double timeSinceLastPaint = currentTime() - m_lastPaintTime; 1138 return max(0., m_deferredRepaintDelay - timeSinceLastPaint); 1139 } 1140 1141 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*) 1142 { 1143 doDeferredRepaints(); 1144 } 1145 1146 void FrameView::layoutTimerFired(Timer<FrameView>*) 1147 { 1148 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1149 if (!m_frame->document()->ownerElement()) 1150 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime()); 1151 #endif 1152 layout(); 1153 } 1154 1155 void FrameView::scheduleRelayout() 1156 { 1157 // FIXME: We should assert the page is not in the page cache, but that is causing 1158 // too many false assertions. See <rdar://problem/7218118>. 1159 ASSERT(m_frame->view() == this); 1160 1161 if (m_layoutRoot) { 1162 m_layoutRoot->markContainingBlocksForLayout(false); 1163 m_layoutRoot = 0; 1164 } 1165 if (!m_layoutSchedulingEnabled) 1166 return; 1167 if (!needsLayout()) 1168 return; 1169 if (!m_frame->document()->shouldScheduleLayout()) 1170 return; 1171 1172 #if defined(FLATTEN_IFRAME) || defined(FLATTEN_FRAMESET) 1173 // This is the Android frame flattening code. The common code below is not 1174 // used as frameSetFlatteningEnabled() is false on Android. 1175 if (m_frame->ownerRenderer()) 1176 m_frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc(); 1177 #endif 1178 1179 // When frameset flattening is enabled, the contents of the frame affects layout of the parent frames. 1180 // Also invalidate parent frame starting from the owner element of this frame. 1181 if (m_frame->settings()->frameSetFlatteningEnabled() && m_frame->ownerRenderer()) 1182 m_frame->ownerRenderer()->setNeedsLayout(true, true); 1183 1184 int delay = m_frame->document()->minimumLayoutDelay(); 1185 if (m_layoutTimer.isActive() && m_delayedLayout && !delay) 1186 unscheduleRelayout(); 1187 if (m_layoutTimer.isActive()) 1188 return; 1189 1190 m_delayedLayout = delay != 0; 1191 1192 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1193 if (!m_frame->document()->ownerElement()) 1194 printf("Scheduling layout for %d\n", delay); 1195 #endif 1196 1197 m_layoutTimer.startOneShot(delay * 0.001); 1198 } 1199 1200 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant) 1201 { 1202 for (RenderObject* r = descendant; r; r = r->container()) { 1203 if (r == ancestor) 1204 return true; 1205 } 1206 return false; 1207 } 1208 1209 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot) 1210 { 1211 ASSERT(m_frame->view() == this); 1212 1213 if (!m_layoutSchedulingEnabled || (m_frame->contentRenderer() 1214 && m_frame->contentRenderer()->needsLayout())) { 1215 if (relayoutRoot) 1216 relayoutRoot->markContainingBlocksForLayout(false); 1217 return; 1218 } 1219 1220 if (layoutPending()) { 1221 if (m_layoutRoot != relayoutRoot) { 1222 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) { 1223 // Keep the current root 1224 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot); 1225 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) { 1226 // Re-root at relayoutRoot 1227 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot); 1228 m_layoutRoot = relayoutRoot; 1229 } else { 1230 // Just do a full relayout 1231 if (m_layoutRoot) 1232 m_layoutRoot->markContainingBlocksForLayout(false); 1233 m_layoutRoot = 0; 1234 relayoutRoot->markContainingBlocksForLayout(false); 1235 } 1236 } 1237 } else { 1238 int delay = m_frame->document()->minimumLayoutDelay(); 1239 m_layoutRoot = relayoutRoot; 1240 m_delayedLayout = delay != 0; 1241 m_layoutTimer.startOneShot(delay * 0.001); 1242 } 1243 } 1244 1245 bool FrameView::layoutPending() const 1246 { 1247 return m_layoutTimer.isActive(); 1248 } 1249 1250 bool FrameView::needsLayout() const 1251 { 1252 // This can return true in cases where the document does not have a body yet. 1253 // Document::shouldScheduleLayout takes care of preventing us from scheduling 1254 // layout in that case. 1255 if (!m_frame) 1256 return false; 1257 RenderView* root = m_frame->contentRenderer(); 1258 Document* document = m_frame->document(); 1259 return layoutPending() 1260 || (root && root->needsLayout()) 1261 || m_layoutRoot 1262 || (document && document->childNeedsStyleRecalc()) // can occur when using WebKit ObjC interface 1263 || m_frame->needsReapplyStyles() 1264 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred); 1265 } 1266 1267 void FrameView::setNeedsLayout() 1268 { 1269 if (m_deferSetNeedsLayouts) { 1270 m_setNeedsLayoutWasDeferred = true; 1271 return; 1272 } 1273 RenderView* root = m_frame->contentRenderer(); 1274 if (root) 1275 root->setNeedsLayout(true); 1276 } 1277 1278 void FrameView::unscheduleRelayout() 1279 { 1280 if (!m_layoutTimer.isActive()) 1281 return; 1282 1283 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1284 if (!m_frame->document()->ownerElement()) 1285 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime()); 1286 #endif 1287 1288 m_layoutTimer.stop(); 1289 m_delayedLayout = false; 1290 } 1291 1292 bool FrameView::isTransparent() const 1293 { 1294 return m_isTransparent; 1295 } 1296 1297 void FrameView::setTransparent(bool isTransparent) 1298 { 1299 m_isTransparent = isTransparent; 1300 } 1301 1302 Color FrameView::baseBackgroundColor() const 1303 { 1304 return m_baseBackgroundColor; 1305 } 1306 1307 void FrameView::setBaseBackgroundColor(Color bc) 1308 { 1309 if (!bc.isValid()) 1310 bc = Color::white; 1311 m_baseBackgroundColor = bc; 1312 } 1313 1314 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent) 1315 { 1316 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) { 1317 FrameView* view = frame->view(); 1318 if (!view) 1319 continue; 1320 1321 view->setTransparent(transparent); 1322 view->setBaseBackgroundColor(backgroundColor); 1323 } 1324 } 1325 1326 bool FrameView::shouldUpdateWhileOffscreen() const 1327 { 1328 return m_shouldUpdateWhileOffscreen; 1329 } 1330 1331 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen) 1332 { 1333 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen; 1334 } 1335 1336 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget) 1337 { 1338 if (!m_enqueueEvents) { 1339 ExceptionCode ec = 0; 1340 eventTarget->dispatchEvent(event, ec); 1341 return; 1342 } 1343 1344 ScheduledEvent* scheduledEvent = new ScheduledEvent; 1345 scheduledEvent->m_event = event; 1346 scheduledEvent->m_eventTarget = eventTarget; 1347 m_scheduledEvents.append(scheduledEvent); 1348 } 1349 1350 void FrameView::pauseScheduledEvents() 1351 { 1352 ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents); 1353 m_enqueueEvents++; 1354 } 1355 1356 void FrameView::resumeScheduledEvents() 1357 { 1358 m_enqueueEvents--; 1359 if (!m_enqueueEvents) 1360 dispatchScheduledEvents(); 1361 ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents); 1362 } 1363 1364 void FrameView::scrollToAnchor() 1365 { 1366 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor; 1367 if (!anchorNode) 1368 return; 1369 1370 if (!anchorNode->renderer()) 1371 return; 1372 1373 IntRect rect; 1374 if (anchorNode != m_frame->document()) 1375 rect = anchorNode->getRect(); 1376 1377 // Scroll nested layers and frames to reveal the anchor. 1378 // Align to the top and to the closest side (this matches other browsers). 1379 anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways); 1380 1381 if (AXObjectCache::accessibilityEnabled()) 1382 m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get()); 1383 1384 // scrollRectToVisible can call into scrollRectIntoViewRecursively(), which resets m_maintainScrollPositionAnchor. 1385 m_maintainScrollPositionAnchor = anchorNode; 1386 } 1387 1388 bool FrameView::updateWidgets() 1389 { 1390 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty()) 1391 return true; 1392 1393 Vector<RenderEmbeddedObject*> objectVector; 1394 copyToVector(*m_widgetUpdateSet, objectVector); 1395 size_t size = objectVector.size(); 1396 for (size_t i = 0; i < size; ++i) { 1397 RenderEmbeddedObject* object = objectVector[i]; 1398 object->updateWidget(false); 1399 1400 // updateWidget() can destroy the RenderPartObject, so we need to make sure it's 1401 // alive by checking if it's still in m_widgetUpdateSet. 1402 if (m_widgetUpdateSet->contains(object)) { 1403 object->updateWidgetPosition(); 1404 m_widgetUpdateSet->remove(object); 1405 } 1406 } 1407 1408 return m_widgetUpdateSet->isEmpty(); 1409 } 1410 1411 void FrameView::performPostLayoutTasks() 1412 { 1413 if (m_firstLayoutCallbackPending) { 1414 m_firstLayoutCallbackPending = false; 1415 m_frame->loader()->didFirstLayout(); 1416 } 1417 1418 if (m_isVisuallyNonEmpty && m_firstVisuallyNonEmptyLayoutCallbackPending) { 1419 m_firstVisuallyNonEmptyLayoutCallbackPending = false; 1420 m_frame->loader()->didFirstVisuallyNonEmptyLayout(); 1421 } 1422 1423 RenderView* root = m_frame->contentRenderer(); 1424 1425 root->updateWidgetPositions(); 1426 1427 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) { 1428 if (updateWidgets()) 1429 break; 1430 } 1431 1432 scrollToAnchor(); 1433 1434 resumeScheduledEvents(); 1435 1436 if (!root->printing()) { 1437 IntSize currentSize = IntSize(width(), height()); 1438 float currentZoomFactor = root->style()->zoom(); 1439 bool resized = !m_firstLayout && (currentSize != m_lastLayoutSize || currentZoomFactor != m_lastZoomFactor); 1440 m_lastLayoutSize = currentSize; 1441 m_lastZoomFactor = currentZoomFactor; 1442 if (resized) 1443 m_frame->eventHandler()->sendResizeEvent(); 1444 } 1445 } 1446 1447 void FrameView::postLayoutTimerFired(Timer<FrameView>*) 1448 { 1449 performPostLayoutTasks(); 1450 } 1451 1452 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow) 1453 { 1454 if (!m_viewportRenderer) 1455 return; 1456 1457 if (m_overflowStatusDirty) { 1458 m_horizontalOverflow = horizontalOverflow; 1459 m_verticalOverflow = verticalOverflow; 1460 m_overflowStatusDirty = false; 1461 return; 1462 } 1463 1464 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow); 1465 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow); 1466 1467 if (horizontalOverflowChanged || verticalOverflowChanged) { 1468 m_horizontalOverflow = horizontalOverflow; 1469 m_verticalOverflow = verticalOverflow; 1470 1471 scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, 1472 verticalOverflowChanged, verticalOverflow), 1473 m_viewportRenderer->node()); 1474 } 1475 1476 } 1477 1478 void FrameView::dispatchScheduledEvents() 1479 { 1480 if (m_scheduledEvents.isEmpty()) 1481 return; 1482 1483 Vector<ScheduledEvent*> scheduledEventsCopy = m_scheduledEvents; 1484 m_scheduledEvents.clear(); 1485 1486 Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end(); 1487 for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) { 1488 ScheduledEvent* scheduledEvent = *it; 1489 1490 ExceptionCode ec = 0; 1491 1492 // Only dispatch events to nodes that are in the document 1493 if (scheduledEvent->m_eventTarget->inDocument()) 1494 scheduledEvent->m_eventTarget->dispatchEvent(scheduledEvent->m_event, ec); 1495 1496 delete scheduledEvent; 1497 } 1498 } 1499 1500 IntRect FrameView::windowClipRect(bool clipToContents) const 1501 { 1502 ASSERT(m_frame->view() == this); 1503 1504 // Set our clip rect to be our contents. 1505 IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents)); 1506 if (!m_frame || !m_frame->document()->ownerElement()) 1507 return clipRect; 1508 1509 // Take our owner element and get the clip rect from the enclosing layer. 1510 Element* elt = m_frame->document()->ownerElement(); 1511 RenderLayer* layer = elt->renderer()->enclosingLayer(); 1512 // FIXME: layer should never be null, but sometimes seems to be anyway. 1513 if (!layer) 1514 return clipRect; 1515 FrameView* parentView = elt->document()->view(); 1516 clipRect.intersect(parentView->windowClipRectForLayer(layer, true)); 1517 return clipRect; 1518 } 1519 1520 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const 1521 { 1522 // If we have no layer, just return our window clip rect. 1523 if (!layer) 1524 return windowClipRect(); 1525 1526 // Apply the clip from the layer. 1527 IntRect clipRect; 1528 if (clipToLayerContents) 1529 clipRect = layer->childrenClipRect(); 1530 else 1531 clipRect = layer->selfClipRect(); 1532 clipRect = contentsToWindow(clipRect); 1533 return intersection(clipRect, windowClipRect()); 1534 } 1535 1536 bool FrameView::isActive() const 1537 { 1538 Page* page = frame()->page(); 1539 return page && page->focusController()->isActive(); 1540 } 1541 1542 void FrameView::valueChanged(Scrollbar* bar) 1543 { 1544 // Figure out if we really moved. 1545 IntSize offset = scrollOffset(); 1546 ScrollView::valueChanged(bar); 1547 if (offset != scrollOffset()) 1548 frame()->eventHandler()->sendScrollEvent(); 1549 frame()->loader()->client()->didChangeScrollOffset(); 1550 } 1551 1552 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect) 1553 { 1554 // Add in our offset within the FrameView. 1555 IntRect dirtyRect = rect; 1556 dirtyRect.move(scrollbar->x(), scrollbar->y()); 1557 invalidateRect(dirtyRect); 1558 } 1559 1560 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const 1561 { 1562 tickmarks = frame()->document()->renderedRectsForMarkers(DocumentMarker::TextMatch); 1563 } 1564 1565 IntRect FrameView::windowResizerRect() const 1566 { 1567 Page* page = frame() ? frame()->page() : 0; 1568 if (!page) 1569 return IntRect(); 1570 return page->chrome()->windowResizerRect(); 1571 } 1572 1573 #if ENABLE(DASHBOARD_SUPPORT) 1574 void FrameView::updateDashboardRegions() 1575 { 1576 Document* document = m_frame->document(); 1577 if (!document->hasDashboardRegions()) 1578 return; 1579 Vector<DashboardRegionValue> newRegions; 1580 document->renderBox()->collectDashboardRegions(newRegions); 1581 if (newRegions == document->dashboardRegions()) 1582 return; 1583 document->setDashboardRegions(newRegions); 1584 Page* page = m_frame->page(); 1585 if (!page) 1586 return; 1587 page->chrome()->client()->dashboardRegionsChanged(); 1588 } 1589 #endif 1590 1591 void FrameView::invalidateScrollCorner() 1592 { 1593 invalidateRect(scrollCornerRect()); 1594 } 1595 1596 void FrameView::updateScrollCorner() 1597 { 1598 RenderObject* renderer = 0; 1599 RefPtr<RenderStyle> cornerStyle; 1600 1601 if (!scrollCornerRect().isEmpty()) { 1602 // Try the <body> element first as a scroll corner source. 1603 Document* doc = m_frame->document(); 1604 Element* body = doc ? doc->body() : 0; 1605 if (body && body->renderer()) { 1606 renderer = body->renderer(); 1607 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style()); 1608 } 1609 1610 if (!cornerStyle) { 1611 // If the <body> didn't have a custom style, then the root element might. 1612 Element* docElement = doc ? doc->documentElement() : 0; 1613 if (docElement && docElement->renderer()) { 1614 renderer = docElement->renderer(); 1615 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style()); 1616 } 1617 } 1618 1619 if (!cornerStyle) { 1620 // If we have an owning iframe/frame element, then it can set the custom scrollbar also. 1621 if (RenderPart* renderer = m_frame->ownerRenderer()) 1622 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style()); 1623 } 1624 } 1625 1626 if (cornerStyle) { 1627 if (!m_scrollCorner) 1628 m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document()); 1629 m_scrollCorner->setStyle(cornerStyle.release()); 1630 invalidateRect(scrollCornerRect()); 1631 } else if (m_scrollCorner) { 1632 m_scrollCorner->destroy(); 1633 m_scrollCorner = 0; 1634 } 1635 } 1636 1637 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect) 1638 { 1639 if (context->updatingControlTints()) { 1640 updateScrollCorner(); 1641 return; 1642 } 1643 1644 if (m_scrollCorner) { 1645 m_scrollCorner->paintIntoRect(context, cornerRect.x(), cornerRect.y(), cornerRect); 1646 return; 1647 } 1648 1649 ScrollView::paintScrollCorner(context, cornerRect); 1650 } 1651 1652 bool FrameView::hasCustomScrollbars() const 1653 { 1654 const HashSet<RefPtr<Widget> >* viewChildren = children(); 1655 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end(); 1656 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) { 1657 Widget* widget = current->get(); 1658 if (widget->isFrameView()) { 1659 if (static_cast<FrameView*>(widget)->hasCustomScrollbars()) 1660 return true; 1661 } else if (widget->isScrollbar()) { 1662 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget); 1663 if (scrollbar->isCustomScrollbar()) 1664 return true; 1665 } 1666 } 1667 1668 return false; 1669 } 1670 1671 void FrameView::updateControlTints() 1672 { 1673 // This is called when control tints are changed from aqua/graphite to clear and vice versa. 1674 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate. 1675 // This is only done if the theme supports control tinting. It's up to the theme and platform 1676 // to define when controls get the tint and to call this function when that changes. 1677 1678 // Optimize the common case where we bring a window to the front while it's still empty. 1679 if (!m_frame || m_frame->loader()->url().isEmpty()) 1680 return; 1681 1682 if ((m_frame->contentRenderer() && m_frame->contentRenderer()->theme()->supportsControlTints()) || hasCustomScrollbars()) { 1683 if (needsLayout()) 1684 layout(); 1685 PlatformGraphicsContext* const noContext = 0; 1686 GraphicsContext context(noContext); 1687 context.setUpdatingControlTints(true); 1688 if (platformWidget()) 1689 paintContents(&context, visibleContentRect()); 1690 else 1691 paint(&context, frameRect()); 1692 } 1693 } 1694 1695 bool FrameView::wasScrolledByUser() const 1696 { 1697 return m_wasScrolledByUser; 1698 } 1699 1700 void FrameView::setWasScrolledByUser(bool wasScrolledByUser) 1701 { 1702 if (m_inProgrammaticScroll) 1703 return; 1704 m_maintainScrollPositionAnchor = 0; 1705 m_wasScrolledByUser = wasScrolledByUser; 1706 } 1707 1708 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) 1709 { 1710 if (!frame()) 1711 return; 1712 1713 #if ENABLE(INSPECTOR) 1714 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent()) 1715 timelineAgent->willPaint(rect); 1716 #endif 1717 1718 Document* document = frame()->document(); 1719 1720 #ifndef NDEBUG 1721 bool fillWithRed; 1722 if (document->printing()) 1723 fillWithRed = false; // Printing, don't fill with red (can't remember why). 1724 else if (document->ownerElement()) 1725 fillWithRed = false; // Subframe, don't fill with red. 1726 else if (isTransparent()) 1727 fillWithRed = false; // Transparent, don't fill with red. 1728 else if (m_paintBehavior & PaintBehaviorSelectionOnly) 1729 fillWithRed = false; // Selections are transparent, don't fill with red. 1730 else if (m_nodeToDraw) 1731 fillWithRed = false; // Element images are transparent, don't fill with red. 1732 else 1733 fillWithRed = true; 1734 1735 if (fillWithRed) 1736 p->fillRect(rect, Color(0xFF, 0, 0), DeviceColorSpace); 1737 #endif 1738 1739 bool isTopLevelPainter = !sCurrentPaintTimeStamp; 1740 if (isTopLevelPainter) 1741 sCurrentPaintTimeStamp = currentTime(); 1742 1743 RenderView* contentRenderer = frame()->contentRenderer(); 1744 if (!contentRenderer) { 1745 LOG_ERROR("called Frame::paint with nil renderer"); 1746 return; 1747 } 1748 1749 ASSERT(!needsLayout()); 1750 if (needsLayout()) 1751 return; 1752 1753 #if USE(ACCELERATED_COMPOSITING) 1754 if (!p->paintingDisabled()) { 1755 if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer()) 1756 rootLayer->syncCompositingState(); 1757 } 1758 #endif 1759 1760 ASSERT(!m_isPainting); 1761 1762 m_isPainting = true; 1763 1764 // m_nodeToDraw is used to draw only one element (and its descendants) 1765 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0; 1766 1767 PaintBehavior paintBehavior = m_paintBehavior; 1768 if (paintBehavior == PaintBehaviorNormal) 1769 document->invalidateRenderedRectsForMarkersInRect(rect); 1770 1771 if (document->printing()) 1772 paintBehavior |= PaintBehaviorFlattenCompositingLayers; 1773 1774 contentRenderer->layer()->paint(p, rect, paintBehavior, eltRenderer); 1775 1776 m_isPainting = false; 1777 m_lastPaintTime = currentTime(); 1778 1779 #if ENABLE(DASHBOARD_SUPPORT) 1780 // Regions may have changed as a result of the visibility/z-index of element changing. 1781 if (document->dashboardRegionsDirty()) 1782 updateDashboardRegions(); 1783 #endif 1784 1785 if (isTopLevelPainter) 1786 sCurrentPaintTimeStamp = 0; 1787 1788 #if ENABLE(INSPECTOR) 1789 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent()) 1790 timelineAgent->didPaint(); 1791 #endif 1792 } 1793 1794 void FrameView::setPaintBehavior(PaintBehavior behavior) 1795 { 1796 m_paintBehavior = behavior; 1797 } 1798 1799 bool FrameView::isPainting() const 1800 { 1801 return m_isPainting; 1802 } 1803 1804 void FrameView::setNodeToDraw(Node* node) 1805 { 1806 m_nodeToDraw = node; 1807 } 1808 1809 void FrameView::layoutIfNeededRecursive() 1810 { 1811 // We have to crawl our entire tree looking for any FrameViews that need 1812 // layout and make sure they are up to date. 1813 // Mac actually tests for intersection with the dirty region and tries not to 1814 // update layout for frames that are outside the dirty region. Not only does this seem 1815 // pointless (since those frames will have set a zero timer to layout anyway), but 1816 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty 1817 // region but then become included later by the second frame adding rects to the dirty region 1818 // when it lays out. 1819 1820 if (needsLayout()) 1821 layout(); 1822 1823 const HashSet<RefPtr<Widget> >* viewChildren = children(); 1824 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end(); 1825 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) { 1826 Widget* widget = (*current).get(); 1827 if (widget->isFrameView()) 1828 static_cast<FrameView*>(widget)->layoutIfNeededRecursive(); 1829 } 1830 1831 // layoutIfNeededRecursive is called when we need to make sure layout is up-to-date before 1832 // painting, so we need to flush out any deferred repaints too. 1833 flushDeferredRepaints(); 1834 } 1835 1836 void FrameView::flushDeferredRepaints() 1837 { 1838 if (!m_deferredRepaintTimer.isActive()) 1839 return; 1840 m_deferredRepaintTimer.stop(); 1841 doDeferredRepaints(); 1842 } 1843 1844 void FrameView::forceLayout(bool allowSubtree) 1845 { 1846 layout(allowSubtree); 1847 // We cannot unschedule a pending relayout, since the force can be called with 1848 // a tiny rectangle from a drawRect update. By unscheduling we in effect 1849 // "validate" and stop the necessary full repaint from occurring. Basically any basic 1850 // append/remove DHTML is broken by this call. For now, I have removed the optimization 1851 // until we have a better invalidation stategy. -dwh 1852 //unscheduleRelayout(); 1853 } 1854 1855 void FrameView::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth, bool _adjustViewSize) 1856 { 1857 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see 1858 // the state of things before and after the layout 1859 RenderView *root = toRenderView(m_frame->document()->renderer()); 1860 if (root) { 1861 // This magic is basically copied from khtmlview::print 1862 int pageW = (int)ceilf(minPageWidth); 1863 root->setWidth(pageW); 1864 root->setNeedsLayoutAndPrefWidthsRecalc(); 1865 forceLayout(); 1866 1867 // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the 1868 // maximum page width, we will lay out to the maximum page width and clip extra content. 1869 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping 1870 // implementation should not do this! 1871 int rightmostPos = root->rightmostPosition(); 1872 if (rightmostPos > minPageWidth) { 1873 pageW = std::min(rightmostPos, (int)ceilf(maxPageWidth)); 1874 root->setWidth(pageW); 1875 root->setNeedsLayoutAndPrefWidthsRecalc(); 1876 forceLayout(); 1877 } 1878 } 1879 1880 if (_adjustViewSize) 1881 adjustViewSize(); 1882 } 1883 1884 void FrameView::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/) 1885 { 1886 RenderView* root = m_frame->contentRenderer(); 1887 if (root) { 1888 // Use a context with painting disabled. 1889 GraphicsContext context((PlatformGraphicsContext*)0); 1890 root->setTruncatedAt((int)floorf(oldBottom)); 1891 IntRect dirtyRect(0, (int)floorf(oldTop), root->rightLayoutOverflow(), (int)ceilf(oldBottom - oldTop)); 1892 root->layer()->paint(&context, dirtyRect); 1893 *newBottom = root->bestTruncatedAt(); 1894 if (*newBottom == 0) 1895 *newBottom = oldBottom; 1896 } else 1897 *newBottom = oldBottom; 1898 } 1899 1900 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const 1901 { 1902 IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox(); 1903 1904 // Convert from page ("absolute") to FrameView coordinates. 1905 rect.move(-scrollX(), -scrollY()); 1906 1907 return rect; 1908 } 1909 1910 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const 1911 { 1912 IntRect rect = viewRect; 1913 1914 // Convert from FrameView coords into page ("absolute") coordinates. 1915 rect.move(scrollX(), scrollY()); 1916 1917 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just 1918 // move the rect for now. 1919 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */))); 1920 return rect; 1921 } 1922 1923 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const 1924 { 1925 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */)); 1926 1927 // Convert from page ("absolute") to FrameView coordinates. 1928 point.move(-scrollX(), -scrollY()); 1929 return point; 1930 } 1931 1932 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const 1933 { 1934 IntPoint point = viewPoint; 1935 1936 // Convert from FrameView coords into page ("absolute") coordinates. 1937 point += IntSize(scrollX(), scrollY()); 1938 1939 return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */)); 1940 } 1941 1942 IntRect FrameView::convertToContainingView(const IntRect& localRect) const 1943 { 1944 if (const ScrollView* parentScrollView = parent()) { 1945 if (parentScrollView->isFrameView()) { 1946 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView); 1947 // Get our renderer in the parent view 1948 RenderPart* renderer = m_frame->ownerRenderer(); 1949 if (!renderer) 1950 return localRect; 1951 1952 IntRect rect(localRect); 1953 // Add borders and padding?? 1954 rect.move(renderer->borderLeft() + renderer->paddingLeft(), 1955 renderer->borderTop() + renderer->paddingTop()); 1956 return parentView->convertFromRenderer(renderer, rect); 1957 } 1958 1959 return Widget::convertToContainingView(localRect); 1960 } 1961 1962 return localRect; 1963 } 1964 1965 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const 1966 { 1967 if (const ScrollView* parentScrollView = parent()) { 1968 if (parentScrollView->isFrameView()) { 1969 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView); 1970 1971 // Get our renderer in the parent view 1972 RenderPart* renderer = m_frame->ownerRenderer(); 1973 if (!renderer) 1974 return parentRect; 1975 1976 IntRect rect = parentView->convertToRenderer(renderer, parentRect); 1977 // Subtract borders and padding 1978 rect.move(-renderer->borderLeft() - renderer->paddingLeft(), 1979 -renderer->borderTop() - renderer->paddingTop()); 1980 return rect; 1981 } 1982 1983 return Widget::convertFromContainingView(parentRect); 1984 } 1985 1986 return parentRect; 1987 } 1988 1989 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const 1990 { 1991 if (const ScrollView* parentScrollView = parent()) { 1992 if (parentScrollView->isFrameView()) { 1993 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView); 1994 1995 // Get our renderer in the parent view 1996 RenderPart* renderer = m_frame->ownerRenderer(); 1997 if (!renderer) 1998 return localPoint; 1999 2000 IntPoint point(localPoint); 2001 2002 // Add borders and padding 2003 point.move(renderer->borderLeft() + renderer->paddingLeft(), 2004 renderer->borderTop() + renderer->paddingTop()); 2005 return parentView->convertFromRenderer(renderer, point); 2006 } 2007 2008 return Widget::convertToContainingView(localPoint); 2009 } 2010 2011 return localPoint; 2012 } 2013 2014 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const 2015 { 2016 if (const ScrollView* parentScrollView = parent()) { 2017 if (parentScrollView->isFrameView()) { 2018 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView); 2019 2020 // Get our renderer in the parent view 2021 RenderPart* renderer = m_frame->ownerRenderer(); 2022 if (!renderer) 2023 return parentPoint; 2024 2025 IntPoint point = parentView->convertToRenderer(renderer, parentPoint); 2026 // Subtract borders and padding 2027 point.move(-renderer->borderLeft() - renderer->paddingLeft(), 2028 -renderer->borderTop() - renderer->paddingTop()); 2029 return point; 2030 } 2031 2032 return Widget::convertFromContainingView(parentPoint); 2033 } 2034 2035 return parentPoint; 2036 } 2037 2038 } // namespace WebCore 2039