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