cd0c2758ee18f476a4fd7346670dcd71cbcbca8e
[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         return style->cursorImage()->image();
555
556     switch (style ? style->cursor() : CURSOR_AUTO) {
557         case CURSOR_AUTO: {
558             bool editable = (node && node->isContentEditable());
559             if ((event.isOverLink() || isSubmitImage(node)) && (!editable || event.event().shiftKey()))
560                 return handCursor();
561             if (editable || (renderer && renderer->isText() && renderer->canSelect()))
562                 return iBeamCursor();
563             return pointerCursor();
564         }
565         case CURSOR_CROSS:
566             return crossCursor();
567         case CURSOR_POINTER:
568             return handCursor();
569         case CURSOR_MOVE:
570             return moveCursor();
571         case CURSOR_E_RESIZE:
572             return eastResizeCursor();
573         case CURSOR_W_RESIZE:
574             return westResizeCursor();
575         case CURSOR_N_RESIZE:
576             return northResizeCursor();
577         case CURSOR_S_RESIZE:
578             return southResizeCursor();
579         case CURSOR_NE_RESIZE:
580             return northEastResizeCursor();
581         case CURSOR_SW_RESIZE:
582             return southWestResizeCursor();
583         case CURSOR_NW_RESIZE:
584             return northWestResizeCursor();
585         case CURSOR_SE_RESIZE:
586             return southEastResizeCursor();
587         case CURSOR_TEXT:
588             return iBeamCursor();
589         case CURSOR_WAIT:
590             return waitCursor();
591         case CURSOR_HELP:
592             return helpCursor();
593         case CURSOR_DEFAULT:
594             return pointerCursor();
595     }
596     return pointerCursor();
597 }
598
599 void FrameView::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent)
600 {
601     // in Radar 3703768 we saw frequent crashes apparently due to the
602     // part being null here, which seems impossible, so check for nil
603     // but also assert so that we can try to figure this out in debug
604     // builds, if it happens.
605     ASSERT(m_frame);
606     if (!m_frame || !m_frame->document())
607         return;
608
609     RefPtr<FrameView> protector(this);
610     
611     if (d->hoverTimer.isActive())
612         d->hoverTimer.stop();
613
614     if (d->resizingFrameSet) {
615         dispatchMouseEvent(mousemoveEvent, d->resizingFrameSet.get(), false, 0, mouseEvent, false);
616         return;
617     }
618
619     // Treat mouse move events while the mouse is pressed as "read-only" in prepareMouseEvent
620     // if we are allowed to select.
621     // This means that :hover and :active freeze in the state they were in when the mouse
622     // was pressed, rather than updating for nodes the mouse moves over as you hold the mouse down.
623     MouseEventWithHitTestResults mev = prepareMouseEvent(d->mousePressed && m_frame->mouseDownMayStartSelect(),
624         d->mousePressed, true, mouseEvent);
625
626     if (d->oldSubframe)
627         m_frame->passSubframeEventToSubframe(mev, d->oldSubframe.get());
628
629     bool swallowEvent = dispatchMouseEvent(mousemoveEvent, mev.targetNode(), false, 0, mouseEvent, true);
630     if (!swallowEvent)
631         m_frame->handleMouseMoveEvent(mev);
632     
633     RefPtr<Frame> newSubframe = subframeForEvent(mev);
634     
635     if (newSubframe && d->oldSubframe != newSubframe)
636         m_frame->passSubframeEventToSubframe(mev, newSubframe.get());
637     else
638         setCursor(selectCursor(mev, m_frame.get(), d->mousePressed));
639     
640     d->oldSubframe = newSubframe;
641 }
642
643 void FrameView::invalidateClick()
644 {
645     d->clickCount = 0;
646     d->clickNode = 0;
647 }
648
649 void FrameView::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
650 {
651     if (!m_frame->document())
652         return;
653
654     RefPtr<FrameView> protector(this);
655
656     d->mousePressed = false;
657
658     if (d->resizingFrameSet) {
659         dispatchMouseEvent(mouseupEvent, d->resizingFrameSet.get(), true, d->clickCount, mouseEvent, false);
660         return;
661     }
662
663     MouseEventWithHitTestResults mev = prepareMouseEvent(false, false, false, mouseEvent);
664
665     if (m_frame->passSubframeEventToSubframe(mev))
666         return;
667
668     bool swallowEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode(), true, d->clickCount, mouseEvent, false);
669
670     if (d->clickCount > 0 && mev.targetNode() == d->clickNode)
671         dispatchMouseEvent(clickEvent, mev.targetNode(), true, d->clickCount, mouseEvent, true);
672
673     if (!swallowEvent)
674         m_frame->handleMouseReleaseEvent(mev);
675
676     invalidateClick();
677 }
678
679 bool FrameView::dispatchDragEvent(const AtomicString& eventType, Node *dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard)
680 {
681     IntPoint clientPos = viewportToContents(event.pos());
682     
683     RefPtr<MouseEvent> me = new MouseEvent(eventType,
684         true, true, m_frame->document()->defaultView(),
685         0, event.globalX(), event.globalY(), clientPos.x(), clientPos.y(),
686         event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
687         0, 0, clipboard);
688
689     ExceptionCode ec = 0;
690     EventTargetNodeCast(dragTarget)->dispatchEvent(me.get(), ec, true);
691     return me->defaultPrevented();
692 }
693
694 bool FrameView::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
695 {
696     bool accept = false;
697
698     MouseEventWithHitTestResults mev = prepareMouseEvent(true, false, false, PlatformMouseEvent());
699
700     // Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
701     Node* newTarget = mev.targetNode();
702     if (newTarget && newTarget->isTextNode())
703         newTarget = newTarget->parentNode();
704     if (newTarget)
705         newTarget = newTarget->shadowAncestorNode();
706
707     if (d->dragTarget != newTarget) {
708         // note this ordering is explicitly chosen to match WinIE
709         if (newTarget)
710             accept = dispatchDragEvent(dragenterEvent, newTarget, event, clipboard);
711         if (d->dragTarget)
712             dispatchDragEvent(dragleaveEvent, d->dragTarget.get(), event, clipboard);
713     } else {
714         if (newTarget)
715             accept = dispatchDragEvent(dragoverEvent, newTarget, event, clipboard);
716     }
717     d->dragTarget = newTarget;
718
719     return accept;
720 }
721
722 void FrameView::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
723 {
724     if (d->dragTarget)
725         dispatchDragEvent(dragleaveEvent, d->dragTarget.get(), event, clipboard);
726     d->dragTarget = 0;
727 }
728
729 bool FrameView::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
730 {
731     bool accept = false;
732     if (d->dragTarget)
733         accept = dispatchDragEvent(dropEvent, d->dragTarget.get(), event, clipboard);
734     d->dragTarget = 0;
735     return accept;
736 }
737
738 Node* FrameView::nodeUnderMouse() const
739 {
740     return d->underMouse.get();
741 }
742
743 bool FrameView::scrollTo(const IntRect& bounds)
744 {
745     d->scrollingSelf = true; // so scroll events get ignored
746
747     int x, y, xe, ye;
748     x = bounds.x();
749     y = bounds.y();
750     xe = bounds.right() - 1;
751     ye = bounds.bottom() - 1;
752     
753     int deltax;
754     int deltay;
755
756     int curHeight = visibleHeight();
757     int curWidth = visibleWidth();
758
759     if (ye - y>curHeight-d->borderY)
760         ye = y + curHeight - d->borderY;
761
762     if (xe - x>curWidth-d->borderX)
763         xe = x + curWidth - d->borderX;
764
765     // is xpos of target left of the view's border?
766     if (x < contentsX() + d->borderX)
767         deltax = x - contentsX() - d->borderX;
768     // is xpos of target right of the view's right border?
769     else if (xe + d->borderX > contentsX() + curWidth)
770         deltax = xe + d->borderX - (contentsX() + curWidth);
771     else
772         deltax = 0;
773
774     // is ypos of target above upper border?
775     if (y < contentsY() + d->borderY)
776         deltay = y - contentsY() - d->borderY;
777     // is ypos of target below lower border?
778     else if (ye + d->borderY > contentsY() + curHeight)
779         deltay = ye + d->borderY - (contentsY() + curHeight);
780     else
781         deltay = 0;
782
783     int maxx = curWidth - d->borderX;
784     int maxy = curHeight - d->borderY;
785
786     int scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax > -maxx ? deltax : -maxx);
787     int scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay > -maxy ? deltay : -maxy);
788
789     if (contentsX() + scrollX < 0)
790         scrollX = -contentsX();
791     else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
792         scrollX = contentsWidth() - visibleWidth() - contentsX();
793
794     if (contentsY() + scrollY < 0)
795         scrollY = -contentsY();
796     else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
797         scrollY = contentsHeight() - visibleHeight() - contentsY();
798
799     scrollBy(scrollX, scrollY);
800
801     // generate abs(scroll.)
802     if (scrollX < 0)
803         scrollX = -scrollX;
804     if (scrollY < 0)
805         scrollY = -scrollY;
806
807     d->scrollingSelf = false;
808
809     return scrollX != maxx && scrollY != maxy;
810 }
811
812 void FrameView::focusNextPrevNode(bool next)
813 {
814     // Sets the focus node of the document to be the node after (or if next is false, before) the current focus node.
815     // Only nodes that are selectable (i.e. for which isSelectable() returns true) are taken into account, and the order
816     // used is that specified in the HTML spec (see Document::nextFocusNode() and Document::previousFocusNode()
817     // for details).
818
819     Document *doc = m_frame->document();
820     Node *oldFocusNode = doc->focusNode();
821     Node *newFocusNode;
822
823     // Find the next/previous node from the current one
824     if (next)
825         newFocusNode = doc->nextFocusNode(oldFocusNode);
826     else
827         newFocusNode = doc->previousFocusNode(oldFocusNode);
828
829     // If there was previously no focus node and the user has scrolled the document, then instead of picking the first
830     // focusable node in the document, use the first one that lies within the visible area (if possible).
831     if (!oldFocusNode && newFocusNode && d->scrollBarMoved) {
832         bool visible = false;
833         Node *toFocus = newFocusNode;
834         while (!visible && toFocus) {
835             if (toFocus->getRect().intersects(IntRect(contentsX(), contentsY(), visibleWidth(), visibleHeight()))) {
836                 // toFocus is visible in the contents area
837                 visible = true;
838             } else {
839                 // toFocus is _not_ visible in the contents area, pick the next node
840                 if (next)
841                     toFocus = doc->nextFocusNode(toFocus);
842                 else
843                     toFocus = doc->previousFocusNode(toFocus);
844             }
845         }
846
847         if (toFocus)
848             newFocusNode = toFocus;
849     }
850
851     d->scrollBarMoved = false;
852
853     if (!newFocusNode)
854       {
855         // No new focus node, scroll to bottom or top depending on next
856         if (next)
857             scrollTo(IntRect(contentsX()+visibleWidth()/2,contentsHeight(),0,0));
858         else
859             scrollTo(IntRect(contentsX()+visibleWidth()/2,0,0,0));
860     }
861     else {
862         // EDIT FIXME: if it's an editable element, activate the caret
863         // otherwise, hide it
864         if (newFocusNode->isContentEditable()) {
865             // make caret visible
866         } 
867         else {
868             // hide caret
869         }
870
871         // Scroll the view as necessary to ensure that the new focus node is visible
872         if (oldFocusNode) {
873             if (!scrollTo(newFocusNode->getRect()))
874                 return;
875         }
876         else {
877             if (doc->renderer()) {
878                 doc->renderer()->enclosingLayer()->scrollRectToVisible(IntRect(contentsX(), next ? 0: contentsHeight(), 0, 0));
879             }
880         }
881     }
882     // Set focus node on the document
883     m_frame->document()->setFocusNode(newFocusNode);
884 }
885
886 void FrameView::setMediaType(const String& mediaType)
887 {
888     d->m_mediaType = mediaType;
889 }
890
891 String FrameView::mediaType() const
892 {
893     // See if we have an override type.
894     String overrideType = m_frame->overrideMediaType();
895     if (!overrideType.isNull())
896         return overrideType;
897     return d->m_mediaType;
898 }
899
900 void FrameView::useSlowRepaints()
901 {
902     d->useSlowRepaints = true;
903     setStaticBackground(true);
904 }
905
906 void FrameView::setScrollBarsMode(ScrollBarMode mode)
907 {
908     d->vmode = mode;
909     d->hmode = mode;
910     
911     ScrollView::setScrollBarsMode(mode);
912 }
913
914 void FrameView::setVScrollBarMode(ScrollBarMode mode)
915 {
916     d->vmode = mode;
917     ScrollView::setVScrollBarMode(mode);
918 }
919
920 void FrameView::setHScrollBarMode(ScrollBarMode mode)
921 {
922     d->hmode = mode;
923     ScrollView::setHScrollBarMode(mode);
924 }
925
926 void FrameView::restoreScrollBar()
927 {
928     suppressScrollBars(false);
929 }
930
931 void FrameView::setResizingFrameSet(HTMLFrameSetElement* frameSet)
932 {
933     d->resizingFrameSet = frameSet;
934 }
935
936 MouseEventWithHitTestResults FrameView::prepareMouseEvent(bool readonly, bool active, bool mouseMove, const PlatformMouseEvent& mev)
937 {
938     ASSERT(m_frame);
939     ASSERT(m_frame->document());
940     
941     IntPoint vPoint = viewportToContents(mev.pos());
942     return m_frame->document()->prepareMouseEvent(readonly, active, mouseMove, vPoint, mev);
943 }
944
945 bool FrameView::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool cancelable,
946     int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder)
947 {
948     // if the target node is a text node, dispatch on the parent node - rdar://4196646
949     if (targetNode && targetNode->isTextNode())
950         targetNode = targetNode->parentNode();
951     if (targetNode)
952         targetNode = targetNode->shadowAncestorNode();
953     d->underMouse = targetNode;
954
955     // mouseout/mouseover
956     if (setUnder) {
957         if (d->oldUnder && d->oldUnder->document() != frame()->document())
958             d->oldUnder = 0;
959
960         if (d->oldUnder != targetNode) {
961             // send mouseout event to the old node
962             if (d->oldUnder)
963                 EventTargetNodeCast(d->oldUnder.get())->dispatchMouseEvent(mouseEvent, mouseoutEvent, 0, targetNode);
964             // send mouseover event to the new node
965             if (targetNode)
966                 EventTargetNodeCast(targetNode)->dispatchMouseEvent(mouseEvent, mouseoverEvent, 0, d->oldUnder.get());
967         }
968         d->oldUnder = targetNode;
969     }
970
971     bool swallowEvent = false;
972
973     if (targetNode)
974         swallowEvent = EventTargetNodeCast(targetNode)->dispatchMouseEvent(mouseEvent, eventType, clickCount);
975     
976     if (!swallowEvent && eventType == mousedownEvent) {
977         // Blur current focus node when a link/button is clicked; this
978         // is expected by some sites that rely on onChange handlers running
979         // from form fields before the button click is processed.
980         Node* node = targetNode;
981         RenderObject* renderer = node ? node->renderer() : 0;
982                 
983         // Walk up the render tree to search for a node to focus.
984         // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
985         while (renderer) {
986             node = renderer->element();
987             if (node && node->isFocusable())
988                 break;
989             renderer = renderer->parent();
990         }
991         // If focus shift is blocked, we eat the event.  Note we should never clear swallowEvent
992         // if the page already set it (e.g., by canceling default behavior).
993         if (node && node->isMouseFocusable()) {
994             if (!m_frame->document()->setFocusNode(node))
995                 swallowEvent = true;
996         } else if (!node || !node->focused()) {
997             if (!m_frame->document()->setFocusNode(0))
998                 swallowEvent = true;
999         }
1000     }
1001
1002     return swallowEvent;
1003 }
1004
1005 void FrameView::setIgnoreWheelEvents(bool e)
1006 {
1007     d->ignoreWheelEvents = e;
1008 }
1009
1010 void FrameView::handleWheelEvent(PlatformWheelEvent& e)
1011 {
1012     Document *doc = m_frame->document();
1013     if (doc) {
1014         RenderObject *docRenderer = doc->renderer();
1015         if (docRenderer) {
1016             IntPoint vPoint = viewportToContents(e.pos());
1017
1018             RenderObject::NodeInfo hitTestResult(true, false);
1019             doc->renderer()->layer()->hitTest(hitTestResult, vPoint); 
1020             Node *node = hitTestResult.innerNode();
1021
1022            if (m_frame->passWheelEventToChildWidget(node)) {
1023                 e.accept();
1024                 return;
1025             }
1026             if (node) {
1027                 node = node->shadowAncestorNode();
1028                 EventTargetNodeCast(node)->dispatchWheelEvent(e);
1029                 if (e.isAccepted())
1030                     return;
1031             }
1032         }
1033     }
1034 }
1035
1036 void FrameView::scrollBarMoved()
1037 {
1038     // FIXME: Need to arrange for this to be called when the view is scrolled!
1039     if (!d->scrollingSelf)
1040         d->scrollBarMoved = true;
1041 }
1042
1043 void FrameView::repaintRectangle(const IntRect& r, bool immediate)
1044 {
1045     updateContents(r, immediate);
1046 }
1047
1048 void FrameView::layoutTimerFired(Timer<FrameView>*)
1049 {
1050 #if INSTRUMENT_LAYOUT_SCHEDULING
1051     if (m_frame->document() && !m_frame->document()->ownerElement())
1052         printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
1053 #endif
1054     layout();
1055 }
1056
1057 void FrameView::hoverTimerFired(Timer<FrameView>*)
1058 {
1059     d->hoverTimer.stop();
1060     prepareMouseEvent(false, false, true, PlatformMouseEvent());
1061 }
1062
1063 void FrameView::scheduleRelayout()
1064 {
1065     if (!d->layoutSchedulingEnabled)
1066         return;
1067
1068     if (!m_frame->document() || !m_frame->document()->shouldScheduleLayout())
1069         return;
1070
1071     int delay = m_frame->document()->minimumLayoutDelay();
1072     if (d->layoutTimer.isActive() && d->delayedLayout && !delay)
1073         unscheduleRelayout();
1074     if (d->layoutTimer.isActive())
1075         return;
1076
1077     d->delayedLayout = delay != 0;
1078
1079 #if INSTRUMENT_LAYOUT_SCHEDULING
1080     if (!m_frame->document()->ownerElement())
1081         printf("Scheduling layout for %d\n", delay);
1082 #endif
1083
1084     d->layoutTimer.startOneShot(delay * 0.001);
1085 }
1086
1087 bool FrameView::layoutPending()
1088 {
1089     return d->layoutTimer.isActive();
1090 }
1091
1092 bool FrameView::haveDelayedLayoutScheduled()
1093 {
1094     return d->layoutTimer.isActive() && d->delayedLayout;
1095 }
1096
1097 void FrameView::unscheduleRelayout()
1098 {
1099     if (!d->layoutTimer.isActive())
1100         return;
1101
1102 #if INSTRUMENT_LAYOUT_SCHEDULING
1103     if (m_frame->document() && !m_frame->document()->ownerElement())
1104         printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
1105 #endif
1106     
1107     d->layoutTimer.stop();
1108     d->delayedLayout = false;
1109 }
1110
1111 bool FrameView::isTransparent() const
1112 {
1113     return d->isTransparent;
1114 }
1115
1116 void FrameView::setTransparent(bool isTransparent)
1117 {
1118     d->isTransparent = isTransparent;
1119 }
1120
1121 void FrameView::scheduleHoverStateUpdate()
1122 {
1123     if (!d->hoverTimer.isActive())
1124         d->hoverTimer.startOneShot(0);
1125 }
1126
1127 void FrameView::setHasBorder(bool b)
1128 {
1129     d->m_hasBorder = b;
1130     updateBorder();
1131 }
1132
1133 bool FrameView::hasBorder() const
1134 {
1135     return d->m_hasBorder;
1136 }
1137
1138 void FrameView::cleared()
1139 {
1140     if (m_frame)
1141         if (RenderPart* renderer = m_frame->ownerRenderer())
1142             renderer->viewCleared();
1143 }
1144
1145 }