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