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