LayoutTests:
[WebKit-https.git] / WebCore / page / FrameView.cpp
1 /* This file is part of the KDE project
2  *
3  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
4  *                     1999 Lars Knoll <knoll@kde.org>
5  *                     1999 Antti Koivisto <koivisto@kde.org>
6  *                     2000 Dirk Mueller <mueller@kde.org>
7  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
8  *           (C) 2006 Graham Dennis (graham.dennis@gmail.com)
9  *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
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., 59 Temple Place - Suite 330,
24  * Boston, MA 02111-1307, USA.
25  */
26
27 #include "config.h"
28 #include "FrameView.h"
29
30 #include "AXObjectCache.h"
31 #include "CachedImage.h"
32 #include "Cursor.h"
33 #include "EventNames.h"
34 #include "FloatRect.h"
35 #include "Frame.h"
36 #include "FrameLoader.h"
37 #include "FrameTree.h"
38 #include "HTMLDocument.h"
39 #include "HTMLFrameElementBase.h"
40 #include "HTMLFrameSetElement.h"
41 #include "HTMLInputElement.h"
42 #include "HTMLNames.h"
43 #include "HitTestRequest.h"
44 #include "HitTestResult.h"
45 #include "Image.h"
46 #include "KeyboardEvent.h"
47 #include "MouseEvent.h"
48 #include "MouseEventWithHitTestResults.h"
49 #include "OverflowEvent.h"
50 #include "PlatformKeyboardEvent.h"
51 #include "PlatformScrollBar.h"
52 #include "PlatformWheelEvent.h"
53 #include "RenderArena.h"
54 #include "RenderPart.h"
55 #include "RenderText.h"
56 #include "RenderView.h"
57 #include "SelectionController.h"
58 #include "Settings.h"
59 #include "cssstyleselector.h"
60
61 #ifdef SVG_SUPPORT
62 #include "XLinkNames.h"
63 #include "SVGNames.h"
64 #include "SVGCursorElement.h"
65 #include "SVGLength.h"
66 #endif
67
68 namespace WebCore {
69
70 using namespace EventNames;
71 using namespace HTMLNames;
72 #ifdef SVG_SUPPORT
73 using namespace SVGNames;
74 #endif
75
76 struct ScheduledEvent {
77     RefPtr<Event> m_event;
78     RefPtr<EventTargetNode> m_eventTarget;
79     bool m_tempEvent;
80 };
81
82 class FrameViewPrivate {
83 public:
84     FrameViewPrivate(FrameView* view)
85         : m_hasBorder(false)
86         , layoutTimer(view, &FrameView::layoutTimerFired)
87         , hoverTimer(view, &FrameView::hoverTimerFired)
88         , m_resizeLayer(0)
89         , m_mediaType("screen")
90         , m_scheduledEvents(0)
91         , m_overflowStatusDirty(true)
92         , m_viewportRenderer(0)
93     {
94         repaintRects = 0;
95         isTransparent = false;
96         baseBackgroundColor = Color::white;
97         vmode = hmode = ScrollbarAuto;
98         needToInitScrollbars = true;
99         reset();
100     }
101     ~FrameViewPrivate()
102     {
103         delete repaintRects;
104         delete m_scheduledEvents;
105     }
106     void reset()
107     {
108         underMouse = 0;
109         oldUnder = 0;
110         oldSubframe = 0;
111         oldScrollbar = 0;
112         linkPressed = false;
113         useSlowRepaints = false;
114         slowRepaintObjectCount = 0;
115         dragTarget = 0;
116         borderTouched = false;
117         ignoreWheelEvents = false;
118         borderX = 30;
119         borderY = 30;
120         clickCount = 0;
121         clickNode = 0;
122         layoutTimer.stop();
123         layoutRoot = 0;
124         delayedLayout = false;
125         mousePressed = false;
126         doFullRepaint = true;
127         layoutSchedulingEnabled = true;
128         layoutCount = 0;
129         firstLayout = true;
130         hoverTimer.stop();
131         if (repaintRects)
132             repaintRects->clear();
133         resizingFrameSet = 0;
134         m_resizeLayer = 0;
135         m_currentMousePosition = IntPoint();
136     }
137
138     RefPtr<Node> underMouse;
139     RefPtr<Node> oldUnder;
140     RefPtr<Frame> oldSubframe;
141     RefPtr<PlatformScrollbar> oldScrollbar;
142
143     bool borderTouched : 1;
144     bool borderStart : 1;
145     bool doFullRepaint : 1;
146     bool m_hasBorder : 1;
147     
148     ScrollbarMode vmode;
149     ScrollbarMode hmode;
150     bool linkPressed;
151     bool useSlowRepaints;
152     unsigned slowRepaintObjectCount;
153     bool ignoreWheelEvents;
154
155     int borderX, borderY;
156     int clickCount;
157     RefPtr<Node> clickNode;
158
159     Timer<FrameView> layoutTimer;
160     bool delayedLayout;
161     RefPtr<Node> layoutRoot;
162     
163     bool layoutSchedulingEnabled;
164     int layoutCount;
165
166     bool firstLayout;
167     bool needToInitScrollbars;
168     bool mousePressed;
169     bool isTransparent;
170     Color baseBackgroundColor;
171
172     Timer<FrameView> hoverTimer;
173     
174     RenderLayer* m_resizeLayer;
175     IntSize offsetFromResizeCorner;
176     
177     // Used by objects during layout to communicate repaints that need to take place only
178     // after all layout has been completed.
179     DeprecatedPtrList<RenderObject::RepaintInfo>* repaintRects;
180     
181     RefPtr<Node> dragTarget;
182     RefPtr<HTMLFrameSetElement> resizingFrameSet;
183     
184     String m_mediaType;
185     
186     Vector<ScheduledEvent*>* m_scheduledEvents;
187     
188     bool m_overflowStatusDirty;
189     bool horizontalOverflow;
190     bool m_verticalOverflow;    
191     RenderObject* m_viewportRenderer;
192     
193     IntPoint m_currentMousePosition;
194 };
195
196 FrameView::FrameView(Frame *frame)
197     : m_refCount(1)
198     , m_frame(frame)
199     , d(new FrameViewPrivate(this))
200 {
201     init();
202
203     show();
204 }
205
206 FrameView::~FrameView()
207 {
208     resetScrollbars();
209
210     ASSERT(m_refCount == 0);
211
212     if (d->hoverTimer.isActive())
213         d->hoverTimer.stop();
214     if (m_frame) {
215         // FIXME: Is this really the right place to call detach on the document?
216         if (Document* doc = m_frame->document())
217             doc->detach();
218         if (RenderPart* renderer = m_frame->ownerRenderer())
219             renderer->setWidget(0);
220     }
221
222     delete d;
223     d = 0;
224 }
225
226 bool FrameView::isFrameView() const 
227
228     return true; 
229 }
230
231 void FrameView::clearPart()
232 {
233     m_frame = 0;
234 }
235
236 void FrameView::resetScrollbars()
237 {
238     // Reset the document's scrollbars back to our defaults before we yield the floor.
239     d->firstLayout = true;
240     suppressScrollbars(true);
241     ScrollView::setVScrollbarMode(d->vmode);
242     ScrollView::setHScrollbarMode(d->hmode);
243     suppressScrollbars(false);
244 }
245
246 void FrameView::init()
247 {
248     m_margins = IntSize(-1, -1); // undefined
249     m_size = IntSize();
250 }
251
252 void FrameView::clear()
253 {
254     setStaticBackground(false);
255     
256     m_frame->selectionController()->clear();
257
258     d->reset();
259
260 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
261     if (d->layoutTimer.isActive() && m_frame->document() && !m_frame->document()->ownerElement())
262         printf("Killing the layout timer from a clear at %d\n", m_frame->document()->elapsedTime());
263 #endif    
264     d->layoutTimer.stop();
265
266     if (m_frame)
267         if (RenderPart* renderer = m_frame->ownerRenderer())
268             renderer->viewCleared();
269
270     suppressScrollbars(true);
271 }
272
273 bool FrameView::didFirstLayout() const
274 {
275     return !d->firstLayout;
276 }
277
278 void FrameView::initScrollbars()
279 {
280     if (!d->needToInitScrollbars)
281         return;
282     d->needToInitScrollbars = false;
283     setScrollbarsMode(hScrollbarMode());
284 }
285
286 void FrameView::setMarginWidth(int w)
287 {
288     // make it update the rendering area when set
289     m_margins.setWidth(w);
290 }
291
292 void FrameView::setMarginHeight(int h)
293 {
294     // make it update the rendering area when set
295     m_margins.setHeight(h);
296 }
297
298 void FrameView::adjustViewSize()
299 {
300     if (m_frame->document()) {
301         Document *document = m_frame->document();
302
303         RenderView* root = static_cast<RenderView *>(document->renderer());
304         if (!root)
305             return;
306         
307         int docw = root->docWidth();
308         int doch = root->docHeight();
309     
310         resizeContents(docw, doch);
311     }
312 }
313
314 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
315 {
316     // Handle the overflow:hidden/scroll case for the body/html elements.  WinIE treats
317     // overflow:hidden and overflow:scroll on <body> as applying to the document's
318     // scrollbars.  The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
319     // use the root element.
320     switch (o->style()->overflowX()) {
321         case OHIDDEN:
322             hMode = ScrollbarAlwaysOff;
323             break;
324         case OSCROLL:
325             hMode = ScrollbarAlwaysOn;
326             break;
327         case OAUTO:
328             hMode = ScrollbarAuto;
329             break;
330         default:
331             // Don't set it at all.
332             ;
333     }
334     
335      switch (o->style()->overflowY()) {
336         case OHIDDEN:
337             vMode = ScrollbarAlwaysOff;
338             break;
339         case OSCROLL:
340             vMode = ScrollbarAlwaysOn;
341             break;
342         case OAUTO:
343             vMode = ScrollbarAuto;
344             break;
345         default:
346             // Don't set it at all.
347             ;
348     }
349
350     d->m_viewportRenderer = o;
351 }
352
353 int FrameView::layoutCount() const
354 {
355     return d->layoutCount;
356 }
357
358 bool FrameView::needsFullRepaint() const
359 {
360     return d->doFullRepaint;
361 }
362
363 void FrameView::addRepaintInfo(RenderObject* o, const IntRect& r)
364 {
365     if (!d->repaintRects) {
366         d->repaintRects = new DeprecatedPtrList<RenderObject::RepaintInfo>;
367         d->repaintRects->setAutoDelete(true);
368     }
369     
370     d->repaintRects->append(new RenderObject::RepaintInfo(o, r));
371 }
372
373 Node* FrameView::layoutRoot() const
374 {
375     return layoutPending() ? 0 : d->layoutRoot.get();
376 }
377
378 void FrameView::layout(bool allowSubtree)
379 {
380     d->layoutTimer.stop();
381     d->delayedLayout = false;
382
383     // Protect the view from being deleted during layout (in recalcStyle)
384     RefPtr<FrameView> protector(this);
385
386     if (!m_frame) {
387         // FIXME: Do we need to set m_size.width here?
388         // FIXME: Should we set m_size.height here too?
389         m_size.setWidth(visibleWidth());
390         return;
391     }
392
393     if (!allowSubtree && d->layoutRoot) {
394         if (d->layoutRoot->renderer())
395             d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
396         d->layoutRoot = 0;
397     }
398
399     bool subtree = d->layoutRoot;
400     Document* document = m_frame->document();
401     if (!document) {
402         // FIXME: Should we set m_size.height here too?
403         m_size.setWidth(visibleWidth());
404         return;
405     }
406
407     Node* rootNode = subtree ? d->layoutRoot.get() : document;
408     d->layoutSchedulingEnabled = false;
409
410     // Always ensure our style info is up-to-date.  This can happen in situations where
411     // the layout beats any sort of style recalc update that needs to occur.
412     if (document->hasChangedChild())
413         document->recalcStyle();
414     
415     // If there is only one ref to this view left, then its going to be destroyed as soon as we exit, 
416     // so there's no point to continuiing to layout
417     if (protector->hasOneRef())
418         return;
419
420     RenderObject* root = rootNode->renderer();
421     if (!root) {
422         // FIXME: Do we need to set m_size here?
423         d->layoutSchedulingEnabled = true;
424         return;
425     }
426
427     ScrollbarMode hMode = d->hmode;
428     ScrollbarMode vMode = d->vmode;
429     
430     if (!subtree) {
431         Document* document = static_cast<Document*>(rootNode);
432         RenderObject* rootRenderer = document->documentElement() ? document->documentElement()->renderer() : 0;
433         if (document->isHTMLDocument()) {
434             Node *body = static_cast<HTMLDocument*>(document)->body();
435             if (body && body->renderer()) {
436                 if (body->hasTagName(framesetTag)) {
437                     body->renderer()->setNeedsLayout(true);
438                     vMode = ScrollbarAlwaysOff;
439                     hMode = ScrollbarAlwaysOff;
440                 } else if (body->hasTagName(bodyTag)) {
441                     if (!d->firstLayout && m_size.height() != visibleHeight() && static_cast<RenderBox*>(body->renderer())->stretchesToViewHeight())
442                         body->renderer()->setChildNeedsLayout(true);
443                     // It's sufficient to just check one overflow direction, since it's illegal to have visible in only one direction.
444                     RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE ? body->renderer() : rootRenderer;
445                     applyOverflowToViewport(o, hMode, vMode); // Only applies to HTML UAs, not to XML/XHTML UAs
446                 }
447             }
448         } else if (rootRenderer)
449             applyOverflowToViewport(rootRenderer, hMode, vMode); // XML/XHTML UAs use the root element.
450 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
451         if (d->firstLayout && !document->ownerElement())
452             printf("Elapsed time before first layout: %d\n", document->elapsedTime());
453 #endif
454     }
455
456     d->doFullRepaint = !subtree && (d->firstLayout || static_cast<RenderView*>(root)->printingMode());
457     if (d->repaintRects)
458         d->repaintRects->clear();
459
460     bool didFirstLayout = false;
461     if (!subtree) {
462         // Now set our scrollbar state for the layout.
463         ScrollbarMode currentHMode = hScrollbarMode();
464         ScrollbarMode currentVMode = vScrollbarMode();
465
466         if (d->firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
467             suppressScrollbars(true);
468             if (d->firstLayout) {
469                 d->firstLayout = false;
470                 didFirstLayout = true;
471                 
472                 // Set the initial vMode to AlwaysOn if we're auto.
473                 if (vMode == ScrollbarAuto)
474                     ScrollView::setVScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
475                 // Set the initial hMode to AlwaysOff if we're auto.
476                 if (hMode == ScrollbarAuto)
477                     ScrollView::setHScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
478             }
479             
480             if (hMode == vMode)
481                 ScrollView::setScrollbarsMode(hMode);
482             else {
483                 ScrollView::setHScrollbarMode(hMode);
484                 ScrollView::setVScrollbarMode(vMode);
485             }
486
487             suppressScrollbars(false, true);
488         }
489
490         IntSize oldSize = m_size;
491
492         m_size = IntSize(visibleWidth(), visibleHeight());
493
494         if (oldSize != m_size)
495             d->doFullRepaint = true;
496     }
497     
498     RenderLayer* layer = root->enclosingLayer();
499      
500     if (!d->doFullRepaint) {
501         layer->checkForRepaintOnResize();
502         root->repaintObjectsBeforeLayout();
503     }
504
505     if (subtree) {
506         if (root->recalcMinMax())
507             root->recalcMinMaxWidths();
508     }
509     root->layout();
510     d->layoutRoot = 0;
511
512     m_frame->invalidateSelection();
513    
514     d->layoutSchedulingEnabled=true;
515
516     if (!subtree && !static_cast<RenderView*>(root)->printingMode())
517         resizeContents(layer->width(), layer->height());
518
519     // Now update the positions of all layers.
520     layer->updateLayerPositions(d->doFullRepaint);
521
522     // We update our widget positions right after doing a layout.
523     if (!subtree)
524         static_cast<RenderView*>(root)->updateWidgetPositions();
525     
526     if (d->repaintRects && !d->repaintRects->isEmpty()) {
527         // FIXME: Could optimize this and have objects removed from this list
528         // if they ever do full repaints.
529         RenderObject::RepaintInfo* r;
530         DeprecatedPtrListIterator<RenderObject::RepaintInfo> it(*d->repaintRects);
531         for (; (r = it.current()); ++it)
532             r->m_object->repaintRectangle(r->m_repaintRect);
533         d->repaintRects->clear();
534     }
535     
536     d->layoutCount++;
537
538 #if PLATFORM(MAC)
539     if (AXObjectCache::accessibilityEnabled())
540         root->document()->axObjectCache()->postNotificationToElement(root, "AXLayoutComplete");
541     updateDashboardRegions();
542 #endif
543
544     if (didFirstLayout)
545         m_frame->loader()->didFirstLayout();
546     
547     if (root->needsLayout()) {
548         scheduleRelayout();
549         return;
550     }
551     setStaticBackground(useSlowRepaints());
552
553     if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
554         updateOverflowStatus(visibleWidth() < contentsWidth(),
555                              visibleHeight() < contentsHeight());
556
557     // Dispatch events scheduled during layout
558     dispatchScheduledEvents();    
559 }
560
561 //
562 // Event Handling
563 //
564 /////////////////
565
566 static Frame* subframeForTargetNode(Node* node)
567 {
568     if (!node)
569         return 0;
570
571     RenderObject* renderer = node->renderer();
572     if (!renderer || !renderer->isWidget())
573         return 0;
574
575     Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
576     if (!widget || !widget->isFrameView())
577         return 0;
578
579     return static_cast<FrameView*>(widget)->frame();
580 }
581
582 IntPoint FrameView::currentMousePosition() const
583 {
584     return d->m_currentMousePosition;
585 }
586
587 void FrameView::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
588 {
589     if (!m_frame->document())
590         return;
591
592     RefPtr<FrameView> protector(this);
593
594     d->mousePressed = true;
595     d->m_currentMousePosition = mouseEvent.pos();
596     
597     MouseEventWithHitTestResults mev = prepareMouseEvent(false, true, false, mouseEvent);
598
599     if (!mev.targetNode()) {
600         invalidateClick();
601         return;
602     }
603
604     Frame* subframe = subframeForTargetNode(mev.targetNode());
605     if (subframe && passMousePressEventToSubframe(mev, subframe)) {
606         invalidateClick();
607         return;
608     }
609
610     d->clickCount = mouseEvent.clickCount();
611     d->clickNode = mev.targetNode();
612     
613     RenderLayer* layer = d->clickNode->renderer()? d->clickNode->renderer()->enclosingLayer() : 0;
614     IntPoint p =  windowToContents(mouseEvent.pos());
615     if (layer && layer->isPointInResizeControl(p)) {
616         layer->setInResizeMode(true);
617         d->m_resizeLayer = layer;
618         d->offsetFromResizeCorner = layer->offsetFromResizeCorner(p);
619         invalidateClick();
620         return;  
621     }
622
623     bool swallowEvent = dispatchMouseEvent(mousedownEvent, mev.targetNode(), true, d->clickCount, mouseEvent, true);
624
625     if (!swallowEvent) {
626         // Refetch the event target node if it currently is the shadow node inside an <input> element.
627         // If a mouse event handler changes the input element type to one that has a widget associated,
628         // we'd like to Frame::handleMousePressEvent to pass the event to the widget and thus the
629         // event target node can't still be the shadow node.
630         if (mev.targetNode()->isShadowNode() && mev.targetNode()->shadowParentNode()->hasTagName(inputTag))
631             mev = prepareMouseEvent(true, true, false, mouseEvent);
632
633         PlatformScrollbar* scrollbar = scrollbarUnderMouse(mouseEvent);
634         if (!scrollbar)
635             scrollbar = mev.scrollbar();
636         if (!scrollbar || !passMousePressEventToScrollbar(mev, scrollbar))
637             m_frame->handleMousePressEvent(mev);
638
639         // Many AK widgets run their own event loops and consume events while the mouse is down.
640         // When they finish, currentEvent is the mouseUp that they exited on.  We need to update
641         // the khtml state with this mouseUp, which khtml never saw.
642         // If this event isn't a mouseUp, we assume that the mouseUp will be coming later.  There
643         // is a hole here if the widget consumes the mouseUp and subsequent events.
644         if (m_frame->lastEventIsMouseUp())
645             d->mousePressed = false;
646     }
647 }
648
649 // This method only exists for platforms that don't know how to deliver 
650 void FrameView::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent)
651 {
652     if (!m_frame->document())
653         return;
654
655     RefPtr<FrameView> protector(this);
656
657     // We get this instead of a second mouse-up 
658     d->mousePressed = false;
659     d->m_currentMousePosition = mouseEvent.pos();
660
661     MouseEventWithHitTestResults mev = prepareMouseEvent(false, true, false, mouseEvent);
662     Frame* subframe = subframeForTargetNode(mev.targetNode());
663     if (subframe && passMousePressEventToSubframe(mev, subframe))
664         return;
665
666     d->clickCount = mouseEvent.clickCount();
667     bool swallowEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode(), true, d->clickCount, mouseEvent, false);
668
669     if (mev.targetNode() == d->clickNode)
670         dispatchMouseEvent(clickEvent, mev.targetNode(), true, d->clickCount, mouseEvent, true);
671
672     if (!swallowEvent)
673         m_frame->handleMouseReleaseEvent(mev);
674
675     invalidateClick();
676 }
677
678 static bool isSubmitImage(Node *node)
679 {
680     return node && node->hasTagName(inputTag) && static_cast<HTMLInputElement*>(node)->inputType() == HTMLInputElement::IMAGE;
681 }
682
683 // Returns true if the node's editable block is not current focused for editing
684 static bool nodeIsNotBeingEdited(Node* node, Frame* frame)
685 {
686     return frame->selectionController()->rootEditableElement() != node->rootEditableElement();
687 }
688
689 static Cursor selectCursor(const MouseEventWithHitTestResults& event, Frame* frame, bool mousePressed, PlatformScrollbar* scrollbar)
690 {
691     // During selection, use an I-beam no matter what we're over.
692     if (mousePressed && frame->selectionController()->isCaretOrRange())
693         return iBeamCursor();
694
695     Node* node = event.targetNode();
696     RenderObject* renderer = node ? node->renderer() : 0;
697     RenderStyle* style = renderer ? renderer->style() : 0;
698
699     if (style && style->cursors()) {
700         const CursorList* cursors = style->cursors();
701         for (unsigned i = 0; i < cursors->size(); ++i) {
702             CachedImage* cimage = (*cursors)[i].cursorImage;
703             IntPoint hotSpot = (*cursors)[i].hotSpot;
704 #ifdef SVG_SUPPORT
705             if (!cimage) {
706                 Element* e = node->document()->getElementById((*cursors)[i].cursorFragmentId);
707                 if (e && e->hasTagName(cursorTag)) {
708                     hotSpot.setX(int(static_cast<SVGCursorElement*>(e)->x()->value()));
709                     hotSpot.setY(int(static_cast<SVGCursorElement*>(e)->y()->value()));
710                     cimage = static_cast<SVGCursorElement*>(e)->cachedImage();
711                 }
712             }
713 #endif
714             if (!cimage)
715                 continue;
716             if (cimage->image()->isNull())
717                 break;
718             if (!cimage->isErrorImage()) {
719                 return Cursor(cimage->image(), hotSpot);
720 }
721         }
722     }
723
724     switch (style ? style->cursor() : CURSOR_AUTO) {
725         case CURSOR_AUTO: {
726             bool editable = (node && node->isContentEditable());
727             bool editableLinkEnabled = false;
728
729             // If the link is editable, then we need to check the settings to see whether or not the link should be followed
730             if (editable) {
731                 switch(frame->settings()->editableLinkBehavior()) {
732                     default:
733                     case Settings::EditableLinkDefaultBehavior:
734                     case Settings::EditableLinkAlwaysLive:
735                         editableLinkEnabled = true;
736                         break;
737                     
738                     case Settings::EditableLinkLiveWhenNotFocused:
739                         editableLinkEnabled = nodeIsNotBeingEdited(node, frame) || event.event().shiftKey();
740                         break;
741                     
742                     case Settings::EditableLinkOnlyLiveWithShiftKey:
743                         editableLinkEnabled = event.event().shiftKey();
744                         break;
745                 }
746             }
747             
748             if ((event.isOverLink() || isSubmitImage(node)) && (!editable || editableLinkEnabled))
749                 return handCursor();
750             RenderLayer* layer = renderer ? renderer->enclosingLayer() : 0;
751             bool inResizer = false;
752             if (frame->view() && layer && layer->isPointInResizeControl(frame->view()->windowToContents(event.event().pos())))
753                 inResizer = true;
754             if ((editable || (renderer && renderer->isText() && renderer->canSelect())) && !inResizer && !scrollbar)
755                 return iBeamCursor();
756             return pointerCursor();
757         }
758         case CURSOR_CROSS:
759             return crossCursor();
760         case CURSOR_POINTER:
761             return handCursor();
762         case CURSOR_MOVE:
763             return moveCursor();
764         case CURSOR_ALL_SCROLL:
765             return moveCursor();
766         case CURSOR_E_RESIZE:
767             return eastResizeCursor();
768         case CURSOR_W_RESIZE:
769             return westResizeCursor();
770         case CURSOR_N_RESIZE:
771             return northResizeCursor();
772         case CURSOR_S_RESIZE:
773             return southResizeCursor();
774         case CURSOR_NE_RESIZE:
775             return northEastResizeCursor();
776         case CURSOR_SW_RESIZE:
777             return southWestResizeCursor();
778         case CURSOR_NW_RESIZE:
779             return northWestResizeCursor();
780         case CURSOR_SE_RESIZE:
781             return southEastResizeCursor();
782         case CURSOR_NS_RESIZE:
783             return northSouthResizeCursor();
784         case CURSOR_EW_RESIZE:
785             return eastWestResizeCursor();
786         case CURSOR_NESW_RESIZE:
787             return northEastSouthWestResizeCursor();
788         case CURSOR_NWSE_RESIZE:
789             return northWestSouthEastResizeCursor();
790         case CURSOR_COL_RESIZE:
791             return columnResizeCursor();
792         case CURSOR_ROW_RESIZE:
793             return rowResizeCursor();
794         case CURSOR_TEXT:
795             return iBeamCursor();
796         case CURSOR_WAIT:
797             return waitCursor();
798         case CURSOR_HELP:
799             return helpCursor();
800         case CURSOR_DEFAULT:
801             return pointerCursor();
802     }
803     return pointerCursor();
804 }
805
806 void FrameView::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent)
807 {
808     // in Radar 3703768 we saw frequent crashes apparently due to the
809     // part being null here, which seems impossible, so check for nil
810     // but also assert so that we can try to figure this out in debug
811     // builds, if it happens.
812     ASSERT(m_frame);
813     if (!m_frame || !m_frame->document())
814         return;
815
816     RefPtr<FrameView> protector(this);
817     d->m_currentMousePosition = mouseEvent.pos();
818    
819     if (d->hoverTimer.isActive())
820         d->hoverTimer.stop();
821
822     if (d->resizingFrameSet) {
823         dispatchMouseEvent(mousemoveEvent, d->resizingFrameSet.get(), false, 0, mouseEvent, false);
824         return;
825     }
826
827     // Treat mouse move events while the mouse is pressed as "read-only" in prepareMouseEvent
828     // if we are allowed to select.
829     // This means that :hover and :active freeze in the state they were in when the mouse
830     // was pressed, rather than updating for nodes the mouse moves over as you hold the mouse down.
831     MouseEventWithHitTestResults mev = prepareMouseEvent(d->mousePressed && m_frame->mouseDownMayStartSelect(),
832         d->mousePressed, true, mouseEvent);
833
834     if (d->oldSubframe && d->oldSubframe->tree()->isDescendantOf(m_frame.get()))
835         passMouseMoveEventToSubframe(mev, d->oldSubframe.get());
836
837     bool swallowEvent = dispatchMouseEvent(mousemoveEvent, mev.targetNode(), false, 0, mouseEvent, true);
838     
839     PlatformScrollbar* scrollbar = scrollbarUnderMouse(mouseEvent);
840     if (!scrollbar)
841         scrollbar = mev.scrollbar();
842
843     if (d->oldScrollbar != scrollbar) {
844         // Send mouse exited to the old scrollbar.
845         if (d->oldScrollbar)
846             d->oldScrollbar->handleMouseOutEvent(mouseEvent);
847         d->oldScrollbar = scrollbar;
848     }
849
850     if (d->m_resizeLayer && d->m_resizeLayer->inResizeMode())
851         d->m_resizeLayer->resize(mouseEvent, d->offsetFromResizeCorner);
852
853     if (!swallowEvent)
854         m_frame->handleMouseMoveEvent(mev);
855     
856     RefPtr<Frame> newSubframe = subframeForTargetNode(mev.targetNode());
857     if (newSubframe) {
858         if (d->oldSubframe != newSubframe)
859             passMouseMoveEventToSubframe(mev, newSubframe.get());
860     } else {
861         if (scrollbar && !d->mousePressed)
862             scrollbar->handleMouseMoveEvent(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
863         if (!d->m_resizeLayer || !d->m_resizeLayer->inResizeMode())
864             setCursor(selectCursor(mev, m_frame.get(), d->mousePressed, scrollbar));
865     }
866
867     d->oldSubframe = newSubframe;
868 }
869
870 void FrameView::invalidateClick()
871 {
872     d->clickCount = 0;
873     d->clickNode = 0;
874 }
875
876 bool FrameView::mousePressed()
877 {
878     return d->mousePressed;
879 }
880
881 void FrameView::setMousePressed(bool pressed)
882 {
883     d->mousePressed = pressed;
884 }
885
886 void FrameView::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
887 {
888     if (!m_frame->document())
889         return;
890
891     RefPtr<FrameView> protector(this);
892
893     d->mousePressed = false;
894     d->m_currentMousePosition = mouseEvent.pos();
895
896     if (d->resizingFrameSet) {
897         dispatchMouseEvent(mouseupEvent, d->resizingFrameSet.get(), true, d->clickCount, mouseEvent, false);
898         return;
899     }
900
901     MouseEventWithHitTestResults mev = prepareMouseEvent(false, false, false, mouseEvent);
902     Frame* subframe = subframeForTargetNode(mev.targetNode());
903     if (subframe && passMouseReleaseEventToSubframe(mev, subframe))
904         return;
905
906     bool swallowEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode(), true, d->clickCount, mouseEvent, false);
907
908     if (d->clickCount > 0 && mev.targetNode() == d->clickNode)
909         dispatchMouseEvent(clickEvent, mev.targetNode(), true, d->clickCount, mouseEvent, true);
910
911     if (d->m_resizeLayer) {
912         d->m_resizeLayer->setInResizeMode(false);
913         d->m_resizeLayer = 0;
914     }
915
916     if (!swallowEvent)
917         m_frame->handleMouseReleaseEvent(mev);
918
919     invalidateClick();
920 }
921
922 bool FrameView::dispatchDragEvent(const AtomicString& eventType, Node *dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard)
923 {
924     IntPoint contentsPos = windowToContents(event.pos());
925     
926     RefPtr<MouseEvent> me = new MouseEvent(eventType,
927         true, true, m_frame->document()->defaultView(),
928         0, event.globalX(), event.globalY(), contentsPos.x(), contentsPos.y(),
929         event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
930         0, 0, clipboard);
931
932     ExceptionCode ec = 0;
933     EventTargetNodeCast(dragTarget)->dispatchEvent(me.get(), ec, true);
934     return me->defaultPrevented();
935 }
936
937 bool FrameView::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
938 {
939     bool accept = false;
940
941     MouseEventWithHitTestResults mev = prepareMouseEvent(true, false, false, event);
942
943     // Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
944     Node* newTarget = mev.targetNode();
945     if (newTarget && newTarget->isTextNode())
946         newTarget = newTarget->parentNode();
947     if (newTarget)
948         newTarget = newTarget->shadowAncestorNode();
949
950     if (d->dragTarget != newTarget) {
951         // FIXME: this ordering was explicitly chosen to match WinIE. However,
952         // it is sometimes incorrect when dragging within subframes, as seen with
953         // LayoutTests/fast/events/drag-in-frames.html.
954         if (newTarget)
955             if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag))
956                 accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->view()->updateDragAndDrop(event, clipboard);
957             else
958                 accept = dispatchDragEvent(dragenterEvent, newTarget, event, clipboard);
959         
960         if (d->dragTarget)
961             if (d->dragTarget->hasTagName(frameTag) || d->dragTarget->hasTagName(iframeTag))
962                 accept = static_cast<HTMLFrameElementBase*>(d->dragTarget.get())->contentFrame()->view()->updateDragAndDrop(event, clipboard);
963             else
964                 dispatchDragEvent(dragleaveEvent, d->dragTarget.get(), event, clipboard);
965     } else {
966         if (newTarget)
967             if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag))
968                 accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->view()->updateDragAndDrop(event, clipboard);
969             else
970                 accept = dispatchDragEvent(dragoverEvent, newTarget, event, clipboard);
971     }
972     d->dragTarget = newTarget;
973
974     return accept;
975 }
976
977 void FrameView::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
978 {
979     if (d->dragTarget)
980         if (d->dragTarget->hasTagName(frameTag) || d->dragTarget->hasTagName(iframeTag))
981             static_cast<HTMLFrameElementBase*>(d->dragTarget.get())->contentFrame()->view()->cancelDragAndDrop(event, clipboard);
982         else
983             dispatchDragEvent(dragleaveEvent, d->dragTarget.get(), event, clipboard);
984     d->dragTarget = 0;
985 }
986
987 bool FrameView::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
988 {
989     bool accept = false;
990     if (d->dragTarget)
991         if (d->dragTarget->hasTagName(frameTag) || d->dragTarget->hasTagName(iframeTag))
992             accept = static_cast<HTMLFrameElementBase*>(d->dragTarget.get())->contentFrame()->view()->performDragAndDrop(event, clipboard);
993         else
994             accept = dispatchDragEvent(dropEvent, d->dragTarget.get(), event, clipboard);
995     d->dragTarget = 0;
996     return accept;
997 }
998
999 Node* FrameView::nodeUnderMouse() const
1000 {
1001     return d->underMouse.get();
1002 }
1003
1004 bool FrameView::scrollTo(const IntRect& bounds)
1005 {
1006     int x, y, xe, ye;
1007     x = bounds.x();
1008     y = bounds.y();
1009     xe = bounds.right() - 1;
1010     ye = bounds.bottom() - 1;
1011     
1012     int deltax;
1013     int deltay;
1014
1015     int curHeight = visibleHeight();
1016     int curWidth = visibleWidth();
1017
1018     if (ye - y>curHeight-d->borderY)
1019         ye = y + curHeight - d->borderY;
1020
1021     if (xe - x>curWidth-d->borderX)
1022         xe = x + curWidth - d->borderX;
1023
1024     // is xpos of target left of the view's border?
1025     if (x < contentsX() + d->borderX)
1026         deltax = x - contentsX() - d->borderX;
1027     // is xpos of target right of the view's right border?
1028     else if (xe + d->borderX > contentsX() + curWidth)
1029         deltax = xe + d->borderX - (contentsX() + curWidth);
1030     else
1031         deltax = 0;
1032
1033     // is ypos of target above upper border?
1034     if (y < contentsY() + d->borderY)
1035         deltay = y - contentsY() - d->borderY;
1036     // is ypos of target below lower border?
1037     else if (ye + d->borderY > contentsY() + curHeight)
1038         deltay = ye + d->borderY - (contentsY() + curHeight);
1039     else
1040         deltay = 0;
1041
1042     int maxx = curWidth - d->borderX;
1043     int maxy = curHeight - d->borderY;
1044
1045     int scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax > -maxx ? deltax : -maxx);
1046     int scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay > -maxy ? deltay : -maxy);
1047
1048     if (contentsX() + scrollX < 0)
1049         scrollX = -contentsX();
1050     else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
1051         scrollX = contentsWidth() - visibleWidth() - contentsX();
1052
1053     if (contentsY() + scrollY < 0)
1054         scrollY = -contentsY();
1055     else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
1056         scrollY = contentsHeight() - visibleHeight() - contentsY();
1057
1058     scrollBy(scrollX, scrollY);
1059
1060     // generate abs(scroll.)
1061     if (scrollX < 0)
1062         scrollX = -scrollX;
1063     if (scrollY < 0)
1064         scrollY = -scrollY;
1065
1066     return scrollX != maxx && scrollY != maxy;
1067 }
1068
1069 bool FrameView::advanceFocus(KeyboardEvent* event)
1070 {
1071     Document* document = m_frame->document();
1072     if (!document)
1073         return false;
1074
1075     Node* node = event->shiftKey()
1076         ? document->previousFocusNode(document->focusNode(), event)
1077         : document->nextFocusNode(document->focusNode(), event);
1078
1079     if (!node)
1080         // FIXME: Need to support tabbing out of the document to the UI.
1081         return false;
1082
1083     if (!node->isElementNode())
1084         // FIXME: May need a way to focus a document here.
1085         return false;
1086
1087     static_cast<Element*>(node)->focus();
1088     return true;
1089 }
1090
1091 void FrameView::setMediaType(const String& mediaType)
1092 {
1093     d->m_mediaType = mediaType;
1094 }
1095
1096 String FrameView::mediaType() const
1097 {
1098     // See if we have an override type.
1099     String overrideType = m_frame->loader()->overrideMediaType();
1100     if (!overrideType.isNull())
1101         return overrideType;
1102     return d->m_mediaType;
1103 }
1104
1105 bool FrameView::useSlowRepaints() const
1106 {
1107     return d->useSlowRepaints || d->slowRepaintObjectCount > 0;
1108 }
1109
1110 void FrameView::setUseSlowRepaints()
1111 {
1112     d->useSlowRepaints = true;
1113     setStaticBackground(true);
1114 }
1115
1116 void FrameView::addSlowRepaintObject()
1117 {
1118     if (d->slowRepaintObjectCount == 0)
1119         setStaticBackground(true);
1120     d->slowRepaintObjectCount++;
1121 }
1122
1123 void FrameView::removeSlowRepaintObject()
1124 {
1125     d->slowRepaintObjectCount--;
1126     if (d->slowRepaintObjectCount == 0)
1127         setStaticBackground(d->useSlowRepaints);
1128 }
1129
1130 void FrameView::setScrollbarsMode(ScrollbarMode mode)
1131 {
1132     d->vmode = mode;
1133     d->hmode = mode;
1134     
1135     ScrollView::setScrollbarsMode(mode);
1136 }
1137
1138 void FrameView::setVScrollbarMode(ScrollbarMode mode)
1139 {
1140     d->vmode = mode;
1141     ScrollView::setVScrollbarMode(mode);
1142 }
1143
1144 void FrameView::setHScrollbarMode(ScrollbarMode mode)
1145 {
1146     d->hmode = mode;
1147     ScrollView::setHScrollbarMode(mode);
1148 }
1149
1150 void FrameView::restoreScrollbar()
1151 {
1152     suppressScrollbars(false);
1153 }
1154
1155 void FrameView::setResizingFrameSet(HTMLFrameSetElement* frameSet)
1156 {
1157     d->resizingFrameSet = frameSet;
1158 }
1159
1160 void FrameView::scrollPointRecursively(int x, int y)
1161 {
1162     if (frame()->prohibitsScrolling())
1163         return;
1164
1165     ScrollView::scrollPointRecursively(x, y);
1166 }
1167
1168 void FrameView::setContentsPos(int x, int y)
1169 {
1170     if (frame()->prohibitsScrolling())
1171         return;
1172
1173     ScrollView::setContentsPos(x, y);
1174 }
1175
1176 MouseEventWithHitTestResults FrameView::prepareMouseEvent(bool readonly, bool active, bool mouseMove, const PlatformMouseEvent& mev)
1177 {
1178     ASSERT(m_frame);
1179     ASSERT(m_frame->document());
1180     
1181     IntPoint vPoint = windowToContents(mev.pos());
1182     return m_frame->document()->prepareMouseEvent(readonly, active, mouseMove, vPoint, mev);
1183 }
1184
1185 bool FrameView::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool cancelable,
1186     int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder)
1187 {
1188     // if the target node is a text node, dispatch on the parent node - rdar://4196646
1189     if (targetNode && targetNode->isTextNode())
1190         targetNode = targetNode->parentNode();
1191     if (targetNode)
1192         targetNode = targetNode->shadowAncestorNode();
1193     d->underMouse = targetNode;
1194
1195     // mouseout/mouseover
1196     if (setUnder) {
1197         if (d->oldUnder && d->oldUnder->document() != frame()->document()) {
1198             d->oldUnder = 0;
1199             d->oldScrollbar = 0;
1200         }
1201
1202         if (d->oldUnder != targetNode) {
1203             // send mouseout event to the old node
1204             if (d->oldUnder)
1205                 EventTargetNodeCast(d->oldUnder.get())->dispatchMouseEvent(mouseEvent, mouseoutEvent, 0, targetNode);
1206             // send mouseover event to the new node
1207             if (targetNode)
1208                 EventTargetNodeCast(targetNode)->dispatchMouseEvent(mouseEvent, mouseoverEvent, 0, d->oldUnder.get());
1209         }
1210         d->oldUnder = targetNode;
1211     }
1212
1213     bool swallowEvent = false;
1214
1215     if (targetNode)
1216         swallowEvent = EventTargetNodeCast(targetNode)->dispatchMouseEvent(mouseEvent, eventType, clickCount);
1217     
1218     if (!swallowEvent && eventType == mousedownEvent) {
1219         // Blur current focus node when a link/button is clicked; this
1220         // is expected by some sites that rely on onChange handlers running
1221         // from form fields before the button click is processed.
1222         Node* node = targetNode;
1223         RenderObject* renderer = node ? node->renderer() : 0;
1224                 
1225         // Walk up the render tree to search for a node to focus.
1226         // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
1227         while (renderer) {
1228             node = renderer->element();
1229             if (node && node->isFocusable())
1230                 break;
1231             renderer = renderer->parent();
1232         }
1233         // If focus shift is blocked, we eat the event.  Note we should never clear swallowEvent
1234         // if the page already set it (e.g., by canceling default behavior).
1235         if (node && node->isMouseFocusable()) {
1236             if (!m_frame->document()->setFocusNode(node))
1237                 swallowEvent = true;
1238         } else if (!node || !node->focused()) {
1239             if (!m_frame->document()->setFocusNode(0))
1240                 swallowEvent = true;
1241         }
1242
1243 #if PLATFORM(WIN)
1244         // It's ok to shift focus to this view now that we know that no focus change got blocked.
1245         if (!swallowEvent && !hasFocus())
1246             setFocus();
1247 #endif
1248     }
1249
1250     return swallowEvent;
1251 }
1252
1253 void FrameView::setIgnoreWheelEvents(bool e)
1254 {
1255     d->ignoreWheelEvents = e;
1256 }
1257
1258 void FrameView::handleWheelEvent(PlatformWheelEvent& e)
1259 {
1260     Document *doc = m_frame->document();
1261     if (doc) {
1262         RenderObject *docRenderer = doc->renderer();
1263         if (docRenderer) {
1264             IntPoint vPoint = windowToContents(e.pos());
1265
1266             HitTestRequest hitTestRequest(true, false);
1267             HitTestResult hitTestResult(vPoint);
1268             doc->renderer()->layer()->hitTest(hitTestRequest, hitTestResult); 
1269             Node *node = hitTestResult.innerNode();
1270             Frame* subframe = subframeForTargetNode(node);
1271             if (subframe && passWheelEventToSubframe(e, subframe)) {
1272                 e.accept();
1273                 return;
1274             }
1275             
1276             if (node) {
1277                 node = node->shadowAncestorNode();
1278                 EventTargetNodeCast(node)->dispatchWheelEvent(e);
1279                 if (e.isAccepted())
1280                     return;
1281                     
1282                 if (node->renderer()) {
1283                     // Just break up into two scrolls if we need to.  Diagonal movement on 
1284                     // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
1285                     if (e.deltaX() && node->renderer()->scroll(e.deltaX() < 0 ? ScrollRight : ScrollLeft, ScrollByWheel,
1286                                                                e.deltaX() < 0 ? -e.deltaX() : e.deltaX()))
1287                         e.accept();
1288                     if (e.deltaY() && node->renderer()->scroll(e.deltaY() < 0 ? ScrollDown : ScrollUp, ScrollByWheel,
1289                                                                e.deltaY() < 0 ? -e.deltaY() : e.deltaY()))
1290                         e.accept();
1291                         
1292                     if (!e.isAccepted())
1293                         wheelEvent(e);
1294                 }
1295             }
1296         }
1297     }
1298 }
1299
1300 void FrameView::repaintRectangle(const IntRect& r, bool immediate)
1301 {
1302     updateContents(r, immediate);
1303 }
1304
1305 void FrameView::layoutTimerFired(Timer<FrameView>*)
1306 {
1307 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1308     if (m_frame->document() && !m_frame->document()->ownerElement())
1309         printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
1310 #endif
1311     layout();
1312 }
1313
1314 void FrameView::hoverTimerFired(Timer<FrameView>*)
1315 {
1316     d->hoverTimer.stop();
1317     prepareMouseEvent(false, false, true, PlatformMouseEvent(PlatformMouseEvent::currentEvent));
1318 }
1319
1320 void FrameView::scheduleRelayout()
1321 {
1322     if (d->layoutRoot) {
1323         if (d->layoutRoot->renderer())
1324             d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
1325         d->layoutRoot = 0;
1326     }
1327     if (!d->layoutSchedulingEnabled)
1328         return;
1329
1330     if (!m_frame->document() || !m_frame->document()->shouldScheduleLayout())
1331         return;
1332
1333     int delay = m_frame->document()->minimumLayoutDelay();
1334     if (d->layoutTimer.isActive() && d->delayedLayout && !delay)
1335         unscheduleRelayout();
1336     if (d->layoutTimer.isActive())
1337         return;
1338
1339     d->delayedLayout = delay != 0;
1340
1341 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1342     if (!m_frame->document()->ownerElement())
1343         printf("Scheduling layout for %d\n", delay);
1344 #endif
1345
1346     d->layoutTimer.startOneShot(delay * 0.001);
1347 }
1348
1349 void FrameView::scheduleRelayoutOfSubtree(Node* n)
1350 {
1351     if (!d->layoutSchedulingEnabled || m_frame->document() && m_frame->document()->renderer() && m_frame->document()->renderer()->needsLayout()) {
1352         if (n->renderer())
1353             n->renderer()->markContainingBlocksForLayout(false);
1354         return;
1355     }
1356
1357     if (layoutPending()) {
1358         if (d->layoutRoot != n) {
1359             // Just do a full relayout
1360             if (d->layoutRoot && d->layoutRoot->renderer())
1361                 d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
1362             d->layoutRoot = 0;
1363             if (n->renderer())
1364                 n->renderer()->markContainingBlocksForLayout(false);
1365         }
1366     } else {
1367         int delay = m_frame->document()->minimumLayoutDelay();
1368         d->layoutRoot = n;
1369         d->delayedLayout = delay != 0;
1370         d->layoutTimer.startOneShot(delay * 0.001);
1371     }
1372 }
1373
1374 bool FrameView::layoutPending() const
1375 {
1376     return d->layoutTimer.isActive();
1377 }
1378
1379 bool FrameView::haveDelayedLayoutScheduled()
1380 {
1381     return d->layoutTimer.isActive() && d->delayedLayout;
1382 }
1383
1384 void FrameView::unscheduleRelayout()
1385 {
1386     if (!d->layoutTimer.isActive())
1387         return;
1388
1389 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1390     if (m_frame->document() && !m_frame->document()->ownerElement())
1391         printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
1392 #endif
1393     
1394     d->layoutTimer.stop();
1395     d->delayedLayout = false;
1396 }
1397
1398 bool FrameView::isTransparent() const
1399 {
1400     return d->isTransparent;
1401 }
1402
1403 void FrameView::setTransparent(bool isTransparent)
1404 {
1405     d->isTransparent = isTransparent;
1406 }
1407
1408 Color FrameView::baseBackgroundColor() const
1409 {
1410     return d->baseBackgroundColor;
1411 }
1412
1413 void FrameView::setBaseBackgroundColor(Color bc)
1414 {
1415     if (!bc.isValid())
1416         bc = Color::white;
1417     d->baseBackgroundColor = bc;
1418 }
1419
1420 void FrameView::scheduleHoverStateUpdate()
1421 {
1422     if (!d->hoverTimer.isActive())
1423         d->hoverTimer.startOneShot(0);
1424 }
1425
1426 void FrameView::setHasBorder(bool b)
1427 {
1428     d->m_hasBorder = b;
1429     updateBorder();
1430 }
1431
1432 bool FrameView::hasBorder() const
1433 {
1434     return d->m_hasBorder;
1435 }
1436
1437 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<EventTargetNode> eventTarget, bool tempEvent)
1438 {
1439     if (!d->m_scheduledEvents)
1440         d->m_scheduledEvents = new Vector<ScheduledEvent*>;
1441     
1442     ScheduledEvent *scheduledEvent = new ScheduledEvent;
1443     scheduledEvent->m_event = event;
1444     scheduledEvent->m_eventTarget = eventTarget;
1445     scheduledEvent->m_tempEvent = tempEvent;
1446     
1447     d->m_scheduledEvents->append(scheduledEvent);
1448 }
1449
1450 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
1451 {
1452     if (!d->m_viewportRenderer)
1453         return;
1454     
1455     if (d->m_overflowStatusDirty) {
1456         d->horizontalOverflow = horizontalOverflow;
1457         d->m_verticalOverflow = verticalOverflow;
1458         d->m_overflowStatusDirty = false;
1459         
1460         return;
1461     }
1462     
1463     bool horizontalOverflowChanged = (d->horizontalOverflow != horizontalOverflow);
1464     bool verticalOverflowChanged = (d->m_verticalOverflow != verticalOverflow);
1465     
1466     if (horizontalOverflowChanged || verticalOverflowChanged) {
1467         d->horizontalOverflow = horizontalOverflow;
1468         d->m_verticalOverflow = verticalOverflow;
1469         
1470         scheduleEvent(new OverflowEvent(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow),
1471                                         EventTargetNodeCast(d->m_viewportRenderer->element()), true);
1472     }
1473     
1474 }
1475
1476 void FrameView::dispatchScheduledEvents()
1477 {
1478     if (!d->m_scheduledEvents)
1479         return;
1480     
1481     Vector<ScheduledEvent*> scheduledEventsCopy = *d->m_scheduledEvents;
1482     d->m_scheduledEvents->clear();
1483     
1484     Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end();
1485     for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) {
1486         ScheduledEvent* scheduledEvent = *it;
1487         
1488         ExceptionCode ec = 0;
1489         
1490         // Only dispatch events to nodes that are in the document
1491         if (scheduledEvent->m_eventTarget->inDocument())
1492             scheduledEvent->m_eventTarget->dispatchEvent(scheduledEvent->m_event, ec, scheduledEvent->m_tempEvent);
1493         
1494         delete scheduledEvent;
1495     }    
1496 }
1497
1498 IntRect FrameView::windowClipRect() const
1499 {
1500     return windowClipRect(true);
1501 }
1502
1503 IntRect FrameView::windowClipRect(bool clipToContents) const
1504 {
1505     // Set our clip rect to be our contents.
1506     IntRect clipRect;
1507     if (clipToContents)
1508         clipRect = enclosingIntRect(visibleContentRect());
1509     else
1510         clipRect = IntRect(contentsX(), contentsY(), width(), height());
1511     clipRect.setLocation(contentsToWindow(clipRect.location()));
1512     if (!m_frame || !m_frame->document() || !m_frame->document()->ownerElement())
1513         return clipRect;
1514
1515     // Take our owner element and get the clip rect from the enclosing layer.
1516     Element* elt = m_frame->document()->ownerElement();
1517     RenderLayer* layer = elt->renderer()->enclosingLayer();
1518     // FIXME: layer should never be null, but sometimes seems to be anyway.
1519     if (!layer)
1520         return clipRect;
1521     FrameView* parentView = elt->document()->view();
1522     clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
1523     return clipRect;
1524 }
1525
1526 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const
1527 {
1528     // Apply the clip from the layer.
1529     IntRect clipRect;
1530     if (clipToLayerContents)
1531         clipRect = layer->childrenClipRect();
1532     else
1533         clipRect = layer->selfClipRect();
1534
1535     clipRect.setLocation(contentsToWindow(clipRect.location()));
1536  
1537     // Now apply the clip from our view.
1538     clipRect.intersect(windowClipRect());
1539
1540     // Return the result.
1541     return clipRect;
1542 }
1543
1544 }