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