• 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 
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 
FrameView(Frame * frame)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 
create(Frame * frame)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 
create(Frame * frame,const IntSize & initialSize)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 
~FrameView()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 
reset()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 
isFrameView() const218 bool FrameView::isFrameView() const
219 {
220     return true;
221 }
222 
clearFrame()223 void FrameView::clearFrame()
224 {
225     m_frame = 0;
226 }
227 
resetScrollbars()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 
init()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 
detachCustomScrollbars()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 
clear()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 
didFirstLayout() const295 bool FrameView::didFirstLayout() const
296 {
297     return !m_firstLayout;
298 }
299 
invalidateRect(const IntRect & rect)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 
setMarginWidth(int w)321 void FrameView::setMarginWidth(int w)
322 {
323     // make it update the rendering area when set
324     m_margins.setWidth(w);
325 }
326 
setMarginHeight(int h)327 void FrameView::setMarginHeight(int h)
328 {
329     // make it update the rendering area when set
330     m_margins.setHeight(h);
331 }
332 
setCanHaveScrollbars(bool canHaveScrollbars)333 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
334 {
335     m_canHaveScrollbars = canHaveScrollbars;
336     ScrollView::setCanHaveScrollbars(canHaveScrollbars);
337 }
338 
updateCanHaveScrollbars()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 
createScrollbar(ScrollbarOrientation orientation)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 
setContentsSize(const IntSize & size)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 
adjustViewSize()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 
applyOverflowToViewport(RenderObject * o,ScrollbarMode & hMode,ScrollbarMode & vMode)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)
updateCompositingLayers()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 
setNeedsOneShotDrawingSynchronization()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 
syncCompositingStateRecursive()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 
didMoveOnscreen()499 void FrameView::didMoveOnscreen()
500 {
501     RenderView* view = m_frame->contentRenderer();
502     if (view)
503         view->didMoveOnscreen();
504 }
505 
willMoveOffscreen()506 void FrameView::willMoveOffscreen()
507 {
508     RenderView* view = m_frame->contentRenderer();
509     if (view)
510         view->willMoveOffscreen();
511 }
512 
layoutRoot(bool onlyDuringLayout) const513 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
514 {
515     return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
516 }
517 
layout(bool allowSubtree)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 
addWidgetToUpdate(RenderEmbeddedObject * object)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 
removeWidgetToUpdate(RenderEmbeddedObject * object)783 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object)
784 {
785     if (!m_widgetUpdateSet)
786         return;
787 
788     m_widgetUpdateSet->remove(object);
789 }
790 
setMediaType(const String & mediaType)791 void FrameView::setMediaType(const String& mediaType)
792 {
793     m_mediaType = mediaType;
794 }
795 
mediaType() const796 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 
useSlowRepaints() const805 bool FrameView::useSlowRepaints() const
806 {
807     return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || m_isOverlapped || !m_contentIsOpaque;
808 }
809 
useSlowRepaintsIfNotOverlapped() const810 bool FrameView::useSlowRepaintsIfNotOverlapped() const
811 {
812     return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || !m_contentIsOpaque;
813 }
814 
setUseSlowRepaints()815 void FrameView::setUseSlowRepaints()
816 {
817     m_useSlowRepaints = true;
818     setCanBlitOnScroll(false);
819 }
820 
addSlowRepaintObject()821 void FrameView::addSlowRepaintObject()
822 {
823     if (!m_slowRepaintObjectCount)
824         setCanBlitOnScroll(false);
825     m_slowRepaintObjectCount++;
826 }
827 
removeSlowRepaintObject()828 void FrameView::removeSlowRepaintObject()
829 {
830     ASSERT(m_slowRepaintObjectCount > 0);
831     m_slowRepaintObjectCount--;
832     if (!m_slowRepaintObjectCount)
833         setCanBlitOnScroll(!useSlowRepaints());
834 }
835 
setIsOverlapped(bool isOverlapped)836 void FrameView::setIsOverlapped(bool isOverlapped)
837 {
838     if (isOverlapped == m_isOverlapped)
839         return;
840 
841     m_isOverlapped = isOverlapped;
842     setCanBlitOnScroll(!useSlowRepaints());
843 }
844 
setContentIsOpaque(bool contentIsOpaque)845 void FrameView::setContentIsOpaque(bool contentIsOpaque)
846 {
847     if (contentIsOpaque == m_contentIsOpaque)
848         return;
849 
850     m_contentIsOpaque = contentIsOpaque;
851     setCanBlitOnScroll(!useSlowRepaints());
852 }
853 
restoreScrollbar()854 void FrameView::restoreScrollbar()
855 {
856     setScrollbarsSuppressed(false);
857 }
858 
scrollToFragment(const KURL & url)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 
scrollToAnchor(const String & name)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 
maintainScrollPositionAtAnchor(Node * anchorNode)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 
scrollRectIntoViewRecursively(const IntRect & r)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 
setScrollPosition(const IntPoint & scrollPoint)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 
scrollPositionChanged()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 
hostWindow() const984 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 
repaintContentRectangle(const IntRect & r,bool immediate)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 
visibleContentsResized()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 
beginDeferredRepaints()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 
endDeferredRepaints()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 
checkStopDelayingDeferredRepaints()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 
doDeferredRepaints()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 
updateDeferredRepaintDelay()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 
resetDeferredRepaintDelay()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 
adjustedDeferredRepaintDelay() const1133 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 
deferredRepaintTimerFired(Timer<FrameView> *)1141 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
1142 {
1143     doDeferredRepaints();
1144 }
1145 
layoutTimerFired(Timer<FrameView> *)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 
scheduleRelayout()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 
isObjectAncestorContainerOf(RenderObject * ancestor,RenderObject * descendant)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 
scheduleRelayoutOfSubtree(RenderObject * relayoutRoot)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 
layoutPending() const1245 bool FrameView::layoutPending() const
1246 {
1247     return m_layoutTimer.isActive();
1248 }
1249 
needsLayout() const1250 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 
setNeedsLayout()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 
unscheduleRelayout()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 
isTransparent() const1292 bool FrameView::isTransparent() const
1293 {
1294     return m_isTransparent;
1295 }
1296 
setTransparent(bool isTransparent)1297 void FrameView::setTransparent(bool isTransparent)
1298 {
1299     m_isTransparent = isTransparent;
1300 }
1301 
baseBackgroundColor() const1302 Color FrameView::baseBackgroundColor() const
1303 {
1304     return m_baseBackgroundColor;
1305 }
1306 
setBaseBackgroundColor(Color bc)1307 void FrameView::setBaseBackgroundColor(Color bc)
1308 {
1309     if (!bc.isValid())
1310         bc = Color::white;
1311     m_baseBackgroundColor = bc;
1312 }
1313 
updateBackgroundRecursively(const Color & backgroundColor,bool transparent)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 
shouldUpdateWhileOffscreen() const1326 bool FrameView::shouldUpdateWhileOffscreen() const
1327 {
1328     return m_shouldUpdateWhileOffscreen;
1329 }
1330 
setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)1331 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
1332 {
1333     m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
1334 }
1335 
scheduleEvent(PassRefPtr<Event> event,PassRefPtr<Node> eventTarget)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 
pauseScheduledEvents()1350 void FrameView::pauseScheduledEvents()
1351 {
1352     ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
1353     m_enqueueEvents++;
1354 }
1355 
resumeScheduledEvents()1356 void FrameView::resumeScheduledEvents()
1357 {
1358     m_enqueueEvents--;
1359     if (!m_enqueueEvents)
1360         dispatchScheduledEvents();
1361     ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
1362 }
1363 
scrollToAnchor()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 
updateWidgets()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 
performPostLayoutTasks()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 
postLayoutTimerFired(Timer<FrameView> *)1447 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
1448 {
1449     performPostLayoutTasks();
1450 }
1451 
updateOverflowStatus(bool horizontalOverflow,bool verticalOverflow)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 
dispatchScheduledEvents()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 
windowClipRect(bool clipToContents) const1500 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 
windowClipRectForLayer(const RenderLayer * layer,bool clipToLayerContents) const1520 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 
isActive() const1536 bool FrameView::isActive() const
1537 {
1538     Page* page = frame()->page();
1539     return page && page->focusController()->isActive();
1540 }
1541 
valueChanged(Scrollbar * bar)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 
invalidateScrollbarRect(Scrollbar * scrollbar,const IntRect & rect)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 
getTickmarks(Vector<IntRect> & tickmarks) const1560 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
1561 {
1562     tickmarks = frame()->document()->renderedRectsForMarkers(DocumentMarker::TextMatch);
1563 }
1564 
windowResizerRect() const1565 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)
updateDashboardRegions()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 
invalidateScrollCorner()1591 void FrameView::invalidateScrollCorner()
1592 {
1593     invalidateRect(scrollCornerRect());
1594 }
1595 
updateScrollCorner()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 
paintScrollCorner(GraphicsContext * context,const IntRect & cornerRect)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 
hasCustomScrollbars() const1652 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 
updateControlTints()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 
wasScrolledByUser() const1695 bool FrameView::wasScrolledByUser() const
1696 {
1697     return m_wasScrolledByUser;
1698 }
1699 
setWasScrolledByUser(bool wasScrolledByUser)1700 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
1701 {
1702     if (m_inProgrammaticScroll)
1703         return;
1704     m_maintainScrollPositionAnchor = 0;
1705     m_wasScrolledByUser = wasScrolledByUser;
1706 }
1707 
paintContents(GraphicsContext * p,const IntRect & rect)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 
setPaintBehavior(PaintBehavior behavior)1794 void FrameView::setPaintBehavior(PaintBehavior behavior)
1795 {
1796     m_paintBehavior = behavior;
1797 }
1798 
isPainting() const1799 bool FrameView::isPainting() const
1800 {
1801     return m_isPainting;
1802 }
1803 
setNodeToDraw(Node * node)1804 void FrameView::setNodeToDraw(Node* node)
1805 {
1806     m_nodeToDraw = node;
1807 }
1808 
layoutIfNeededRecursive()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 
flushDeferredRepaints()1836 void FrameView::flushDeferredRepaints()
1837 {
1838     if (!m_deferredRepaintTimer.isActive())
1839         return;
1840     m_deferredRepaintTimer.stop();
1841     doDeferredRepaints();
1842 }
1843 
forceLayout(bool allowSubtree)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 
forceLayoutWithPageWidthRange(float minPageWidth,float maxPageWidth,bool _adjustViewSize)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 
adjustPageHeight(float * newBottom,float oldTop,float oldBottom,float)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 
convertFromRenderer(const RenderObject * renderer,const IntRect & rendererRect) const1900 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 
convertToRenderer(const RenderObject * renderer,const IntRect & viewRect) const1910 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 
convertFromRenderer(const RenderObject * renderer,const IntPoint & rendererPoint) const1923 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 
convertToRenderer(const RenderObject * renderer,const IntPoint & viewPoint) const1932 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 
convertToContainingView(const IntRect & localRect) const1942 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 
convertFromContainingView(const IntRect & parentRect) const1965 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 
convertToContainingView(const IntPoint & localPoint) const1989 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 
convertFromContainingView(const IntPoint & parentPoint) const2014 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