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