6192c0e8e52a356fe8ad20656513b08be0d62661
[WebKit-https.git] / WebCore / page / FrameView.cpp
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  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "FrameView.h"
28
29 #include "AXObjectCache.h"
30 #include "CSSStyleSelector.h"
31 #include "ChromeClient.h"
32 #include "EventHandler.h"
33 #include "FloatRect.h"
34 #include "FocusController.h"
35 #include "Frame.h"
36 #include "FrameLoader.h"
37 #include "FrameLoaderClient.h"
38 #include "FrameTree.h"
39 #include "GraphicsContext.h"
40 #include "HTMLDocument.h"
41 #include "HTMLFrameElement.h"
42 #include "HTMLFrameSetElement.h"
43 #include "HTMLNames.h"
44 #include "OverflowEvent.h"
45 #include "Page.h"
46 #include "RenderPart.h"
47 #include "RenderPartObject.h"
48 #include "RenderScrollbar.h"
49 #include "RenderTheme.h"
50 #include "RenderView.h"
51 #include "Settings.h"
52 #include "SystemTime.h"
53
54 namespace WebCore {
55
56 using namespace HTMLNames;
57
58 double FrameView::sCurrentPaintTimeStamp = 0.0;
59
60 struct ScheduledEvent {
61     RefPtr<Event> m_event;
62     RefPtr<EventTargetNode> m_eventTarget;
63 };
64
65 class FrameViewPrivate {
66 public:
67     FrameViewPrivate(FrameView* view)
68         : m_slowRepaintObjectCount(0)
69         , m_layoutTimer(view, &FrameView::layoutTimerFired)
70         , m_layoutRoot(0)
71         , m_postLayoutTasksTimer(view, &FrameView::postLayoutTimerFired)
72         , m_mediaType("screen")
73         , m_enqueueEvents(0)
74         , m_overflowStatusDirty(true)
75         , m_viewportRenderer(0)
76         , m_wasScrolledByUser(false)
77         , m_inProgrammaticScroll(false)
78         , m_shouldUpdateWhileOffscreen(true)
79     {
80         m_isTransparent = false;
81         m_baseBackgroundColor = Color::white;
82         m_vmode = m_hmode = ScrollbarAuto;
83         m_needToInitScrollbars = true;
84         reset();
85     }
86     void reset()
87     {
88         m_useSlowRepaints = false;
89         m_borderX = 30;
90         m_borderY = 30;
91         m_layoutTimer.stop();
92         m_layoutRoot = 0;
93         m_delayedLayout = false;
94         m_doFullRepaint = true;
95         m_layoutSchedulingEnabled = true;
96         m_midLayout = false;
97         m_layoutCount = 0;
98         m_nestedLayoutCount = 0;
99         m_postLayoutTasksTimer.stop();
100         m_firstLayout = true;
101         m_firstLayoutCallbackPending = false;
102         m_wasScrolledByUser = false;
103         m_lastLayoutSize = IntSize();
104         m_lastZoomFactor = 1.0f;
105         m_deferringRepaints = 0;
106         m_repaintCount = 0;
107         m_repaintRect = IntRect();
108         m_repaintRects.clear();
109         m_paintRestriction = PaintRestrictionNone;
110         m_isPainting = false;
111         m_isVisuallyNonEmpty = false;
112         m_firstVisuallyNonEmptyLayoutCallbackPending = true;
113     }
114
115     bool m_doFullRepaint;
116     
117     ScrollbarMode m_vmode;
118     ScrollbarMode m_hmode;
119     bool m_useSlowRepaints;
120     unsigned m_slowRepaintObjectCount;
121
122     int m_borderX, m_borderY;
123
124     Timer<FrameView> m_layoutTimer;
125     bool m_delayedLayout;
126     RenderObject* m_layoutRoot;
127     
128     bool m_layoutSchedulingEnabled;
129     bool m_midLayout;
130     int m_layoutCount;
131     unsigned m_nestedLayoutCount;
132     Timer<FrameView> m_postLayoutTasksTimer;
133     bool m_firstLayoutCallbackPending;
134
135     bool m_firstLayout;
136     bool m_needToInitScrollbars;
137     bool m_isTransparent;
138     Color m_baseBackgroundColor;
139     IntSize m_lastLayoutSize;
140     float m_lastZoomFactor;
141
142     String m_mediaType;
143     
144     unsigned m_enqueueEvents;
145     Vector<ScheduledEvent*> m_scheduledEvents;
146     
147     bool m_overflowStatusDirty;
148     bool m_horizontalOverflow;
149     bool m_verticalOverflow;    
150     RenderObject* m_viewportRenderer;
151
152     bool m_wasScrolledByUser;
153     bool m_inProgrammaticScroll;
154     
155     unsigned m_deferringRepaints;
156     unsigned m_repaintCount;
157     IntRect m_repaintRect;
158     Vector<IntRect> m_repaintRects;
159
160     bool m_shouldUpdateWhileOffscreen;
161
162     RefPtr<Node> m_nodeToDraw;
163     PaintRestriction m_paintRestriction;
164     bool m_isPainting;
165
166     bool m_isVisuallyNonEmpty;
167     bool m_firstVisuallyNonEmptyLayoutCallbackPending;
168 };
169
170 FrameView::FrameView(Frame* frame)
171     : m_refCount(1)
172     , m_frame(frame)
173     , d(new FrameViewPrivate(this))
174 {
175     init();
176     show();
177 }
178
179 FrameView::FrameView(Frame* frame, const IntSize& initialSize)
180     : m_refCount(1)
181     , m_frame(frame)
182     , d(new FrameViewPrivate(this))
183 {
184     init();
185     Widget::setFrameRect(IntRect(x(), y(), initialSize.width(), initialSize.height()));
186     show();
187 }
188
189 FrameView::~FrameView()
190 {
191     if (d->m_postLayoutTasksTimer.isActive()) {
192         d->m_postLayoutTasksTimer.stop();
193         d->m_scheduledEvents.clear();
194         d->m_enqueueEvents = 0;
195     }
196
197     resetScrollbars();
198     setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
199     setHasVerticalScrollbar(false);
200     
201     ASSERT(m_refCount == 0);
202     ASSERT(d->m_scheduledEvents.isEmpty());
203     ASSERT(!d->m_enqueueEvents);
204
205     if (m_frame) {
206         ASSERT(m_frame->view() != this || !m_frame->document() || !m_frame->contentRenderer());
207         RenderPart* renderer = m_frame->ownerRenderer();
208         if (renderer && renderer->widget() == this)
209             renderer->setWidget(0);
210     }
211
212     delete d;
213     d = 0;
214 }
215
216 bool FrameView::isFrameView() const 
217
218     return true; 
219 }
220
221 void FrameView::clearFrame()
222 {
223     m_frame = 0;
224 }
225
226 void FrameView::resetScrollbars()
227 {
228     // Reset the document's scrollbars back to our defaults before we yield the floor.
229     d->m_firstLayout = true;
230     setScrollbarsSuppressed(true);
231     setScrollbarModes(d->m_hmode, d->m_vmode);
232     setScrollbarsSuppressed(false);
233 }
234
235 void FrameView::init()
236 {
237     m_margins = IntSize(-1, -1); // undefined
238     m_size = IntSize();
239
240     // Propagate the marginwidth/height and scrolling modes to the view.
241     Element* ownerElement = m_frame && m_frame->document() ? m_frame->document()->ownerElement() : 0;
242     if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
243         HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement);
244         if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
245             setCanHaveScrollbars(false);
246         int marginWidth = frameElt->getMarginWidth();
247         int marginHeight = frameElt->getMarginHeight();
248         if (marginWidth != -1)
249             setMarginWidth(marginWidth);
250         if (marginHeight != -1)
251             setMarginHeight(marginHeight);
252     }
253 }
254
255 void FrameView::clear()
256 {
257     setCanBlitOnScroll(true);
258     
259     d->reset();
260
261     if (m_frame)
262         if (RenderPart* renderer = m_frame->ownerRenderer())
263             renderer->viewCleared();
264
265     setScrollbarsSuppressed(true);
266 }
267
268 bool FrameView::didFirstLayout() const
269 {
270     return !d->m_firstLayout;
271 }
272
273 void FrameView::initScrollbars()
274 {
275     if (!d->m_needToInitScrollbars)
276         return;
277     d->m_needToInitScrollbars = false;
278     d->m_hmode = horizontalScrollbarMode();
279     d->m_vmode = verticalScrollbarMode();
280     setScrollbarModes(d->m_hmode, d->m_vmode);
281 }
282
283 void FrameView::invalidateRect(const IntRect& rect)
284 {
285     if (!parent()) {
286         if (hostWindow())
287             hostWindow()->repaint(rect, true);
288         return;
289     }
290
291     if (!m_frame)
292         return;
293
294     RenderPart* renderer = m_frame->ownerRenderer();
295     if (!renderer)
296         return;
297
298     IntRect repaintRect = rect;
299     repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
300                      renderer->borderTop() + renderer->paddingTop());
301     renderer->repaintRectangle(repaintRect);
302 }
303
304 void FrameView::setMarginWidth(int w)
305 {
306     // make it update the rendering area when set
307     m_margins.setWidth(w);
308 }
309
310 void FrameView::setMarginHeight(int h)
311 {
312     // make it update the rendering area when set
313     m_margins.setHeight(h);
314 }
315
316 void FrameView::setCanHaveScrollbars(bool canScroll)
317 {
318     ScrollView::setCanHaveScrollbars(canScroll);
319     scrollbarModes(d->m_hmode, d->m_vmode);
320 }
321
322 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
323 {
324     // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
325     Document* doc = m_frame->document();
326     if (!doc)
327         return ScrollView::createScrollbar(orientation);
328
329     // Try the <body> element first as a scrollbar source.
330     Element* body = doc->body();
331     if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(RenderStyle::SCROLLBAR))
332         return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderer());
333     
334     // If the <body> didn't have a custom style, then the root element might.
335     Element* docElement = doc->documentElement();
336     if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(RenderStyle::SCROLLBAR))
337         return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderer());
338         
339     // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
340     RenderPart* frameRenderer = m_frame->ownerRenderer();
341     if (frameRenderer && frameRenderer->style()->hasPseudoStyle(RenderStyle::SCROLLBAR))
342         return RenderScrollbar::createCustomScrollbar(this, orientation, frameRenderer);
343     
344     // Nobody set a custom style, so we just use a native scrollbar.
345     return ScrollView::createScrollbar(orientation);
346 }
347
348 void FrameView::adjustViewSize()
349 {
350     ASSERT(m_frame->view() == this);
351     RenderView* root = m_frame->contentRenderer();
352     if (!root)
353         return;
354     setContentsSize(IntSize(root->overflowWidth(), root->overflowHeight()));
355 }
356
357 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
358 {
359     // Handle the overflow:hidden/scroll case for the body/html elements.  WinIE treats
360     // overflow:hidden and overflow:scroll on <body> as applying to the document's
361     // scrollbars.  The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
362     // use the root element.
363     switch (o->style()->overflowX()) {
364         case OHIDDEN:
365             hMode = ScrollbarAlwaysOff;
366             break;
367         case OSCROLL:
368             hMode = ScrollbarAlwaysOn;
369             break;
370         case OAUTO:
371             hMode = ScrollbarAuto;
372             break;
373         default:
374             // Don't set it at all.
375             ;
376     }
377     
378      switch (o->style()->overflowY()) {
379         case OHIDDEN:
380             vMode = ScrollbarAlwaysOff;
381             break;
382         case OSCROLL:
383             vMode = ScrollbarAlwaysOn;
384             break;
385         case OAUTO:
386             vMode = ScrollbarAuto;
387             break;
388         default:
389             // Don't set it at all.
390             ;
391     }
392
393     d->m_viewportRenderer = o;
394 }
395
396 int FrameView::layoutCount() const
397 {
398     return d->m_layoutCount;
399 }
400
401 bool FrameView::needsFullRepaint() const
402 {
403     return d->m_doFullRepaint;
404 }
405
406 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
407 {
408     return onlyDuringLayout && layoutPending() ? 0 : d->m_layoutRoot;
409 }
410
411 void FrameView::layout(bool allowSubtree)
412 {
413     if (d->m_midLayout)
414         return;
415
416     d->m_layoutTimer.stop();
417     d->m_delayedLayout = false;
418
419     // Protect the view from being deleted during layout (in recalcStyle)
420     RefPtr<FrameView> protector(this);
421
422     if (!m_frame) {
423         // FIXME: Do we need to set m_size.width here?
424         // FIXME: Should we set m_size.height here too?
425         m_size.setWidth(layoutWidth());
426         return;
427     }
428     
429     // we shouldn't enter layout() while painting
430     ASSERT(!isPainting());
431     if (isPainting())
432         return;
433
434     if (!allowSubtree && d->m_layoutRoot) {
435         d->m_layoutRoot->markContainingBlocksForLayout(false);
436         d->m_layoutRoot = 0;
437     }
438
439     ASSERT(m_frame->view() == this);
440     // This early return should be removed when rdar://5598072 is resolved. In the meantime, there is a
441     // gigantic CrashTracer because of this issue, and the early return will hopefully cause graceful 
442     // failure instead.  
443     if (m_frame->view() != this)
444         return;
445
446     Document* document = m_frame->document();
447     if (!document) {
448         // FIXME: Should we set m_size.height here too?
449         m_size.setWidth(layoutWidth());
450         return;
451     }
452
453     d->m_layoutSchedulingEnabled = false;
454
455     if (!d->m_nestedLayoutCount && d->m_postLayoutTasksTimer.isActive()) {
456         // This is a new top-level layout. If there are any remaining tasks from the previous
457         // layout, finish them now.
458         d->m_postLayoutTasksTimer.stop();
459         performPostLayoutTasks();
460     }
461
462     // Viewport-dependent media queries may cause us to need completely different style information.
463     // Check that here.
464     if (document->styleSelector()->affectedByViewportChange())
465         document->updateStyleSelector();
466
467     // Always ensure our style info is up-to-date.  This can happen in situations where
468     // the layout beats any sort of style recalc update that needs to occur.
469     if (m_frame->needsReapplyStyles())
470         m_frame->reapplyStyles();
471     else if (document->hasChangedChild())
472         document->recalcStyle();
473     
474     bool subtree = d->m_layoutRoot;
475
476     // If there is only one ref to this view left, then its going to be destroyed as soon as we exit, 
477     // so there's no point to continuing to layout
478     if (protector->hasOneRef())
479         return;
480
481     RenderObject* root = subtree ? d->m_layoutRoot : document->renderer();
482     if (!root) {
483         // FIXME: Do we need to set m_size here?
484         d->m_layoutSchedulingEnabled = true;
485         return;
486     }
487
488     d->m_nestedLayoutCount++;
489
490     ScrollbarMode hMode = d->m_hmode;
491     ScrollbarMode vMode = d->m_vmode;
492
493     if (!subtree) {
494         RenderObject* rootRenderer = document->documentElement() ? document->documentElement()->renderer() : 0;
495         Node* body = document->body();
496         if (body && body->renderer()) {
497             if (body->hasTagName(framesetTag)) {
498                 body->renderer()->setChildNeedsLayout(true);
499                 vMode = ScrollbarAlwaysOff;
500                 hMode = ScrollbarAlwaysOff;
501             } else if (body->hasTagName(bodyTag)) {
502                 if (!d->m_firstLayout && m_size.height() != layoutHeight()
503                         && static_cast<RenderBox*>(body->renderer())->stretchesToViewHeight())
504                     body->renderer()->setChildNeedsLayout(true);
505                 // It's sufficient to just check the X overflow,
506                 // since it's illegal to have visible in only one direction.
507                 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
508                 applyOverflowToViewport(o, hMode, vMode);
509             }
510         } else if (rootRenderer)
511             applyOverflowToViewport(rootRenderer, hMode, vMode);
512 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
513         if (d->m_firstLayout && !document->ownerElement())
514             printf("Elapsed time before first layout: %d\n", document->elapsedTime());
515 #endif
516     }
517
518     d->m_doFullRepaint = !subtree && (d->m_firstLayout || static_cast<RenderView*>(root)->printing());
519
520     if (!subtree) {
521         // Now set our scrollbar state for the layout.
522         ScrollbarMode currentHMode = horizontalScrollbarMode();
523         ScrollbarMode currentVMode = verticalScrollbarMode();
524
525         if (d->m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
526             setScrollbarsSuppressed(true);
527             if (d->m_firstLayout) {
528                 d->m_firstLayout = false;
529                 d->m_firstLayoutCallbackPending = true;
530                 d->m_lastLayoutSize = IntSize(width(), height());
531                 d->m_lastZoomFactor = root->style()->zoom();
532
533                 // Set the initial vMode to AlwaysOn if we're auto.
534                 if (vMode == ScrollbarAuto)
535                     setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
536                 // Set the initial hMode to AlwaysOff if we're auto.
537                 if (hMode == ScrollbarAuto)
538                     setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
539             }
540             setScrollbarModes(hMode, vMode);
541             setScrollbarsSuppressed(false, true);
542         }
543
544         IntSize oldSize = m_size;
545
546         m_size = IntSize(layoutWidth(), layoutHeight());
547
548         if (oldSize != m_size)
549             d->m_doFullRepaint = true;
550     }
551
552     RenderLayer* layer = root->enclosingLayer();
553
554     pauseScheduledEvents();
555
556     if (subtree)
557         root->view()->pushLayoutState(root);
558         
559     d->m_midLayout = true;
560     beginDeferredRepaints();
561     root->layout();
562     endDeferredRepaints();
563     d->m_midLayout = false;
564
565     if (subtree)
566         root->view()->popLayoutState();
567     d->m_layoutRoot = 0;
568
569     m_frame->invalidateSelection();
570    
571     d->m_layoutSchedulingEnabled = true;
572
573     if (!subtree && !static_cast<RenderView*>(root)->printing())
574         adjustViewSize();
575
576     // Now update the positions of all layers.
577     beginDeferredRepaints();
578     layer->updateLayerPositions(d->m_doFullRepaint);
579     endDeferredRepaints();
580     
581     d->m_layoutCount++;
582
583 #if PLATFORM(MAC)
584     if (AXObjectCache::accessibilityEnabled())
585         root->document()->axObjectCache()->postNotificationToElement(root, "AXLayoutComplete");
586 #endif
587 #if ENABLE(DASHBOARD_SUPPORT)
588     updateDashboardRegions();
589 #endif
590
591     ASSERT(!root->needsLayout());
592
593     setCanBlitOnScroll(!useSlowRepaints());
594
595     if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
596         updateOverflowStatus(layoutWidth() < contentsWidth(),
597                              layoutHeight() < contentsHeight());
598
599     if (!d->m_postLayoutTasksTimer.isActive()) {
600         // Calls resumeScheduledEvents()
601         performPostLayoutTasks();
602
603         if (needsLayout()) {
604             // Post-layout widget updates or an event handler made us need layout again.
605             // Lay out again, but this time defer widget updates and event dispatch until after
606             // we return.
607             d->m_postLayoutTasksTimer.startOneShot(0);
608             pauseScheduledEvents();
609             layout();
610         }
611     } else {
612         resumeScheduledEvents();
613         ASSERT(d->m_enqueueEvents);
614     }
615
616     d->m_nestedLayoutCount--;
617 }
618
619 void FrameView::addWidgetToUpdate(RenderPartObject* object)
620 {
621     if (!m_widgetUpdateSet)
622         m_widgetUpdateSet.set(new HashSet<RenderPartObject*>);
623
624     m_widgetUpdateSet->add(object);
625 }
626
627 void FrameView::removeWidgetToUpdate(RenderPartObject* object)
628 {
629     if (!m_widgetUpdateSet)
630         return;
631
632     m_widgetUpdateSet->remove(object);
633 }
634
635 void FrameView::setMediaType(const String& mediaType)
636 {
637     d->m_mediaType = mediaType;
638 }
639
640 String FrameView::mediaType() const
641 {
642     // See if we have an override type.
643     String overrideType = m_frame->loader()->client()->overrideMediaType();
644     if (!overrideType.isNull())
645         return overrideType;
646     return d->m_mediaType;
647 }
648
649 bool FrameView::useSlowRepaints() const
650 {
651     return d->m_useSlowRepaints || d->m_slowRepaintObjectCount > 0;
652 }
653
654 void FrameView::setUseSlowRepaints()
655 {
656     d->m_useSlowRepaints = true;
657     setCanBlitOnScroll(false);
658 }
659
660 void FrameView::addSlowRepaintObject()
661 {
662     if (!d->m_slowRepaintObjectCount)
663         setCanBlitOnScroll(false);
664     d->m_slowRepaintObjectCount++;
665 }
666
667 void FrameView::removeSlowRepaintObject()
668 {
669     ASSERT(d->m_slowRepaintObjectCount > 0);
670     d->m_slowRepaintObjectCount--;
671     if (!d->m_slowRepaintObjectCount)
672         setCanBlitOnScroll(!d->m_useSlowRepaints);
673 }
674
675 void FrameView::restoreScrollbar()
676 {
677     setScrollbarsSuppressed(false);
678 }
679
680 void FrameView::scrollRectIntoViewRecursively(const IntRect& r)
681 {
682     bool wasInProgrammaticScroll = d->m_inProgrammaticScroll;
683     d->m_inProgrammaticScroll = true;
684     ScrollView::scrollRectIntoViewRecursively(r);
685     d->m_inProgrammaticScroll = wasInProgrammaticScroll;
686 }
687
688 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
689 {
690     bool wasInProgrammaticScroll = d->m_inProgrammaticScroll;
691     d->m_inProgrammaticScroll = true;
692     ScrollView::setScrollPosition(scrollPoint);
693     d->m_inProgrammaticScroll = wasInProgrammaticScroll;
694 }
695
696 HostWindow* FrameView::hostWindow() const
697 {
698     Page* page = frame() ? frame()->page() : 0;
699     if (!page)
700         return 0;
701     return page->chrome();
702 }
703
704 const unsigned cRepaintRectUnionThreshold = 25;
705
706 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
707 {
708     ASSERT(!m_frame->document()->ownerElement());
709
710     if (d->m_deferringRepaints && !immediate) {
711         IntRect visibleContent = visibleContentRect();
712         visibleContent.intersect(r);
713         if (!visibleContent.isEmpty()) {
714             d->m_repaintCount++;
715             d->m_repaintRect.unite(r);
716             if (d->m_repaintCount == cRepaintRectUnionThreshold)
717                 d->m_repaintRects.clear();
718             else if (d->m_repaintCount < cRepaintRectUnionThreshold)
719                 d->m_repaintRects.append(r);
720         }
721         return;
722     }
723     
724     if (!immediate && isOffscreen() && !shouldUpdateWhileOffscreen())
725         return;
726
727     ScrollView::repaintContentRectangle(r, immediate);
728 }
729
730 void FrameView::beginDeferredRepaints()
731 {
732     Page* page = m_frame->page();
733     if (page->mainFrame() != m_frame)
734         return page->mainFrame()->view()->beginDeferredRepaints();
735
736     d->m_deferringRepaints++;
737     d->m_repaintCount = 0;
738     d->m_repaintRect = IntRect();
739     d->m_repaintRects.clear();
740 }
741
742
743 void FrameView::endDeferredRepaints()
744 {
745     Page* page = m_frame->page();
746     if (page->mainFrame() != m_frame)
747         return page->mainFrame()->view()->endDeferredRepaints();
748
749     ASSERT(d->m_deferringRepaints > 0);
750     if (--d->m_deferringRepaints == 0) {
751         if (d->m_repaintCount >= cRepaintRectUnionThreshold)
752             repaintContentRectangle(d->m_repaintRect, false);
753         else {
754             unsigned size = d->m_repaintRects.size();
755             for (unsigned i = 0; i < size; i++)
756                 repaintContentRectangle(d->m_repaintRects[i], false);
757             d->m_repaintRects.clear();
758         }
759     }
760 }
761
762 void FrameView::layoutTimerFired(Timer<FrameView>*)
763 {
764 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
765     if (m_frame->document() && !m_frame->document()->ownerElement())
766         printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
767 #endif
768     layout();
769 }
770
771 void FrameView::scheduleRelayout()
772 {
773     ASSERT(!m_frame->document() || !m_frame->document()->inPageCache());
774     ASSERT(m_frame->view() == this);
775
776     if (d->m_layoutRoot) {
777         d->m_layoutRoot->markContainingBlocksForLayout(false);
778         d->m_layoutRoot = 0;
779     }
780     if (!d->m_layoutSchedulingEnabled)
781         return;
782     if (!needsLayout())
783         return;
784     if (!m_frame->document() || !m_frame->document()->shouldScheduleLayout())
785         return;
786
787     int delay = m_frame->document()->minimumLayoutDelay();
788     if (d->m_layoutTimer.isActive() && d->m_delayedLayout && !delay)
789         unscheduleRelayout();
790     if (d->m_layoutTimer.isActive())
791         return;
792
793     d->m_delayedLayout = delay != 0;
794
795 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
796     if (!m_frame->document()->ownerElement())
797         printf("Scheduling layout for %d\n", delay);
798 #endif
799
800     d->m_layoutTimer.startOneShot(delay * 0.001);
801 }
802
803 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
804 {
805     for (RenderObject* r = descendant; r; r = r->container()) {
806         if (r == ancestor)
807             return true;
808     }
809     return false;
810 }
811
812 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
813 {
814     ASSERT(m_frame->view() == this);
815
816     if (!d->m_layoutSchedulingEnabled || (m_frame->contentRenderer()
817             && m_frame->contentRenderer()->needsLayout())) {
818         if (relayoutRoot)
819             relayoutRoot->markContainingBlocksForLayout(false);
820         return;
821     }
822
823     if (layoutPending()) {
824         if (d->m_layoutRoot != relayoutRoot) {
825             if (isObjectAncestorContainerOf(d->m_layoutRoot, relayoutRoot)) {
826                 // Keep the current root
827                 relayoutRoot->markContainingBlocksForLayout(false, d->m_layoutRoot);
828             } else if (d->m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, d->m_layoutRoot)) {
829                 // Re-root at relayoutRoot
830                 d->m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
831                 d->m_layoutRoot = relayoutRoot;
832             } else {
833                 // Just do a full relayout
834                 if (d->m_layoutRoot)
835                     d->m_layoutRoot->markContainingBlocksForLayout(false);
836                 d->m_layoutRoot = 0;
837                 relayoutRoot->markContainingBlocksForLayout(false);
838             }
839         }
840     } else {
841         int delay = m_frame->document()->minimumLayoutDelay();
842         d->m_layoutRoot = relayoutRoot;
843         d->m_delayedLayout = delay != 0;
844         d->m_layoutTimer.startOneShot(delay * 0.001);
845     }
846 }
847
848 bool FrameView::layoutPending() const
849 {
850     return d->m_layoutTimer.isActive();
851 }
852
853 bool FrameView::needsLayout() const
854 {
855     // This can return true in cases where the document does not have a body yet.
856     // Document::shouldScheduleLayout takes care of preventing us from scheduling
857     // layout in that case.
858     if (!m_frame)
859         return false;
860     RenderView* root = m_frame->contentRenderer();
861     Document* document = m_frame->document();
862     return layoutPending()
863         || (root && root->needsLayout())
864         || d->m_layoutRoot
865         || (document && document->hasChangedChild()) // can occur when using WebKit ObjC interface
866         || m_frame->needsReapplyStyles();
867 }
868
869 void FrameView::setNeedsLayout()
870 {
871     RenderView* root = m_frame->contentRenderer();
872     if (root)
873         root->setNeedsLayout(true);
874 }
875
876 void FrameView::unscheduleRelayout()
877 {
878     if (!d->m_layoutTimer.isActive())
879         return;
880
881 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
882     if (m_frame->document() && !m_frame->document()->ownerElement())
883         printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
884 #endif
885     
886     d->m_layoutTimer.stop();
887     d->m_delayedLayout = false;
888 }
889
890 bool FrameView::isTransparent() const
891 {
892     return d->m_isTransparent;
893 }
894
895 void FrameView::setTransparent(bool isTransparent)
896 {
897     d->m_isTransparent = isTransparent;
898 }
899
900 Color FrameView::baseBackgroundColor() const
901 {
902     return d->m_baseBackgroundColor;
903 }
904
905 void FrameView::setBaseBackgroundColor(Color bc)
906 {
907     if (!bc.isValid())
908         bc = Color::white;
909     d->m_baseBackgroundColor = bc;
910 }
911
912 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
913 {
914     for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
915         FrameView* view = frame->view();
916         if (!view)
917             continue;
918
919         view->setTransparent(transparent);
920         view->setBaseBackgroundColor(backgroundColor);
921     }
922 }
923
924 bool FrameView::shouldUpdateWhileOffscreen() const
925 {
926     return d->m_shouldUpdateWhileOffscreen;
927 }
928
929 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
930 {
931     d->m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
932 }
933
934 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<EventTargetNode> eventTarget)
935 {
936     if (!d->m_enqueueEvents) {
937         ExceptionCode ec = 0;
938         eventTarget->dispatchEvent(event, ec);
939         return;
940     }
941
942     ScheduledEvent* scheduledEvent = new ScheduledEvent;
943     scheduledEvent->m_event = event;
944     scheduledEvent->m_eventTarget = eventTarget;
945     d->m_scheduledEvents.append(scheduledEvent);
946 }
947
948 void FrameView::pauseScheduledEvents()
949 {
950     ASSERT(d->m_scheduledEvents.isEmpty() || d->m_enqueueEvents);
951     d->m_enqueueEvents++;
952 }
953
954 void FrameView::resumeScheduledEvents()
955 {
956     d->m_enqueueEvents--;
957     if (!d->m_enqueueEvents)
958         dispatchScheduledEvents();
959     ASSERT(d->m_scheduledEvents.isEmpty() || d->m_enqueueEvents);
960 }
961
962 void FrameView::performPostLayoutTasks()
963 {
964     if (d->m_firstLayoutCallbackPending) {
965         d->m_firstLayoutCallbackPending = false;
966         m_frame->loader()->didFirstLayout();
967     }
968
969     if (d->m_isVisuallyNonEmpty && d->m_firstVisuallyNonEmptyLayoutCallbackPending) {
970         d->m_firstVisuallyNonEmptyLayoutCallbackPending = false;
971         m_frame->loader()->didFirstVisuallyNonEmptyLayout();
972     }
973
974     RenderView* root = m_frame->contentRenderer();
975
976     root->updateWidgetPositions();
977     if (m_widgetUpdateSet && d->m_nestedLayoutCount <= 1) {
978         Vector<RenderPartObject*> objectVector;
979         copyToVector(*m_widgetUpdateSet, objectVector);
980         size_t size = objectVector.size();
981         for (size_t i = 0; i < size; ++i) {
982             RenderPartObject* object = objectVector[i];
983             object->updateWidget(false);
984
985             // updateWidget() can destroy the RenderPartObject, so we need to make sure it's
986             // alive by checking if it's still in m_widgetUpdateSet.
987             if (m_widgetUpdateSet->contains(object))
988                 object->updateWidgetPosition();
989         }
990         m_widgetUpdateSet->clear();
991     }
992
993     resumeScheduledEvents();
994
995     if (!root->printing()) {
996         IntSize currentSize = IntSize(width(), height());
997         float currentZoomFactor = root->style()->zoom();
998         bool resized = !d->m_firstLayout && (currentSize != d->m_lastLayoutSize || currentZoomFactor != d->m_lastZoomFactor);
999         d->m_lastLayoutSize = currentSize;
1000         d->m_lastZoomFactor = currentZoomFactor;
1001         if (resized)
1002             m_frame->sendResizeEvent();
1003     }
1004 }
1005
1006 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
1007 {
1008     performPostLayoutTasks();
1009 }
1010
1011 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
1012 {
1013     if (!d->m_viewportRenderer)
1014         return;
1015     
1016     if (d->m_overflowStatusDirty) {
1017         d->m_horizontalOverflow = horizontalOverflow;
1018         d->m_verticalOverflow = verticalOverflow;
1019         d->m_overflowStatusDirty = false;
1020         return;
1021     }
1022     
1023     bool horizontalOverflowChanged = (d->m_horizontalOverflow != horizontalOverflow);
1024     bool verticalOverflowChanged = (d->m_verticalOverflow != verticalOverflow);
1025     
1026     if (horizontalOverflowChanged || verticalOverflowChanged) {
1027         d->m_horizontalOverflow = horizontalOverflow;
1028         d->m_verticalOverflow = verticalOverflow;
1029         
1030         scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
1031             verticalOverflowChanged, verticalOverflow),
1032             EventTargetNodeCast(d->m_viewportRenderer->element()));
1033     }
1034     
1035 }
1036
1037 void FrameView::dispatchScheduledEvents()
1038 {
1039     if (d->m_scheduledEvents.isEmpty())
1040         return;
1041
1042     Vector<ScheduledEvent*> scheduledEventsCopy = d->m_scheduledEvents;
1043     d->m_scheduledEvents.clear();
1044     
1045     Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end();
1046     for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) {
1047         ScheduledEvent* scheduledEvent = *it;
1048         
1049         ExceptionCode ec = 0;
1050         
1051         // Only dispatch events to nodes that are in the document
1052         if (scheduledEvent->m_eventTarget->inDocument())
1053             scheduledEvent->m_eventTarget->dispatchEvent(scheduledEvent->m_event, ec);
1054         
1055         delete scheduledEvent;
1056     }
1057 }
1058
1059 IntRect FrameView::windowClipRect(bool clipToContents) const
1060 {
1061     ASSERT(m_frame->view() == this);
1062
1063     // Set our clip rect to be our contents.
1064     IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
1065     if (!m_frame || !m_frame->document() || !m_frame->document()->ownerElement())
1066         return clipRect;
1067
1068     // Take our owner element and get the clip rect from the enclosing layer.
1069     Element* elt = m_frame->document()->ownerElement();
1070     RenderLayer* layer = elt->renderer()->enclosingLayer();
1071     // FIXME: layer should never be null, but sometimes seems to be anyway.
1072     if (!layer)
1073         return clipRect;
1074     FrameView* parentView = elt->document()->view();
1075     clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
1076     return clipRect;
1077 }
1078
1079 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const
1080 {
1081     // If we have no layer, just return our window clip rect.
1082     if (!layer)
1083         return windowClipRect();
1084
1085     // Apply the clip from the layer.
1086     IntRect clipRect;
1087     if (clipToLayerContents)
1088         clipRect = layer->childrenClipRect();
1089     else
1090         clipRect = layer->selfClipRect();
1091     clipRect = contentsToWindow(clipRect); 
1092     return intersection(clipRect, windowClipRect());
1093 }
1094
1095 bool FrameView::isActive() const
1096 {
1097     Page* page = frame()->page();
1098     return page && page->focusController()->isActive();
1099 }
1100
1101 void FrameView::valueChanged(Scrollbar* bar)
1102 {
1103     // Figure out if we really moved.
1104     IntSize offset = scrollOffset();
1105     ScrollView::valueChanged(bar);
1106     if (offset != scrollOffset())
1107         frame()->sendScrollEvent();
1108 }
1109
1110 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
1111 {
1112     // Add in our offset within the FrameView.
1113     IntRect dirtyRect = rect;
1114     dirtyRect.move(scrollbar->x(), scrollbar->y());
1115     invalidateRect(dirtyRect);
1116 }
1117
1118 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
1119 {
1120     tickmarks = frame()->document()->renderedRectsForMarkers(DocumentMarker::TextMatch);
1121 }
1122
1123 IntRect FrameView::windowResizerRect() const
1124 {
1125     Page* page = frame() ? frame()->page() : 0;
1126     if (!page)
1127         return IntRect();
1128     return page->chrome()->windowResizerRect();
1129 }
1130
1131 #if ENABLE(DASHBOARD_SUPPORT)
1132 void FrameView::updateDashboardRegions()
1133 {
1134     Document* document = m_frame->document();
1135     if (!document->hasDashboardRegions())
1136         return;
1137     Vector<DashboardRegionValue> newRegions;
1138     document->renderer()->collectDashboardRegions(newRegions);
1139     if (newRegions == document->dashboardRegions())
1140         return;
1141     document->setDashboardRegions(newRegions);
1142     Page* page = m_frame->page();
1143     if (!page)
1144         return;
1145     page->chrome()->client()->dashboardRegionsChanged();
1146 }
1147 #endif
1148
1149 void FrameView::updateControlTints()
1150 {
1151     // This is called when control tints are changed from aqua/graphite to clear and vice versa.
1152     // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
1153     // This is only done if the theme supports control tinting. It's up to the theme and platform
1154     // to define when controls get the tint and to call this function when that changes.
1155     
1156     // Optimize the common case where we bring a window to the front while it's still empty.
1157     if (!m_frame || m_frame->loader()->url().isEmpty()) 
1158         return;
1159     
1160     if (theme()->supportsControlTints() && m_frame->contentRenderer()) {
1161         if (needsLayout())
1162             layout();
1163         PlatformGraphicsContext* const noContext = 0;
1164         GraphicsContext context(noContext);
1165         context.setUpdatingControlTints(true);
1166         if (platformWidget())
1167             paintContents(&context, visibleContentRect());
1168         else
1169             paint(&context, frameRect());
1170     }
1171 }
1172
1173 bool FrameView::wasScrolledByUser() const
1174 {
1175     return d->m_wasScrolledByUser;
1176 }
1177
1178 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
1179 {
1180     if (d->m_inProgrammaticScroll)
1181         return;
1182     d->m_wasScrolledByUser = wasScrolledByUser;
1183 }
1184
1185 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
1186 {
1187     if (!frame())
1188         return;
1189     
1190     Document* document = frame()->document();
1191     if (!document)
1192         return;
1193
1194 #ifndef NDEBUG
1195     bool fillWithRed;
1196     if (document || document->printing())
1197         fillWithRed = false; // Printing, don't fill with red (can't remember why).
1198     else if (document->ownerElement())
1199         fillWithRed = false; // Subframe, don't fill with red.
1200     else if (isTransparent())
1201         fillWithRed = false; // Transparent, don't fill with red.
1202     else if (d->m_paintRestriction == PaintRestrictionSelectionOnly || d->m_paintRestriction == PaintRestrictionSelectionOnlyBlackText)
1203         fillWithRed = false; // Selections are transparent, don't fill with red.
1204     else if (d->m_nodeToDraw)
1205         fillWithRed = false; // Element images are transparent, don't fill with red.
1206     else
1207         fillWithRed = true;
1208     
1209     if (fillWithRed)
1210         p->fillRect(rect, Color(0xFF, 0, 0));
1211 #endif
1212
1213     bool isTopLevelPainter = !sCurrentPaintTimeStamp;
1214     if (isTopLevelPainter)
1215         sCurrentPaintTimeStamp = currentTime();
1216     
1217     RenderView* contentRenderer = frame()->contentRenderer();
1218     if (!contentRenderer) {
1219         LOG_ERROR("called Frame::paint with nil renderer");
1220         return;
1221     }
1222
1223     ASSERT(!needsLayout());
1224     ASSERT(!d->m_isPainting);
1225         
1226     d->m_isPainting = true;
1227         
1228     // m_nodeToDraw is used to draw only one element (and its descendants)
1229     RenderObject* eltRenderer = d->m_nodeToDraw ? d->m_nodeToDraw->renderer() : 0;
1230     if (d->m_paintRestriction == PaintRestrictionNone)
1231         document->invalidateRenderedRectsForMarkersInRect(rect);
1232     contentRenderer->layer()->paint(p, rect, d->m_paintRestriction, eltRenderer);
1233         
1234     d->m_isPainting = false;
1235
1236 #if ENABLE(DASHBOARD_SUPPORT)
1237     // Regions may have changed as a result of the visibility/z-index of element changing.
1238     if (document->dashboardRegionsDirty())
1239         updateDashboardRegions();
1240 #endif
1241
1242     if (isTopLevelPainter)
1243         sCurrentPaintTimeStamp = 0;
1244 }
1245
1246 void FrameView::setPaintRestriction(PaintRestriction pr)
1247 {
1248     d->m_paintRestriction = pr;
1249 }
1250     
1251 bool FrameView::isPainting() const
1252 {
1253     return d->m_isPainting;
1254 }
1255
1256 void FrameView::setNodeToDraw(Node* node)
1257 {
1258     d->m_nodeToDraw = node;
1259 }
1260
1261 void FrameView::layoutIfNeededRecursive()
1262 {
1263     // We have to crawl our entire tree looking for any FrameViews that need
1264     // layout and make sure they are up to date.
1265     // Mac actually tests for intersection with the dirty region and tries not to
1266     // update layout for frames that are outside the dirty region.  Not only does this seem
1267     // pointless (since those frames will have set a zero timer to layout anyway), but
1268     // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
1269     // region but then become included later by the second frame adding rects to the dirty region
1270     // when it lays out.
1271
1272     if (needsLayout())
1273         layout();
1274
1275     const HashSet<Widget*>* viewChildren = children();
1276     HashSet<Widget*>::const_iterator end = viewChildren->end();
1277     for (HashSet<Widget*>::const_iterator current = viewChildren->begin(); current != end; ++current)
1278         if ((*current)->isFrameView())
1279             static_cast<FrameView*>(*current)->layoutIfNeededRecursive();
1280 }
1281
1282 void FrameView::setIsVisuallyNonEmpty()
1283 {
1284     d->m_isVisuallyNonEmpty = true;
1285 }
1286
1287 } // namespace WebCore