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