Refactor the code that sends the mouse down to scrollbars.
[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         if (!mev.scrollbar() || !passMousePressEventToScrollbar(mev))
617             m_frame->handleMousePressEvent(mev);
618
619         // Many AK widgets run their own event loops and consume events while the mouse is down.
620         // When they finish, currentEvent is the mouseUp that they exited on.  We need to update
621         // the khtml state with this mouseUp, which khtml never saw.
622         // If this event isn't a mouseUp, we assume that the mouseUp will be coming later.  There
623         // is a hole here if the widget consumes the mouseUp and subsequent events.
624         if (m_frame->lastEventIsMouseUp())
625             d->mousePressed = false;
626     }
627 }
628
629 // This method only exists for platforms that don't know how to deliver 
630 void FrameView::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent)
631 {
632     if (!m_frame->document())
633         return;
634
635     RefPtr<FrameView> protector(this);
636
637     // We get this instead of a second mouse-up 
638     d->mousePressed = false;
639     d->m_currentMousePosition = convertFromContainingWindow(mouseEvent.pos());
640
641     MouseEventWithHitTestResults mev = prepareMouseEvent(false, true, false, mouseEvent);
642     Frame* subframe = subframeForTargetNode(mev.targetNode());
643     if (subframe && passMousePressEventToSubframe(mev, subframe))
644         return;
645
646     d->clickCount = mouseEvent.clickCount();
647     bool swallowEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode(), true, d->clickCount, mouseEvent, false);
648
649     if (mev.targetNode() == d->clickNode)
650         dispatchMouseEvent(clickEvent, mev.targetNode(), true, d->clickCount, mouseEvent, true);
651
652     if (!swallowEvent)
653         m_frame->handleMouseReleaseEvent(mev);
654
655     invalidateClick();
656 }
657
658 static bool isSubmitImage(Node *node)
659 {
660     return node && node->hasTagName(inputTag) && static_cast<HTMLInputElement*>(node)->inputType() == HTMLInputElement::IMAGE;
661 }
662
663 static Cursor selectCursor(const MouseEventWithHitTestResults& event, Frame* frame, bool mousePressed)
664 {
665     // During selection, use an I-beam no matter what we're over.
666     if (mousePressed && frame->hasSelection())
667         return iBeamCursor();
668
669     Node* node = event.targetNode();
670     RenderObject* renderer = node ? node->renderer() : 0;
671     RenderStyle* style = renderer ? renderer->style() : 0;
672
673     if (style && style->cursors()) {
674         const CursorList* cursors = style->cursors();
675         for (unsigned i = 0; i < cursors->size(); ++i) {
676             CachedImage* cimage = (*cursors)[i].cursorImage;
677             IntPoint hotSpot = (*cursors)[i].hotSpot;
678 #ifdef SVG_SUPPORT
679             if (!cimage) {
680                 Element* e = node->document()->getElementById((*cursors)[i].cursorFragmentId);
681                 if (e && e->hasTagName(cursorTag)) {
682                     hotSpot.setX(int(static_cast<SVGCursorElement*>(e)->x()->value()));
683                     hotSpot.setY(int(static_cast<SVGCursorElement*>(e)->y()->value()));
684                     cimage = static_cast<SVGCursorElement*>(e)->cachedImage();
685                 }
686             }
687 #endif
688             if (!cimage)
689                 continue;
690             if (cimage->image()->isNull())
691                 break;
692             if (!cimage->isErrorImage()) {
693                 return Cursor(cimage->image(), hotSpot);
694 }
695         }
696     }
697
698     switch (style ? style->cursor() : CURSOR_AUTO) {
699         case CURSOR_AUTO: {
700             bool editable = (node && node->isContentEditable());
701             if ((event.isOverLink() || isSubmitImage(node)) && (!editable || event.event().shiftKey()))
702                 return handCursor();
703             RenderLayer* layer = renderer ? renderer->enclosingLayer() : 0;
704             bool inResizer = false;
705             if (frame->view() && layer && layer->isPointInResizeControl(frame->view()->convertFromContainingWindow(event.event().pos())))
706                 inResizer = true;
707             if ((editable || (renderer && renderer->isText() && renderer->canSelect())) && !inResizer && !event.scrollbar())
708                 return iBeamCursor();
709             // FIXME: If the point is in a layer's overflow scrollbars, we should use the pointer cursor
710             return pointerCursor();
711         }
712         case CURSOR_CROSS:
713             return crossCursor();
714         case CURSOR_POINTER:
715             return handCursor();
716         case CURSOR_MOVE:
717             return moveCursor();
718         case CURSOR_E_RESIZE:
719             return eastResizeCursor();
720         case CURSOR_W_RESIZE:
721             return westResizeCursor();
722         case CURSOR_N_RESIZE:
723             return northResizeCursor();
724         case CURSOR_S_RESIZE:
725             return southResizeCursor();
726         case CURSOR_NE_RESIZE:
727             return northEastResizeCursor();
728         case CURSOR_SW_RESIZE:
729             return southWestResizeCursor();
730         case CURSOR_NW_RESIZE:
731             return northWestResizeCursor();
732         case CURSOR_SE_RESIZE:
733             return southEastResizeCursor();
734         case CURSOR_NS_RESIZE:
735             return northSouthResizeCursor();
736         case CURSOR_EW_RESIZE:
737             return eastWestResizeCursor();
738         case CURSOR_NESW_RESIZE:
739             return northEastSouthWestResizeCursor();
740         case CURSOR_NWSE_RESIZE:
741             return northWestSouthEastResizeCursor();
742         case CURSOR_COL_RESIZE:
743             return columnResizeCursor();
744         case CURSOR_ROW_RESIZE:
745             return rowResizeCursor();
746         case CURSOR_TEXT:
747             return iBeamCursor();
748         case CURSOR_WAIT:
749             return waitCursor();
750         case CURSOR_HELP:
751             return helpCursor();
752         case CURSOR_DEFAULT:
753             return pointerCursor();
754     }
755     return pointerCursor();
756 }
757
758 void FrameView::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent)
759 {
760     // in Radar 3703768 we saw frequent crashes apparently due to the
761     // part being null here, which seems impossible, so check for nil
762     // but also assert so that we can try to figure this out in debug
763     // builds, if it happens.
764     ASSERT(m_frame);
765     if (!m_frame || !m_frame->document())
766         return;
767
768     RefPtr<FrameView> protector(this);
769     d->m_currentMousePosition = convertFromContainingWindow(mouseEvent.pos());
770    
771     if (d->hoverTimer.isActive())
772         d->hoverTimer.stop();
773
774     if (d->resizingFrameSet) {
775         dispatchMouseEvent(mousemoveEvent, d->resizingFrameSet.get(), false, 0, mouseEvent, false);
776         return;
777     }
778
779     // Treat mouse move events while the mouse is pressed as "read-only" in prepareMouseEvent
780     // if we are allowed to select.
781     // This means that :hover and :active freeze in the state they were in when the mouse
782     // was pressed, rather than updating for nodes the mouse moves over as you hold the mouse down.
783     MouseEventWithHitTestResults mev = prepareMouseEvent(d->mousePressed && m_frame->mouseDownMayStartSelect(),
784         d->mousePressed, true, mouseEvent);
785
786     if (d->oldSubframe && d->oldSubframe->tree()->isDescendantOf(m_frame.get()))
787         passMouseMoveEventToSubframe(mev, d->oldSubframe.get());
788
789     bool swallowEvent = dispatchMouseEvent(mousemoveEvent, mev.targetNode(), false, 0, mouseEvent, true);
790     
791     if (d->oldScrollBar != mev.scrollbar()) {
792         // Send mouse exited to the old scrollbar.
793         if (d->oldScrollBar)
794             d->oldScrollBar->handleMouseOutEvent(mouseEvent);
795         d->oldScrollBar = mev.scrollbar();
796     }
797
798     if (d->m_resizeLayer && d->m_resizeLayer->inResizeMode())
799         d->m_resizeLayer->resize(mouseEvent, d->offsetFromResizeCorner);
800
801     if (!swallowEvent)
802         m_frame->handleMouseMoveEvent(mev);
803     
804     RefPtr<Frame> newSubframe = subframeForTargetNode(mev.targetNode());
805     if (newSubframe && d->oldSubframe != newSubframe)
806         passMouseMoveEventToSubframe(mev, newSubframe.get());
807     else {
808         if (mev.scrollbar() && !d->mousePressed)
809             mev.scrollbar()->handleMouseMoveEvent(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
810         setCursor(selectCursor(mev, m_frame.get(), d->mousePressed));
811     }
812
813     d->oldSubframe = newSubframe;
814 }
815
816 void FrameView::invalidateClick()
817 {
818     d->clickCount = 0;
819     d->clickNode = 0;
820 }
821
822 bool FrameView::mousePressed()
823 {
824     return d->mousePressed;
825 }
826
827 void FrameView::setMousePressed(bool pressed)
828 {
829     d->mousePressed = pressed;
830 }
831
832 void FrameView::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
833 {
834     if (!m_frame->document())
835         return;
836
837     RefPtr<FrameView> protector(this);
838
839     d->mousePressed = false;
840     d->m_currentMousePosition = convertFromContainingWindow(mouseEvent.pos());
841
842     if (d->resizingFrameSet) {
843         dispatchMouseEvent(mouseupEvent, d->resizingFrameSet.get(), true, d->clickCount, mouseEvent, false);
844         return;
845     }
846
847     MouseEventWithHitTestResults mev = prepareMouseEvent(false, false, false, mouseEvent);
848     Frame* subframe = subframeForTargetNode(mev.targetNode());
849     if (subframe && passMouseReleaseEventToSubframe(mev, subframe))
850         return;
851
852     bool swallowEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode(), true, d->clickCount, mouseEvent, false);
853
854     if (d->clickCount > 0 && mev.targetNode() == d->clickNode)
855         dispatchMouseEvent(clickEvent, mev.targetNode(), true, d->clickCount, mouseEvent, true);
856
857     if (d->m_resizeLayer) {
858         d->m_resizeLayer->setInResizeMode(false);
859         d->m_resizeLayer = 0;
860     }
861
862     if (!swallowEvent)
863         m_frame->handleMouseReleaseEvent(mev);
864
865     invalidateClick();
866 }
867
868 bool FrameView::dispatchDragEvent(const AtomicString& eventType, Node *dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard)
869 {
870     IntPoint contentsPos = convertFromContainingWindow(event.pos());
871     
872     RefPtr<MouseEvent> me = new MouseEvent(eventType,
873         true, true, m_frame->document()->defaultView(),
874         0, event.globalX(), event.globalY(), contentsPos.x(), contentsPos.y(),
875         event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
876         0, 0, clipboard);
877
878     ExceptionCode ec = 0;
879     EventTargetNodeCast(dragTarget)->dispatchEvent(me.get(), ec, true);
880     return me->defaultPrevented();
881 }
882
883 bool FrameView::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
884 {
885     bool accept = false;
886
887     MouseEventWithHitTestResults mev = prepareMouseEvent(true, false, false, event);
888
889     // Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
890     Node* newTarget = mev.targetNode();
891     if (newTarget && newTarget->isTextNode())
892         newTarget = newTarget->parentNode();
893     if (newTarget)
894         newTarget = newTarget->shadowAncestorNode();
895
896     if (d->dragTarget != newTarget) {
897         // note this ordering is explicitly chosen to match WinIE
898         if (newTarget)
899             accept = dispatchDragEvent(dragenterEvent, newTarget, event, clipboard);
900         if (d->dragTarget)
901             dispatchDragEvent(dragleaveEvent, d->dragTarget.get(), event, clipboard);
902     } else {
903         if (newTarget)
904             accept = dispatchDragEvent(dragoverEvent, newTarget, event, clipboard);
905     }
906     d->dragTarget = newTarget;
907
908     return accept;
909 }
910
911 void FrameView::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
912 {
913     if (d->dragTarget)
914         dispatchDragEvent(dragleaveEvent, d->dragTarget.get(), event, clipboard);
915     d->dragTarget = 0;
916 }
917
918 bool FrameView::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
919 {
920     bool accept = false;
921     if (d->dragTarget)
922         accept = dispatchDragEvent(dropEvent, d->dragTarget.get(), event, clipboard);
923     d->dragTarget = 0;
924     return accept;
925 }
926
927 Node* FrameView::nodeUnderMouse() const
928 {
929     return d->underMouse.get();
930 }
931
932 bool FrameView::scrollTo(const IntRect& bounds)
933 {
934     d->scrollingSelf = true; // so scroll events get ignored
935
936     int x, y, xe, ye;
937     x = bounds.x();
938     y = bounds.y();
939     xe = bounds.right() - 1;
940     ye = bounds.bottom() - 1;
941     
942     int deltax;
943     int deltay;
944
945     int curHeight = visibleHeight();
946     int curWidth = visibleWidth();
947
948     if (ye - y>curHeight-d->borderY)
949         ye = y + curHeight - d->borderY;
950
951     if (xe - x>curWidth-d->borderX)
952         xe = x + curWidth - d->borderX;
953
954     // is xpos of target left of the view's border?
955     if (x < contentsX() + d->borderX)
956         deltax = x - contentsX() - d->borderX;
957     // is xpos of target right of the view's right border?
958     else if (xe + d->borderX > contentsX() + curWidth)
959         deltax = xe + d->borderX - (contentsX() + curWidth);
960     else
961         deltax = 0;
962
963     // is ypos of target above upper border?
964     if (y < contentsY() + d->borderY)
965         deltay = y - contentsY() - d->borderY;
966     // is ypos of target below lower border?
967     else if (ye + d->borderY > contentsY() + curHeight)
968         deltay = ye + d->borderY - (contentsY() + curHeight);
969     else
970         deltay = 0;
971
972     int maxx = curWidth - d->borderX;
973     int maxy = curHeight - d->borderY;
974
975     int scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax > -maxx ? deltax : -maxx);
976     int scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay > -maxy ? deltay : -maxy);
977
978     if (contentsX() + scrollX < 0)
979         scrollX = -contentsX();
980     else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
981         scrollX = contentsWidth() - visibleWidth() - contentsX();
982
983     if (contentsY() + scrollY < 0)
984         scrollY = -contentsY();
985     else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
986         scrollY = contentsHeight() - visibleHeight() - contentsY();
987
988     scrollBy(scrollX, scrollY);
989
990     // generate abs(scroll.)
991     if (scrollX < 0)
992         scrollX = -scrollX;
993     if (scrollY < 0)
994         scrollY = -scrollY;
995
996     d->scrollingSelf = false;
997
998     return scrollX != maxx && scrollY != maxy;
999 }
1000
1001 void FrameView::focusNextPrevNode(bool next)
1002 {
1003     // Sets the focus node of the document to be the node after (or if next is false, before) the current focus node.
1004     // Only nodes that are selectable (i.e. for which isSelectable() returns true) are taken into account, and the order
1005     // used is that specified in the HTML spec (see Document::nextFocusNode() and Document::previousFocusNode()
1006     // for details).
1007
1008     Document *doc = m_frame->document();
1009     Node *oldFocusNode = doc->focusNode();
1010     Node *newFocusNode;
1011
1012     // Find the next/previous node from the current one
1013     if (next)
1014         newFocusNode = doc->nextFocusNode(oldFocusNode);
1015     else
1016         newFocusNode = doc->previousFocusNode(oldFocusNode);
1017
1018     // If there was previously no focus node and the user has scrolled the document, then instead of picking the first
1019     // focusable node in the document, use the first one that lies within the visible area (if possible).
1020     if (!oldFocusNode && newFocusNode && d->scrollBarMoved) {
1021         bool visible = false;
1022         Node *toFocus = newFocusNode;
1023         while (!visible && toFocus) {
1024             if (toFocus->getRect().intersects(IntRect(contentsX(), contentsY(), visibleWidth(), visibleHeight()))) {
1025                 // toFocus is visible in the contents area
1026                 visible = true;
1027             } else {
1028                 // toFocus is _not_ visible in the contents area, pick the next node
1029                 if (next)
1030                     toFocus = doc->nextFocusNode(toFocus);
1031                 else
1032                     toFocus = doc->previousFocusNode(toFocus);
1033             }
1034         }
1035
1036         if (toFocus)
1037             newFocusNode = toFocus;
1038     }
1039
1040     d->scrollBarMoved = false;
1041
1042     if (!newFocusNode)
1043       {
1044         // No new focus node, scroll to bottom or top depending on next
1045         if (next)
1046             scrollTo(IntRect(contentsX()+visibleWidth()/2,contentsHeight(),0,0));
1047         else
1048             scrollTo(IntRect(contentsX()+visibleWidth()/2,0,0,0));
1049     }
1050     else {
1051         // EDIT FIXME: if it's an editable element, activate the caret
1052         // otherwise, hide it
1053         if (newFocusNode->isContentEditable()) {
1054             // make caret visible
1055         } 
1056         else {
1057             // hide caret
1058         }
1059
1060         // Scroll the view as necessary to ensure that the new focus node is visible
1061         if (oldFocusNode) {
1062             if (!scrollTo(newFocusNode->getRect()))
1063                 return;
1064         }
1065         else {
1066             if (doc->renderer()) {
1067                 doc->renderer()->enclosingLayer()->scrollRectToVisible(IntRect(contentsX(), next ? 0: contentsHeight(), 0, 0));
1068             }
1069         }
1070     }
1071     // Set focus node on the document
1072     m_frame->document()->setFocusNode(newFocusNode);
1073 }
1074
1075 void FrameView::setMediaType(const String& mediaType)
1076 {
1077     d->m_mediaType = mediaType;
1078 }
1079
1080 String FrameView::mediaType() const
1081 {
1082     // See if we have an override type.
1083     String overrideType = m_frame->overrideMediaType();
1084     if (!overrideType.isNull())
1085         return overrideType;
1086     return d->m_mediaType;
1087 }
1088
1089 bool FrameView::useSlowRepaints() const
1090 {
1091     return d->useSlowRepaints || d->slowRepaintObjectCount > 0;
1092 }
1093
1094 void FrameView::setUseSlowRepaints()
1095 {
1096     d->useSlowRepaints = true;
1097     setStaticBackground(true);
1098 }
1099
1100 void FrameView::addSlowRepaintObject()
1101 {
1102     if (d->slowRepaintObjectCount == 0)
1103         setStaticBackground(true);
1104     d->slowRepaintObjectCount++;
1105 }
1106
1107 void FrameView::removeSlowRepaintObject()
1108 {
1109     d->slowRepaintObjectCount--;
1110     if (d->slowRepaintObjectCount == 0)
1111         setStaticBackground(d->useSlowRepaints);
1112 }
1113
1114 void FrameView::setScrollBarsMode(ScrollBarMode mode)
1115 {
1116     d->vmode = mode;
1117     d->hmode = mode;
1118     
1119     ScrollView::setScrollBarsMode(mode);
1120 }
1121
1122 void FrameView::setVScrollBarMode(ScrollBarMode mode)
1123 {
1124     d->vmode = mode;
1125     ScrollView::setVScrollBarMode(mode);
1126 }
1127
1128 void FrameView::setHScrollBarMode(ScrollBarMode mode)
1129 {
1130     d->hmode = mode;
1131     ScrollView::setHScrollBarMode(mode);
1132 }
1133
1134 void FrameView::restoreScrollBar()
1135 {
1136     suppressScrollBars(false);
1137 }
1138
1139 void FrameView::setResizingFrameSet(HTMLFrameSetElement* frameSet)
1140 {
1141     d->resizingFrameSet = frameSet;
1142 }
1143
1144 void FrameView::scrollPointRecursively(int x, int y)
1145 {
1146     if (frame()->prohibitsScrolling())
1147         return;
1148
1149     ScrollView::scrollPointRecursively(x, y);
1150 }
1151
1152 void FrameView::setContentsPos(int x, int y)
1153 {
1154     if (frame()->prohibitsScrolling())
1155         return;
1156
1157     ScrollView::setContentsPos(x, y);
1158 }
1159
1160 MouseEventWithHitTestResults FrameView::prepareMouseEvent(bool readonly, bool active, bool mouseMove, const PlatformMouseEvent& mev)
1161 {
1162     ASSERT(m_frame);
1163     ASSERT(m_frame->document());
1164     
1165     IntPoint vPoint = convertFromContainingWindow(mev.pos());
1166     return m_frame->document()->prepareMouseEvent(readonly, active, mouseMove, vPoint, mev);
1167 }
1168
1169 bool FrameView::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool cancelable,
1170     int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder)
1171 {
1172     // if the target node is a text node, dispatch on the parent node - rdar://4196646
1173     if (targetNode && targetNode->isTextNode())
1174         targetNode = targetNode->parentNode();
1175     if (targetNode)
1176         targetNode = targetNode->shadowAncestorNode();
1177     d->underMouse = targetNode;
1178
1179     // mouseout/mouseover
1180     if (setUnder) {
1181         if (d->oldUnder && d->oldUnder->document() != frame()->document()) {
1182             d->oldUnder = 0;
1183             d->oldScrollBar = 0;
1184         }
1185
1186         if (d->oldUnder != targetNode) {
1187             // send mouseout event to the old node
1188             if (d->oldUnder)
1189                 EventTargetNodeCast(d->oldUnder.get())->dispatchMouseEvent(mouseEvent, mouseoutEvent, 0, targetNode);
1190             // send mouseover event to the new node
1191             if (targetNode)
1192                 EventTargetNodeCast(targetNode)->dispatchMouseEvent(mouseEvent, mouseoverEvent, 0, d->oldUnder.get());
1193         }
1194         d->oldUnder = targetNode;
1195     }
1196
1197     bool swallowEvent = false;
1198
1199     if (targetNode)
1200         swallowEvent = EventTargetNodeCast(targetNode)->dispatchMouseEvent(mouseEvent, eventType, clickCount);
1201     
1202     if (!swallowEvent && eventType == mousedownEvent) {
1203         // Blur current focus node when a link/button is clicked; this
1204         // is expected by some sites that rely on onChange handlers running
1205         // from form fields before the button click is processed.
1206         Node* node = targetNode;
1207         RenderObject* renderer = node ? node->renderer() : 0;
1208                 
1209         // Walk up the render tree to search for a node to focus.
1210         // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
1211         while (renderer) {
1212             node = renderer->element();
1213             if (node && node->isFocusable())
1214                 break;
1215             renderer = renderer->parent();
1216         }
1217         // If focus shift is blocked, we eat the event.  Note we should never clear swallowEvent
1218         // if the page already set it (e.g., by canceling default behavior).
1219         if (node && node->isMouseFocusable()) {
1220             if (!m_frame->document()->setFocusNode(node))
1221                 swallowEvent = true;
1222         } else if (!node || !node->focused()) {
1223             if (!m_frame->document()->setFocusNode(0))
1224                 swallowEvent = true;
1225         }
1226     }
1227
1228     return swallowEvent;
1229 }
1230
1231 void FrameView::setIgnoreWheelEvents(bool e)
1232 {
1233     d->ignoreWheelEvents = e;
1234 }
1235
1236 void FrameView::handleWheelEvent(PlatformWheelEvent& e)
1237 {
1238     Document *doc = m_frame->document();
1239     if (doc) {
1240         RenderObject *docRenderer = doc->renderer();
1241         if (docRenderer) {
1242             IntPoint vPoint = convertFromContainingWindow(e.pos());
1243
1244             RenderObject::NodeInfo hitTestResult(true, false);
1245             doc->renderer()->layer()->hitTest(hitTestResult, vPoint); 
1246             Node *node = hitTestResult.innerNode();
1247             Frame* subframe = subframeForTargetNode(node);
1248             if (subframe && passWheelEventToSubframe(e, subframe)) {
1249                 e.accept();
1250                 return;
1251             }
1252             
1253             if (node) {
1254                 node = node->shadowAncestorNode();
1255                 EventTargetNodeCast(node)->dispatchWheelEvent(e);
1256                 if (e.isAccepted())
1257                     return;
1258                     
1259                 if (node->renderer()) {
1260                     // Just break up into two scrolls if we need to.  Diagonal movement on 
1261                     // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
1262                     if (e.deltaX() && node->renderer()->scroll(e.deltaX() < 0 ? ScrollRight : ScrollLeft, ScrollByWheel,
1263                                                                e.deltaX() < 0 ? -e.deltaX() : e.deltaX()))
1264                         e.accept();
1265                     if (e.deltaY() && node->renderer()->scroll(e.deltaY() < 0 ? ScrollDown : ScrollUp, ScrollByWheel,
1266                                                                e.deltaY() < 0 ? -e.deltaY() : e.deltaY()))
1267                         e.accept();
1268                         
1269                     if (!e.isAccepted())
1270                         wheelEvent(e);
1271                 }
1272             }
1273         }
1274     }
1275 }
1276
1277 void FrameView::scrollBarMoved()
1278 {
1279     // FIXME: Need to arrange for this to be called when the view is scrolled!
1280     if (!d->scrollingSelf)
1281         d->scrollBarMoved = true;
1282 }
1283
1284 void FrameView::repaintRectangle(const IntRect& r, bool immediate)
1285 {
1286     updateContents(r, immediate);
1287 }
1288
1289 void FrameView::layoutTimerFired(Timer<FrameView>*)
1290 {
1291 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1292     if (m_frame->document() && !m_frame->document()->ownerElement())
1293         printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
1294 #endif
1295     layout();
1296 }
1297
1298 void FrameView::hoverTimerFired(Timer<FrameView>*)
1299 {
1300     d->hoverTimer.stop();
1301     prepareMouseEvent(false, false, true, PlatformMouseEvent(PlatformMouseEvent::currentEvent));
1302 }
1303
1304 void FrameView::scheduleRelayout()
1305 {
1306     if (d->layoutRoot) {
1307         if (d->layoutRoot->renderer())
1308             d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
1309         d->layoutRoot = 0;
1310     }
1311     if (!d->layoutSchedulingEnabled)
1312         return;
1313
1314     if (!m_frame->document() || !m_frame->document()->shouldScheduleLayout())
1315         return;
1316
1317     int delay = m_frame->document()->minimumLayoutDelay();
1318     if (d->layoutTimer.isActive() && d->delayedLayout && !delay)
1319         unscheduleRelayout();
1320     if (d->layoutTimer.isActive())
1321         return;
1322
1323     d->delayedLayout = delay != 0;
1324
1325 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1326     if (!m_frame->document()->ownerElement())
1327         printf("Scheduling layout for %d\n", delay);
1328 #endif
1329
1330     d->layoutTimer.startOneShot(delay * 0.001);
1331 }
1332
1333 void FrameView::scheduleRelayoutOfSubtree(Node* n)
1334 {
1335     if (!d->layoutSchedulingEnabled || m_frame->document() && m_frame->document()->renderer() && m_frame->document()->renderer()->needsLayout()) {
1336         if (n->renderer())
1337             n->renderer()->markContainingBlocksForLayout(false);
1338         return;
1339     }
1340
1341     if (layoutPending()) {
1342         if (d->layoutRoot != n) {
1343             // Just do a full relayout
1344             if (d->layoutRoot && d->layoutRoot->renderer())
1345                 d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
1346             d->layoutRoot = 0;
1347             if (n->renderer())
1348                 n->renderer()->markContainingBlocksForLayout(false);
1349         }
1350     } else {
1351         int delay = m_frame->document()->minimumLayoutDelay();
1352         d->layoutRoot = n;
1353         d->delayedLayout = delay != 0;
1354         d->layoutTimer.startOneShot(delay * 0.001);
1355     }
1356 }
1357
1358 bool FrameView::layoutPending() const
1359 {
1360     return d->layoutTimer.isActive();
1361 }
1362
1363 bool FrameView::haveDelayedLayoutScheduled()
1364 {
1365     return d->layoutTimer.isActive() && d->delayedLayout;
1366 }
1367
1368 void FrameView::unscheduleRelayout()
1369 {
1370     if (!d->layoutTimer.isActive())
1371         return;
1372
1373 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1374     if (m_frame->document() && !m_frame->document()->ownerElement())
1375         printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
1376 #endif
1377     
1378     d->layoutTimer.stop();
1379     d->delayedLayout = false;
1380 }
1381
1382 bool FrameView::isTransparent() const
1383 {
1384     return d->isTransparent;
1385 }
1386
1387 void FrameView::setTransparent(bool isTransparent)
1388 {
1389     d->isTransparent = isTransparent;
1390 }
1391
1392 Color FrameView::baseBackgroundColor() const
1393 {
1394     return d->baseBackgroundColor;
1395 }
1396
1397 void FrameView::setBaseBackgroundColor(Color bc)
1398 {
1399     if (!bc.isValid())
1400         bc = Color::white;
1401     d->baseBackgroundColor = bc;
1402 }
1403
1404 void FrameView::scheduleHoverStateUpdate()
1405 {
1406     if (!d->hoverTimer.isActive())
1407         d->hoverTimer.startOneShot(0);
1408 }
1409
1410 void FrameView::setHasBorder(bool b)
1411 {
1412     d->m_hasBorder = b;
1413     updateBorder();
1414 }
1415
1416 bool FrameView::hasBorder() const
1417 {
1418     return d->m_hasBorder;
1419 }
1420
1421 void FrameView::cleared()
1422 {
1423     if (m_frame)
1424         if (RenderPart* renderer = m_frame->ownerRenderer())
1425             renderer->viewCleared();
1426 }
1427
1428
1429 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<EventTargetNode> eventTarget, bool tempEvent)
1430 {
1431     if (!d->m_scheduledEvents)
1432         d->m_scheduledEvents = new Vector<ScheduledEvent*>;
1433     
1434     ScheduledEvent *scheduledEvent = new ScheduledEvent;
1435     scheduledEvent->m_event = event;
1436     scheduledEvent->m_eventTarget = eventTarget;
1437     scheduledEvent->m_tempEvent = tempEvent;
1438     
1439     d->m_scheduledEvents->append(scheduledEvent);
1440 }
1441
1442 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
1443 {
1444     if (!d->m_viewportRenderer)
1445         return;
1446     
1447     if (d->m_overflowStatusDirty) {
1448         d->horizontalOverflow = horizontalOverflow;
1449         d->m_verticalOverflow = verticalOverflow;
1450         d->m_overflowStatusDirty = false;
1451         
1452         return;
1453     }
1454     
1455     bool horizontalOverflowChanged = (d->horizontalOverflow != horizontalOverflow);
1456     bool verticalOverflowChanged = (d->m_verticalOverflow != verticalOverflow);
1457     
1458     if (horizontalOverflowChanged || verticalOverflowChanged) {
1459         d->horizontalOverflow = horizontalOverflow;
1460         d->m_verticalOverflow = verticalOverflow;
1461         
1462         scheduleEvent(new OverflowEvent(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow),
1463                                         EventTargetNodeCast(d->m_viewportRenderer->element()), true);
1464     }
1465     
1466 }
1467
1468 void FrameView::dispatchScheduledEvents()
1469 {
1470     if (!d->m_scheduledEvents)
1471         return;
1472     
1473     Vector<ScheduledEvent*> scheduledEventsCopy = *d->m_scheduledEvents;
1474     d->m_scheduledEvents->clear();
1475     
1476     Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end();
1477     for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) {
1478         ScheduledEvent* scheduledEvent = *it;
1479         
1480         ExceptionCode ec = 0;
1481         
1482         // Only dispatch events to nodes that are in the document
1483         if (scheduledEvent->m_eventTarget->inDocument())
1484             scheduledEvent->m_eventTarget->dispatchEvent(scheduledEvent->m_event, ec, scheduledEvent->m_tempEvent);
1485         
1486         delete scheduledEvent;
1487     }    
1488 }
1489
1490 }