EventHandler.cpp revision 5f17e4c7a30a97ea3f000145b03b0aa9da8b5e66
1/*
2 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "EventHandler.h"
29
30#include "AXObjectCache.h"
31#include "CachedImage.h"
32#include "ChromeClient.h"
33#include "Cursor.h"
34#include "Document.h"
35#include "DragController.h"
36#include "Editor.h"
37#include "EventNames.h"
38#include "FloatPoint.h"
39#include "FloatRect.h"
40#include "FocusController.h"
41#include "Frame.h"
42#include "FrameLoader.h"
43#include "FrameTree.h"
44#include "FrameView.h"
45#include "HTMLFrameElementBase.h"
46#include "HTMLFrameSetElement.h"
47#include "HTMLInputElement.h"
48#include "HTMLNames.h"
49#include "HitTestRequest.h"
50#include "HitTestResult.h"
51#include "Image.h"
52#include "InspectorController.h"
53#include "KeyboardEvent.h"
54#include "MouseEvent.h"
55#include "MouseEventWithHitTestResults.h"
56#include "Page.h"
57#include "PlatformKeyboardEvent.h"
58#include "PlatformWheelEvent.h"
59#include "PluginView.h"
60#include "RenderFrameSet.h"
61#include "RenderTextControlSingleLine.h"
62#include "RenderView.h"
63#include "RenderWidget.h"
64#include "Scrollbar.h"
65#include "SelectionController.h"
66#include "Settings.h"
67#include "TextEvent.h"
68#include "htmlediting.h" // for comparePositions()
69#include <wtf/StdLibExtras.h>
70
71#if ENABLE(SVG)
72#include "SVGDocument.h"
73#include "SVGElementInstance.h"
74#include "SVGNames.h"
75#include "SVGUseElement.h"
76#endif
77
78#if ENABLE(TOUCH_EVENTS)
79#include "PlatformTouchEvent.h"
80#include "TouchEvent.h"
81#endif
82
83#if defined(ANDROID_PLUGINS)
84#include "WebViewCore.h"
85#endif
86
87namespace WebCore {
88
89using namespace HTMLNames;
90
91#if ENABLE(DRAG_SUPPORT)
92// The link drag hysteresis is much larger than the others because there
93// needs to be enough space to cancel the link press without starting a link drag,
94// and because dragging links is rare.
95const int LinkDragHysteresis = 40;
96const int ImageDragHysteresis = 5;
97const int TextDragHysteresis = 3;
98const int GeneralDragHysteresis = 3;
99#endif // ENABLE(DRAG_SUPPORT)
100
101// Match key code of composition keydown event on windows.
102// IE sends VK_PROCESSKEY which has value 229;
103const int CompositionEventKeyCode = 229;
104
105#if ENABLE(SVG)
106using namespace SVGNames;
107#endif
108
109// When the autoscroll or the panScroll is triggered when do the scroll every 0.05s to make it smooth
110const double autoscrollInterval = 0.05;
111
112static Frame* subframeForHitTestResult(const MouseEventWithHitTestResults&);
113
114static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDirection, ScrollDirection negativeDirection, PlatformWheelEvent& e, Node* node, Node** stopNode)
115{
116    if (!delta)
117        return;
118
119    // Find the nearest enclosing box.
120    RenderBox* enclosingBox = node->renderer()->enclosingBox();
121
122    if (e.granularity() == ScrollByPageWheelEvent) {
123        if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPage, 1, stopNode))
124            e.accept();
125        return;
126    }
127
128    float pixelsToScroll = delta > 0 ? delta : -delta;
129    if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, pixelsToScroll, stopNode))
130        e.accept();
131}
132
133#if !PLATFORM(MAC)
134
135inline bool EventHandler::eventLoopHandleMouseUp(const MouseEventWithHitTestResults&)
136{
137    return false;
138}
139
140#if ENABLE(DRAG_SUPPORT)
141inline bool EventHandler::eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&)
142{
143    return false;
144}
145#endif
146
147#endif
148
149EventHandler::EventHandler(Frame* frame)
150    : m_frame(frame)
151    , m_mousePressed(false)
152    , m_capturesDragging(false)
153    , m_mouseDownMayStartSelect(false)
154#if ENABLE(DRAG_SUPPORT)
155    , m_mouseDownMayStartDrag(false)
156#endif
157    , m_mouseDownWasSingleClickInSelection(false)
158    , m_beganSelectingText(false)
159    , m_panScrollInProgress(false)
160    , m_panScrollButtonPressed(false)
161    , m_springLoadedPanScrollInProgress(false)
162    , m_hoverTimer(this, &EventHandler::hoverTimerFired)
163    , m_autoscrollTimer(this, &EventHandler::autoscrollTimerFired)
164    , m_autoscrollRenderer(0)
165    , m_autoscrollInProgress(false)
166    , m_mouseDownMayStartAutoscroll(false)
167    , m_mouseDownWasInSubframe(false)
168#if ENABLE(SVG)
169    , m_svgPan(false)
170#endif
171    , m_resizeLayer(0)
172    , m_capturingMouseEventsNode(0)
173    , m_clickCount(0)
174    , m_mouseDownTimestamp(0)
175    , m_useLatchedWheelEventNode(false)
176    , m_widgetIsLatched(false)
177#if PLATFORM(MAC)
178    , m_mouseDownView(nil)
179    , m_sendingEventToSubview(false)
180    , m_activationEventNumber(0)
181#endif
182{
183}
184
185EventHandler::~EventHandler()
186{
187}
188
189#if ENABLE(DRAG_SUPPORT)
190EventHandler::EventHandlerDragState& EventHandler::dragState()
191{
192    DEFINE_STATIC_LOCAL(EventHandlerDragState, state, ());
193    return state;
194}
195#endif // ENABLE(DRAG_SUPPORT)
196
197void EventHandler::clear()
198{
199    m_hoverTimer.stop();
200    m_resizeLayer = 0;
201    m_nodeUnderMouse = 0;
202    m_lastNodeUnderMouse = 0;
203#if ENABLE(SVG)
204    m_instanceUnderMouse = 0;
205    m_lastInstanceUnderMouse = 0;
206#endif
207    m_lastMouseMoveEventSubframe = 0;
208    m_lastScrollbarUnderMouse = 0;
209    m_clickCount = 0;
210    m_clickNode = 0;
211#if ENABLE(TOUCH_EVENTS)
212    m_touchEventTarget = 0;
213#endif
214    m_frameSetBeingResized = 0;
215#if ENABLE(DRAG_SUPPORT)
216    m_dragTarget = 0;
217    m_shouldOnlyFireDragOverEvent = false;
218#endif
219    m_currentMousePosition = IntPoint();
220    m_mousePressNode = 0;
221    m_mousePressed = false;
222    m_capturesDragging = false;
223    m_capturingMouseEventsNode = 0;
224    m_latchedWheelEventNode = 0;
225    m_previousWheelScrolledNode = 0;
226}
227
228void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result)
229{
230    Node* innerNode = result.targetNode();
231    VisibleSelection newSelection;
232
233    if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
234        VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
235        if (pos.isNotNull()) {
236            newSelection = VisibleSelection(pos);
237            newSelection.expandUsingGranularity(WordGranularity);
238        }
239
240        if (newSelection.isRange()) {
241            m_frame->setSelectionGranularity(WordGranularity);
242            m_beganSelectingText = true;
243            if (result.event().clickCount() == 2 && m_frame->editor()->isSelectTrailingWhitespaceEnabled())
244                newSelection.appendTrailingWhitespace();
245        }
246
247        if (m_frame->shouldChangeSelection(newSelection))
248            m_frame->selection()->setSelection(newSelection);
249    }
250}
251
252void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults& result)
253{
254    if (!result.hitTestResult().isLiveLink())
255        return selectClosestWordFromMouseEvent(result);
256
257    Node* innerNode = result.targetNode();
258
259    if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
260        VisibleSelection newSelection;
261        Element* URLElement = result.hitTestResult().URLElement();
262        VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
263        if (pos.isNotNull() && pos.deepEquivalent().node()->isDescendantOf(URLElement))
264            newSelection = VisibleSelection::selectionFromContentsOfNode(URLElement);
265
266        if (newSelection.isRange()) {
267            m_frame->setSelectionGranularity(WordGranularity);
268            m_beganSelectingText = true;
269        }
270
271        if (m_frame->shouldChangeSelection(newSelection))
272            m_frame->selection()->setSelection(newSelection);
273    }
274}
275
276bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event)
277{
278    if (event.event().button() != LeftButton)
279        return false;
280
281    if (m_frame->selection()->isRange())
282        // A double-click when range is already selected
283        // should not change the selection.  So, do not call
284        // selectClosestWordFromMouseEvent, but do set
285        // m_beganSelectingText to prevent handleMouseReleaseEvent
286        // from setting caret selection.
287        m_beganSelectingText = true;
288    else
289        selectClosestWordFromMouseEvent(event);
290
291    return true;
292}
293
294bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event)
295{
296    if (event.event().button() != LeftButton)
297        return false;
298
299    Node* innerNode = event.targetNode();
300    if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
301        return false;
302
303    VisibleSelection newSelection;
304    VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint()));
305    if (pos.isNotNull()) {
306        newSelection = VisibleSelection(pos);
307        newSelection.expandUsingGranularity(ParagraphGranularity);
308    }
309    if (newSelection.isRange()) {
310        m_frame->setSelectionGranularity(ParagraphGranularity);
311        m_beganSelectingText = true;
312    }
313
314    if (m_frame->shouldChangeSelection(newSelection))
315        m_frame->selection()->setSelection(newSelection);
316
317    return true;
318}
319
320bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
321{
322    Node* innerNode = event.targetNode();
323    if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
324        return false;
325
326    // Extend the selection if the Shift key is down, unless the click is in a link.
327    bool extendSelection = event.event().shiftKey() && !event.isOverLink();
328
329    // Don't restart the selection when the mouse is pressed on an
330    // existing selection so we can allow for text dragging.
331    if (FrameView* view = m_frame->view()) {
332        IntPoint vPoint = view->windowToContents(event.event().pos());
333        if (!extendSelection && m_frame->selection()->contains(vPoint)) {
334            m_mouseDownWasSingleClickInSelection = true;
335            return false;
336        }
337    }
338
339    VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(event.localPoint()));
340    if (visiblePos.isNull())
341        visiblePos = VisiblePosition(innerNode, 0, DOWNSTREAM);
342    Position pos = visiblePos.deepEquivalent();
343
344    VisibleSelection newSelection = m_frame->selection()->selection();
345    if (extendSelection && newSelection.isCaretOrRange()) {
346        m_frame->selection()->setLastChangeWasHorizontalExtension(false);
347
348        // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection
349        // was created right-to-left
350        Position start = newSelection.start();
351        Position end = newSelection.end();
352        if (comparePositions(pos, start) <= 0)
353            newSelection = VisibleSelection(pos, end);
354        else
355            newSelection = VisibleSelection(start, pos);
356
357        if (m_frame->selectionGranularity() != CharacterGranularity)
358            newSelection.expandUsingGranularity(m_frame->selectionGranularity());
359        m_beganSelectingText = true;
360    } else {
361        newSelection = VisibleSelection(visiblePos);
362        m_frame->setSelectionGranularity(CharacterGranularity);
363    }
364
365    if (m_frame->shouldChangeSelection(newSelection))
366        m_frame->selection()->setSelection(newSelection);
367
368    return true;
369}
370
371bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event)
372{
373#if ENABLE(DRAG_SUPPORT)
374    // Reset drag state.
375    dragState().m_dragSrc = 0;
376#endif
377
378    if (ScrollView* scrollView = m_frame->view()) {
379        if (scrollView->isPointInScrollbarCorner(event.event().pos()))
380            return false;
381    }
382
383    bool singleClick = event.event().clickCount() <= 1;
384
385    // If we got the event back, that must mean it wasn't prevented,
386    // so it's allowed to start a drag or selection.
387    m_mouseDownMayStartSelect = canMouseDownStartSelect(event.targetNode());
388
389#if ENABLE(DRAG_SUPPORT)
390    // Careful that the drag starting logic stays in sync with eventMayStartDrag()
391    m_mouseDownMayStartDrag = singleClick;
392#endif
393
394    m_mouseDownWasSingleClickInSelection = false;
395
396    m_mouseDown = event.event();
397
398    if (event.isOverWidget() && passWidgetMouseDownEventToWidget(event))
399        return true;
400
401#if ENABLE(SVG)
402    if (m_frame->document()->isSVGDocument() &&
403       static_cast<SVGDocument*>(m_frame->document())->zoomAndPanEnabled()) {
404        if (event.event().shiftKey() && singleClick) {
405            m_svgPan = true;
406            static_cast<SVGDocument*>(m_frame->document())->startPan(event.event().pos());
407            return true;
408        }
409    }
410#endif
411
412    // We don't do this at the start of mouse down handling,
413    // because we don't want to do it until we know we didn't hit a widget.
414    if (singleClick)
415        focusDocumentView();
416
417    Node* innerNode = event.targetNode();
418
419    m_mousePressNode = innerNode;
420#if ENABLE(DRAG_SUPPORT)
421    m_dragStartPos = event.event().pos();
422#endif
423
424    bool swallowEvent = false;
425    m_frame->selection()->setCaretBlinkingSuspended(true);
426    m_mousePressed = true;
427    m_beganSelectingText = false;
428
429    if (event.event().clickCount() == 2)
430        swallowEvent = handleMousePressEventDoubleClick(event);
431    else if (event.event().clickCount() >= 3)
432        swallowEvent = handleMousePressEventTripleClick(event);
433    else
434        swallowEvent = handleMousePressEventSingleClick(event);
435
436    m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect ||
437        (m_mousePressNode && m_mousePressNode->renderBox() && m_mousePressNode->renderBox()->canBeProgramaticallyScrolled(true));
438
439    return swallowEvent;
440}
441
442#if ENABLE(DRAG_SUPPORT)
443bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event)
444{
445    if (handleDrag(event))
446        return true;
447
448    if (!m_mousePressed)
449        return false;
450
451    Node* targetNode = event.targetNode();
452    if (event.event().button() != LeftButton || !targetNode || !targetNode->renderer())
453        return false;
454
455#if PLATFORM(MAC) // FIXME: Why does this assertion fire on other platforms?
456    ASSERT(m_mouseDownMayStartSelect || m_mouseDownMayStartAutoscroll);
457#endif
458
459    m_mouseDownMayStartDrag = false;
460
461    if (m_mouseDownMayStartAutoscroll && !m_panScrollInProgress) {
462        // If the selection is contained in a layer that can scroll, that layer should handle the autoscroll
463        // Otherwise, let the bridge handle it so the view can scroll itself.
464        RenderObject* renderer = targetNode->renderer();
465        while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeScrolledAndHasScrollableArea())) {
466            if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement())
467                renderer = renderer->document()->ownerElement()->renderer();
468            else
469                renderer = renderer->parent();
470        }
471
472        if (renderer) {
473            m_autoscrollInProgress = true;
474            handleAutoscroll(renderer);
475        }
476
477        m_mouseDownMayStartAutoscroll = false;
478    }
479
480    updateSelectionForMouseDrag(targetNode, event.localPoint());
481    return true;
482}
483
484bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const
485{
486    // This is a pre-flight check of whether the event might lead to a drag being started.  Be careful
487    // that its logic needs to stay in sync with handleMouseMoveEvent() and the way we setMouseDownMayStartDrag
488    // in handleMousePressEvent
489
490    if (!m_frame->contentRenderer() || !m_frame->contentRenderer()->hasLayer())
491        return false;
492
493    if (event.button() != LeftButton || event.clickCount() != 1)
494        return false;
495
496    bool DHTMLFlag;
497    bool UAFlag;
498    allowDHTMLDrag(DHTMLFlag, UAFlag);
499    if (!DHTMLFlag && !UAFlag)
500        return false;
501
502    FrameView* view = m_frame->view();
503    if (!view)
504        return false;
505
506    HitTestRequest request(HitTestRequest::ReadOnly);
507    HitTestResult result(view->windowToContents(event.pos()));
508    m_frame->contentRenderer()->layer()->hitTest(request, result);
509    bool srcIsDHTML;
510    return result.innerNode() && result.innerNode()->renderer()->draggableNode(DHTMLFlag, UAFlag, result.point().x(), result.point().y(), srcIsDHTML);
511}
512
513void EventHandler::updateSelectionForMouseDrag()
514{
515    FrameView* view = m_frame->view();
516    if (!view)
517        return;
518    RenderView* renderer = m_frame->contentRenderer();
519    if (!renderer)
520        return;
521    RenderLayer* layer = renderer->layer();
522    if (!layer)
523        return;
524
525    HitTestRequest request(HitTestRequest::ReadOnly |
526                           HitTestRequest::Active |
527                           HitTestRequest::MouseMove);
528    HitTestResult result(view->windowToContents(m_currentMousePosition));
529    layer->hitTest(request, result);
530    updateSelectionForMouseDrag(result.innerNode(), result.localPoint());
531}
532
533void EventHandler::updateSelectionForMouseDrag(Node* targetNode, const IntPoint& localPoint)
534{
535    if (!m_mouseDownMayStartSelect)
536        return;
537
538    if (!targetNode)
539        return;
540
541    RenderObject* targetRenderer = targetNode->renderer();
542    if (!targetRenderer)
543        return;
544
545    if (!canMouseDragExtendSelect(targetNode))
546        return;
547
548    VisiblePosition targetPosition(targetRenderer->positionForPoint(localPoint));
549
550    // Don't modify the selection if we're not on a node.
551    if (targetPosition.isNull())
552        return;
553
554    // Restart the selection if this is the first mouse move. This work is usually
555    // done in handleMousePressEvent, but not if the mouse press was on an existing selection.
556    VisibleSelection newSelection = m_frame->selection()->selection();
557
558#if ENABLE(SVG)
559    // Special case to limit selection to the containing block for SVG text.
560    // FIXME: Isn't there a better non-SVG-specific way to do this?
561    if (Node* selectionBaseNode = newSelection.base().node())
562        if (RenderObject* selectionBaseRenderer = selectionBaseNode->renderer())
563            if (selectionBaseRenderer->isSVGText())
564                if (targetNode->renderer()->containingBlock() != selectionBaseRenderer->containingBlock())
565                    return;
566#endif
567
568    if (!m_beganSelectingText) {
569        m_beganSelectingText = true;
570        newSelection = VisibleSelection(targetPosition);
571    }
572
573    newSelection.setExtent(targetPosition);
574    if (m_frame->selectionGranularity() != CharacterGranularity)
575        newSelection.expandUsingGranularity(m_frame->selectionGranularity());
576
577    if (m_frame->shouldChangeSelection(newSelection)) {
578        m_frame->selection()->setLastChangeWasHorizontalExtension(false);
579        m_frame->selection()->setSelection(newSelection);
580    }
581}
582#endif // ENABLE(DRAG_SUPPORT)
583
584bool EventHandler::handleMouseUp(const MouseEventWithHitTestResults& event)
585{
586    if (eventLoopHandleMouseUp(event))
587        return true;
588
589    // If this was the first click in the window, we don't even want to clear the selection.
590    // This case occurs when the user clicks on a draggable element, since we have to process
591    // the mouse down and drag events to see if we might start a drag.  For other first clicks
592    // in a window, we just don't acceptFirstMouse, and the whole down-drag-up sequence gets
593    // ignored upstream of this layer.
594    return eventActivatedView(event.event());
595}
596
597bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
598{
599    if (m_autoscrollInProgress)
600        stopAutoscrollTimer();
601
602    if (handleMouseUp(event))
603        return true;
604
605    // Used to prevent mouseMoveEvent from initiating a drag before
606    // the mouse is pressed again.
607    m_frame->selection()->setCaretBlinkingSuspended(false);
608    m_mousePressed = false;
609    m_capturesDragging = false;
610#if ENABLE(DRAG_SUPPORT)
611    m_mouseDownMayStartDrag = false;
612#endif
613    m_mouseDownMayStartSelect = false;
614    m_mouseDownMayStartAutoscroll = false;
615    m_mouseDownWasInSubframe = false;
616
617    bool handled = false;
618
619    // Clear the selection if the mouse didn't move after the last mouse
620    // press and it's not a context menu click.  We do this so when clicking
621    // on the selection, the selection goes away.  However, if we are
622    // editing, place the caret.
623    if (m_mouseDownWasSingleClickInSelection && !m_beganSelectingText
624#if ENABLE(DRAG_SUPPORT)
625            && m_dragStartPos == event.event().pos()
626#endif
627            && m_frame->selection()->isRange()
628            && event.event().button() != RightButton) {
629        VisibleSelection newSelection;
630        Node *node = event.targetNode();
631        bool caretBrowsing = m_frame->settings()->caretBrowsingEnabled();
632        if (node && (caretBrowsing || node->isContentEditable()) && node->renderer()) {
633            VisiblePosition pos = node->renderer()->positionForPoint(event.localPoint());
634            newSelection = VisibleSelection(pos);
635        }
636        if (m_frame->shouldChangeSelection(newSelection))
637            m_frame->selection()->setSelection(newSelection);
638
639        handled = true;
640    }
641
642    m_frame->notifyRendererOfSelectionChange(true);
643
644    m_frame->selection()->selectFrameElementInParentIfFullySelected();
645
646    return handled;
647}
648
649void EventHandler::handleAutoscroll(RenderObject* renderer)
650{
651    // We don't want to trigger the autoscroll or the panScroll if it's already active
652    if (m_autoscrollTimer.isActive())
653        return;
654
655    setAutoscrollRenderer(renderer);
656
657#if ENABLE(PAN_SCROLLING)
658    if (m_panScrollInProgress) {
659        m_panScrollStartPos = currentMousePosition();
660        if (FrameView* view = m_frame->view())
661            view->addPanScrollIcon(m_panScrollStartPos);
662        // If we're not in the top frame we notify it that we doing a panScroll.
663        if (Page* page = m_frame->page()) {
664            Frame* mainFrame = page->mainFrame();
665            if (m_frame != mainFrame)
666                mainFrame->eventHandler()->setPanScrollInProgress(true);
667        }
668    }
669#endif
670
671    startAutoscrollTimer();
672}
673
674void EventHandler::autoscrollTimerFired(Timer<EventHandler>*)
675{
676    RenderObject* r = autoscrollRenderer();
677    if (!r || !r->isBox()) {
678        stopAutoscrollTimer();
679        return;
680    }
681
682    if (m_autoscrollInProgress) {
683        if (!m_mousePressed) {
684            stopAutoscrollTimer();
685            return;
686        }
687        toRenderBox(r)->autoscroll();
688    } else {
689        // we verify that the main frame hasn't received the order to stop the panScroll
690        if (Page* page = m_frame->page()) {
691            if (!page->mainFrame()->eventHandler()->panScrollInProgress()) {
692                stopAutoscrollTimer();
693                return;
694            }
695        }
696#if ENABLE(PAN_SCROLLING)
697        updatePanScrollState();
698        toRenderBox(r)->panScroll(m_panScrollStartPos);
699#endif
700    }
701}
702
703#if ENABLE(PAN_SCROLLING)
704
705void EventHandler::updatePanScrollState()
706{
707    FrameView* view = m_frame->view();
708    if (!view)
709        return;
710
711    // At the original click location we draw a 4 arrowed icon. Over this icon there won't be any scroll
712    // So we don't want to change the cursor over this area
713    bool east = m_panScrollStartPos.x() < (m_currentMousePosition.x() - ScrollView::noPanScrollRadius);
714    bool west = m_panScrollStartPos.x() > (m_currentMousePosition.x() + ScrollView::noPanScrollRadius);
715    bool north = m_panScrollStartPos.y() > (m_currentMousePosition.y() + ScrollView::noPanScrollRadius);
716    bool south = m_panScrollStartPos.y() < (m_currentMousePosition.y() - ScrollView::noPanScrollRadius);
717
718    if ((east || west || north || south) && m_panScrollButtonPressed)
719        m_springLoadedPanScrollInProgress = true;
720
721    if (north) {
722        if (east)
723            view->setCursor(northEastPanningCursor());
724        else if (west)
725            view->setCursor(northWestPanningCursor());
726        else
727            view->setCursor(northPanningCursor());
728    } else if (south) {
729        if (east)
730            view->setCursor(southEastPanningCursor());
731        else if (west)
732            view->setCursor(southWestPanningCursor());
733        else
734            view->setCursor(southPanningCursor());
735    } else if (east)
736        view->setCursor(eastPanningCursor());
737    else if (west)
738        view->setCursor(westPanningCursor());
739    else
740        view->setCursor(middlePanningCursor());
741}
742
743#endif  // ENABLE(PAN_SCROLLING)
744
745RenderObject* EventHandler::autoscrollRenderer() const
746{
747    return m_autoscrollRenderer;
748}
749
750void EventHandler::updateAutoscrollRenderer()
751{
752    if (!m_autoscrollRenderer)
753        return;
754
755    HitTestResult hitTest = hitTestResultAtPoint(m_panScrollStartPos, true);
756
757    if (Node* nodeAtPoint = hitTest.innerNode())
758        m_autoscrollRenderer = nodeAtPoint->renderer();
759
760    while (m_autoscrollRenderer && (!m_autoscrollRenderer->isBox() || !toRenderBox(m_autoscrollRenderer)->canBeScrolledAndHasScrollableArea()))
761        m_autoscrollRenderer = m_autoscrollRenderer->parent();
762}
763
764void EventHandler::setAutoscrollRenderer(RenderObject* renderer)
765{
766    m_autoscrollRenderer = renderer;
767}
768
769#if ENABLE(DRAG_SUPPORT)
770void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const
771{
772    flagDHTML = false;
773    flagUA = false;
774
775    if (!m_frame)
776        return;
777
778    Page* page = m_frame->page();
779    if (!page)
780        return;
781
782    FrameView* view = m_frame->view();
783    if (!view)
784        return;
785
786    unsigned mask = page->dragController()->delegateDragSourceAction(view->contentsToWindow(m_mouseDownPos));
787    flagDHTML = (mask & DragSourceActionDHTML) != DragSourceActionNone;
788    flagUA = ((mask & DragSourceActionImage) || (mask & DragSourceActionLink) || (mask & DragSourceActionSelection));
789}
790#endif // ENABLE(DRAG_SUPPORT)
791
792HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent, bool ignoreClipping, HitTestScrollbars testScrollbars)
793{
794    HitTestResult result(point);
795    if (!m_frame->contentRenderer())
796        return result;
797    int hitType = HitTestRequest::ReadOnly | HitTestRequest::Active;
798    if (ignoreClipping)
799        hitType |= HitTestRequest::IgnoreClipping;
800    m_frame->contentRenderer()->layer()->hitTest(HitTestRequest(hitType), result);
801
802    while (true) {
803        Node* n = result.innerNode();
804        if (!result.isOverWidget() || !n || !n->renderer() || !n->renderer()->isWidget())
805            break;
806        RenderWidget* renderWidget = toRenderWidget(n->renderer());
807        Widget* widget = renderWidget->widget();
808        if (!widget || !widget->isFrameView())
809            break;
810        Frame* frame = static_cast<HTMLFrameElementBase*>(n)->contentFrame();
811        if (!frame || !frame->contentRenderer())
812            break;
813        FrameView* view = static_cast<FrameView*>(widget);
814        IntPoint widgetPoint(result.localPoint().x() + view->scrollX() - renderWidget->borderLeft() - renderWidget->paddingLeft(),
815            result.localPoint().y() + view->scrollY() - renderWidget->borderTop() - renderWidget->paddingTop());
816        HitTestResult widgetHitTestResult(widgetPoint);
817        frame->contentRenderer()->layer()->hitTest(HitTestRequest(hitType), widgetHitTestResult);
818        result = widgetHitTestResult;
819
820        if (testScrollbars == ShouldHitTestScrollbars) {
821            Scrollbar* eventScrollbar = view->scrollbarAtPoint(point);
822            if (eventScrollbar)
823                result.setScrollbar(eventScrollbar);
824        }
825    }
826
827    // If our HitTestResult is not visible, then we started hit testing too far down the frame chain.
828    // Another hit test at the main frame level should get us the correct visible result.
829    Frame* resultFrame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : 0;
830    if (Page* page = m_frame->page()) {
831        Frame* mainFrame = page->mainFrame();
832        if (m_frame != mainFrame && resultFrame && resultFrame != mainFrame && !resultFrame->editor()->insideVisibleArea(result.point())) {
833            FrameView* resultView = resultFrame->view();
834            FrameView* mainView = mainFrame->view();
835            if (resultView && mainView) {
836                IntPoint windowPoint = resultView->contentsToWindow(result.point());
837                IntPoint mainFramePoint = mainView->windowToContents(windowPoint);
838                result = mainFrame->eventHandler()->hitTestResultAtPoint(mainFramePoint, allowShadowContent, ignoreClipping);
839            }
840        }
841    }
842
843    if (!allowShadowContent)
844        result.setToNonShadowAncestor();
845
846    return result;
847}
848
849
850void EventHandler::startAutoscrollTimer()
851{
852    m_autoscrollTimer.startRepeating(autoscrollInterval);
853}
854
855void EventHandler::stopAutoscrollTimer(bool rendererIsBeingDestroyed)
856{
857    if (m_autoscrollInProgress) {
858        if (m_mouseDownWasInSubframe) {
859            if (Frame* subframe = subframeForTargetNode(m_mousePressNode.get()))
860                subframe->eventHandler()->stopAutoscrollTimer(rendererIsBeingDestroyed);
861            return;
862        }
863    }
864
865    if (autoscrollRenderer()) {
866        if (!rendererIsBeingDestroyed && (m_autoscrollInProgress || m_panScrollInProgress))
867            toRenderBox(autoscrollRenderer())->stopAutoscroll();
868#if ENABLE(PAN_SCROLLING)
869        if (m_panScrollInProgress) {
870            if (FrameView* view = m_frame->view()) {
871                view->removePanScrollIcon();
872                view->setCursor(pointerCursor());
873            }
874        }
875#endif
876
877        setAutoscrollRenderer(0);
878    }
879
880    m_autoscrollTimer.stop();
881
882    m_panScrollInProgress = false;
883    m_springLoadedPanScrollInProgress = false;
884
885    // If we're not in the top frame we notify it that we are not doing a panScroll any more.
886    if (Page* page = m_frame->page()) {
887        Frame* mainFrame = page->mainFrame();
888        if (m_frame != mainFrame)
889            mainFrame->eventHandler()->setPanScrollInProgress(false);
890    }
891
892    m_autoscrollInProgress = false;
893}
894
895Node* EventHandler::mousePressNode() const
896{
897    return m_mousePressNode.get();
898}
899
900void EventHandler::setMousePressNode(PassRefPtr<Node> node)
901{
902    m_mousePressNode = node;
903}
904
905bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity)
906{
907    Node* node = m_frame->document()->focusedNode();
908    if (!node)
909        node = m_mousePressNode.get();
910
911    if (node) {
912        RenderObject* r = node->renderer();
913        if (r && !r->isListBox() && r->enclosingBox()->scroll(direction, granularity)) {
914            setFrameWasScrolledByUser();
915            return true;
916        }
917    }
918
919    return false;
920}
921
922bool EventHandler::scrollRecursively(ScrollDirection direction, ScrollGranularity granularity)
923{
924    bool handled = scrollOverflow(direction, granularity);
925    if (!handled) {
926        Frame* frame = m_frame;
927        do {
928            FrameView* view = frame->view();
929            handled = view ? view->scroll(direction, granularity) : false;
930            frame = frame->tree()->parent();
931        } while (!handled && frame);
932     }
933
934    return handled;
935}
936
937IntPoint EventHandler::currentMousePosition() const
938{
939    return m_currentMousePosition;
940}
941
942Frame* subframeForHitTestResult(const MouseEventWithHitTestResults& hitTestResult)
943{
944    if (!hitTestResult.isOverWidget())
945        return 0;
946    return EventHandler::subframeForTargetNode(hitTestResult.targetNode());
947}
948
949Frame* EventHandler::subframeForTargetNode(Node* node)
950{
951    if (!node)
952        return 0;
953
954    RenderObject* renderer = node->renderer();
955    if (!renderer || !renderer->isWidget())
956        return 0;
957
958    Widget* widget = toRenderWidget(renderer)->widget();
959    if (!widget || !widget->isFrameView())
960        return 0;
961
962    return static_cast<FrameView*>(widget)->frame();
963}
964
965static bool isSubmitImage(Node* node)
966{
967    return node && node->hasTagName(inputTag)
968        && static_cast<HTMLInputElement*>(node)->inputType() == HTMLInputElement::IMAGE;
969}
970
971// Returns true if the node's editable block is not current focused for editing
972static bool nodeIsNotBeingEdited(Node* node, Frame* frame)
973{
974    return frame->selection()->rootEditableElement() != node->rootEditableElement();
975}
976
977Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Scrollbar* scrollbar)
978{
979    // During selection, use an I-beam no matter what we're over.
980    // If you're capturing mouse events for a particular node, don't treat this as a selection.
981    if (m_mousePressed && m_mouseDownMayStartSelect && m_frame->selection()->isCaretOrRange() && !m_capturingMouseEventsNode)
982        return iBeamCursor();
983
984    Node* node = event.targetNode();
985    RenderObject* renderer = node ? node->renderer() : 0;
986    RenderStyle* style = renderer ? renderer->style() : 0;
987
988    if (renderer && renderer->isFrameSet()) {
989        RenderFrameSet* frameSetRenderer = toRenderFrameSet(renderer);
990        if (frameSetRenderer->canResizeRow(event.localPoint()))
991            return rowResizeCursor();
992        if (frameSetRenderer->canResizeColumn(event.localPoint()))
993            return columnResizeCursor();
994    }
995
996    if (style && style->cursors()) {
997        const CursorList* cursors = style->cursors();
998        for (unsigned i = 0; i < cursors->size(); ++i) {
999            CachedImage* cimage = (*cursors)[i].cursorImage.get();
1000            IntPoint hotSpot = (*cursors)[i].hotSpot;
1001            if (!cimage)
1002                continue;
1003            // Limit the size of cursors so that they cannot be used to cover UI elements in chrome.
1004            IntSize size = cimage->image()->size();
1005            if (size.width() > 128 || size.height() > 128)
1006                continue;
1007            // Do not let the hotspot be outside the bounds of the image.
1008            if (hotSpot.x() < 0 || hotSpot.y() < 0 || hotSpot.x() > size.width() || hotSpot.y() > size.height())
1009                continue;
1010            if (cimage->image()->isNull())
1011                break;
1012            if (!cimage->errorOccurred())
1013                return Cursor(cimage->image(), hotSpot);
1014        }
1015    }
1016
1017    switch (style ? style->cursor() : CURSOR_AUTO) {
1018        case CURSOR_AUTO: {
1019            bool editable = (node && node->isContentEditable());
1020            bool editableLinkEnabled = false;
1021
1022            // If the link is editable, then we need to check the settings to see whether or not the link should be followed
1023            if (editable) {
1024                ASSERT(m_frame->settings());
1025                switch (m_frame->settings()->editableLinkBehavior()) {
1026                    default:
1027                    case EditableLinkDefaultBehavior:
1028                    case EditableLinkAlwaysLive:
1029                        editableLinkEnabled = true;
1030                        break;
1031
1032                    case EditableLinkNeverLive:
1033                        editableLinkEnabled = false;
1034                        break;
1035
1036                    case EditableLinkLiveWhenNotFocused:
1037                        editableLinkEnabled = nodeIsNotBeingEdited(node, m_frame) || event.event().shiftKey();
1038                        break;
1039
1040                    case EditableLinkOnlyLiveWithShiftKey:
1041                        editableLinkEnabled = event.event().shiftKey();
1042                        break;
1043                }
1044            }
1045
1046            if ((event.isOverLink() || isSubmitImage(node)) && (!editable || editableLinkEnabled))
1047                return handCursor();
1048            bool inResizer = false;
1049            if (renderer) {
1050                if (RenderLayer* layer = renderer->enclosingLayer()) {
1051                    if (FrameView* view = m_frame->view())
1052                        inResizer = layer->isPointInResizeControl(view->windowToContents(event.event().pos()));
1053                }
1054            }
1055            if ((editable || (renderer && renderer->isText() && node->canStartSelection())) && !inResizer && !scrollbar)
1056                return iBeamCursor();
1057            return pointerCursor();
1058        }
1059        case CURSOR_CROSS:
1060            return crossCursor();
1061        case CURSOR_POINTER:
1062            return handCursor();
1063        case CURSOR_MOVE:
1064            return moveCursor();
1065        case CURSOR_ALL_SCROLL:
1066            return moveCursor();
1067        case CURSOR_E_RESIZE:
1068            return eastResizeCursor();
1069        case CURSOR_W_RESIZE:
1070            return westResizeCursor();
1071        case CURSOR_N_RESIZE:
1072            return northResizeCursor();
1073        case CURSOR_S_RESIZE:
1074            return southResizeCursor();
1075        case CURSOR_NE_RESIZE:
1076            return northEastResizeCursor();
1077        case CURSOR_SW_RESIZE:
1078            return southWestResizeCursor();
1079        case CURSOR_NW_RESIZE:
1080            return northWestResizeCursor();
1081        case CURSOR_SE_RESIZE:
1082            return southEastResizeCursor();
1083        case CURSOR_NS_RESIZE:
1084            return northSouthResizeCursor();
1085        case CURSOR_EW_RESIZE:
1086            return eastWestResizeCursor();
1087        case CURSOR_NESW_RESIZE:
1088            return northEastSouthWestResizeCursor();
1089        case CURSOR_NWSE_RESIZE:
1090            return northWestSouthEastResizeCursor();
1091        case CURSOR_COL_RESIZE:
1092            return columnResizeCursor();
1093        case CURSOR_ROW_RESIZE:
1094            return rowResizeCursor();
1095        case CURSOR_TEXT:
1096            return iBeamCursor();
1097        case CURSOR_WAIT:
1098            return waitCursor();
1099        case CURSOR_HELP:
1100            return helpCursor();
1101        case CURSOR_VERTICAL_TEXT:
1102            return verticalTextCursor();
1103        case CURSOR_CELL:
1104            return cellCursor();
1105        case CURSOR_CONTEXT_MENU:
1106            return contextMenuCursor();
1107        case CURSOR_PROGRESS:
1108            return progressCursor();
1109        case CURSOR_NO_DROP:
1110            return noDropCursor();
1111        case CURSOR_ALIAS:
1112            return aliasCursor();
1113        case CURSOR_COPY:
1114            return copyCursor();
1115        case CURSOR_NONE:
1116            return noneCursor();
1117        case CURSOR_NOT_ALLOWED:
1118            return notAllowedCursor();
1119        case CURSOR_DEFAULT:
1120            return pointerCursor();
1121        case CURSOR_WEBKIT_ZOOM_IN:
1122            return zoomInCursor();
1123        case CURSOR_WEBKIT_ZOOM_OUT:
1124            return zoomOutCursor();
1125        case CURSOR_WEBKIT_GRAB:
1126            return grabCursor();
1127        case CURSOR_WEBKIT_GRABBING:
1128            return grabbingCursor();
1129    }
1130    return pointerCursor();
1131}
1132
1133static IntPoint documentPointForWindowPoint(Frame* frame, const IntPoint& windowPoint)
1134{
1135    FrameView* view = frame->view();
1136    // FIXME: Is it really OK to use the wrong coordinates here when view is 0?
1137    // Historically the code would just crash; this is clearly no worse than that.
1138    return view ? view->windowToContents(windowPoint) : windowPoint;
1139}
1140
1141bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
1142{
1143    RefPtr<FrameView> protector(m_frame->view());
1144
1145    m_mousePressed = true;
1146    m_capturesDragging = true;
1147    m_currentMousePosition = mouseEvent.pos();
1148    m_mouseDownTimestamp = mouseEvent.timestamp();
1149#if ENABLE(DRAG_SUPPORT)
1150    m_mouseDownMayStartDrag = false;
1151#endif
1152    m_mouseDownMayStartSelect = false;
1153    m_mouseDownMayStartAutoscroll = false;
1154    if (FrameView* view = m_frame->view())
1155        m_mouseDownPos = view->windowToContents(mouseEvent.pos());
1156    else {
1157        invalidateClick();
1158        return false;
1159    }
1160    m_mouseDownWasInSubframe = false;
1161
1162    HitTestRequest request(HitTestRequest::Active);
1163    // Save the document point we generate in case the window coordinate is invalidated by what happens
1164    // when we dispatch the event.
1165    IntPoint documentPoint = documentPointForWindowPoint(m_frame, mouseEvent.pos());
1166    MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent);
1167
1168    if (!mev.targetNode()) {
1169        invalidateClick();
1170        return false;
1171    }
1172
1173    m_mousePressNode = mev.targetNode();
1174
1175#if ENABLE(INSPECTOR)
1176    if (Page* page = m_frame->page()) {
1177        InspectorController* inspector = page->inspectorController();
1178        if (inspector && inspector->enabled() && inspector->searchingForNodeInPage()) {
1179            inspector->handleMousePressOnNode(m_mousePressNode.get());
1180            invalidateClick();
1181            return true;
1182        }
1183    }
1184#endif
1185
1186    Frame* subframe = subframeForHitTestResult(mev);
1187    if (subframe && passMousePressEventToSubframe(mev, subframe)) {
1188        // Start capturing future events for this frame.  We only do this if we didn't clear
1189        // the m_mousePressed flag, which may happen if an AppKit widget entered a modal event loop.
1190        m_capturesDragging = subframe->eventHandler()->capturesDragging();
1191        if (m_mousePressed && m_capturesDragging)
1192            m_capturingMouseEventsNode = mev.targetNode();
1193        invalidateClick();
1194        return true;
1195    }
1196
1197#if ENABLE(PAN_SCROLLING)
1198    Page* page = m_frame->page();
1199    if (page && page->mainFrame()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress) {
1200        stopAutoscrollTimer();
1201        invalidateClick();
1202        return true;
1203    }
1204
1205    if (mouseEvent.button() == MiddleButton && !mev.isOverLink()) {
1206        RenderObject* renderer = mev.targetNode()->renderer();
1207
1208        while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeScrolledAndHasScrollableArea())) {
1209            if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement())
1210                renderer = renderer->document()->ownerElement()->renderer();
1211            else
1212                renderer = renderer->parent();
1213        }
1214
1215        if (renderer) {
1216            m_panScrollInProgress = true;
1217            m_panScrollButtonPressed = true;
1218            handleAutoscroll(renderer);
1219            invalidateClick();
1220            return true;
1221        }
1222    }
1223#endif
1224
1225    m_clickCount = mouseEvent.clickCount();
1226    m_clickNode = mev.targetNode();
1227
1228    if (FrameView* view = m_frame->view()) {
1229        RenderLayer* layer = m_clickNode->renderer() ? m_clickNode->renderer()->enclosingLayer() : 0;
1230        IntPoint p = view->windowToContents(mouseEvent.pos());
1231        if (layer && layer->isPointInResizeControl(p)) {
1232            layer->setInResizeMode(true);
1233            m_resizeLayer = layer;
1234            m_offsetFromResizeCorner = layer->offsetFromResizeCorner(p);
1235            invalidateClick();
1236            return true;
1237        }
1238    }
1239
1240    bool swallowEvent = dispatchMouseEvent(eventNames().mousedownEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
1241    m_capturesDragging = !swallowEvent;
1242
1243    // If the hit testing originally determined the event was in a scrollbar, refetch the MouseEventWithHitTestResults
1244    // in case the scrollbar widget was destroyed when the mouse event was handled.
1245    if (mev.scrollbar()) {
1246        const bool wasLastScrollBar = mev.scrollbar() == m_lastScrollbarUnderMouse.get();
1247        HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
1248        mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent);
1249        if (wasLastScrollBar && mev.scrollbar() != m_lastScrollbarUnderMouse.get())
1250            m_lastScrollbarUnderMouse = 0;
1251    }
1252
1253    if (swallowEvent) {
1254        // scrollbars should get events anyway, even disabled controls might be scrollable
1255        Scrollbar* scrollbar = mev.scrollbar();
1256
1257        updateLastScrollbarUnderMouse(scrollbar, true);
1258
1259        if (scrollbar)
1260            passMousePressEventToScrollbar(mev, scrollbar);
1261    } else {
1262        // Refetch the event target node if it currently is the shadow node inside an <input> element.
1263        // If a mouse event handler changes the input element type to one that has a widget associated,
1264        // we'd like to EventHandler::handleMousePressEvent to pass the event to the widget and thus the
1265        // event target node can't still be the shadow node.
1266        if (mev.targetNode()->isShadowNode() && mev.targetNode()->shadowParentNode()->hasTagName(inputTag)) {
1267            HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
1268            mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent);
1269        }
1270
1271        FrameView* view = m_frame->view();
1272        Scrollbar* scrollbar = view ? view->scrollbarAtPoint(mouseEvent.pos()) : 0;
1273        if (!scrollbar)
1274            scrollbar = mev.scrollbar();
1275
1276        updateLastScrollbarUnderMouse(scrollbar, true);
1277
1278        if (scrollbar && passMousePressEventToScrollbar(mev, scrollbar))
1279            swallowEvent = true;
1280        else
1281            swallowEvent = handleMousePressEvent(mev);
1282    }
1283
1284    return swallowEvent;
1285}
1286
1287// This method only exists for platforms that don't know how to deliver
1288bool EventHandler::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent)
1289{
1290    RefPtr<FrameView> protector(m_frame->view());
1291
1292    // We get this instead of a second mouse-up
1293    m_mousePressed = false;
1294    m_currentMousePosition = mouseEvent.pos();
1295
1296    HitTestRequest request(HitTestRequest::Active);
1297    MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
1298    Frame* subframe = subframeForHitTestResult(mev);
1299    if (subframe && passMousePressEventToSubframe(mev, subframe)) {
1300        m_capturingMouseEventsNode = 0;
1301        return true;
1302    }
1303
1304    m_clickCount = mouseEvent.clickCount();
1305    bool swallowMouseUpEvent = dispatchMouseEvent(eventNames().mouseupEvent, mev.targetNode(), true, m_clickCount, mouseEvent, false);
1306
1307    bool swallowClickEvent = false;
1308    // Don't ever dispatch click events for right clicks
1309    if (mouseEvent.button() != RightButton && mev.targetNode() == m_clickNode)
1310        swallowClickEvent = dispatchMouseEvent(eventNames().clickEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
1311
1312    if (m_lastScrollbarUnderMouse)
1313        swallowMouseUpEvent = m_lastScrollbarUnderMouse->mouseUp();
1314
1315    bool swallowMouseReleaseEvent = false;
1316    if (!swallowMouseUpEvent)
1317        swallowMouseReleaseEvent = handleMouseReleaseEvent(mev);
1318
1319    invalidateClick();
1320
1321    return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
1322}
1323
1324bool EventHandler::mouseMoved(const PlatformMouseEvent& event)
1325{
1326    HitTestResult hoveredNode = HitTestResult(IntPoint());
1327    bool result = handleMouseMoveEvent(event, &hoveredNode);
1328
1329    Page* page = m_frame->page();
1330    if (!page)
1331        return result;
1332
1333    hoveredNode.setToNonShadowAncestor();
1334    page->chrome()->mouseDidMoveOverElement(hoveredNode, event.modifierFlags());
1335    page->chrome()->setToolTip(hoveredNode);
1336    return result;
1337}
1338
1339bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, HitTestResult* hoveredNode)
1340{
1341    // in Radar 3703768 we saw frequent crashes apparently due to the
1342    // part being null here, which seems impossible, so check for nil
1343    // but also assert so that we can try to figure this out in debug
1344    // builds, if it happens.
1345    ASSERT(m_frame);
1346    if (!m_frame)
1347        return false;
1348
1349    RefPtr<FrameView> protector(m_frame->view());
1350    m_currentMousePosition = mouseEvent.pos();
1351
1352    if (m_hoverTimer.isActive())
1353        m_hoverTimer.stop();
1354
1355#if ENABLE(SVG)
1356    if (m_svgPan) {
1357        static_cast<SVGDocument*>(m_frame->document())->updatePan(m_currentMousePosition);
1358        return true;
1359    }
1360#endif
1361
1362    if (m_frameSetBeingResized)
1363        return dispatchMouseEvent(eventNames().mousemoveEvent, m_frameSetBeingResized.get(), false, 0, mouseEvent, false);
1364
1365    // Send events right to a scrollbar if the mouse is pressed.
1366    if (m_lastScrollbarUnderMouse && m_mousePressed)
1367        return m_lastScrollbarUnderMouse->mouseMoved(mouseEvent);
1368
1369    // Treat mouse move events while the mouse is pressed as "read-only" in prepareMouseEvent
1370    // if we are allowed to select.
1371    // This means that :hover and :active freeze in the state they were in when the mouse
1372    // was pressed, rather than updating for nodes the mouse moves over as you hold the mouse down.
1373    int hitType = HitTestRequest::MouseMove;
1374    if (m_mousePressed && m_mouseDownMayStartSelect)
1375        hitType |= HitTestRequest::ReadOnly;
1376    if (m_mousePressed)
1377        hitType |= HitTestRequest::Active;
1378    HitTestRequest request(hitType);
1379    MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
1380    if (hoveredNode)
1381        *hoveredNode = mev.hitTestResult();
1382
1383    Scrollbar* scrollbar = 0;
1384
1385    if (m_resizeLayer && m_resizeLayer->inResizeMode())
1386        m_resizeLayer->resize(mouseEvent, m_offsetFromResizeCorner);
1387    else {
1388        if (FrameView* view = m_frame->view())
1389            scrollbar = view->scrollbarAtPoint(mouseEvent.pos());
1390
1391        if (!scrollbar)
1392            scrollbar = mev.scrollbar();
1393
1394        updateLastScrollbarUnderMouse(scrollbar, !m_mousePressed);
1395    }
1396
1397    bool swallowEvent = false;
1398    RefPtr<Frame> newSubframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev);
1399
1400    // We want mouseouts to happen first, from the inside out.  First send a move event to the last subframe so that it will fire mouseouts.
1401    if (m_lastMouseMoveEventSubframe && m_lastMouseMoveEventSubframe->tree()->isDescendantOf(m_frame) && m_lastMouseMoveEventSubframe != newSubframe)
1402        passMouseMoveEventToSubframe(mev, m_lastMouseMoveEventSubframe.get());
1403
1404    if (newSubframe) {
1405        // Update over/out state before passing the event to the subframe.
1406        updateMouseEventTargetNode(mev.targetNode(), mouseEvent, true);
1407
1408        // Event dispatch in updateMouseEventTargetNode may have caused the subframe of the target
1409        // node to be detached from its FrameView, in which case the event should not be passed.
1410        if (newSubframe->view())
1411            swallowEvent |= passMouseMoveEventToSubframe(mev, newSubframe.get(), hoveredNode);
1412    } else {
1413        if (scrollbar && !m_mousePressed)
1414            scrollbar->mouseMoved(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
1415        if (Page* page = m_frame->page()) {
1416            if ((!m_resizeLayer || !m_resizeLayer->inResizeMode()) && !page->mainFrame()->eventHandler()->panScrollInProgress()) {
1417                if (FrameView* view = m_frame->view())
1418                    view->setCursor(selectCursor(mev, scrollbar));
1419            }
1420        }
1421    }
1422
1423    m_lastMouseMoveEventSubframe = newSubframe;
1424
1425    if (swallowEvent)
1426        return true;
1427
1428    swallowEvent = dispatchMouseEvent(eventNames().mousemoveEvent, mev.targetNode(), false, 0, mouseEvent, true);
1429#if ENABLE(DRAG_SUPPORT)
1430    if (!swallowEvent)
1431        swallowEvent = handleMouseDraggedEvent(mev);
1432#endif // ENABLE(DRAG_SUPPORT)
1433
1434    return swallowEvent;
1435}
1436
1437void EventHandler::invalidateClick()
1438{
1439    m_clickCount = 0;
1440    m_clickNode = 0;
1441}
1442
1443bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
1444{
1445    RefPtr<FrameView> protector(m_frame->view());
1446
1447#if ENABLE(PAN_SCROLLING)
1448    if (mouseEvent.button() == MiddleButton)
1449        m_panScrollButtonPressed = false;
1450    if (m_springLoadedPanScrollInProgress)
1451       stopAutoscrollTimer();
1452#endif
1453
1454    m_mousePressed = false;
1455    m_currentMousePosition = mouseEvent.pos();
1456
1457#if ENABLE(SVG)
1458    if (m_svgPan) {
1459        m_svgPan = false;
1460        static_cast<SVGDocument*>(m_frame->document())->updatePan(m_currentMousePosition);
1461        return true;
1462    }
1463#endif
1464
1465    if (m_frameSetBeingResized)
1466        return dispatchMouseEvent(eventNames().mouseupEvent, m_frameSetBeingResized.get(), true, m_clickCount, mouseEvent, false);
1467
1468    if (m_lastScrollbarUnderMouse) {
1469        invalidateClick();
1470        return m_lastScrollbarUnderMouse->mouseUp();
1471    }
1472
1473    HitTestRequest request(HitTestRequest::MouseUp);
1474    MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
1475    Frame* subframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev);
1476    if (subframe && passMouseReleaseEventToSubframe(mev, subframe)) {
1477        m_capturingMouseEventsNode = 0;
1478        return true;
1479    }
1480
1481    bool swallowMouseUpEvent = dispatchMouseEvent(eventNames().mouseupEvent, mev.targetNode(), true, m_clickCount, mouseEvent, false);
1482
1483    // Don't ever dispatch click events for right clicks
1484    bool swallowClickEvent = false;
1485    if (m_clickCount > 0 && mouseEvent.button() != RightButton && mev.targetNode() == m_clickNode)
1486        swallowClickEvent = dispatchMouseEvent(eventNames().clickEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
1487
1488    if (m_resizeLayer) {
1489        m_resizeLayer->setInResizeMode(false);
1490        m_resizeLayer = 0;
1491    }
1492
1493    bool swallowMouseReleaseEvent = false;
1494    if (!swallowMouseUpEvent)
1495        swallowMouseReleaseEvent = handleMouseReleaseEvent(mev);
1496
1497    invalidateClick();
1498
1499    return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
1500}
1501
1502#if ENABLE(DRAG_SUPPORT)
1503bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard)
1504{
1505    FrameView* view = m_frame->view();
1506
1507    // FIXME: We might want to dispatch a dragleave even if the view is gone.
1508    if (!view)
1509        return false;
1510
1511    view->resetDeferredRepaintDelay();
1512    IntPoint contentsPos = view->windowToContents(event.pos());
1513
1514    RefPtr<MouseEvent> me = MouseEvent::create(eventType,
1515        true, true, m_frame->document()->defaultView(),
1516        0, event.globalX(), event.globalY(), contentsPos.x(), contentsPos.y(),
1517        event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
1518        0, 0, clipboard);
1519
1520    ExceptionCode ec;
1521    dragTarget->dispatchEvent(me.get(), ec);
1522    return me->defaultPrevented();
1523}
1524
1525bool EventHandler::canHandleDragAndDropForTarget(DragAndDropHandleType type, Node* target, const PlatformMouseEvent& event, Clipboard* clipboard, bool* accepted)
1526{
1527    bool canHandle = false;
1528    bool wasAccepted = false;
1529
1530    if (target->hasTagName(frameTag) || target->hasTagName(iframeTag)) {
1531        Frame* frame = static_cast<HTMLFrameElementBase*>(target)->contentFrame();
1532        if (frame) {
1533            switch (type) {
1534                case UpdateDragAndDrop:
1535                    wasAccepted = frame->eventHandler()->updateDragAndDrop(event, clipboard);
1536                    break;
1537                case CancelDragAndDrop:
1538                    frame->eventHandler()->cancelDragAndDrop(event, clipboard);
1539                    break;
1540                case PerformDragAndDrop:
1541                    wasAccepted = frame->eventHandler()->performDragAndDrop(event, clipboard);
1542                    break;
1543            }
1544        }
1545    } else
1546        canHandle = true;
1547
1548    if (accepted)
1549        *accepted = wasAccepted;
1550
1551    return canHandle;
1552}
1553
1554bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
1555{
1556    bool accept = false;
1557
1558    if (!m_frame->view())
1559        return false;
1560
1561    HitTestRequest request(HitTestRequest::ReadOnly);
1562    MouseEventWithHitTestResults mev = prepareMouseEvent(request, event);
1563
1564    // Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
1565    Node* newTarget = mev.targetNode();
1566    if (newTarget && newTarget->isTextNode())
1567        newTarget = newTarget->parentNode();
1568    if (newTarget)
1569        newTarget = newTarget->shadowAncestorNode();
1570
1571    if (m_dragTarget != newTarget) {
1572        // FIXME: this ordering was explicitly chosen to match WinIE. However,
1573        // it is sometimes incorrect when dragging within subframes, as seen with
1574        // LayoutTests/fast/events/drag-in-frames.html.
1575        //
1576        // Moreover, this ordering conforms to section 7.9.4 of the HTML 5 spec. <http://dev.w3.org/html5/spec/Overview.html#drag-and-drop-processing-model>.
1577        if (newTarget && canHandleDragAndDropForTarget(UpdateDragAndDrop, newTarget, event, clipboard, &accept)) {
1578            // As per section 7.9.4 of the HTML 5 spec., we must always fire a drag event before firing a dragenter, dragleave, or dragover event.
1579            if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) {
1580                // for now we don't care if event handler cancels default behavior, since there is none
1581                dispatchDragSrcEvent(eventNames().dragEvent, event);
1582            }
1583            accept = dispatchDragEvent(eventNames().dragenterEvent, newTarget, event, clipboard);
1584        }
1585
1586        if (m_dragTarget && canHandleDragAndDropForTarget(UpdateDragAndDrop, m_dragTarget.get(), event, clipboard, &accept))
1587            dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard);
1588
1589        if (newTarget) {
1590            // We do not explicitly call dispatchDragEvent here because it could ultimately result in the appearance that
1591            // two dragover events fired. So, we mark that we should only fire a dragover event on the next call to this function.
1592            m_shouldOnlyFireDragOverEvent = true;
1593        }
1594    } else {
1595        if (newTarget && canHandleDragAndDropForTarget(UpdateDragAndDrop, newTarget, event, clipboard, &accept)) {
1596            // Note, when dealing with sub-frames, we may need to fire only a dragover event as a drag event may have been fired earlier.
1597            if (!m_shouldOnlyFireDragOverEvent && dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) {
1598                // for now we don't care if event handler cancels default behavior, since there is none
1599                dispatchDragSrcEvent(eventNames().dragEvent, event);
1600            }
1601            accept = dispatchDragEvent(eventNames().dragoverEvent, newTarget, event, clipboard);
1602            m_shouldOnlyFireDragOverEvent = false;
1603        }
1604    }
1605    m_dragTarget = newTarget;
1606
1607    return accept;
1608}
1609
1610void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
1611{
1612    if (m_dragTarget && canHandleDragAndDropForTarget(CancelDragAndDrop, m_dragTarget.get(), event, clipboard)) {
1613        if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML)
1614            dispatchDragSrcEvent(eventNames().dragEvent, event);
1615        dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard);
1616    }
1617    clearDragState();
1618}
1619
1620bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
1621{
1622    bool accept = false;
1623    if (m_dragTarget && canHandleDragAndDropForTarget(PerformDragAndDrop, m_dragTarget.get(), event, clipboard, &accept))
1624        dispatchDragEvent(eventNames().dropEvent, m_dragTarget.get(), event, clipboard);
1625    clearDragState();
1626    return accept;
1627}
1628
1629void EventHandler::clearDragState()
1630{
1631    m_dragTarget = 0;
1632    m_capturingMouseEventsNode = 0;
1633    m_shouldOnlyFireDragOverEvent = false;
1634#if PLATFORM(MAC)
1635    m_sendingEventToSubview = false;
1636#endif
1637}
1638#endif // ENABLE(DRAG_SUPPORT)
1639
1640void EventHandler::setCapturingMouseEventsNode(PassRefPtr<Node> n)
1641{
1642    m_capturingMouseEventsNode = n;
1643}
1644
1645MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestRequest& request, const PlatformMouseEvent& mev)
1646{
1647    ASSERT(m_frame);
1648    ASSERT(m_frame->document());
1649
1650    return m_frame->document()->prepareMouseEvent(request, documentPointForWindowPoint(m_frame, mev.pos()), mev);
1651}
1652
1653#if ENABLE(SVG)
1654static inline SVGElementInstance* instanceAssociatedWithShadowTreeElement(Node* referenceNode)
1655{
1656    if (!referenceNode || !referenceNode->isSVGElement())
1657        return 0;
1658
1659    Node* shadowTreeElement = referenceNode->shadowTreeRootNode();
1660    if (!shadowTreeElement)
1661        return 0;
1662
1663    Node* shadowTreeParentElement = shadowTreeElement->shadowParentNode();
1664    if (!shadowTreeParentElement)
1665        return 0;
1666
1667    ASSERT(shadowTreeParentElement->hasTagName(useTag));
1668    return static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode);
1669}
1670#endif
1671
1672void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMouseEvent& mouseEvent, bool fireMouseOverOut)
1673{
1674    Node* result = targetNode;
1675
1676    // If we're capturing, we always go right to that node.
1677    if (m_capturingMouseEventsNode)
1678        result = m_capturingMouseEventsNode.get();
1679    else {
1680        // If the target node is a text node, dispatch on the parent node - rdar://4196646
1681        if (result && result->isTextNode())
1682            result = result->parentNode();
1683        if (result)
1684            result = result->shadowAncestorNode();
1685    }
1686    m_nodeUnderMouse = result;
1687#if ENABLE(SVG)
1688    m_instanceUnderMouse = instanceAssociatedWithShadowTreeElement(result);
1689
1690    // <use> shadow tree elements may have been recloned, update node under mouse in any case
1691    if (m_lastInstanceUnderMouse) {
1692        SVGElement* lastCorrespondingElement = m_lastInstanceUnderMouse->correspondingElement();
1693        SVGElement* lastCorrespondingUseElement = m_lastInstanceUnderMouse->correspondingUseElement();
1694
1695        if (lastCorrespondingElement && lastCorrespondingUseElement) {
1696            HashSet<SVGElementInstance*> instances = lastCorrespondingElement->instancesForElement();
1697
1698            // Locate the recloned shadow tree element for our corresponding instance
1699            HashSet<SVGElementInstance*>::iterator end = instances.end();
1700            for (HashSet<SVGElementInstance*>::iterator it = instances.begin(); it != end; ++it) {
1701                SVGElementInstance* instance = (*it);
1702                ASSERT(instance->correspondingElement() == lastCorrespondingElement);
1703
1704                if (instance == m_lastInstanceUnderMouse)
1705                    continue;
1706
1707                if (instance->correspondingUseElement() != lastCorrespondingUseElement)
1708                    continue;
1709
1710                SVGElement* shadowTreeElement = instance->shadowTreeElement();
1711                if (!shadowTreeElement->inDocument() || m_lastNodeUnderMouse == shadowTreeElement)
1712                    continue;
1713
1714                m_lastNodeUnderMouse = shadowTreeElement;
1715                m_lastInstanceUnderMouse = instance;
1716                break;
1717            }
1718        }
1719    }
1720#endif
1721
1722    // Fire mouseout/mouseover if the mouse has shifted to a different node.
1723    if (fireMouseOverOut) {
1724        if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame->document()) {
1725            m_lastNodeUnderMouse = 0;
1726            m_lastScrollbarUnderMouse = 0;
1727#if ENABLE(SVG)
1728            m_lastInstanceUnderMouse = 0;
1729#endif
1730        }
1731
1732        if (m_lastNodeUnderMouse != m_nodeUnderMouse) {
1733            // send mouseout event to the old node
1734            if (m_lastNodeUnderMouse)
1735                m_lastNodeUnderMouse->dispatchMouseEvent(mouseEvent, eventNames().mouseoutEvent, 0, m_nodeUnderMouse.get());
1736            // send mouseover event to the new node
1737            if (m_nodeUnderMouse)
1738                m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventNames().mouseoverEvent, 0, m_lastNodeUnderMouse.get());
1739        }
1740        m_lastNodeUnderMouse = m_nodeUnderMouse;
1741#if ENABLE(SVG)
1742        m_lastInstanceUnderMouse = instanceAssociatedWithShadowTreeElement(m_nodeUnderMouse.get());
1743#endif
1744    }
1745}
1746
1747bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool /*cancelable*/, int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder)
1748{
1749    if (FrameView* view = m_frame->view())
1750        view->resetDeferredRepaintDelay();
1751
1752    updateMouseEventTargetNode(targetNode, mouseEvent, setUnder);
1753
1754    bool swallowEvent = false;
1755
1756    if (m_nodeUnderMouse)
1757        swallowEvent = m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventType, clickCount);
1758
1759    if (!swallowEvent && eventType == eventNames().mousedownEvent) {
1760        // The layout needs to be up to date to determine if an element is focusable.
1761        m_frame->document()->updateLayoutIgnorePendingStylesheets();
1762
1763        // Blur current focus node when a link/button is clicked; this
1764        // is expected by some sites that rely on onChange handlers running
1765        // from form fields before the button click is processed.
1766        Node* node = m_nodeUnderMouse.get();
1767        RenderObject* renderer = node ? node->renderer() : 0;
1768
1769        // Walk up the render tree to search for a node to focus.
1770        // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
1771        while (renderer) {
1772            node = renderer->node();
1773            if (node && node->isFocusable()) {
1774                // To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus a
1775                // node on mouse down if it's selected and inside a focused node. It will be
1776                // focused if the user does a mouseup over it, however, because the mouseup
1777                // will set a selection inside it, which will call setFocuseNodeIfNeeded.
1778                ExceptionCode ec = 0;
1779                Node* n = node->isShadowNode() ? node->shadowParentNode() : node;
1780                if (m_frame->selection()->isRange() &&
1781                    m_frame->selection()->toNormalizedRange()->compareNode(n, ec) == Range::NODE_INSIDE &&
1782                    n->isDescendantOf(m_frame->document()->focusedNode()))
1783                    return false;
1784
1785                break;
1786            }
1787
1788            renderer = renderer->parent();
1789        }
1790
1791        // If focus shift is blocked, we eat the event.  Note we should never clear swallowEvent
1792        // if the page already set it (e.g., by canceling default behavior).
1793        if (Page* page = m_frame->page()) {
1794            if (node && node->isMouseFocusable()) {
1795                if (!page->focusController()->setFocusedNode(node, m_frame))
1796                    swallowEvent = true;
1797            } else if (!node || !node->focused()) {
1798                if (!page->focusController()->setFocusedNode(0, m_frame))
1799                    swallowEvent = true;
1800            }
1801        }
1802    }
1803
1804    return swallowEvent;
1805}
1806
1807#if !PLATFORM(GTK) && !(PLATFORM(CHROMIUM) && PLATFORM(LINUX))
1808bool EventHandler::shouldTurnVerticalTicksIntoHorizontal(const HitTestResult&) const
1809{
1810    return false;
1811}
1812#endif
1813
1814bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
1815{
1816    Document* doc = m_frame->document();
1817
1818    RenderObject* docRenderer = doc->renderer();
1819    if (!docRenderer)
1820        return false;
1821
1822    RefPtr<FrameView> protector(m_frame->view());
1823
1824    FrameView* view = m_frame->view();
1825    if (!view)
1826        return false;
1827    setFrameWasScrolledByUser();
1828    IntPoint vPoint = view->windowToContents(e.pos());
1829
1830    Node* node;
1831    bool isOverWidget;
1832    bool didSetLatchedNode = false;
1833
1834    HitTestRequest request(HitTestRequest::ReadOnly);
1835    HitTestResult result(vPoint);
1836    doc->renderView()->layer()->hitTest(request, result);
1837
1838    if (m_useLatchedWheelEventNode) {
1839        if (!m_latchedWheelEventNode) {
1840            m_latchedWheelEventNode = result.innerNode();
1841            m_widgetIsLatched = result.isOverWidget();
1842            didSetLatchedNode = true;
1843        }
1844
1845        node = m_latchedWheelEventNode.get();
1846        isOverWidget = m_widgetIsLatched;
1847    } else {
1848        if (m_latchedWheelEventNode)
1849            m_latchedWheelEventNode = 0;
1850        if (m_previousWheelScrolledNode)
1851            m_previousWheelScrolledNode = 0;
1852
1853        node = result.innerNode();
1854        isOverWidget = result.isOverWidget();
1855    }
1856
1857    if (shouldTurnVerticalTicksIntoHorizontal(result))
1858        e.turnVerticalTicksIntoHorizontal();
1859
1860    if (node) {
1861        // Figure out which view to send the event to.
1862        RenderObject* target = node->renderer();
1863
1864        if (isOverWidget && target && target->isWidget()) {
1865            Widget* widget = toRenderWidget(target)->widget();
1866            if (widget && passWheelEventToWidget(e, widget)) {
1867                e.accept();
1868                return true;
1869            }
1870        }
1871
1872        node = node->shadowAncestorNode();
1873        node->dispatchWheelEvent(e);
1874        if (e.isAccepted())
1875            return true;
1876
1877        // If we don't have a renderer, send the wheel event to the first node we find with a renderer.
1878        // This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll.
1879        while (node && !node->renderer())
1880            node = node->parent();
1881
1882        if (node && node->renderer()) {
1883            // Just break up into two scrolls if we need to.  Diagonal movement on
1884            // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
1885            Node* stopNode = m_previousWheelScrolledNode.get();
1886            scrollAndAcceptEvent(e.deltaX(), ScrollLeft, ScrollRight, e, node, &stopNode);
1887            scrollAndAcceptEvent(e.deltaY(), ScrollUp, ScrollDown, e, node, &stopNode);
1888            if (!m_useLatchedWheelEventNode)
1889                m_previousWheelScrolledNode = stopNode;
1890        }
1891    }
1892
1893    if (e.isAccepted())
1894        return true;
1895
1896    view = m_frame->view();
1897    if (!view)
1898        return false;
1899
1900    view->wheelEvent(e);
1901    return e.isAccepted();
1902}
1903
1904#if ENABLE(CONTEXT_MENUS)
1905bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event)
1906{
1907    Document* doc = m_frame->document();
1908    FrameView* v = m_frame->view();
1909    if (!v)
1910        return false;
1911
1912    bool swallowEvent;
1913    IntPoint viewportPos = v->windowToContents(event.pos());
1914    HitTestRequest request(HitTestRequest::Active);
1915    MouseEventWithHitTestResults mev = doc->prepareMouseEvent(request, viewportPos, event);
1916
1917    // Context menu events shouldn't select text in GTK+ applications or in Chromium.
1918    // FIXME: This should probably be configurable by embedders. Consider making it a WebPreferences setting.
1919    // See: https://bugs.webkit.org/show_bug.cgi?id=15279
1920#if !PLATFORM(GTK) && !PLATFORM(CHROMIUM)
1921    if (!m_frame->selection()->contains(viewportPos) &&
1922        // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse.
1923        // If the selection is non-editable, we do word selection to make it easier to use the contextual menu items
1924        // available for text selections.  But only if we're above text.
1925        (m_frame->selection()->isContentEditable() || (mev.targetNode() && mev.targetNode()->isTextNode()))) {
1926        m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection
1927        selectClosestWordOrLinkFromMouseEvent(mev);
1928    }
1929#endif
1930
1931    swallowEvent = dispatchMouseEvent(eventNames().contextmenuEvent, mev.targetNode(), true, 0, event, true);
1932
1933    return swallowEvent;
1934}
1935#endif // ENABLE(CONTEXT_MENUS)
1936
1937void EventHandler::scheduleHoverStateUpdate()
1938{
1939    if (!m_hoverTimer.isActive())
1940        m_hoverTimer.startOneShot(0);
1941}
1942
1943// Whether or not a mouse down can begin the creation of a selection.  Fires the selectStart event.
1944bool EventHandler::canMouseDownStartSelect(Node* node)
1945{
1946    if (!node || !node->renderer())
1947        return true;
1948
1949    // Some controls and images can't start a select on a mouse down.
1950    if (!node->canStartSelection())
1951        return false;
1952
1953    for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) {
1954        if (Node* node = curr->node())
1955            return node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true));
1956    }
1957
1958    return true;
1959}
1960
1961#if ENABLE(DRAG_SUPPORT)
1962bool EventHandler::canMouseDragExtendSelect(Node* node)
1963{
1964    if (!node || !node->renderer())
1965        return true;
1966
1967    for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) {
1968        if (Node* node = curr->node())
1969            return node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true));
1970    }
1971
1972    return true;
1973}
1974#endif // ENABLE(DRAG_SUPPORT)
1975
1976void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet)
1977{
1978    m_frameSetBeingResized = frameSet;
1979}
1980
1981void EventHandler::resizeLayerDestroyed()
1982{
1983    ASSERT(m_resizeLayer);
1984    m_resizeLayer = 0;
1985}
1986
1987void EventHandler::hoverTimerFired(Timer<EventHandler>*)
1988{
1989    m_hoverTimer.stop();
1990
1991    ASSERT(m_frame);
1992    ASSERT(m_frame->document());
1993
1994    if (RenderView* renderer = m_frame->contentRenderer()) {
1995        if (FrameView* view = m_frame->view()) {
1996            HitTestRequest request(HitTestRequest::MouseMove);
1997            HitTestResult result(view->windowToContents(m_currentMousePosition));
1998            renderer->layer()->hitTest(request, result);
1999            m_frame->document()->updateStyleIfNeeded();
2000        }
2001    }
2002}
2003
2004static Node* eventTargetNodeForDocument(Document* doc)
2005{
2006    if (!doc)
2007        return 0;
2008    Node* node = doc->focusedNode();
2009
2010#if defined(ANDROID_PLUGINS)
2011    if (!node && doc->frame() && doc->frame()->view())
2012        node = android::WebViewCore::getWebViewCore(doc->frame()->view())
2013                                     ->cursorNodeIsPlugin();
2014#endif
2015
2016    if (!node && doc->isHTMLDocument())
2017        node = doc->body();
2018    if (!node)
2019        node = doc->documentElement();
2020    return node;
2021}
2022
2023bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& evt)
2024{
2025    // FIXME: Ignoring the state of Shift key is what neither IE nor Firefox do.
2026    // IE matches lower and upper case access keys regardless of Shift key state - but if both upper and
2027    // lower case variants are present in a document, the correct element is matched based on Shift key state.
2028    // Firefox only matches an access key if Shift is not pressed, and does that case-insensitively.
2029    ASSERT(!(accessKeyModifiers() & PlatformKeyboardEvent::ShiftKey));
2030    if ((evt.modifiers() & ~PlatformKeyboardEvent::ShiftKey) != accessKeyModifiers())
2031        return false;
2032    String key = evt.unmodifiedText();
2033    Element* elem = m_frame->document()->getElementByAccessKey(key.lower());
2034    if (!elem)
2035        return false;
2036    elem->accessKeyAction(false);
2037    return true;
2038}
2039
2040#if !PLATFORM(MAC)
2041bool EventHandler::needsKeyboardEventDisambiguationQuirks() const
2042{
2043    return false;
2044}
2045#endif
2046
2047bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent)
2048{
2049#if ENABLE(PAN_SCROLLING)
2050    if (Page* page = m_frame->page()) {
2051        if (page->mainFrame()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress) {
2052            // If a key is pressed while the autoscroll/panScroll is in progress then we want to stop
2053            if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyDown || initialKeyEvent.type() == PlatformKeyboardEvent::RawKeyDown)
2054                stopAutoscrollTimer();
2055
2056            // If we were in autoscroll/panscroll mode, we swallow the key event
2057            return true;
2058        }
2059    }
2060#endif
2061
2062    // Check for cases where we are too early for events -- possible unmatched key up
2063    // from pressing return in the location bar.
2064    RefPtr<Node> node = eventTargetNodeForDocument(m_frame->document());
2065    if (!node)
2066        return false;
2067
2068    if (FrameView* view = m_frame->view())
2069        view->resetDeferredRepaintDelay();
2070
2071    // FIXME: what is this doing here, in keyboard event handler?
2072    m_frame->loader()->resetMultipleFormSubmissionProtection();
2073
2074    // In IE, access keys are special, they are handled after default keydown processing, but cannot be canceled - this is hard to match.
2075    // On Mac OS X, we process them before dispatching keydown, as the default keydown handler implements Emacs key bindings, which may conflict
2076    // with access keys. Then we dispatch keydown, but suppress its default handling.
2077    // On Windows, WebKit explicitly calls handleAccessKey() instead of dispatching a keypress event for WM_SYSCHAR messages.
2078    // Other platforms currently match either Mac or Windows behavior, depending on whether they send combined KeyDown events.
2079    bool matchedAnAccessKey = false;
2080    if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyDown)
2081        matchedAnAccessKey = handleAccessKey(initialKeyEvent);
2082
2083    // FIXME: it would be fair to let an input method handle KeyUp events before DOM dispatch.
2084    if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyUp || initialKeyEvent.type() == PlatformKeyboardEvent::Char)
2085        return !node->dispatchKeyEvent(initialKeyEvent);
2086
2087    bool backwardCompatibilityMode = needsKeyboardEventDisambiguationQuirks();
2088
2089    ExceptionCode ec;
2090    PlatformKeyboardEvent keyDownEvent = initialKeyEvent;
2091    if (keyDownEvent.type() != PlatformKeyboardEvent::RawKeyDown)
2092        keyDownEvent.disambiguateKeyDownEvent(PlatformKeyboardEvent::RawKeyDown, backwardCompatibilityMode);
2093    RefPtr<KeyboardEvent> keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->defaultView());
2094    if (matchedAnAccessKey)
2095        keydown->setDefaultPrevented(true);
2096    keydown->setTarget(node);
2097
2098    if (initialKeyEvent.type() == PlatformKeyboardEvent::RawKeyDown) {
2099        node->dispatchEvent(keydown, ec);
2100        return keydown->defaultHandled() || keydown->defaultPrevented();
2101    }
2102
2103    // Run input method in advance of DOM event handling.  This may result in the IM
2104    // modifying the page prior the keydown event, but this behaviour is necessary
2105    // in order to match IE:
2106    // 1. preventing default handling of keydown and keypress events has no effect on IM input;
2107    // 2. if an input method handles the event, its keyCode is set to 229 in keydown event.
2108    m_frame->editor()->handleInputMethodKeydown(keydown.get());
2109
2110    bool handledByInputMethod = keydown->defaultHandled();
2111
2112    if (handledByInputMethod) {
2113        keyDownEvent.setWindowsVirtualKeyCode(CompositionEventKeyCode);
2114        keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->defaultView());
2115        keydown->setTarget(node);
2116        keydown->setDefaultHandled();
2117    }
2118
2119    node->dispatchEvent(keydown, ec);
2120    bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented();
2121    if (handledByInputMethod || (keydownResult && !backwardCompatibilityMode))
2122        return keydownResult;
2123
2124    // Focus may have changed during keydown handling, so refetch node.
2125    // But if we are dispatching a fake backward compatibility keypress, then we pretend that the keypress happened on the original node.
2126    if (!keydownResult) {
2127        node = eventTargetNodeForDocument(m_frame->document());
2128        if (!node)
2129            return false;
2130    }
2131
2132    PlatformKeyboardEvent keyPressEvent = initialKeyEvent;
2133    keyPressEvent.disambiguateKeyDownEvent(PlatformKeyboardEvent::Char, backwardCompatibilityMode);
2134    if (keyPressEvent.text().isEmpty())
2135        return keydownResult;
2136    RefPtr<KeyboardEvent> keypress = KeyboardEvent::create(keyPressEvent, m_frame->document()->defaultView());
2137    keypress->setTarget(node);
2138    if (keydownResult)
2139        keypress->setDefaultPrevented(true);
2140#if PLATFORM(MAC)
2141    keypress->keypressCommands() = keydown->keypressCommands();
2142#endif
2143    node->dispatchEvent(keypress, ec);
2144
2145    return keydownResult || keypress->defaultPrevented() || keypress->defaultHandled();
2146}
2147
2148void EventHandler::handleKeyboardSelectionMovement(KeyboardEvent* event)
2149{
2150    if (!event)
2151        return;
2152
2153    String key = event->keyIdentifier();
2154    bool isShifted = event->getModifierState("Shift");
2155    bool isOptioned = event->getModifierState("Alt");
2156    bool isCommanded = event->getModifierState("Meta");
2157
2158    if (key == "Up") {
2159        m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::BACKWARD, (isCommanded) ? DocumentBoundary : LineGranularity, true);
2160        event->setDefaultHandled();
2161    }
2162    else if (key == "Down") {
2163        m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::FORWARD, (isCommanded) ? DocumentBoundary : LineGranularity, true);
2164        event->setDefaultHandled();
2165    }
2166    else if (key == "Left") {
2167        m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::LEFT, (isCommanded) ? LineBoundary : (isOptioned) ? WordGranularity : CharacterGranularity, true);
2168        event->setDefaultHandled();
2169    }
2170    else if (key == "Right") {
2171        m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::RIGHT, (isCommanded) ? LineBoundary : (isOptioned) ? WordGranularity : CharacterGranularity, true);
2172        event->setDefaultHandled();
2173    }
2174}
2175
2176void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event)
2177{
2178    if (event->type() == eventNames().keydownEvent) {
2179        m_frame->editor()->handleKeyboardEvent(event);
2180        if (event->defaultHandled())
2181            return;
2182        if (event->keyIdentifier() == "U+0009")
2183            defaultTabEventHandler(event);
2184
2185       // provides KB navigation and selection for enhanced accessibility users
2186       if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled())
2187           handleKeyboardSelectionMovement(event);
2188    }
2189    if (event->type() == eventNames().keypressEvent) {
2190        m_frame->editor()->handleKeyboardEvent(event);
2191        if (event->defaultHandled())
2192            return;
2193        if (event->charCode() == ' ')
2194            defaultSpaceEventHandler(event);
2195    }
2196}
2197
2198#if ENABLE(DRAG_SUPPORT)
2199bool EventHandler::dragHysteresisExceeded(const FloatPoint& floatDragViewportLocation) const
2200{
2201    IntPoint dragViewportLocation((int)floatDragViewportLocation.x(), (int)floatDragViewportLocation.y());
2202    return dragHysteresisExceeded(dragViewportLocation);
2203}
2204
2205bool EventHandler::dragHysteresisExceeded(const IntPoint& dragViewportLocation) const
2206{
2207    FrameView* view = m_frame->view();
2208    if (!view)
2209        return false;
2210    IntPoint dragLocation = view->windowToContents(dragViewportLocation);
2211    IntSize delta = dragLocation - m_mouseDownPos;
2212
2213    int threshold = GeneralDragHysteresis;
2214    if (dragState().m_dragSrcIsImage)
2215        threshold = ImageDragHysteresis;
2216    else if (dragState().m_dragSrcIsLink)
2217        threshold = LinkDragHysteresis;
2218    else if (dragState().m_dragSrcInSelection)
2219        threshold = TextDragHysteresis;
2220
2221    return abs(delta.width()) >= threshold || abs(delta.height()) >= threshold;
2222}
2223
2224void EventHandler::freeClipboard()
2225{
2226    if (dragState().m_dragClipboard)
2227        dragState().m_dragClipboard->setAccessPolicy(ClipboardNumb);
2228}
2229
2230bool EventHandler::shouldDragAutoNode(Node* node, const IntPoint& point) const
2231{
2232    if (!node || !m_frame->view())
2233        return false;
2234    Page* page = m_frame->page();
2235    return page && page->dragController()->mayStartDragAtEventLocation(m_frame, point);
2236}
2237
2238void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, DragOperation operation)
2239{
2240    if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) {
2241        dragState().m_dragClipboard->setDestinationOperation(operation);
2242        // for now we don't care if event handler cancels default behavior, since there is none
2243        dispatchDragSrcEvent(eventNames().dragendEvent, event);
2244    }
2245    freeClipboard();
2246    dragState().m_dragSrc = 0;
2247    // In case the drag was ended due to an escape key press we need to ensure
2248    // that consecutive mousemove events don't reinitiate the drag and drop.
2249    m_mouseDownMayStartDrag = false;
2250}
2251
2252// returns if we should continue "default processing", i.e., whether eventhandler canceled
2253bool EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent& event)
2254{
2255    return !dispatchDragEvent(eventType, dragState().m_dragSrc.get(), event, dragState().m_dragClipboard.get());
2256}
2257
2258bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event)
2259{
2260    if (event.event().button() != LeftButton || event.event().eventType() != MouseEventMoved) {
2261        // If we allowed the other side of the bridge to handle a drag
2262        // last time, then m_mousePressed might still be set. So we
2263        // clear it now to make sure the next move after a drag
2264        // doesn't look like a drag.
2265        m_mousePressed = false;
2266        return false;
2267    }
2268
2269    if (eventLoopHandleMouseDragged(event))
2270        return true;
2271
2272    // Careful that the drag starting logic stays in sync with eventMayStartDrag()
2273
2274    if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
2275        allowDHTMLDrag(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA);
2276        if (!dragState().m_dragSrcMayBeDHTML && !dragState().m_dragSrcMayBeUA)
2277            m_mouseDownMayStartDrag = false;     // no element is draggable
2278    }
2279
2280    if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
2281        // try to find an element that wants to be dragged
2282        HitTestRequest request(HitTestRequest::ReadOnly);
2283        HitTestResult result(m_mouseDownPos);
2284        m_frame->contentRenderer()->layer()->hitTest(request, result);
2285        Node* node = result.innerNode();
2286        if (node && node->renderer())
2287            dragState().m_dragSrc = node->renderer()->draggableNode(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA,
2288                                                                    m_mouseDownPos.x(), m_mouseDownPos.y(), dragState().m_dragSrcIsDHTML);
2289        else
2290            dragState().m_dragSrc = 0;
2291
2292        if (!dragState().m_dragSrc)
2293            m_mouseDownMayStartDrag = false;     // no element is draggable
2294        else {
2295            // remember some facts about this source, while we have a HitTestResult handy
2296            node = result.URLElement();
2297            dragState().m_dragSrcIsLink = node && node->isLink();
2298
2299            node = result.innerNonSharedNode();
2300            dragState().m_dragSrcIsImage = node && node->renderer() && node->renderer()->isImage();
2301
2302            dragState().m_dragSrcInSelection = m_frame->selection()->contains(m_mouseDownPos);
2303        }
2304    }
2305
2306    // For drags starting in the selection, the user must wait between the mousedown and mousedrag,
2307    // or else we bail on the dragging stuff and allow selection to occur
2308    if (m_mouseDownMayStartDrag && !dragState().m_dragSrcIsImage && dragState().m_dragSrcInSelection && event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay) {
2309        m_mouseDownMayStartDrag = false;
2310        dragState().m_dragSrc = 0;
2311        // ...but if this was the first click in the window, we don't even want to start selection
2312        if (eventActivatedView(event.event()))
2313            m_mouseDownMayStartSelect = false;
2314    }
2315
2316    if (!m_mouseDownMayStartDrag)
2317        return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll;
2318
2319    // We are starting a text/image/url drag, so the cursor should be an arrow
2320    if (FrameView* view = m_frame->view())
2321        view->setCursor(pointerCursor());
2322
2323    if (!dragHysteresisExceeded(event.event().pos()))
2324        return true;
2325
2326    // Once we're past the hysteresis point, we don't want to treat this gesture as a click
2327    invalidateClick();
2328
2329    DragOperation srcOp = DragOperationNone;
2330
2331    freeClipboard();    // would only happen if we missed a dragEnd.  Do it anyway, just
2332                        // to make sure it gets numbified
2333    dragState().m_dragClipboard = createDraggingClipboard();
2334
2335    if (dragState().m_dragSrcMayBeDHTML) {
2336        // Check to see if the is a DOM based drag, if it is get the DOM specified drag
2337        // image and offset
2338        if (dragState().m_dragSrcIsDHTML) {
2339            if (RenderObject* renderer = dragState().m_dragSrc->renderer()) {
2340                // FIXME: This doesn't work correctly with transforms.
2341                FloatPoint absPos = renderer->localToAbsolute();
2342                IntSize delta = m_mouseDownPos - roundedIntPoint(absPos);
2343                dragState().m_dragClipboard->setDragImageElement(dragState().m_dragSrc.get(), IntPoint() + delta);
2344            } else {
2345                // The renderer has disappeared, this can happen if the onStartDrag handler has hidden
2346                // the element in some way.  In this case we just kill the drag.
2347                m_mouseDownMayStartDrag = false;
2348                goto cleanupDrag;
2349            }
2350        }
2351
2352        m_mouseDownMayStartDrag = dispatchDragSrcEvent(eventNames().dragstartEvent, m_mouseDown)
2353            && !m_frame->selection()->isInPasswordField();
2354
2355        // Invalidate clipboard here against anymore pasteboard writing for security.  The drag
2356        // image can still be changed as we drag, but not the pasteboard data.
2357        dragState().m_dragClipboard->setAccessPolicy(ClipboardImageWritable);
2358
2359        if (m_mouseDownMayStartDrag) {
2360            // gather values from DHTML element, if it set any
2361            dragState().m_dragClipboard->sourceOperation(srcOp);
2362
2363            // Yuck, a draggedImage:moveTo: message can be fired as a result of kicking off the
2364            // drag with dragImage!  Because of that dumb reentrancy, we may think we've not
2365            // started the drag when that happens.  So we have to assume it's started before we
2366            // kick it off.
2367            dragState().m_dragClipboard->setDragHasStarted();
2368        }
2369    }
2370
2371    if (m_mouseDownMayStartDrag) {
2372        Page* page = m_frame->page();
2373        DragController* dragController = page ? page->dragController() : 0;
2374        bool startedDrag = dragController && dragController->startDrag(m_frame, dragState().m_dragClipboard.get(), srcOp, event.event(), m_mouseDownPos, dragState().m_dragSrcIsDHTML);
2375        if (!startedDrag && dragState().m_dragSrcMayBeDHTML) {
2376            // Drag was canned at the last minute - we owe m_dragSrc a DRAGEND event
2377            dispatchDragSrcEvent(eventNames().dragendEvent, event.event());
2378            m_mouseDownMayStartDrag = false;
2379        }
2380    }
2381
2382cleanupDrag:
2383    if (!m_mouseDownMayStartDrag) {
2384        // something failed to start the drag, cleanup
2385        freeClipboard();
2386        dragState().m_dragSrc = 0;
2387    }
2388
2389    // No more default handling (like selection), whether we're past the hysteresis bounds or not
2390    return true;
2391}
2392#endif // ENABLE(DRAG_SUPPORT)
2393
2394bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEvent, bool isLineBreak, bool isBackTab)
2395{
2396    // Platforms should differentiate real commands like selectAll from text input in disguise (like insertNewline),
2397    // and avoid dispatching text input events from keydown default handlers.
2398    ASSERT(!underlyingEvent || !underlyingEvent->isKeyboardEvent() || static_cast<KeyboardEvent*>(underlyingEvent)->type() == eventNames().keypressEvent);
2399
2400    if (!m_frame)
2401        return false;
2402
2403    EventTarget* target;
2404    if (underlyingEvent)
2405        target = underlyingEvent->target();
2406    else
2407        target = eventTargetNodeForDocument(m_frame->document());
2408    if (!target)
2409        return false;
2410
2411    if (FrameView* view = m_frame->view())
2412        view->resetDeferredRepaintDelay();
2413
2414    RefPtr<TextEvent> event = TextEvent::create(m_frame->domWindow(), text);
2415    event->setUnderlyingEvent(underlyingEvent);
2416    event->setIsLineBreak(isLineBreak);
2417    event->setIsBackTab(isBackTab);
2418    ExceptionCode ec;
2419    target->dispatchEvent(event, ec);
2420    return event->defaultHandled();
2421}
2422
2423
2424#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(HAIKU)
2425bool EventHandler::invertSenseOfTabsToLinks(KeyboardEvent*) const
2426{
2427    return false;
2428}
2429#endif
2430
2431bool EventHandler::tabsToLinks(KeyboardEvent* event) const
2432{
2433    Page* page = m_frame->page();
2434    if (!page)
2435        return false;
2436
2437    if (page->chrome()->client()->tabsToLinks())
2438        return !invertSenseOfTabsToLinks(event);
2439
2440    return invertSenseOfTabsToLinks(event);
2441}
2442
2443void EventHandler::defaultTextInputEventHandler(TextEvent* event)
2444{
2445    String data = event->data();
2446    if (data == "\n") {
2447        if (event->isLineBreak()) {
2448            if (m_frame->editor()->insertLineBreak())
2449                event->setDefaultHandled();
2450        } else {
2451            if (m_frame->editor()->insertParagraphSeparator())
2452                event->setDefaultHandled();
2453        }
2454    } else {
2455        if (m_frame->editor()->insertTextWithoutSendingTextEvent(data, false, event))
2456            event->setDefaultHandled();
2457    }
2458}
2459
2460#if PLATFORM(QT) || PLATFORM(MAC) || PLATFORM(ANDROID)
2461
2462// These two platforms handle the space event in the platform-specific WebKit code.
2463// Eventually it would be good to eliminate that and use the code here instead, but
2464// the Qt version is inside an ifdef and the Mac version has some extra behavior
2465// so we can't unify everything yet.
2466void EventHandler::defaultSpaceEventHandler(KeyboardEvent*)
2467{
2468}
2469
2470#else
2471
2472void EventHandler::defaultSpaceEventHandler(KeyboardEvent* event)
2473{
2474    ScrollDirection direction = event->shiftKey() ? ScrollUp : ScrollDown;
2475    if (scrollOverflow(direction, ScrollByPage)) {
2476        event->setDefaultHandled();
2477        return;
2478    }
2479
2480    FrameView* view = m_frame->view();
2481    if (!view)
2482        return;
2483
2484    if (view->scroll(direction, ScrollByPage))
2485        event->setDefaultHandled();
2486}
2487
2488#endif
2489
2490void EventHandler::defaultTabEventHandler(KeyboardEvent* event)
2491{
2492    // We should only advance focus on tabs if no special modifier keys are held down.
2493    if (event->ctrlKey() || event->metaKey() || event->altGraphKey())
2494        return;
2495
2496    Page* page = m_frame->page();
2497    if (!page)
2498        return;
2499    if (!page->tabKeyCyclesThroughElements())
2500        return;
2501
2502    FocusDirection focusDirection = event->shiftKey() ? FocusDirectionBackward : FocusDirectionForward;
2503
2504    // Tabs can be used in design mode editing.
2505    if (m_frame->document()->inDesignMode())
2506        return;
2507
2508    if (page->focusController()->advanceFocus(focusDirection, event))
2509        event->setDefaultHandled();
2510}
2511
2512void EventHandler::capsLockStateMayHaveChanged()
2513{
2514    Document* d = m_frame->document();
2515    if (Node* node = d->focusedNode()) {
2516        if (RenderObject* r = node->renderer()) {
2517            if (r->isTextField())
2518                toRenderTextControlSingleLine(r)->capsLockStateMayHaveChanged();
2519        }
2520    }
2521}
2522
2523void EventHandler::sendResizeEvent()
2524{
2525    m_frame->document()->dispatchWindowEvent(Event::create(eventNames().resizeEvent, false, false));
2526}
2527
2528void EventHandler::sendScrollEvent()
2529{
2530    setFrameWasScrolledByUser();
2531    if (m_frame->view())
2532        m_frame->document()->dispatchEvent(Event::create(eventNames().scrollEvent, true, false));
2533}
2534
2535void EventHandler::setFrameWasScrolledByUser()
2536{
2537    FrameView* v = m_frame->view();
2538    if (v)
2539        v->setWasScrolledByUser(true);
2540}
2541
2542bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults& mev, Scrollbar* scrollbar)
2543{
2544    if (!scrollbar || !scrollbar->enabled())
2545        return false;
2546    setFrameWasScrolledByUser();
2547    return scrollbar->mouseDown(mev.event());
2548}
2549
2550// If scrollbar (under mouse) is different from last, send a mouse exited. Set
2551// last to scrollbar if setLast is true; else set last to 0.
2552void EventHandler::updateLastScrollbarUnderMouse(Scrollbar* scrollbar, bool setLast)
2553{
2554    if (m_lastScrollbarUnderMouse != scrollbar) {
2555        // Send mouse exited to the old scrollbar.
2556        if (m_lastScrollbarUnderMouse)
2557            m_lastScrollbarUnderMouse->mouseExited();
2558        m_lastScrollbarUnderMouse = setLast ? scrollbar : 0;
2559    }
2560}
2561
2562#if ENABLE(TOUCH_EVENTS)
2563#if PLATFORM(ANDROID)
2564// TODO(benm): On Android we return an int back to Java to signify whether the default actions
2565// for longpress/doubletap in the Browser should be prevented. I think that before upstreaming
2566// to webkit.org we can refactor the Java side to not require this.
2567int EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
2568#else
2569bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
2570#endif
2571{
2572    RefPtr<TouchList> touches = TouchList::create();
2573    RefPtr<TouchList> pressedTouches = TouchList::create();
2574    RefPtr<TouchList> releasedTouches = TouchList::create();
2575    RefPtr<TouchList> movedTouches = TouchList::create();
2576    RefPtr<TouchList> targetTouches = TouchList::create();
2577    RefPtr<TouchList> cancelTouches = TouchList::create();
2578
2579    const Vector<PlatformTouchPoint>& points = event.touchPoints();
2580    AtomicString* eventName = 0;
2581
2582    for (int i = 0; i < points.size(); ++i) {
2583        const PlatformTouchPoint& point = points[i];
2584        IntPoint pagePoint = documentPointForWindowPoint(m_frame, point.pos());
2585        HitTestResult result = hitTestResultAtPoint(pagePoint, /*allowShadowContent*/ false);
2586        Node* target = result.innerNode();
2587
2588        // Touch events should not go to text nodes
2589        if (target && target->isTextNode())
2590            target = target->parentNode();
2591
2592        Document* doc = target->document();
2593        if (!doc)
2594            continue;
2595        if (!doc->hasListenerType(Document::TOUCH_LISTENER))
2596            continue;
2597
2598        if (m_frame != doc->frame()) {
2599            // pagePoint should always be relative to the target elements containing frame.
2600            pagePoint = documentPointForWindowPoint(doc->frame(), point.pos());
2601        }
2602
2603        int adjustedPageX = lroundf(pagePoint.x() / m_frame->pageZoomFactor());
2604        int adjustedPageY = lroundf(pagePoint.y() / m_frame->pageZoomFactor());
2605
2606        if ( (event.type() == TouchStart
2607#if PLATFORM(ANDROID)
2608            || event.type() == TouchDoubleTap
2609            || event.type() == TouchLongPress
2610#endif
2611            ) && !i) {
2612            m_touchEventTarget = target;
2613            m_firstTouchScreenPos = point.screenPos();
2614            m_firstTouchPagePos = pagePoint;
2615        }
2616
2617        RefPtr<Touch> touch = Touch::create(doc->frame(), m_touchEventTarget.get(), point.id(),
2618                                            point.screenPos().x(), point.screenPos().y(),
2619                                            adjustedPageX, adjustedPageY);
2620
2621        if (point.state() == PlatformTouchPoint::TouchReleased)
2622            releasedTouches->append(touch);
2623        else if (point.state() == PlatformTouchPoint::TouchCancelled)
2624            cancelTouches->append(touch);
2625        else {
2626            if (point.state() == PlatformTouchPoint::TouchPressed)
2627                pressedTouches->append(touch);
2628            else {
2629                touches->append(touch);
2630                if (m_touchEventTarget == target)
2631                    targetTouches->append(touch);
2632                if (point.state() == PlatformTouchPoint::TouchMoved)
2633                    movedTouches->append(touch);
2634            }
2635        }
2636    }
2637
2638    if (!m_touchEventTarget)
2639#if PLATFORM(ANDROID)
2640        return 0;
2641#else
2642        return false;
2643#endif
2644
2645    bool defaultPrevented = false;
2646#if PLATFORM(ANDROID)
2647    // TODO (benm): We should be able to remove this prior to upstreaming once Java side refactorings to make
2648    // preventDeault work better are complete.
2649    bool longPressPrevented = false;
2650    bool doubleTapPrevented = false;
2651#endif
2652
2653    if (event.type() == TouchCancel) {
2654        eventName = &eventNames().touchcancelEvent;
2655        RefPtr<TouchEvent> cancelEv =
2656            TouchEvent::create(TouchList::create().get(), TouchList::create().get(), cancelTouches.get(),
2657                                                   *eventName, m_touchEventTarget->document()->defaultView(),
2658                                                   m_firstTouchScreenPos.x(), m_firstTouchScreenPos.y(),
2659                                                   m_firstTouchPagePos.x(), m_firstTouchPagePos.y(),
2660                                                   event.ctrlKey(), event.altKey(), event.shiftKey(),
2661                                                   event.metaKey());
2662
2663        ExceptionCode ec = 0;
2664        m_touchEventTarget->dispatchEvent(cancelEv.get(), ec);
2665        defaultPrevented |= cancelEv->defaultPrevented();
2666    }
2667
2668    if (releasedTouches->length() > 0) {
2669        eventName = &eventNames().touchendEvent;
2670        RefPtr<TouchEvent> endEv =
2671            TouchEvent::create(touches.get(), targetTouches.get(), releasedTouches.get(),
2672                                                   *eventName, m_touchEventTarget->document()->defaultView(),
2673                                                   m_firstTouchScreenPos.x(), m_firstTouchScreenPos.y(),
2674                                                   m_firstTouchPagePos.x(), m_firstTouchPagePos.y(),
2675                                                   event.ctrlKey(), event.altKey(), event.shiftKey(),
2676                                                   event.metaKey());
2677        ExceptionCode ec = 0;
2678        m_touchEventTarget->dispatchEvent(endEv.get(), ec);
2679        defaultPrevented |= endEv->defaultPrevented();
2680    }
2681    if (pressedTouches->length() > 0) {
2682        // Add pressed touchpoints to touches and targetTouches
2683        for (int i = 0; i < pressedTouches->length(); ++i) {
2684            touches->append(pressedTouches->item(i));
2685            if (m_touchEventTarget == pressedTouches->item(i)->target())
2686                targetTouches->append(pressedTouches->item(i));
2687        }
2688
2689#if PLATFORM(ANDROID)
2690        if (event.type() == TouchLongPress) {
2691            eventName = &eventNames().touchlongpressEvent;
2692            RefPtr<TouchEvent> longpressEv =
2693                TouchEvent::create(touches.get(), targetTouches.get(), pressedTouches.get(),
2694                                                       *eventName, m_touchEventTarget->document()->defaultView(),
2695                                                       m_firstTouchScreenPos.x(), m_firstTouchScreenPos.y(),
2696                                                       m_firstTouchPagePos.x(), m_firstTouchPagePos.y(),
2697                                                       event.ctrlKey(), event.altKey(), event.shiftKey(),
2698                                                       event.metaKey());
2699
2700            ExceptionCode ec = 0;
2701            m_touchEventTarget->dispatchEvent(longpressEv.get(), ec);
2702            defaultPrevented |= longpressEv->defaultPrevented();
2703        } else if (event.type() == TouchDoubleTap) {
2704            eventName = &eventNames().touchdoubletapEvent;
2705            RefPtr<TouchEvent> doubleTapEv =
2706                TouchEvent::create(touches.get(), targetTouches.get(), pressedTouches.get(),
2707                                                       *eventName, m_touchEventTarget->document()->defaultView(),
2708                                                       m_firstTouchScreenPos.x(), m_firstTouchScreenPos.y(),
2709                                                       m_firstTouchPagePos.x(), m_firstTouchPagePos.y(),
2710                                                       event.ctrlKey(), event.altKey(), event.shiftKey(),
2711                                                       event.metaKey());
2712
2713            ExceptionCode ec = 0;
2714            m_touchEventTarget->dispatchEvent(doubleTapEv.get(), ec);
2715            defaultPrevented |= doubleTapEv->defaultPrevented();
2716        } else {
2717#endif
2718            eventName = &eventNames().touchstartEvent;
2719            RefPtr<TouchEvent> startEv =
2720                TouchEvent::create(touches.get(), targetTouches.get(), pressedTouches.get(),
2721                                                       *eventName, m_touchEventTarget->document()->defaultView(),
2722                                                       m_firstTouchScreenPos.x(), m_firstTouchScreenPos.y(),
2723                                                       m_firstTouchPagePos.x(), m_firstTouchPagePos.y(),
2724                                                       event.ctrlKey(), event.altKey(), event.shiftKey(),
2725                                                       event.metaKey());
2726            ExceptionCode ec = 0;
2727            m_touchEventTarget->dispatchEvent(startEv.get(), ec);
2728            defaultPrevented |= startEv->defaultPrevented();
2729#if PLATFORM(ANDROID)
2730            longPressPrevented |= startEv->longPressPrevented();
2731            doubleTapPrevented |= startEv->doubleTapPrevented();
2732        }
2733#endif
2734    }
2735
2736    if (movedTouches->length() > 0) {
2737        eventName = &eventNames().touchmoveEvent;
2738        RefPtr<TouchEvent> moveEv =
2739            TouchEvent::create(touches.get(), targetTouches.get(), movedTouches.get(),
2740                                                   *eventName, m_touchEventTarget->document()->defaultView(),
2741                                                   m_firstTouchScreenPos.x(), m_firstTouchScreenPos.y(),
2742                                                   m_firstTouchPagePos.x(), m_firstTouchPagePos.y(),
2743                                                   event.ctrlKey(), event.altKey(), event.shiftKey(),
2744                                                   event.metaKey());
2745        ExceptionCode ec = 0;
2746        m_touchEventTarget->dispatchEvent(moveEv.get(), ec);
2747        defaultPrevented |= moveEv->defaultPrevented();
2748    }
2749
2750    if (event.type() == TouchEnd || event.type() == TouchCancel)
2751        m_touchEventTarget = 0;
2752
2753#if PLATFORM(ANDROID)
2754    // TODO (benm): We should be able to remove this prior to upstreaming  once Java side refactorings to make
2755    // preventDefault work better are complete.
2756    if (event.type() == TouchLongPress || event.type() == TouchDoubleTap)
2757        return 0;
2758
2759    return (defaultPrevented ? preventTouch : 0)
2760            | (longPressPrevented ? preventLongPress : 0)
2761            | (doubleTapPrevented ? preventDoubleTap : 0);
2762#else
2763    return defaultPrevented;
2764#endif
2765}
2766#endif
2767
2768}
2769