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