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