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