Switch Windows to using FrameView::layoutIfNeededRecursive
[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 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., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */
25
26 #include "config.h"
27 #include "FrameView.h"
28
29 #include "AXObjectCache.h"
30 #include "EventHandler.h"
31 #include "FloatRect.h"
32 #include "Frame.h"
33 #include "FrameLoader.h"
34 #include "FrameLoaderClient.h"
35 #include "GraphicsContext.h"
36 #include "HTMLDocument.h"
37 #include "HTMLFrameSetElement.h"
38 #include "HTMLNames.h"
39 #include "OverflowEvent.h"
40 #include "RenderPart.h"
41 #include "RenderTheme.h"
42 #include "RenderView.h"
43
44 namespace WebCore {
45
46 using namespace HTMLNames;
47
48 struct ScheduledEvent {
49     RefPtr<Event> m_event;
50     RefPtr<EventTargetNode> m_eventTarget;
51     bool m_tempEvent;
52 };
53
54 class FrameViewPrivate {
55 public:
56     FrameViewPrivate(FrameView* view)
57         : m_slowRepaintObjectCount(0)
58         , layoutTimer(view, &FrameView::layoutTimerFired)
59         , m_mediaType("screen")
60         , m_enqueueEvents(0)
61         , m_overflowStatusDirty(true)
62         , m_viewportRenderer(0)
63         , m_wasScrolledByUser(false)
64         , m_inProgrammaticScroll(false)
65     {
66         isTransparent = false;
67         baseBackgroundColor = Color::white;
68         vmode = hmode = ScrollbarAuto;
69         needToInitScrollbars = true;
70         reset();
71     }
72     void reset()
73     {
74         useSlowRepaints = false;
75         borderX = 30;
76         borderY = 30;
77         layoutTimer.stop();
78         layoutRoot = 0;
79         delayedLayout = false;
80         doFullRepaint = true;
81         layoutSchedulingEnabled = true;
82         midLayout = false;
83         layoutCount = 0;
84         firstLayout = true;
85         repaintRects.clear();
86         m_wasScrolledByUser = false;
87     }
88
89     bool doFullRepaint;
90     
91     ScrollbarMode vmode;
92     ScrollbarMode hmode;
93     bool useSlowRepaints;
94     unsigned m_slowRepaintObjectCount;
95
96     int borderX, borderY;
97
98     Timer<FrameView> layoutTimer;
99     bool delayedLayout;
100     RefPtr<Node> layoutRoot;
101     
102     bool layoutSchedulingEnabled;
103     bool midLayout;
104     int layoutCount;
105
106     bool firstLayout;
107     bool needToInitScrollbars;
108     bool isTransparent;
109     Color baseBackgroundColor;
110
111     // Used by objects during layout to communicate repaints that need to take place only
112     // after all layout has been completed.
113     Vector<RenderObject::RepaintInfo> repaintRects;
114     
115     String m_mediaType;
116     
117     unsigned m_enqueueEvents;
118     Vector<ScheduledEvent*> m_scheduledEvents;
119     
120     bool m_overflowStatusDirty;
121     bool horizontalOverflow;
122     bool m_verticalOverflow;    
123     RenderObject* m_viewportRenderer;
124
125     bool m_wasScrolledByUser;
126     bool m_inProgrammaticScroll;
127 };
128
129 FrameView::FrameView(Frame* frame)
130     : m_refCount(1)
131     , m_frame(frame)
132     , d(new FrameViewPrivate(this))
133 {
134     init();
135     show();
136 }
137
138 FrameView::~FrameView()
139 {
140     resetScrollbars();
141
142     ASSERT(m_refCount == 0);
143     ASSERT((!d->m_scheduledEvents || d->m_scheduledEvents.isEmpty()) && !d->m_enqueueEvents);
144
145     if (m_frame) {
146         ASSERT(m_frame->view() != this || !m_frame->document() || !m_frame->document()->renderer());
147         RenderPart* renderer = m_frame->ownerRenderer();
148         if (renderer && renderer->widget() == this)
149             renderer->setWidget(0);
150     }
151
152     delete d;
153     d = 0;
154 }
155
156 bool FrameView::isFrameView() const 
157
158     return true; 
159 }
160
161 void FrameView::clearFrame()
162 {
163     m_frame = 0;
164 }
165
166 void FrameView::resetScrollbars()
167 {
168     // Reset the document's scrollbars back to our defaults before we yield the floor.
169     d->firstLayout = true;
170     suppressScrollbars(true);
171     ScrollView::setVScrollbarMode(d->vmode);
172     ScrollView::setHScrollbarMode(d->hmode);
173     suppressScrollbars(false);
174 }
175
176 void FrameView::init()
177 {
178     m_margins = IntSize(-1, -1); // undefined
179     m_size = IntSize();
180 }
181
182 void FrameView::clear()
183 {
184     setStaticBackground(false);
185     
186     d->reset();
187
188     if (m_frame)
189         if (RenderPart* renderer = m_frame->ownerRenderer())
190             renderer->viewCleared();
191
192     suppressScrollbars(true);
193 }
194
195 bool FrameView::didFirstLayout() const
196 {
197     return !d->firstLayout;
198 }
199
200 void FrameView::initScrollbars()
201 {
202     if (!d->needToInitScrollbars)
203         return;
204     d->needToInitScrollbars = false;
205     setScrollbarsMode(hScrollbarMode());
206 }
207
208 void FrameView::setMarginWidth(int w)
209 {
210     // make it update the rendering area when set
211     m_margins.setWidth(w);
212 }
213
214 void FrameView::setMarginHeight(int h)
215 {
216     // make it update the rendering area when set
217     m_margins.setHeight(h);
218 }
219
220 void FrameView::adjustViewSize()
221 {
222     ASSERT(m_frame->view() == this);
223     RenderView* root = static_cast<RenderView*>(m_frame->renderer());
224     if (!root)
225         return;
226     resizeContents(root->overflowWidth(), root->overflowHeight());
227 }
228
229 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
230 {
231     // Handle the overflow:hidden/scroll case for the body/html elements.  WinIE treats
232     // overflow:hidden and overflow:scroll on <body> as applying to the document's
233     // scrollbars.  The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
234     // use the root element.
235     switch (o->style()->overflowX()) {
236         case OHIDDEN:
237             hMode = ScrollbarAlwaysOff;
238             break;
239         case OSCROLL:
240             hMode = ScrollbarAlwaysOn;
241             break;
242         case OAUTO:
243             hMode = ScrollbarAuto;
244             break;
245         default:
246             // Don't set it at all.
247             ;
248     }
249     
250      switch (o->style()->overflowY()) {
251         case OHIDDEN:
252             vMode = ScrollbarAlwaysOff;
253             break;
254         case OSCROLL:
255             vMode = ScrollbarAlwaysOn;
256             break;
257         case OAUTO:
258             vMode = ScrollbarAuto;
259             break;
260         default:
261             // Don't set it at all.
262             ;
263     }
264
265     d->m_viewportRenderer = o;
266 }
267
268 int FrameView::layoutCount() const
269 {
270     return d->layoutCount;
271 }
272
273 bool FrameView::needsFullRepaint() const
274 {
275     return d->doFullRepaint;
276 }
277
278 void FrameView::addRepaintInfo(RenderObject* o, const IntRect& r)
279 {
280     d->repaintRects.append(RenderObject::RepaintInfo(o, r));
281 }
282
283 Node* FrameView::layoutRoot() const
284 {
285     return layoutPending() ? 0 : d->layoutRoot.get();
286 }
287
288 void FrameView::layout(bool allowSubtree)
289 {
290     if (d->midLayout)
291         return;
292
293     d->layoutTimer.stop();
294     d->delayedLayout = false;
295
296     // Protect the view from being deleted during layout (in recalcStyle)
297     RefPtr<FrameView> protector(this);
298
299     if (!m_frame) {
300         // FIXME: Do we need to set m_size.width here?
301         // FIXME: Should we set m_size.height here too?
302         m_size.setWidth(visibleWidth());
303         return;
304     }
305     
306     // we shouldn't enter layout() while painting
307     ASSERT(!m_frame->isPainting());
308     if (m_frame->isPainting())
309         return;
310
311     if (!allowSubtree && d->layoutRoot) {
312         if (d->layoutRoot->renderer())
313             d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
314         d->layoutRoot = 0;
315     }
316
317
318     ASSERT(m_frame->view() == this);
319
320     Document* document = m_frame->document();
321     if (!document) {
322         // FIXME: Should we set m_size.height here too?
323         m_size.setWidth(visibleWidth());
324         return;
325     }
326
327     d->layoutSchedulingEnabled = false;
328
329     // Always ensure our style info is up-to-date.  This can happen in situations where
330     // the layout beats any sort of style recalc update that needs to occur.
331     if (document->hasChangedChild())
332         document->recalcStyle();
333     
334     bool subtree = d->layoutRoot;
335     Node* rootNode = subtree ? d->layoutRoot.get() : document;
336
337     // If there is only one ref to this view left, then its going to be destroyed as soon as we exit, 
338     // so there's no point to continuiing to layout
339     if (protector->hasOneRef())
340         return;
341
342     RenderObject* root = rootNode->renderer();
343     if (!root) {
344         // FIXME: Do we need to set m_size here?
345         d->layoutSchedulingEnabled = true;
346         return;
347     }
348
349     ScrollbarMode hMode = d->hmode;
350     ScrollbarMode vMode = d->vmode;
351     
352     if (!subtree) {
353         Document* document = static_cast<Document*>(rootNode);
354         RenderObject* rootRenderer = document->documentElement() ? document->documentElement()->renderer() : 0;
355         if (document->isHTMLDocument()) {
356             Node* body = static_cast<HTMLDocument*>(document)->body();
357             if (body && body->renderer()) {
358                 if (body->hasTagName(framesetTag)) {
359                     body->renderer()->setChildNeedsLayout(true);
360                     vMode = ScrollbarAlwaysOff;
361                     hMode = ScrollbarAlwaysOff;
362                 } else if (body->hasTagName(bodyTag)) {
363                     if (!d->firstLayout && m_size.height() != visibleHeight()
364                             && static_cast<RenderBox*>(body->renderer())->stretchesToViewHeight())
365                         body->renderer()->setChildNeedsLayout(true);
366                     // It's sufficient to just check the X overflow,
367                     // since it's illegal to have visible in only one direction.
368                     RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE 
369                         ? body->renderer() : rootRenderer;
370                     applyOverflowToViewport(o, hMode, vMode); // Only applies to HTML UAs, not to XML/XHTML UAs
371                 }
372             }
373         } else if (rootRenderer)
374             applyOverflowToViewport(rootRenderer, hMode, vMode); // XML/XHTML UAs use the root element.
375 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
376         if (d->firstLayout && !document->ownerElement())
377             printf("Elapsed time before first layout: %d\n", document->elapsedTime());
378 #endif
379     }
380
381     d->doFullRepaint = !subtree && (d->firstLayout || static_cast<RenderView*>(root)->printing());
382     d->repaintRects.clear();
383
384     bool didFirstLayout = false;
385     if (!subtree) {
386         // Now set our scrollbar state for the layout.
387         ScrollbarMode currentHMode = hScrollbarMode();
388         ScrollbarMode currentVMode = vScrollbarMode();
389
390         if (d->firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
391             suppressScrollbars(true);
392             if (d->firstLayout) {
393                 d->firstLayout = false;
394                 didFirstLayout = true;
395                 
396                 // Set the initial vMode to AlwaysOn if we're auto.
397                 if (vMode == ScrollbarAuto)
398                     ScrollView::setVScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
399                 // Set the initial hMode to AlwaysOff if we're auto.
400                 if (hMode == ScrollbarAuto)
401                     ScrollView::setHScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
402             }
403             
404             if (hMode == vMode)
405                 ScrollView::setScrollbarsMode(hMode);
406             else {
407                 ScrollView::setHScrollbarMode(hMode);
408                 ScrollView::setVScrollbarMode(vMode);
409             }
410
411             suppressScrollbars(false, true);
412         }
413
414         IntSize oldSize = m_size;
415
416         m_size = IntSize(visibleWidth(), visibleHeight());
417
418         if (oldSize != m_size)
419             d->doFullRepaint = true;
420     }
421     
422     RenderLayer* layer = root->enclosingLayer();
423      
424     pauseScheduledEvents();
425
426     if (subtree)
427         root->view()->pushLayoutState(root);
428     d->midLayout = true;
429     root->layout();
430     d->midLayout = false;
431     if (subtree)
432         root->view()->popLayoutState();
433     d->layoutRoot = 0;
434
435     m_frame->invalidateSelection();
436    
437     d->layoutSchedulingEnabled=true;
438
439     if (!subtree && !static_cast<RenderView*>(root)->printing())
440         adjustViewSize();
441
442     // Now update the positions of all layers.
443     layer->updateLayerPositions(d->doFullRepaint);
444
445     // We update our widget positions right after doing a layout.
446     if (!subtree)
447         static_cast<RenderView*>(root)->updateWidgetPositions();
448     
449     // FIXME: Could optimize this and have objects removed from this list
450     // if they ever do full repaints.
451     Vector<RenderObject::RepaintInfo>::iterator end = d->repaintRects.end();
452     for (Vector<RenderObject::RepaintInfo>::iterator it = d->repaintRects.begin(); it != end; ++it)
453         it->m_object->repaintRectangle(it->m_repaintRect);
454     d->repaintRects.clear();
455     
456     d->layoutCount++;
457
458 #if PLATFORM(MAC)
459     if (AXObjectCache::accessibilityEnabled())
460         root->document()->axObjectCache()->postNotificationToElement(root, "AXLayoutComplete");
461 #endif
462     updateDashboardRegions();
463
464     if (didFirstLayout)
465         m_frame->loader()->didFirstLayout();
466     
467     ASSERT(!root->needsLayout());
468
469     setStaticBackground(useSlowRepaints());
470
471     if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
472         updateOverflowStatus(visibleWidth() < contentsWidth(),
473                              visibleHeight() < contentsHeight());
474
475     // Allow events scheduled during layout to fire
476     resumeScheduledEvents();
477 }
478
479 //
480 // Event Handling
481 //
482 /////////////////
483
484 bool FrameView::scrollTo(const IntRect& bounds)
485 {
486     int x, y, xe, ye;
487     x = bounds.x();
488     y = bounds.y();
489     xe = bounds.right() - 1;
490     ye = bounds.bottom() - 1;
491     
492     int deltax;
493     int deltay;
494
495     int curHeight = visibleHeight();
496     int curWidth = visibleWidth();
497
498     if (ye - y>curHeight-d->borderY)
499         ye = y + curHeight - d->borderY;
500
501     if (xe - x>curWidth-d->borderX)
502         xe = x + curWidth - d->borderX;
503
504     // is xpos of target left of the view's border?
505     if (x < contentsX() + d->borderX)
506         deltax = x - contentsX() - d->borderX;
507     // is xpos of target right of the view's right border?
508     else if (xe + d->borderX > contentsX() + curWidth)
509         deltax = xe + d->borderX - (contentsX() + curWidth);
510     else
511         deltax = 0;
512
513     // is ypos of target above upper border?
514     if (y < contentsY() + d->borderY)
515         deltay = y - contentsY() - d->borderY;
516     // is ypos of target below lower border?
517     else if (ye + d->borderY > contentsY() + curHeight)
518         deltay = ye + d->borderY - (contentsY() + curHeight);
519     else
520         deltay = 0;
521
522     int maxx = curWidth - d->borderX;
523     int maxy = curHeight - d->borderY;
524
525     int scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax > -maxx ? deltax : -maxx);
526     int scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay > -maxy ? deltay : -maxy);
527
528     if (contentsX() + scrollX < 0)
529         scrollX = -contentsX();
530     else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
531         scrollX = contentsWidth() - visibleWidth() - contentsX();
532
533     if (contentsY() + scrollY < 0)
534         scrollY = -contentsY();
535     else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
536         scrollY = contentsHeight() - visibleHeight() - contentsY();
537
538     scrollBy(scrollX, scrollY);
539
540     // generate abs(scroll.)
541     if (scrollX < 0)
542         scrollX = -scrollX;
543     if (scrollY < 0)
544         scrollY = -scrollY;
545
546     return scrollX != maxx && scrollY != maxy;
547 }
548
549 void FrameView::setMediaType(const String& mediaType)
550 {
551     d->m_mediaType = mediaType;
552 }
553
554 String FrameView::mediaType() const
555 {
556     // See if we have an override type.
557     String overrideType = m_frame->loader()->client()->overrideMediaType();
558     if (!overrideType.isNull())
559         return overrideType;
560     return d->m_mediaType;
561 }
562
563 bool FrameView::useSlowRepaints() const
564 {
565     return d->useSlowRepaints || d->m_slowRepaintObjectCount > 0;
566 }
567
568 void FrameView::setUseSlowRepaints()
569 {
570     d->useSlowRepaints = true;
571     setStaticBackground(true);
572 }
573
574 void FrameView::addSlowRepaintObject()
575 {
576     if (!d->m_slowRepaintObjectCount)
577         setStaticBackground(true);
578     d->m_slowRepaintObjectCount++;
579 }
580
581 void FrameView::removeSlowRepaintObject()
582 {
583     ASSERT(d->m_slowRepaintObjectCount > 0);
584     d->m_slowRepaintObjectCount--;
585     if (!d->m_slowRepaintObjectCount)
586         setStaticBackground(d->useSlowRepaints);
587 }
588
589 void FrameView::setScrollbarsMode(ScrollbarMode mode)
590 {
591     d->vmode = mode;
592     d->hmode = mode;
593     
594     ScrollView::setScrollbarsMode(mode);
595 }
596
597 void FrameView::setVScrollbarMode(ScrollbarMode mode)
598 {
599     d->vmode = mode;
600     ScrollView::setVScrollbarMode(mode);
601 }
602
603 void FrameView::setHScrollbarMode(ScrollbarMode mode)
604 {
605     d->hmode = mode;
606     ScrollView::setHScrollbarMode(mode);
607 }
608
609 void FrameView::restoreScrollbar()
610 {
611     suppressScrollbars(false);
612 }
613
614 void FrameView::scrollRectIntoViewRecursively(const IntRect& r)
615 {
616     if (frame()->prohibitsScrolling())
617         return;
618     bool wasInProgrammaticScroll = d->m_inProgrammaticScroll;
619     d->m_inProgrammaticScroll = true;
620     ScrollView::scrollRectIntoViewRecursively(r);
621     d->m_inProgrammaticScroll = wasInProgrammaticScroll;
622 }
623
624 void FrameView::setContentsPos(int x, int y)
625 {
626     if (frame()->prohibitsScrolling())
627         return;
628     bool wasInProgrammaticScroll = d->m_inProgrammaticScroll;
629     d->m_inProgrammaticScroll = true;
630     ScrollView::setContentsPos(x, y);
631     d->m_inProgrammaticScroll = wasInProgrammaticScroll;
632 }
633
634 void FrameView::repaintRectangle(const IntRect& r, bool immediate)
635 {
636     updateContents(r, immediate);
637 }
638
639 void FrameView::layoutTimerFired(Timer<FrameView>*)
640 {
641 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
642     if (m_frame->document() && !m_frame->document()->ownerElement())
643         printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
644 #endif
645     layout();
646 }
647
648 void FrameView::scheduleRelayout()
649 {
650     ASSERT(m_frame->view() == this);
651
652     if (d->layoutRoot) {
653         if (d->layoutRoot->renderer())
654             d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
655         d->layoutRoot = 0;
656     }
657     if (!d->layoutSchedulingEnabled)
658         return;
659
660     if (!m_frame->document() || !m_frame->document()->shouldScheduleLayout())
661         return;
662
663     int delay = m_frame->document()->minimumLayoutDelay();
664     if (d->layoutTimer.isActive() && d->delayedLayout && !delay)
665         unscheduleRelayout();
666     if (d->layoutTimer.isActive())
667         return;
668
669     d->delayedLayout = delay != 0;
670
671 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
672     if (!m_frame->document()->ownerElement())
673         printf("Scheduling layout for %d\n", delay);
674 #endif
675
676     d->layoutTimer.startOneShot(delay * 0.001);
677 }
678
679 void FrameView::scheduleRelayoutOfSubtree(Node* n)
680 {
681     ASSERT(m_frame->view() == this);
682
683     if (!d->layoutSchedulingEnabled || (m_frame->document()
684             && m_frame->document()->renderer()
685             && m_frame->document()->renderer()->needsLayout())) {
686         if (n->renderer())
687             n->renderer()->markContainingBlocksForLayout(false);
688         return;
689     }
690
691     if (layoutPending()) {
692         if (d->layoutRoot != n) {
693             // Just do a full relayout
694             if (d->layoutRoot && d->layoutRoot->renderer())
695                 d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
696             d->layoutRoot = 0;
697             if (n->renderer())
698                 n->renderer()->markContainingBlocksForLayout(false);
699         }
700     } else {
701         int delay = m_frame->document()->minimumLayoutDelay();
702         d->layoutRoot = n;
703         d->delayedLayout = delay != 0;
704         d->layoutTimer.startOneShot(delay * 0.001);
705     }
706 }
707
708 bool FrameView::layoutPending() const
709 {
710     return d->layoutTimer.isActive();
711 }
712
713 bool FrameView::needsLayout() const
714 {
715     // It is possible that our document will not have a body yet. If this is the case, 
716     // then we are not allowed to schedule layouts yet, so we won't be pending layout.
717     if (!m_frame)
718         return false;
719     RenderView* root = static_cast<RenderView*>(m_frame->renderer());
720     Document * doc = m_frame->document();
721     // doc->hasChangedChild() condition can occur when using WebKit ObjC interface
722     return layoutPending() || (root && root->needsLayout()) || d->layoutRoot || (doc && doc->hasChangedChild());
723 }
724
725 void FrameView::setNeedsLayout()
726 {
727     if (m_frame->renderer())
728         m_frame->renderer()->setNeedsLayout(true);
729 }
730
731 void FrameView::unscheduleRelayout()
732 {
733     if (!d->layoutTimer.isActive())
734         return;
735
736 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
737     if (m_frame->document() && !m_frame->document()->ownerElement())
738         printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
739 #endif
740     
741     d->layoutTimer.stop();
742     d->delayedLayout = false;
743 }
744
745 bool FrameView::isTransparent() const
746 {
747     return d->isTransparent;
748 }
749
750 void FrameView::setTransparent(bool isTransparent)
751 {
752     d->isTransparent = isTransparent;
753 }
754
755 Color FrameView::baseBackgroundColor() const
756 {
757     return d->baseBackgroundColor;
758 }
759
760 void FrameView::setBaseBackgroundColor(Color bc)
761 {
762     if (!bc.isValid())
763         bc = Color::white;
764     d->baseBackgroundColor = bc;
765 }
766
767 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<EventTargetNode> eventTarget, bool tempEvent)
768 {
769     if (!d->m_enqueueEvents) {
770         ExceptionCode ec = 0;
771         eventTarget->dispatchEvent(event, ec, tempEvent);
772         return;
773     }
774
775     ScheduledEvent* scheduledEvent = new ScheduledEvent;
776     scheduledEvent->m_event = event;
777     scheduledEvent->m_eventTarget = eventTarget;
778     scheduledEvent->m_tempEvent = tempEvent;
779     d->m_scheduledEvents.append(scheduledEvent);
780 }
781
782 void FrameView::pauseScheduledEvents()
783 {
784     ASSERT(!d->m_scheduledEvents || d->m_scheduledEvents.isEmpty() || d->m_enqueueEvents);
785     d->m_enqueueEvents++;
786 }
787
788 void FrameView::resumeScheduledEvents()
789 {
790     d->m_enqueueEvents--;
791     if (!d->m_enqueueEvents)
792         dispatchScheduledEvents();
793     ASSERT(!d->m_scheduledEvents || d->m_scheduledEvents.isEmpty() || d->m_enqueueEvents);
794 }
795
796 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
797 {
798     if (!d->m_viewportRenderer)
799         return;
800     
801     if (d->m_overflowStatusDirty) {
802         d->horizontalOverflow = horizontalOverflow;
803         d->m_verticalOverflow = verticalOverflow;
804         d->m_overflowStatusDirty = false;
805         return;
806     }
807     
808     bool horizontalOverflowChanged = (d->horizontalOverflow != horizontalOverflow);
809     bool verticalOverflowChanged = (d->m_verticalOverflow != verticalOverflow);
810     
811     if (horizontalOverflowChanged || verticalOverflowChanged) {
812         d->horizontalOverflow = horizontalOverflow;
813         d->m_verticalOverflow = verticalOverflow;
814         
815         scheduleEvent(new OverflowEvent(horizontalOverflowChanged, horizontalOverflow,
816             verticalOverflowChanged, verticalOverflow),
817             EventTargetNodeCast(d->m_viewportRenderer->element()), true);
818     }
819     
820 }
821
822 void FrameView::dispatchScheduledEvents()
823 {
824     if (!d->m_scheduledEvents)
825         return;
826     
827     Vector<ScheduledEvent*> scheduledEventsCopy = d->m_scheduledEvents;
828     d->m_scheduledEvents.clear();
829     
830     Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end();
831     for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) {
832         ScheduledEvent* scheduledEvent = *it;
833         
834         ExceptionCode ec = 0;
835         
836         // Only dispatch events to nodes that are in the document
837         if (scheduledEvent->m_eventTarget->inDocument())
838             scheduledEvent->m_eventTarget->dispatchEvent(scheduledEvent->m_event,
839                 ec, scheduledEvent->m_tempEvent);
840         
841         delete scheduledEvent;
842     }    
843 }
844
845 IntRect FrameView::windowClipRect() const
846 {
847     return windowClipRect(true);
848 }
849
850 IntRect FrameView::windowClipRect(bool clipToContents) const
851 {
852     ASSERT(m_frame->view() == this);
853
854     // Set our clip rect to be our contents.
855     IntRect clipRect;
856     if (clipToContents)
857         clipRect = enclosingIntRect(visibleContentRect());
858     else
859         clipRect = IntRect(contentsX(), contentsY(), width(), height());
860     clipRect = contentsToWindow(clipRect);
861
862     if (!m_frame || !m_frame->document() || !m_frame->document()->ownerElement())
863         return clipRect;
864
865     // Take our owner element and get the clip rect from the enclosing layer.
866     Element* elt = m_frame->document()->ownerElement();
867     RenderLayer* layer = elt->renderer()->enclosingLayer();
868     // FIXME: layer should never be null, but sometimes seems to be anyway.
869     if (!layer)
870         return clipRect;
871     FrameView* parentView = elt->document()->view();
872     clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
873     return clipRect;
874 }
875
876 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const
877 {
878     // If we have no layer, just return our window clip rect.
879     if (!layer)
880         return windowClipRect();
881
882     // Apply the clip from the layer.
883     IntRect clipRect;
884     if (clipToLayerContents)
885         clipRect = layer->childrenClipRect();
886     else
887         clipRect = layer->selfClipRect();
888     clipRect = contentsToWindow(clipRect); 
889     return intersection(clipRect, windowClipRect());
890 }
891
892 void FrameView::updateDashboardRegions()
893 {
894     Document* doc = m_frame->document();
895     if (doc->hasDashboardRegions()) {
896         Vector<DashboardRegionValue> newRegions;
897         doc->renderer()->collectDashboardRegions(newRegions);
898         doc->setDashboardRegions(newRegions);
899         m_frame.get()->dashboardRegionsChanged();
900     }
901 }
902
903 void FrameView::updateControlTints()
904 {
905     // This is called when control tints are changed from aqua/graphite to clear and vice versa.
906     // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
907     // This is only done if the theme supports control tinting. It's up to the theme and platform
908     // to define when controls get the tint and to call this function when that changes.
909     Document* doc = m_frame->document();
910     if (doc && theme()->supportsControlTints() && m_frame->renderer()) {
911         doc->updateLayout(); // Ensure layout is up to date.
912         PlatformGraphicsContext* const noContext = 0;
913         GraphicsContext context(noContext);
914         context.setUpdatingControlTints(true);
915         m_frame->paint(&context, enclosingIntRect(visibleContentRect()));
916     }
917 }
918
919 bool FrameView::wasScrolledByUser() const
920 {
921     return d->m_wasScrolledByUser;
922 }
923
924 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
925 {
926     if (d->m_inProgrammaticScroll)
927         return;
928     d->m_wasScrolledByUser = wasScrolledByUser;
929 }
930
931 void FrameView::layoutIfNeededRecursive()
932 {
933     // We have to crawl our entire tree looking for any FrameViews that need
934     // layout and make sure they are up to date.
935     // Mac actually tests for intersection with the dirty region and tries not to
936     // update layout for frames that are outside the dirty region.  Not only does this seem
937     // pointless (since those frames will have set a zero timer to layout anyway), but
938     // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
939     // region but then become included later by the second frame adding rects to the dirty region
940     // when it lays out.
941
942     if (needsLayout())
943         layout();
944
945     HashSet<Widget*>* viewChildren = children();
946     HashSet<Widget*>::iterator end = viewChildren->end();
947     for (HashSet<Widget*>::iterator current = viewChildren->begin(); current != end; ++current)
948         if ((*current)->isFrameView())
949             static_cast<FrameView*>(*current)->layoutIfNeededRecursive();
950 }
951
952 }