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