1/*
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2013 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies)
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "config.h"
29#include "EventHandler.h"
30
31#include "AXObjectCache.h"
32#include "AutoscrollController.h"
33#include "CachedImage.h"
34#include "Chrome.h"
35#include "ChromeClient.h"
36#include "Cursor.h"
37#include "CursorList.h"
38#include "Document.h"
39#include "DocumentEventQueue.h"
40#include "DragController.h"
41#include "DragState.h"
42#include "Editor.h"
43#include "EditorClient.h"
44#include "EventNames.h"
45#include "EventPathWalker.h"
46#include "ExceptionCodePlaceholder.h"
47#include "FloatPoint.h"
48#include "FloatRect.h"
49#include "FocusController.h"
50#include "Frame.h"
51#include "FrameLoader.h"
52#include "FrameSelection.h"
53#include "FrameTree.h"
54#include "FrameView.h"
55#include "htmlediting.h"
56#include "HTMLFrameElementBase.h"
57#include "HTMLFrameSetElement.h"
58#include "HTMLInputElement.h"
59#include "HTMLNames.h"
60#include "HitTestRequest.h"
61#include "HitTestResult.h"
62#include "Image.h"
63#include "InspectorInstrumentation.h"
64#include "KeyboardEvent.h"
65#include "MouseEvent.h"
66#include "MouseEventWithHitTestResults.h"
67#include "Page.h"
68#include "PlatformEvent.h"
69#include "PlatformKeyboardEvent.h"
70#include "PlatformWheelEvent.h"
71#include "PluginDocument.h"
72#include "RenderFrameSet.h"
73#include "RenderLayer.h"
74#include "RenderTextControlSingleLine.h"
75#include "RenderView.h"
76#include "RenderWidget.h"
77#include "RuntimeApplicationChecks.h"
78#include "ScrollAnimator.h"
79#include "Scrollbar.h"
80#include "Settings.h"
81#include "ShadowRoot.h"
82#include "SpatialNavigation.h"
83#include "StyleCachedImage.h"
84#include "TextEvent.h"
85#include "TextIterator.h"
86#include "UserTypingGestureIndicator.h"
87#include "WheelEvent.h"
88#include "WindowsKeyboardCodes.h"
89#include <wtf/Assertions.h>
90#include <wtf/CurrentTime.h>
91#include <wtf/StdLibExtras.h>
92#include <wtf/TemporaryChange.h>
93
94#if ENABLE(GESTURE_EVENTS)
95#include "PlatformGestureEvent.h"
96#endif
97
98#if ENABLE(TOUCH_ADJUSTMENT)
99#include "TouchAdjustment.h"
100#endif
101
102#if ENABLE(SVG)
103#include "SVGDocument.h"
104#include "SVGElementInstance.h"
105#include "SVGNames.h"
106#include "SVGUseElement.h"
107#endif
108
109#if ENABLE(TOUCH_EVENTS)
110#include "PlatformTouchEvent.h"
111#include "TouchEvent.h"
112#include "TouchList.h"
113#endif
114
115#if ENABLE(CSS_IMAGE_SET)
116#include "StyleCachedImageSet.h"
117#endif
118
119namespace WebCore {
120
121using namespace HTMLNames;
122
123#if ENABLE(DRAG_SUPPORT)
124// The link drag hysteresis is much larger than the others because there
125// needs to be enough space to cancel the link press without starting a link drag,
126// and because dragging links is rare.
127const int LinkDragHysteresis = 40;
128const int ImageDragHysteresis = 5;
129const int TextDragHysteresis = 3;
130const int GeneralDragHysteresis = 3;
131#endif // ENABLE(DRAG_SUPPORT)
132
133// Match key code of composition keydown event on windows.
134// IE sends VK_PROCESSKEY which has value 229;
135const int CompositionEventKeyCode = 229;
136
137#if ENABLE(SVG)
138using namespace SVGNames;
139#endif
140
141// The amount of time to wait before sending a fake mouse event, triggered
142// during a scroll. The short interval is used if the content responds to the mouse events
143// in fakeMouseMoveDurationThreshold or less, otherwise the long interval is used.
144const double fakeMouseMoveDurationThreshold = 0.01;
145const double fakeMouseMoveShortInterval = 0.1;
146const double fakeMouseMoveLongInterval = 0.25;
147
148// The amount of time to wait for a cursor update on style and layout changes
149// Set to 50Hz, no need to be faster than common screen refresh rate
150const double cursorUpdateInterval = 0.02;
151
152const int maximumCursorSize = 128;
153#if ENABLE(MOUSE_CURSOR_SCALE)
154// It's pretty unlikely that a scale of less than one would ever be used. But all we really
155// need to ensure here is that the scale isn't so small that integer overflow can occur when
156// dividing cursor sizes (limited above) by the scale.
157const double minimumCursorScale = 0.001;
158#endif
159
160enum NoCursorChangeType { NoCursorChange };
161
162class OptionalCursor {
163public:
164    OptionalCursor(NoCursorChangeType) : m_isCursorChange(false) { }
165    OptionalCursor(const Cursor& cursor) : m_isCursorChange(true), m_cursor(cursor) { }
166
167    bool isCursorChange() const { return m_isCursorChange; }
168    const Cursor& cursor() const { ASSERT(m_isCursorChange); return m_cursor; }
169
170private:
171    bool m_isCursorChange;
172    Cursor m_cursor;
173};
174
175class MaximumDurationTracker {
176public:
177    explicit MaximumDurationTracker(double *maxDuration)
178        : m_maxDuration(maxDuration)
179        , m_start(monotonicallyIncreasingTime())
180    {
181    }
182
183    ~MaximumDurationTracker()
184    {
185        *m_maxDuration = max(*m_maxDuration, monotonicallyIncreasingTime() - m_start);
186    }
187
188private:
189    double* m_maxDuration;
190    double m_start;
191};
192
193#if ENABLE(TOUCH_EVENTS)
194class SyntheticTouchPoint : public PlatformTouchPoint {
195public:
196
197    // The default values are based on http://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html
198    explicit SyntheticTouchPoint(const PlatformMouseEvent& event)
199    {
200        const static int idDefaultValue = 0;
201        const static int radiusYDefaultValue = 1;
202        const static int radiusXDefaultValue = 1;
203        const static float rotationAngleDefaultValue = 0.0f;
204        const static float forceDefaultValue = 1.0f;
205
206        m_id = idDefaultValue; // There is only one active TouchPoint.
207        m_screenPos = event.globalPosition();
208        m_pos = event.position();
209        m_radiusY = radiusYDefaultValue;
210        m_radiusX = radiusXDefaultValue;
211        m_rotationAngle = rotationAngleDefaultValue;
212        m_force = forceDefaultValue;
213
214        PlatformEvent::Type type = event.type();
215        ASSERT(type == PlatformEvent::MouseMoved || type == PlatformEvent::MousePressed || type == PlatformEvent::MouseReleased);
216
217        switch (type) {
218        case PlatformEvent::MouseMoved:
219            m_state = TouchMoved;
220            break;
221        case PlatformEvent::MousePressed:
222            m_state = TouchPressed;
223            break;
224        case PlatformEvent::MouseReleased:
225            m_state = TouchReleased;
226            break;
227        default:
228            ASSERT_NOT_REACHED();
229            break;
230        }
231    }
232};
233
234class SyntheticSingleTouchEvent : public PlatformTouchEvent {
235public:
236    explicit SyntheticSingleTouchEvent(const PlatformMouseEvent& event)
237    {
238        switch (event.type()) {
239        case PlatformEvent::MouseMoved:
240            m_type = TouchMove;
241            break;
242        case PlatformEvent::MousePressed:
243            m_type = TouchStart;
244            break;
245        case PlatformEvent::MouseReleased:
246            m_type = TouchEnd;
247            break;
248        default:
249            ASSERT_NOT_REACHED();
250            m_type = NoType;
251            break;
252        }
253        m_timestamp = event.timestamp();
254        m_modifiers = event.modifiers();
255        m_touchPoints.append(SyntheticTouchPoint(event));
256    }
257};
258#endif
259
260static inline ScrollGranularity wheelGranularityToScrollGranularity(unsigned deltaMode)
261{
262    switch (deltaMode) {
263    case WheelEvent::DOM_DELTA_PAGE:
264        return ScrollByPage;
265    case WheelEvent::DOM_DELTA_LINE:
266        return ScrollByLine;
267    case WheelEvent::DOM_DELTA_PIXEL:
268        return ScrollByPixel;
269    default:
270        return ScrollByPixel;
271    }
272}
273
274static inline bool scrollNode(float delta, ScrollGranularity granularity, ScrollDirection positiveDirection, ScrollDirection negativeDirection, Node* node, Node** stopNode)
275{
276    if (!delta)
277        return false;
278    if (!node->renderer())
279        return false;
280    RenderBox* enclosingBox = node->renderer()->enclosingBox();
281    float absDelta = delta > 0 ? delta : -delta;
282    return enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, granularity, absDelta, stopNode);
283}
284
285static inline bool shouldGesturesTriggerActive()
286{
287    // If the platform we're on supports GestureTapDown and GestureTapCancel then we'll
288    // rely on them to set the active state. Unfortunately there's no generic way to
289    // know in advance what event types are supported.
290    return false;
291}
292
293#if !PLATFORM(MAC)
294
295inline bool EventHandler::eventLoopHandleMouseUp(const MouseEventWithHitTestResults&)
296{
297    return false;
298}
299
300#if ENABLE(DRAG_SUPPORT)
301inline bool EventHandler::eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&)
302{
303    return false;
304}
305#endif
306
307#endif
308
309EventHandler::EventHandler(Frame* frame)
310    : m_frame(frame)
311    , m_mousePressed(false)
312    , m_capturesDragging(false)
313    , m_mouseDownMayStartSelect(false)
314#if ENABLE(DRAG_SUPPORT)
315    , m_mouseDownMayStartDrag(false)
316    , m_dragMayStartSelectionInstead(false)
317#endif
318    , m_mouseDownWasSingleClickInSelection(false)
319    , m_selectionInitiationState(HaveNotStartedSelection)
320    , m_hoverTimer(this, &EventHandler::hoverTimerFired)
321    , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired)
322    , m_autoscrollController(adoptPtr(new AutoscrollController))
323    , m_mouseDownMayStartAutoscroll(false)
324    , m_mouseDownWasInSubframe(false)
325    , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFired)
326#if ENABLE(SVG)
327    , m_svgPan(false)
328#endif
329    , m_resizeLayer(0)
330    , m_eventHandlerWillResetCapturingMouseEventsNode(0)
331    , m_clickCount(0)
332    , m_mousePositionIsUnknown(true)
333    , m_mouseDownTimestamp(0)
334    , m_inTrackingScrollGesturePhase(false)
335    , m_widgetIsLatched(false)
336#if PLATFORM(MAC)
337    , m_mouseDownView(nil)
338    , m_sendingEventToSubview(false)
339    , m_activationEventNumber(-1)
340#endif
341#if ENABLE(TOUCH_EVENTS)
342    , m_originatingTouchPointTargetKey(0)
343    , m_touchPressed(false)
344#endif
345#if ENABLE(GESTURE_EVENTS)
346    , m_scrollGestureHandlingNode(0)
347    , m_lastHitTestResultOverWidget(false)
348#endif
349    , m_maxMouseMovedDuration(0)
350    , m_baseEventType(PlatformEvent::NoType)
351    , m_didStartDrag(false)
352    , m_didLongPressInvokeContextMenu(false)
353    , m_isHandlingWheelEvent(false)
354#if ENABLE(CURSOR_VISIBILITY)
355    , m_autoHideCursorTimer(this, &EventHandler::autoHideCursorTimerFired)
356#endif
357{
358}
359
360EventHandler::~EventHandler()
361{
362    ASSERT(!m_fakeMouseMoveEventTimer.isActive());
363#if ENABLE(CURSOR_VISIBILITY)
364    ASSERT(!m_autoHideCursorTimer.isActive());
365#endif
366}
367
368#if ENABLE(DRAG_SUPPORT)
369DragState& EventHandler::dragState()
370{
371    DEFINE_STATIC_LOCAL(DragState, state, ());
372    return state;
373}
374#endif // ENABLE(DRAG_SUPPORT)
375
376void EventHandler::clear()
377{
378    m_hoverTimer.stop();
379    m_cursorUpdateTimer.stop();
380    m_fakeMouseMoveEventTimer.stop();
381#if ENABLE(CURSOR_VISIBILITY)
382    cancelAutoHideCursorTimer();
383#endif
384    m_resizeLayer = 0;
385    m_nodeUnderMouse = 0;
386    m_lastNodeUnderMouse = 0;
387#if ENABLE(SVG)
388    m_instanceUnderMouse = 0;
389    m_lastInstanceUnderMouse = 0;
390#endif
391    m_lastMouseMoveEventSubframe = 0;
392    m_lastScrollbarUnderMouse = 0;
393    m_clickCount = 0;
394    m_clickNode = 0;
395    m_frameSetBeingResized = 0;
396#if ENABLE(DRAG_SUPPORT)
397    m_dragTarget = 0;
398    m_shouldOnlyFireDragOverEvent = false;
399#endif
400    m_mousePositionIsUnknown = true;
401    m_lastKnownMousePosition = IntPoint();
402    m_lastKnownMouseGlobalPosition = IntPoint();
403    m_lastMouseDownUserGestureToken.clear();
404    m_mousePressNode = 0;
405    m_mousePressed = false;
406    m_capturesDragging = false;
407    m_capturingMouseEventsNode = 0;
408    m_latchedWheelEventNode = 0;
409    m_previousWheelScrolledNode = 0;
410#if ENABLE(TOUCH_EVENTS)
411    m_originatingTouchPointTargets.clear();
412    m_originatingTouchPointDocument.clear();
413    m_originatingTouchPointTargetKey = 0;
414#endif
415#if ENABLE(GESTURE_EVENTS)
416    m_scrollGestureHandlingNode = 0;
417    m_lastHitTestResultOverWidget = false;
418    m_previousGestureScrolledNode = 0;
419    m_scrollbarHandlingScrollGesture = 0;
420#endif
421    m_maxMouseMovedDuration = 0;
422    m_baseEventType = PlatformEvent::NoType;
423    m_didStartDrag = false;
424    m_didLongPressInvokeContextMenu = false;
425}
426
427void EventHandler::nodeWillBeRemoved(Node* nodeToBeRemoved)
428{
429    if (nodeToBeRemoved->contains(m_clickNode.get()))
430        m_clickNode = 0;
431}
432
433static void setSelectionIfNeeded(FrameSelection* selection, const VisibleSelection& newSelection)
434{
435    ASSERT(selection);
436    if (selection->selection() != newSelection && selection->shouldChangeSelection(newSelection))
437        selection->setSelection(newSelection);
438}
439
440static inline bool dispatchSelectStart(Node* node)
441{
442    if (!node || !node->renderer())
443        return true;
444
445    return node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true));
446}
447
448static VisibleSelection expandSelectionToRespectUserSelectAll(Node* targetNode, const VisibleSelection& selection)
449{
450#if ENABLE(USERSELECT_ALL)
451    Node* rootUserSelectAll = Position::rootUserSelectAllForNode(targetNode);
452    if (!rootUserSelectAll)
453        return selection;
454
455    VisibleSelection newSelection(selection);
456    newSelection.setBase(positionBeforeNode(rootUserSelectAll).upstream(CanCrossEditingBoundary));
457    newSelection.setExtent(positionAfterNode(rootUserSelectAll).downstream(CanCrossEditingBoundary));
458
459    return newSelection;
460#else
461    UNUSED_PARAM(targetNode);
462    return selection;
463#endif
464}
465
466bool EventHandler::updateSelectionForMouseDownDispatchingSelectStart(Node* targetNode, const VisibleSelection& selection, TextGranularity granularity)
467{
468    if (Position::nodeIsUserSelectNone(targetNode))
469        return false;
470
471    if (!dispatchSelectStart(targetNode))
472        return false;
473
474    if (selection.isRange())
475        m_selectionInitiationState = ExtendedSelection;
476    else {
477        granularity = CharacterGranularity;
478        m_selectionInitiationState = PlacedCaret;
479    }
480
481    m_frame->selection()->setNonDirectionalSelectionIfNeeded(selection, granularity);
482
483    return true;
484}
485
486void EventHandler::selectClosestWordFromHitTestResult(const HitTestResult& result, AppendTrailingWhitespace appendTrailingWhitespace)
487{
488    Node* innerNode = result.targetNode();
489    VisibleSelection newSelection;
490
491    if (innerNode && innerNode->renderer()) {
492        VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
493        if (pos.isNotNull()) {
494            newSelection = VisibleSelection(pos);
495            newSelection.expandUsingGranularity(WordGranularity);
496        }
497
498        if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSelection.isRange())
499            newSelection.appendTrailingWhitespace();
500
501        updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), WordGranularity);
502    }
503}
504
505void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result)
506{
507    if (m_mouseDownMayStartSelect) {
508        selectClosestWordFromHitTestResult(result.hitTestResult(),
509            (result.event().clickCount() == 2 && m_frame->editor().isSelectTrailingWhitespaceEnabled()) ? ShouldAppendTrailingWhitespace : DontAppendTrailingWhitespace);
510    }
511}
512
513void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults& result)
514{
515    if (!result.hitTestResult().isLiveLink())
516        return selectClosestWordFromMouseEvent(result);
517
518    Node* innerNode = result.targetNode();
519
520    if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
521        VisibleSelection newSelection;
522        Element* URLElement = result.hitTestResult().URLElement();
523        VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
524        if (pos.isNotNull() && pos.deepEquivalent().deprecatedNode()->isDescendantOf(URLElement))
525            newSelection = VisibleSelection::selectionFromContentsOfNode(URLElement);
526
527        updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), WordGranularity);
528    }
529}
530
531bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event)
532{
533    if (event.event().button() != LeftButton)
534        return false;
535
536    if (m_frame->selection()->isRange())
537        // A double-click when range is already selected
538        // should not change the selection.  So, do not call
539        // selectClosestWordFromMouseEvent, but do set
540        // m_beganSelectingText to prevent handleMouseReleaseEvent
541        // from setting caret selection.
542        m_selectionInitiationState = ExtendedSelection;
543    else
544        selectClosestWordFromMouseEvent(event);
545
546    return true;
547}
548
549bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event)
550{
551    if (event.event().button() != LeftButton)
552        return false;
553
554    Node* innerNode = event.targetNode();
555    if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
556        return false;
557
558    VisibleSelection newSelection;
559    VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint()));
560    if (pos.isNotNull()) {
561        newSelection = VisibleSelection(pos);
562        newSelection.expandUsingGranularity(ParagraphGranularity);
563    }
564
565    return updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), ParagraphGranularity);
566}
567
568static int textDistance(const Position& start, const Position& end)
569{
570     RefPtr<Range> range = Range::create(start.anchorNode()->document(), start, end);
571     return TextIterator::rangeLength(range.get(), true);
572}
573
574bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
575{
576    m_frame->document()->updateLayoutIgnorePendingStylesheets();
577    Node* innerNode = event.targetNode();
578    if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
579        return false;
580
581    // Extend the selection if the Shift key is down, unless the click is in a link.
582    bool extendSelection = event.event().shiftKey() && !event.isOverLink();
583
584    // Don't restart the selection when the mouse is pressed on an
585    // existing selection so we can allow for text dragging.
586    if (FrameView* view = m_frame->view()) {
587        LayoutPoint vPoint = view->windowToContents(event.event().position());
588        if (!extendSelection && m_frame->selection()->contains(vPoint)) {
589            m_mouseDownWasSingleClickInSelection = true;
590            return false;
591        }
592    }
593
594    VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(event.localPoint()));
595    if (visiblePos.isNull())
596        visiblePos = VisiblePosition(firstPositionInOrBeforeNode(innerNode), DOWNSTREAM);
597    Position pos = visiblePos.deepEquivalent();
598
599    VisibleSelection newSelection = m_frame->selection()->selection();
600    TextGranularity granularity = CharacterGranularity;
601
602    if (extendSelection && newSelection.isCaretOrRange()) {
603        VisibleSelection selectionInUserSelectAll = expandSelectionToRespectUserSelectAll(innerNode, VisibleSelection(pos));
604        if (selectionInUserSelectAll.isRange()) {
605            if (comparePositions(selectionInUserSelectAll.start(), newSelection.start()) < 0)
606                pos = selectionInUserSelectAll.start();
607            else if (comparePositions(newSelection.end(), selectionInUserSelectAll.end()) < 0)
608                pos = selectionInUserSelectAll.end();
609        }
610
611        if (!m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() && pos.isNotNull()) {
612            // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection
613            // was created right-to-left
614            Position start = newSelection.start();
615            Position end = newSelection.end();
616            int distanceToStart = textDistance(start, pos);
617            int distanceToEnd = textDistance(pos, end);
618            if (distanceToStart <= distanceToEnd)
619                newSelection = VisibleSelection(end, pos);
620            else
621                newSelection = VisibleSelection(start, pos);
622        } else
623            newSelection.setExtent(pos);
624
625        if (m_frame->selection()->granularity() != CharacterGranularity) {
626            granularity = m_frame->selection()->granularity();
627            newSelection.expandUsingGranularity(m_frame->selection()->granularity());
628        }
629    } else
630        newSelection = expandSelectionToRespectUserSelectAll(innerNode, visiblePos);
631
632    bool handled = updateSelectionForMouseDownDispatchingSelectStart(innerNode, newSelection, granularity);
633
634    if (event.event().button() == MiddleButton) {
635        // Ignore handled, since we want to paste to where the caret was placed anyway.
636        handled = handlePasteGlobalSelection(event.event()) || handled;
637    }
638    return handled;
639}
640
641static inline bool canMouseDownStartSelect(Node* node)
642{
643    if (!node || !node->renderer())
644        return true;
645
646    return node->canStartSelection() || Position::nodeIsUserSelectAll(node);
647}
648
649bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event)
650{
651#if ENABLE(DRAG_SUPPORT)
652    // Reset drag state.
653    dragState().source = 0;
654#endif
655
656    cancelFakeMouseMoveEvent();
657
658    m_frame->document()->updateLayoutIgnorePendingStylesheets();
659
660    if (ScrollView* scrollView = m_frame->view()) {
661        if (scrollView->isPointInScrollbarCorner(event.event().position()))
662            return false;
663    }
664
665    bool singleClick = event.event().clickCount() <= 1;
666
667    // If we got the event back, that must mean it wasn't prevented,
668    // so it's allowed to start a drag or selection if it wasn't in a scrollbar.
669    m_mouseDownMayStartSelect = canMouseDownStartSelect(event.targetNode()) && !event.scrollbar();
670
671#if ENABLE(DRAG_SUPPORT)
672    // Careful that the drag starting logic stays in sync with eventMayStartDrag()
673    m_mouseDownMayStartDrag = singleClick;
674#endif
675
676    m_mouseDownWasSingleClickInSelection = false;
677
678    m_mouseDown = event.event();
679
680    if (event.isOverWidget() && passWidgetMouseDownEventToWidget(event))
681        return true;
682
683#if ENABLE(SVG)
684    if (m_frame->document()->isSVGDocument()
685        && toSVGDocument(m_frame->document())->zoomAndPanEnabled()) {
686        if (event.event().shiftKey() && singleClick) {
687            m_svgPan = true;
688            toSVGDocument(m_frame->document())->startPan(m_frame->view()->windowToContents(event.event().position()));
689            return true;
690        }
691    }
692#endif
693
694    // We don't do this at the start of mouse down handling,
695    // because we don't want to do it until we know we didn't hit a widget.
696    if (singleClick)
697        focusDocumentView();
698
699    Node* innerNode = event.targetNode();
700
701    m_mousePressNode = innerNode;
702#if ENABLE(DRAG_SUPPORT)
703    m_dragStartPos = event.event().position();
704#endif
705
706    bool swallowEvent = false;
707    m_mousePressed = true;
708    m_selectionInitiationState = HaveNotStartedSelection;
709
710    if (event.event().clickCount() == 2)
711        swallowEvent = handleMousePressEventDoubleClick(event);
712    else if (event.event().clickCount() >= 3)
713        swallowEvent = handleMousePressEventTripleClick(event);
714    else
715        swallowEvent = handleMousePressEventSingleClick(event);
716
717    m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect
718        || (m_mousePressNode && m_mousePressNode->renderBox() && m_mousePressNode->renderBox()->canBeProgramaticallyScrolled());
719
720    return swallowEvent;
721}
722
723#if ENABLE(DRAG_SUPPORT)
724bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event)
725{
726    if (!m_mousePressed)
727        return false;
728
729    if (handleDrag(event, ShouldCheckDragHysteresis))
730        return true;
731
732    Node* targetNode = event.targetNode();
733    if (event.event().button() != LeftButton || !targetNode)
734        return false;
735
736    RenderObject* renderer = targetNode->renderer();
737    if (!renderer) {
738        Node* parent = EventPathWalker::parent(targetNode);
739        if (!parent)
740            return false;
741
742        renderer = parent->renderer();
743        if (!renderer || !renderer->isListBox())
744            return false;
745    }
746
747#if PLATFORM(MAC) // FIXME: Why does this assertion fire on other platforms?
748    ASSERT(m_mouseDownMayStartSelect || m_mouseDownMayStartAutoscroll);
749#endif
750
751    m_mouseDownMayStartDrag = false;
752
753    if (m_mouseDownMayStartAutoscroll && !panScrollInProgress()) {
754        m_autoscrollController->startAutoscrollForSelection(renderer);
755        m_mouseDownMayStartAutoscroll = false;
756    }
757
758    if (m_selectionInitiationState != ExtendedSelection) {
759        HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
760        HitTestResult result(m_mouseDownPos);
761        m_frame->document()->renderView()->hitTest(request, result);
762
763        updateSelectionForMouseDrag(result);
764    }
765    updateSelectionForMouseDrag(event.hitTestResult());
766    return true;
767}
768
769bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const
770{
771    // This is a pre-flight check of whether the event might lead to a drag being started.  Be careful
772    // that its logic needs to stay in sync with handleMouseMoveEvent() and the way we setMouseDownMayStartDrag
773    // in handleMousePressEvent
774
775    if (!m_frame->contentRenderer() || !m_frame->contentRenderer()->hasLayer())
776        return false;
777
778    if (event.button() != LeftButton || event.clickCount() != 1)
779        return false;
780
781    FrameView* view = m_frame->view();
782    if (!view)
783        return false;
784
785    Page* page = m_frame->page();
786    if (!page)
787        return false;
788
789    updateDragSourceActionsAllowed();
790    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent);
791    HitTestResult result(view->windowToContents(event.position()));
792    m_frame->contentRenderer()->hitTest(request, result);
793    DragState state;
794    return result.innerElement() && page->dragController()->draggableElement(m_frame, result.innerElement(), result.roundedPointInInnerNodeFrame(), state);
795}
796
797void EventHandler::updateSelectionForMouseDrag()
798{
799    FrameView* view = m_frame->view();
800    if (!view)
801        return;
802    RenderView* renderer = m_frame->contentRenderer();
803    if (!renderer)
804        return;
805
806    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::Move | HitTestRequest::DisallowShadowContent);
807    HitTestResult result(view->windowToContents(m_lastKnownMousePosition));
808    renderer->hitTest(request, result);
809    updateSelectionForMouseDrag(result);
810}
811
812static VisiblePosition selectionExtentRespectingEditingBoundary(const VisibleSelection& selection, const LayoutPoint& localPoint, Node* targetNode)
813{
814    LayoutPoint selectionEndPoint = localPoint;
815    Element* editableElement = selection.rootEditableElement();
816
817    if (!targetNode->renderer())
818        return VisiblePosition();
819
820    if (editableElement && !editableElement->contains(targetNode)) {
821        if (!editableElement->renderer())
822            return VisiblePosition();
823
824        FloatPoint absolutePoint = targetNode->renderer()->localToAbsolute(FloatPoint(selectionEndPoint));
825        selectionEndPoint = roundedLayoutPoint(editableElement->renderer()->absoluteToLocal(absolutePoint));
826        targetNode = editableElement;
827    }
828
829    return targetNode->renderer()->positionForPoint(selectionEndPoint);
830}
831
832void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResult)
833{
834    if (!m_mouseDownMayStartSelect)
835        return;
836
837    Node* target = hitTestResult.targetNode();
838    if (!target)
839        return;
840
841    VisiblePosition targetPosition = selectionExtentRespectingEditingBoundary(m_frame->selection()->selection(), hitTestResult.localPoint(), target);
842
843    // Don't modify the selection if we're not on a node.
844    if (targetPosition.isNull())
845        return;
846
847    // Restart the selection if this is the first mouse move. This work is usually
848    // done in handleMousePressEvent, but not if the mouse press was on an existing selection.
849    VisibleSelection newSelection = m_frame->selection()->selection();
850
851#if ENABLE(SVG)
852    // Special case to limit selection to the containing block for SVG text.
853    // FIXME: Isn't there a better non-SVG-specific way to do this?
854    if (Node* selectionBaseNode = newSelection.base().deprecatedNode())
855        if (RenderObject* selectionBaseRenderer = selectionBaseNode->renderer())
856            if (selectionBaseRenderer->isSVGText())
857                if (target->renderer()->containingBlock() != selectionBaseRenderer->containingBlock())
858                    return;
859#endif
860
861    if (m_selectionInitiationState == HaveNotStartedSelection && !dispatchSelectStart(target))
862        return;
863
864    if (m_selectionInitiationState != ExtendedSelection) {
865        // Always extend selection here because it's caused by a mouse drag
866        m_selectionInitiationState = ExtendedSelection;
867        newSelection = VisibleSelection(targetPosition);
868    }
869
870#if ENABLE(USERSELECT_ALL)
871    Node* rootUserSelectAllForMousePressNode = Position::rootUserSelectAllForNode(m_mousePressNode.get());
872    if (rootUserSelectAllForMousePressNode && rootUserSelectAllForMousePressNode == Position::rootUserSelectAllForNode(target)) {
873        newSelection.setBase(positionBeforeNode(rootUserSelectAllForMousePressNode).upstream(CanCrossEditingBoundary));
874        newSelection.setExtent(positionAfterNode(rootUserSelectAllForMousePressNode).downstream(CanCrossEditingBoundary));
875    } else {
876        // Reset base for user select all when base is inside user-select-all area and extent < base.
877        if (rootUserSelectAllForMousePressNode && comparePositions(target->renderer()->positionForPoint(hitTestResult.localPoint()), m_mousePressNode->renderer()->positionForPoint(m_dragStartPos)) < 0)
878            newSelection.setBase(positionAfterNode(rootUserSelectAllForMousePressNode).downstream(CanCrossEditingBoundary));
879
880        Node* rootUserSelectAllForTarget = Position::rootUserSelectAllForNode(target);
881        if (rootUserSelectAllForTarget && m_mousePressNode->renderer() && comparePositions(target->renderer()->positionForPoint(hitTestResult.localPoint()), m_mousePressNode->renderer()->positionForPoint(m_dragStartPos)) < 0)
882            newSelection.setExtent(positionBeforeNode(rootUserSelectAllForTarget).upstream(CanCrossEditingBoundary));
883        else if (rootUserSelectAllForTarget && m_mousePressNode->renderer())
884            newSelection.setExtent(positionAfterNode(rootUserSelectAllForTarget).downstream(CanCrossEditingBoundary));
885        else
886            newSelection.setExtent(targetPosition);
887    }
888#else
889    newSelection.setExtent(targetPosition);
890#endif
891
892    if (m_frame->selection()->granularity() != CharacterGranularity)
893        newSelection.expandUsingGranularity(m_frame->selection()->granularity());
894
895    m_frame->selection()->setNonDirectionalSelectionIfNeeded(newSelection, m_frame->selection()->granularity(),
896        FrameSelection::AdjustEndpointsAtBidiBoundary);
897}
898#endif // ENABLE(DRAG_SUPPORT)
899
900void EventHandler::lostMouseCapture()
901{
902    m_frame->selection()->setCaretBlinkingSuspended(false);
903}
904
905bool EventHandler::handleMouseUp(const MouseEventWithHitTestResults& event)
906{
907    if (eventLoopHandleMouseUp(event))
908        return true;
909
910    // If this was the first click in the window, we don't even want to clear the selection.
911    // This case occurs when the user clicks on a draggable element, since we have to process
912    // the mouse down and drag events to see if we might start a drag.  For other first clicks
913    // in a window, we just don't acceptFirstMouse, and the whole down-drag-up sequence gets
914    // ignored upstream of this layer.
915    return eventActivatedView(event.event());
916}
917
918bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
919{
920    if (autoscrollInProgress())
921        stopAutoscrollTimer();
922
923    if (handleMouseUp(event))
924        return true;
925
926    // Used to prevent mouseMoveEvent from initiating a drag before
927    // the mouse is pressed again.
928    m_mousePressed = false;
929    m_capturesDragging = false;
930#if ENABLE(DRAG_SUPPORT)
931    m_mouseDownMayStartDrag = false;
932#endif
933    m_mouseDownMayStartSelect = false;
934    m_mouseDownMayStartAutoscroll = false;
935    m_mouseDownWasInSubframe = false;
936
937    bool handled = false;
938
939    // Clear the selection if the mouse didn't move after the last mouse
940    // press and it's not a context menu click.  We do this so when clicking
941    // on the selection, the selection goes away.  However, if we are
942    // editing, place the caret.
943    if (m_mouseDownWasSingleClickInSelection && m_selectionInitiationState != ExtendedSelection
944#if ENABLE(DRAG_SUPPORT)
945            && m_dragStartPos == event.event().position()
946#endif
947            && m_frame->selection()->isRange()
948            && event.event().button() != RightButton) {
949        VisibleSelection newSelection;
950        Node* node = event.targetNode();
951        bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled();
952        if (node && (caretBrowsing || node->rendererIsEditable()) && node->renderer()) {
953            VisiblePosition pos = node->renderer()->positionForPoint(event.localPoint());
954            newSelection = VisibleSelection(pos);
955        }
956
957        setSelectionIfNeeded(m_frame->selection(), newSelection);
958
959        handled = true;
960    }
961
962    m_frame->selection()->notifyRendererOfSelectionChange(UserTriggered);
963
964    m_frame->selection()->selectFrameElementInParentIfFullySelected();
965
966    if (event.event().button() == MiddleButton) {
967        // Ignore handled, since we want to paste to where the caret was placed anyway.
968        handled = handlePasteGlobalSelection(event.event()) || handled;
969    }
970
971    return handled;
972}
973
974#if ENABLE(PAN_SCROLLING)
975
976void EventHandler::didPanScrollStart()
977{
978    m_autoscrollController->didPanScrollStart();
979}
980
981void EventHandler::didPanScrollStop()
982{
983    m_autoscrollController->didPanScrollStop();
984}
985
986void EventHandler::startPanScrolling(RenderObject* renderer)
987{
988    if (!renderer->isBox())
989        return;
990    m_autoscrollController->startPanScrolling(toRenderBox(renderer), lastKnownMousePosition());
991    invalidateClick();
992}
993
994#endif // ENABLE(PAN_SCROLLING)
995
996RenderObject* EventHandler::autoscrollRenderer() const
997{
998    return m_autoscrollController->autoscrollRenderer();
999}
1000
1001void EventHandler::updateAutoscrollRenderer()
1002{
1003    m_autoscrollController->updateAutoscrollRenderer();
1004}
1005
1006bool EventHandler::autoscrollInProgress() const
1007{
1008    return m_autoscrollController->autoscrollInProgress();
1009}
1010
1011bool EventHandler::panScrollInProgress() const
1012{
1013    return m_autoscrollController->panScrollInProgress();
1014}
1015
1016#if ENABLE(DRAG_SUPPORT)
1017DragSourceAction EventHandler::updateDragSourceActionsAllowed() const
1018{
1019    if (!m_frame)
1020        return DragSourceActionNone;
1021
1022    Page* page = m_frame->page();
1023    if (!page)
1024        return DragSourceActionNone;
1025
1026    FrameView* view = m_frame->view();
1027    if (!view)
1028        return DragSourceActionNone;
1029
1030    return page->dragController()->delegateDragSourceAction(view->contentsToRootView(m_mouseDownPos));
1031}
1032#endif // ENABLE(DRAG_SUPPORT)
1033
1034HitTestResult EventHandler::hitTestResultAtPoint(const LayoutPoint& point, HitTestRequest::HitTestRequestType hitType, const LayoutSize& padding)
1035{
1036    // We always send hitTestResultAtPoint to the main frame if we have one,
1037    // otherwise we might hit areas that are obscured by higher frames.
1038    if (Page* page = m_frame->page()) {
1039        Frame* mainFrame = page->mainFrame();
1040        if (m_frame != mainFrame) {
1041            FrameView* frameView = m_frame->view();
1042            FrameView* mainView = mainFrame->view();
1043            if (frameView && mainView) {
1044                IntPoint mainFramePoint = mainView->rootViewToContents(frameView->contentsToRootView(roundedIntPoint(point)));
1045                return mainFrame->eventHandler()->hitTestResultAtPoint(mainFramePoint, hitType, padding);
1046            }
1047        }
1048    }
1049
1050    HitTestResult result(point, padding.height(), padding.width(), padding.height(), padding.width());
1051
1052    if (!m_frame->contentRenderer())
1053        return result;
1054
1055    // hitTestResultAtPoint is specifically used to hitTest into all frames, thus it always allows child frame content.
1056    HitTestRequest request(hitType | HitTestRequest::AllowChildFrameContent);
1057    m_frame->contentRenderer()->hitTest(request, result);
1058    if (!request.readOnly())
1059        m_frame->document()->updateHoverActiveState(request, result.innerElement());
1060
1061    if (request.disallowsShadowContent())
1062        result.setToNonShadowAncestor();
1063
1064    return result;
1065}
1066
1067void EventHandler::stopAutoscrollTimer(bool rendererIsBeingDestroyed)
1068{
1069    m_autoscrollController->stopAutoscrollTimer(rendererIsBeingDestroyed);
1070}
1071
1072Node* EventHandler::mousePressNode() const
1073{
1074    return m_mousePressNode.get();
1075}
1076
1077void EventHandler::setMousePressNode(PassRefPtr<Node> node)
1078{
1079    m_mousePressNode = node;
1080}
1081
1082bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode)
1083{
1084    Node* node = startingNode;
1085
1086    if (!node)
1087        node = m_frame->document()->focusedElement();
1088
1089    if (!node)
1090        node = m_mousePressNode.get();
1091
1092    if (node) {
1093        RenderObject* r = node->renderer();
1094        if (r && !r->isListBox() && r->enclosingBox()->scroll(direction, granularity)) {
1095            setFrameWasScrolledByUser();
1096            return true;
1097        }
1098    }
1099
1100    return false;
1101}
1102
1103bool EventHandler::logicalScrollOverflow(ScrollLogicalDirection direction, ScrollGranularity granularity, Node* startingNode)
1104{
1105    Node* node = startingNode;
1106
1107    if (!node)
1108        node = m_frame->document()->focusedElement();
1109
1110    if (!node)
1111        node = m_mousePressNode.get();
1112
1113    if (node) {
1114        RenderObject* r = node->renderer();
1115        if (r && !r->isListBox() && r->enclosingBox()->logicalScroll(direction, granularity)) {
1116            setFrameWasScrolledByUser();
1117            return true;
1118        }
1119    }
1120
1121    return false;
1122}
1123
1124bool EventHandler::scrollRecursively(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode)
1125{
1126    // The layout needs to be up to date to determine if we can scroll. We may be
1127    // here because of an onLoad event, in which case the final layout hasn't been performed yet.
1128    m_frame->document()->updateLayoutIgnorePendingStylesheets();
1129    if (scrollOverflow(direction, granularity, startingNode))
1130        return true;
1131    Frame* frame = m_frame;
1132    FrameView* view = frame->view();
1133    if (view && view->scroll(direction, granularity))
1134        return true;
1135    frame = frame->tree()->parent();
1136    if (!frame)
1137        return false;
1138    return frame->eventHandler()->scrollRecursively(direction, granularity, m_frame->ownerElement());
1139}
1140
1141bool EventHandler::logicalScrollRecursively(ScrollLogicalDirection direction, ScrollGranularity granularity, Node* startingNode)
1142{
1143    // The layout needs to be up to date to determine if we can scroll. We may be
1144    // here because of an onLoad event, in which case the final layout hasn't been performed yet.
1145    m_frame->document()->updateLayoutIgnorePendingStylesheets();
1146    if (logicalScrollOverflow(direction, granularity, startingNode))
1147        return true;
1148    Frame* frame = m_frame;
1149    FrameView* view = frame->view();
1150
1151    bool scrolled = false;
1152#if PLATFORM(MAC)
1153    // Mac also resets the scroll position in the inline direction.
1154    if (granularity == ScrollByDocument && view && view->logicalScroll(ScrollInlineDirectionBackward, ScrollByDocument))
1155        scrolled = true;
1156#endif
1157    if (view && view->logicalScroll(direction, granularity))
1158        scrolled = true;
1159
1160    if (scrolled)
1161        return true;
1162
1163    frame = frame->tree()->parent();
1164    if (!frame)
1165        return false;
1166
1167    return frame->eventHandler()->logicalScrollRecursively(direction, granularity, m_frame->ownerElement());
1168}
1169
1170IntPoint EventHandler::lastKnownMousePosition() const
1171{
1172    return m_lastKnownMousePosition;
1173}
1174
1175Frame* EventHandler::subframeForHitTestResult(const MouseEventWithHitTestResults& hitTestResult)
1176{
1177    if (!hitTestResult.isOverWidget())
1178        return 0;
1179    return subframeForTargetNode(hitTestResult.targetNode());
1180}
1181
1182Frame* EventHandler::subframeForTargetNode(Node* node)
1183{
1184    if (!node)
1185        return 0;
1186
1187    RenderObject* renderer = node->renderer();
1188    if (!renderer || !renderer->isWidget())
1189        return 0;
1190
1191    Widget* widget = toRenderWidget(renderer)->widget();
1192    if (!widget || !widget->isFrameView())
1193        return 0;
1194
1195    return toFrameView(widget)->frame();
1196}
1197
1198static bool isSubmitImage(Node* node)
1199{
1200    return node && node->hasTagName(inputTag) && static_cast<HTMLInputElement*>(node)->isImageButton();
1201}
1202
1203// Returns true if the node's editable block is not current focused for editing
1204static bool nodeIsNotBeingEdited(Node* node, Frame* frame)
1205{
1206    return frame->selection()->rootEditableElement() != node->rootEditableElement();
1207}
1208
1209bool EventHandler::useHandCursor(Node* node, bool isOverLink, bool shiftKey)
1210{
1211    if (!node)
1212        return false;
1213
1214    bool editable = node->rendererIsEditable();
1215    bool editableLinkEnabled = false;
1216
1217    // If the link is editable, then we need to check the settings to see whether or not the link should be followed
1218    if (editable) {
1219        ASSERT(m_frame->settings());
1220        switch (m_frame->settings()->editableLinkBehavior()) {
1221        default:
1222        case EditableLinkDefaultBehavior:
1223        case EditableLinkAlwaysLive:
1224            editableLinkEnabled = true;
1225            break;
1226
1227        case EditableLinkNeverLive:
1228            editableLinkEnabled = false;
1229            break;
1230
1231        case EditableLinkLiveWhenNotFocused:
1232            editableLinkEnabled = nodeIsNotBeingEdited(node, m_frame) || shiftKey;
1233            break;
1234
1235        case EditableLinkOnlyLiveWithShiftKey:
1236            editableLinkEnabled = shiftKey;
1237            break;
1238        }
1239    }
1240
1241    return ((isOverLink || isSubmitImage(node)) && (!editable || editableLinkEnabled));
1242}
1243
1244void EventHandler::cursorUpdateTimerFired(Timer<EventHandler>*)
1245{
1246    ASSERT(m_frame);
1247    ASSERT(m_frame->document());
1248
1249    updateCursor();
1250}
1251
1252void EventHandler::updateCursor()
1253{
1254    if (m_mousePositionIsUnknown)
1255        return;
1256
1257    FrameView* view = m_frame->view();
1258    if (!view)
1259        return;
1260
1261    RenderView* renderView = view->renderView();
1262    if (!renderView)
1263        return;
1264
1265    if (!view->shouldSetCursor())
1266        return;
1267
1268    bool shiftKey;
1269    bool ctrlKey;
1270    bool altKey;
1271    bool metaKey;
1272    PlatformKeyboardEvent::getCurrentModifierState(shiftKey, ctrlKey, altKey, metaKey);
1273
1274    m_frame->document()->updateLayout();
1275
1276    HitTestRequest request(HitTestRequest::ReadOnly);
1277    HitTestResult result(view->windowToContents(m_lastKnownMousePosition));
1278    renderView->hitTest(request, result);
1279
1280    OptionalCursor optionalCursor = selectCursor(result, shiftKey);
1281    if (optionalCursor.isCursorChange()) {
1282        m_currentMouseCursor = optionalCursor.cursor();
1283        view->setCursor(m_currentMouseCursor);
1284    }
1285}
1286
1287OptionalCursor EventHandler::selectCursor(const HitTestResult& result, bool shiftKey)
1288{
1289    if (m_resizeLayer && m_resizeLayer->inResizeMode())
1290        return NoCursorChange;
1291
1292    Page* page = m_frame->page();
1293    if (!page)
1294        return NoCursorChange;
1295#if ENABLE(PAN_SCROLLING)
1296    if (page->mainFrame()->eventHandler()->panScrollInProgress())
1297        return NoCursorChange;
1298#endif
1299
1300    Node* node = result.targetNode();
1301    if (!node)
1302        return NoCursorChange;
1303
1304    RenderObject* renderer = node->renderer();
1305    RenderStyle* style = renderer ? renderer->style() : 0;
1306    bool horizontalText = !style || style->isHorizontalWritingMode();
1307    const Cursor& iBeam = horizontalText ? iBeamCursor() : verticalTextCursor();
1308
1309#if ENABLE(CURSOR_VISIBILITY)
1310    if (style && style->cursorVisibility() == CursorVisibilityAutoHide) {
1311        FeatureObserver::observe(m_frame->document(), FeatureObserver::CursorVisibility);
1312        startAutoHideCursorTimer();
1313    } else
1314        cancelAutoHideCursorTimer();
1315#endif
1316
1317    // During selection, use an I-beam no matter what we're over.
1318    // If a drag may be starting or we're capturing mouse events for a particular node, don't treat this as a selection.
1319    if (m_mousePressed && m_mouseDownMayStartSelect
1320#if ENABLE(DRAG_SUPPORT)
1321        && !m_mouseDownMayStartDrag
1322#endif
1323        && m_frame->selection()->isCaretOrRange() && !m_capturingMouseEventsNode)
1324        return iBeam;
1325
1326    if (renderer) {
1327        Cursor overrideCursor;
1328        switch (renderer->getCursor(roundedIntPoint(result.localPoint()), overrideCursor)) {
1329        case SetCursorBasedOnStyle:
1330            break;
1331        case SetCursor:
1332            return overrideCursor;
1333        case DoNotSetCursor:
1334            return NoCursorChange;
1335        }
1336    }
1337
1338    if (style && style->cursors()) {
1339        const CursorList* cursors = style->cursors();
1340        for (unsigned i = 0; i < cursors->size(); ++i) {
1341            StyleImage* styleImage = (*cursors)[i].image();
1342            if (!styleImage)
1343                continue;
1344            CachedImage* cachedImage = styleImage->cachedImage();
1345            if (!cachedImage)
1346                continue;
1347            float scale = styleImage->imageScaleFactor();
1348            // Get hotspot and convert from logical pixels to physical pixels.
1349            IntPoint hotSpot = (*cursors)[i].hotSpot();
1350            hotSpot.scale(scale, scale);
1351            IntSize size = cachedImage->imageForRenderer(renderer)->size();
1352            if (cachedImage->errorOccurred())
1353                continue;
1354            // Limit the size of cursors (in UI pixels) so that they cannot be
1355            // used to cover UI elements in chrome.
1356            size.scale(1 / scale);
1357            if (size.width() > maximumCursorSize || size.height() > maximumCursorSize)
1358                continue;
1359
1360            Image* image = cachedImage->imageForRenderer(renderer);
1361#if ENABLE(MOUSE_CURSOR_SCALE)
1362            // Ensure no overflow possible in calculations above.
1363            if (scale < minimumCursorScale)
1364                continue;
1365            return Cursor(image, hotSpot, scale);
1366#else
1367            ASSERT(scale == 1);
1368            return Cursor(image, hotSpot);
1369#endif // ENABLE(MOUSE_CURSOR_SCALE)
1370        }
1371    }
1372
1373    switch (style ? style->cursor() : CURSOR_AUTO) {
1374    case CURSOR_AUTO: {
1375        bool editable = node->rendererIsEditable();
1376
1377        if (useHandCursor(node, result.isOverLink(), shiftKey))
1378            return handCursor();
1379
1380        bool inResizer = false;
1381        if (renderer) {
1382            if (RenderLayer* layer = renderer->enclosingLayer()) {
1383                if (FrameView* view = m_frame->view())
1384                    inResizer = layer->isPointInResizeControl(view->windowToContents(roundedIntPoint(result.localPoint())));
1385            }
1386        }
1387        if ((editable || (renderer && renderer->isText() && node->canStartSelection())) && !inResizer && !result.scrollbar())
1388            return iBeam;
1389        return pointerCursor();
1390    }
1391    case CURSOR_CROSS:
1392        return crossCursor();
1393    case CURSOR_POINTER:
1394        return handCursor();
1395    case CURSOR_MOVE:
1396        return moveCursor();
1397    case CURSOR_ALL_SCROLL:
1398        return moveCursor();
1399    case CURSOR_E_RESIZE:
1400        return eastResizeCursor();
1401    case CURSOR_W_RESIZE:
1402        return westResizeCursor();
1403    case CURSOR_N_RESIZE:
1404        return northResizeCursor();
1405    case CURSOR_S_RESIZE:
1406        return southResizeCursor();
1407    case CURSOR_NE_RESIZE:
1408        return northEastResizeCursor();
1409    case CURSOR_SW_RESIZE:
1410        return southWestResizeCursor();
1411    case CURSOR_NW_RESIZE:
1412        return northWestResizeCursor();
1413    case CURSOR_SE_RESIZE:
1414        return southEastResizeCursor();
1415    case CURSOR_NS_RESIZE:
1416        return northSouthResizeCursor();
1417    case CURSOR_EW_RESIZE:
1418        return eastWestResizeCursor();
1419    case CURSOR_NESW_RESIZE:
1420        return northEastSouthWestResizeCursor();
1421    case CURSOR_NWSE_RESIZE:
1422        return northWestSouthEastResizeCursor();
1423    case CURSOR_COL_RESIZE:
1424        return columnResizeCursor();
1425    case CURSOR_ROW_RESIZE:
1426        return rowResizeCursor();
1427    case CURSOR_TEXT:
1428        return iBeamCursor();
1429    case CURSOR_WAIT:
1430        return waitCursor();
1431    case CURSOR_HELP:
1432        return helpCursor();
1433    case CURSOR_VERTICAL_TEXT:
1434        return verticalTextCursor();
1435    case CURSOR_CELL:
1436        return cellCursor();
1437    case CURSOR_CONTEXT_MENU:
1438        return contextMenuCursor();
1439    case CURSOR_PROGRESS:
1440        return progressCursor();
1441    case CURSOR_NO_DROP:
1442        return noDropCursor();
1443    case CURSOR_ALIAS:
1444        return aliasCursor();
1445    case CURSOR_COPY:
1446        return copyCursor();
1447    case CURSOR_NONE:
1448        return noneCursor();
1449    case CURSOR_NOT_ALLOWED:
1450        return notAllowedCursor();
1451    case CURSOR_DEFAULT:
1452        return pointerCursor();
1453    case CURSOR_WEBKIT_ZOOM_IN:
1454        return zoomInCursor();
1455    case CURSOR_WEBKIT_ZOOM_OUT:
1456        return zoomOutCursor();
1457    case CURSOR_WEBKIT_GRAB:
1458        return grabCursor();
1459    case CURSOR_WEBKIT_GRABBING:
1460        return grabbingCursor();
1461    }
1462    return pointerCursor();
1463}
1464
1465#if ENABLE(CURSOR_VISIBILITY)
1466void EventHandler::startAutoHideCursorTimer()
1467{
1468    Page* page = m_frame->page();
1469    if (!page)
1470        return;
1471
1472    m_autoHideCursorTimer.startOneShot(page->settings()->timeWithoutMouseMovementBeforeHidingControls());
1473
1474    // The fake mouse move event screws up the auto-hide feature (by resetting the auto-hide timer)
1475    // so cancel any pending fake mouse moves.
1476    if (m_fakeMouseMoveEventTimer.isActive())
1477        m_fakeMouseMoveEventTimer.stop();
1478}
1479
1480void EventHandler::cancelAutoHideCursorTimer()
1481{
1482    if (m_autoHideCursorTimer.isActive())
1483        m_autoHideCursorTimer.stop();
1484}
1485
1486void EventHandler::autoHideCursorTimerFired(Timer<EventHandler>* timer)
1487{
1488    ASSERT_UNUSED(timer, timer == &m_autoHideCursorTimer);
1489    m_currentMouseCursor = noneCursor();
1490    FrameView* view = m_frame->view();
1491    if (view && view->isActive())
1492        view->setCursor(m_currentMouseCursor);
1493}
1494#endif
1495
1496static LayoutPoint documentPointForWindowPoint(Frame* frame, const IntPoint& windowPoint)
1497{
1498    FrameView* view = frame->view();
1499    // FIXME: Is it really OK to use the wrong coordinates here when view is 0?
1500    // Historically the code would just crash; this is clearly no worse than that.
1501    return view ? view->windowToContents(windowPoint) : windowPoint;
1502}
1503
1504bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
1505{
1506    RefPtr<FrameView> protector(m_frame->view());
1507
1508    if (InspectorInstrumentation::handleMousePress(m_frame->page())) {
1509        invalidateClick();
1510        return true;
1511    }
1512
1513#if ENABLE(TOUCH_EVENTS)
1514    bool defaultPrevented = dispatchSyntheticTouchEventIfEnabled(mouseEvent);
1515    if (defaultPrevented)
1516        return true;
1517#endif
1518
1519    UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
1520    m_lastMouseDownUserGestureToken = gestureIndicator.currentToken();
1521
1522    // FIXME (bug 68185): this call should be made at another abstraction layer
1523    m_frame->loader()->resetMultipleFormSubmissionProtection();
1524
1525    cancelFakeMouseMoveEvent();
1526    m_mousePressed = true;
1527    m_capturesDragging = true;
1528    setLastKnownMousePosition(mouseEvent);
1529    m_mouseDownTimestamp = mouseEvent.timestamp();
1530#if ENABLE(DRAG_SUPPORT)
1531    m_mouseDownMayStartDrag = false;
1532#endif
1533    m_mouseDownMayStartSelect = false;
1534    m_mouseDownMayStartAutoscroll = false;
1535    if (FrameView* view = m_frame->view())
1536        m_mouseDownPos = view->windowToContents(mouseEvent.position());
1537    else {
1538        invalidateClick();
1539        return false;
1540    }
1541    m_mouseDownWasInSubframe = false;
1542
1543    HitTestRequest request(HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
1544    // Save the document point we generate in case the window coordinate is invalidated by what happens
1545    // when we dispatch the event.
1546    LayoutPoint documentPoint = documentPointForWindowPoint(m_frame, mouseEvent.position());
1547    MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent);
1548
1549    if (!mev.targetNode()) {
1550        invalidateClick();
1551        return false;
1552    }
1553
1554    m_mousePressNode = mev.targetNode();
1555
1556    RefPtr<Frame> subframe = subframeForHitTestResult(mev);
1557    if (subframe && passMousePressEventToSubframe(mev, subframe.get())) {
1558        // Start capturing future events for this frame.  We only do this if we didn't clear
1559        // the m_mousePressed flag, which may happen if an AppKit widget entered a modal event loop.
1560        m_capturesDragging = subframe->eventHandler()->capturesDragging();
1561        if (m_mousePressed && m_capturesDragging) {
1562            m_capturingMouseEventsNode = mev.targetNode();
1563            m_eventHandlerWillResetCapturingMouseEventsNode = true;
1564        }
1565        invalidateClick();
1566        return true;
1567    }
1568
1569#if ENABLE(PAN_SCROLLING)
1570    // We store whether pan scrolling is in progress before calling stopAutoscrollTimer()
1571    // because it will set m_autoscrollType to NoAutoscroll on return.
1572    bool isPanScrollInProgress = m_frame->page() && m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress();
1573    stopAutoscrollTimer();
1574    if (isPanScrollInProgress) {
1575        // We invalidate the click when exiting pan scrolling so that we don't inadvertently navigate
1576        // away from the current page (e.g. the click was on a hyperlink). See <rdar://problem/6095023>.
1577        invalidateClick();
1578        return true;
1579    }
1580#endif
1581
1582    m_clickCount = mouseEvent.clickCount();
1583    m_clickNode = mev.targetNode();
1584
1585    if (FrameView* view = m_frame->view()) {
1586        RenderLayer* layer = m_clickNode->renderer() ? m_clickNode->renderer()->enclosingLayer() : 0;
1587        IntPoint p = view->windowToContents(mouseEvent.position());
1588        if (layer && layer->isPointInResizeControl(p)) {
1589            layer->setInResizeMode(true);
1590            m_resizeLayer = layer;
1591            m_offsetFromResizeCorner = layer->offsetFromResizeCorner(p);
1592            invalidateClick();
1593            return true;
1594        }
1595    }
1596
1597    m_frame->selection()->setCaretBlinkingSuspended(true);
1598
1599    bool swallowEvent = !dispatchMouseEvent(eventNames().mousedownEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
1600    m_capturesDragging = !swallowEvent || mev.scrollbar();
1601
1602    // If the hit testing originally determined the event was in a scrollbar, refetch the MouseEventWithHitTestResults
1603    // in case the scrollbar widget was destroyed when the mouse event was handled.
1604    if (mev.scrollbar()) {
1605        const bool wasLastScrollBar = mev.scrollbar() == m_lastScrollbarUnderMouse.get();
1606        HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
1607        mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent);
1608        if (wasLastScrollBar && mev.scrollbar() != m_lastScrollbarUnderMouse.get())
1609            m_lastScrollbarUnderMouse = 0;
1610    }
1611
1612    if (swallowEvent) {
1613        // scrollbars should get events anyway, even disabled controls might be scrollable
1614        Scrollbar* scrollbar = mev.scrollbar();
1615
1616        updateLastScrollbarUnderMouse(scrollbar, true);
1617
1618        if (scrollbar)
1619            passMousePressEventToScrollbar(mev, scrollbar);
1620    } else {
1621        // Refetch the event target node if it currently is the shadow node inside an <input> element.
1622        // If a mouse event handler changes the input element type to one that has a widget associated,
1623        // we'd like to EventHandler::handleMousePressEvent to pass the event to the widget and thus the
1624        // event target node can't still be the shadow node.
1625        if (mev.targetNode()->isShadowRoot() && toShadowRoot(mev.targetNode())->host()->hasTagName(inputTag)) {
1626            HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
1627            mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent);
1628        }
1629
1630        FrameView* view = m_frame->view();
1631        Scrollbar* scrollbar = view ? view->scrollbarAtPoint(mouseEvent.position()) : 0;
1632        if (!scrollbar)
1633            scrollbar = mev.scrollbar();
1634
1635        updateLastScrollbarUnderMouse(scrollbar, true);
1636
1637        if (scrollbar && passMousePressEventToScrollbar(mev, scrollbar))
1638            swallowEvent = true;
1639        else
1640            swallowEvent = handleMousePressEvent(mev);
1641    }
1642
1643    return swallowEvent;
1644}
1645
1646// This method only exists for platforms that don't know how to deliver
1647bool EventHandler::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent)
1648{
1649    RefPtr<FrameView> protector(m_frame->view());
1650
1651    m_frame->selection()->setCaretBlinkingSuspended(false);
1652
1653    UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
1654
1655    // We get this instead of a second mouse-up
1656    m_mousePressed = false;
1657    setLastKnownMousePosition(mouseEvent);
1658
1659    HitTestRequest request(HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
1660    MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
1661    Frame* subframe = subframeForHitTestResult(mev);
1662    if (m_eventHandlerWillResetCapturingMouseEventsNode)
1663        m_capturingMouseEventsNode = 0;
1664    if (subframe && passMousePressEventToSubframe(mev, subframe))
1665        return true;
1666
1667    m_clickCount = mouseEvent.clickCount();
1668    bool swallowMouseUpEvent = !dispatchMouseEvent(eventNames().mouseupEvent, mev.targetNode(), true, m_clickCount, mouseEvent, false);
1669
1670    bool swallowClickEvent = mouseEvent.button() != RightButton && mev.targetNode() == m_clickNode && !dispatchMouseEvent(eventNames().clickEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
1671
1672    if (m_lastScrollbarUnderMouse)
1673        swallowMouseUpEvent = m_lastScrollbarUnderMouse->mouseUp(mouseEvent);
1674
1675    bool swallowMouseReleaseEvent = !swallowMouseUpEvent && handleMouseReleaseEvent(mev);
1676
1677    invalidateClick();
1678
1679    return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
1680}
1681
1682static RenderLayer* layerForNode(Node* node)
1683{
1684    if (!node)
1685        return 0;
1686
1687    RenderObject* renderer = node->renderer();
1688    if (!renderer)
1689        return 0;
1690
1691    RenderLayer* layer = renderer->enclosingLayer();
1692    if (!layer)
1693        return 0;
1694
1695    return layer;
1696}
1697
1698bool EventHandler::mouseMoved(const PlatformMouseEvent& event)
1699{
1700    RefPtr<FrameView> protector(m_frame->view());
1701    MaximumDurationTracker maxDurationTracker(&m_maxMouseMovedDuration);
1702
1703    HitTestResult hoveredNode = HitTestResult(LayoutPoint());
1704    bool result = handleMouseMoveEvent(event, &hoveredNode);
1705
1706    Page* page = m_frame->page();
1707    if (!page)
1708        return result;
1709
1710    if (RenderLayer* layer = layerForNode(hoveredNode.innerNode())) {
1711        if (FrameView* frameView = m_frame->view()) {
1712            if (frameView->containsScrollableArea(layer))
1713                layer->mouseMovedInContentArea();
1714        }
1715    }
1716
1717    if (FrameView* frameView = m_frame->view())
1718        frameView->mouseMovedInContentArea();
1719
1720    hoveredNode.setToNonShadowAncestor();
1721    page->chrome().mouseDidMoveOverElement(hoveredNode, event.modifierFlags());
1722    page->chrome().setToolTip(hoveredNode);
1723    return result;
1724}
1725
1726bool EventHandler::passMouseMovedEventToScrollbars(const PlatformMouseEvent& event)
1727{
1728    HitTestResult hoveredNode;
1729    return handleMouseMoveEvent(event, &hoveredNode, true);
1730}
1731
1732bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, HitTestResult* hoveredNode, bool onlyUpdateScrollbars)
1733{
1734    // in Radar 3703768 we saw frequent crashes apparently due to the
1735    // part being null here, which seems impossible, so check for nil
1736    // but also assert so that we can try to figure this out in debug
1737    // builds, if it happens.
1738    ASSERT(m_frame);
1739    if (!m_frame)
1740        return false;
1741
1742#if ENABLE(TOUCH_EVENTS)
1743    bool defaultPrevented = dispatchSyntheticTouchEventIfEnabled(mouseEvent);
1744    if (defaultPrevented)
1745        return true;
1746#endif
1747
1748    RefPtr<FrameView> protector(m_frame->view());
1749
1750    setLastKnownMousePosition(mouseEvent);
1751
1752    if (m_hoverTimer.isActive())
1753        m_hoverTimer.stop();
1754
1755    m_cursorUpdateTimer.stop();
1756
1757    cancelFakeMouseMoveEvent();
1758
1759#if ENABLE(SVG)
1760    if (m_svgPan) {
1761        toSVGDocument(m_frame->document())->updatePan(m_frame->view()->windowToContents(m_lastKnownMousePosition));
1762        return true;
1763    }
1764#endif
1765
1766    if (m_frameSetBeingResized)
1767        return !dispatchMouseEvent(eventNames().mousemoveEvent, m_frameSetBeingResized.get(), false, 0, mouseEvent, false);
1768
1769    // Send events right to a scrollbar if the mouse is pressed.
1770    if (m_lastScrollbarUnderMouse && m_mousePressed)
1771        return m_lastScrollbarUnderMouse->mouseMoved(mouseEvent);
1772
1773    HitTestRequest::HitTestRequestType hitType = HitTestRequest::Move | HitTestRequest::DisallowShadowContent | HitTestRequest::AllowFrameScrollbars;
1774    if (m_mousePressed)
1775        hitType |= HitTestRequest::Active;
1776    else if (onlyUpdateScrollbars) {
1777        // Mouse events should be treated as "read-only" if we're updating only scrollbars. This
1778        // means that :hover and :active freeze in the state they were in, rather than updating
1779        // for nodes the mouse moves while the window is not key (which will be the case if
1780        // onlyUpdateScrollbars is true).
1781        hitType |= HitTestRequest::ReadOnly;
1782    }
1783
1784#if ENABLE(TOUCH_EVENTS)
1785    // Treat any mouse move events as readonly if the user is currently touching the screen.
1786    if (m_touchPressed)
1787        hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly;
1788#endif
1789    HitTestRequest request(hitType);
1790    MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
1791    if (hoveredNode)
1792        *hoveredNode = mev.hitTestResult();
1793
1794    if (m_resizeLayer && m_resizeLayer->inResizeMode())
1795        m_resizeLayer->resize(mouseEvent, m_offsetFromResizeCorner);
1796    else {
1797        Scrollbar* scrollbar = mev.scrollbar();
1798        updateLastScrollbarUnderMouse(scrollbar, !m_mousePressed);
1799        if (!m_mousePressed && scrollbar)
1800            scrollbar->mouseMoved(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
1801        if (onlyUpdateScrollbars)
1802            return true;
1803    }
1804
1805    bool swallowEvent = false;
1806    RefPtr<Frame> newSubframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev);
1807
1808    // 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.
1809    if (m_lastMouseMoveEventSubframe && m_lastMouseMoveEventSubframe->tree()->isDescendantOf(m_frame) && m_lastMouseMoveEventSubframe != newSubframe)
1810        passMouseMoveEventToSubframe(mev, m_lastMouseMoveEventSubframe.get());
1811
1812    if (newSubframe) {
1813        // Update over/out state before passing the event to the subframe.
1814        updateMouseEventTargetNode(mev.targetNode(), mouseEvent, true);
1815
1816        // Event dispatch in updateMouseEventTargetNode may have caused the subframe of the target
1817        // node to be detached from its FrameView, in which case the event should not be passed.
1818        if (newSubframe->view())
1819            swallowEvent |= passMouseMoveEventToSubframe(mev, newSubframe.get(), hoveredNode);
1820    } else {
1821        if (FrameView* view = m_frame->view()) {
1822            OptionalCursor optionalCursor = selectCursor(mev.hitTestResult(), mouseEvent.shiftKey());
1823            if (optionalCursor.isCursorChange()) {
1824                m_currentMouseCursor = optionalCursor.cursor();
1825                view->setCursor(m_currentMouseCursor);
1826            }
1827        }
1828    }
1829
1830    m_lastMouseMoveEventSubframe = newSubframe;
1831
1832    if (swallowEvent)
1833        return true;
1834
1835    swallowEvent = !dispatchMouseEvent(eventNames().mousemoveEvent, mev.targetNode(), false, 0, mouseEvent, true);
1836#if ENABLE(DRAG_SUPPORT)
1837    if (!swallowEvent)
1838        swallowEvent = handleMouseDraggedEvent(mev);
1839#endif // ENABLE(DRAG_SUPPORT)
1840
1841    return swallowEvent;
1842}
1843
1844void EventHandler::invalidateClick()
1845{
1846    m_clickCount = 0;
1847    m_clickNode = 0;
1848}
1849
1850inline static bool mouseIsReleasedOnPressedElement(Node* targetNode, Node* clickNode)
1851{
1852    if (targetNode == clickNode)
1853        return true;
1854
1855    if (!targetNode)
1856        return false;
1857
1858    ShadowRoot* containingShadowRoot = targetNode->containingShadowRoot();
1859    if (!containingShadowRoot)
1860        return false;
1861
1862    // FIXME: When an element in UA ShadowDOM (e.g. inner element in <input>) is clicked,
1863    // we assume that the host element is clicked. This is necessary for implementing <input type="range"> etc.
1864    // However, we should not check ShadowRoot type basically.
1865    // https://bugs.webkit.org/show_bug.cgi?id=108047
1866    if (containingShadowRoot->type() != ShadowRoot::UserAgentShadowRoot)
1867        return false;
1868
1869    Node* adjustedTargetNode = targetNode->shadowHost();
1870    Node* adjustedClickNode = clickNode ? clickNode->shadowHost() : 0;
1871    return adjustedTargetNode == adjustedClickNode;
1872}
1873
1874bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
1875{
1876    RefPtr<FrameView> protector(m_frame->view());
1877
1878    m_frame->selection()->setCaretBlinkingSuspended(false);
1879
1880#if ENABLE(TOUCH_EVENTS)
1881    bool defaultPrevented = dispatchSyntheticTouchEventIfEnabled(mouseEvent);
1882    if (defaultPrevented)
1883        return true;
1884#endif
1885
1886    OwnPtr<UserGestureIndicator> gestureIndicator;
1887
1888    if (m_lastMouseDownUserGestureToken)
1889        gestureIndicator = adoptPtr(new UserGestureIndicator(m_lastMouseDownUserGestureToken.release()));
1890    else
1891        gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProcessingUserGesture));
1892
1893#if ENABLE(PAN_SCROLLING)
1894    m_autoscrollController->handleMouseReleaseEvent(mouseEvent);
1895#endif
1896
1897    m_mousePressed = false;
1898    setLastKnownMousePosition(mouseEvent);
1899
1900#if ENABLE(SVG)
1901    if (m_svgPan) {
1902        m_svgPan = false;
1903        toSVGDocument(m_frame->document())->updatePan(m_frame->view()->windowToContents(m_lastKnownMousePosition));
1904        return true;
1905    }
1906#endif
1907
1908    if (m_frameSetBeingResized)
1909        return !dispatchMouseEvent(eventNames().mouseupEvent, m_frameSetBeingResized.get(), true, m_clickCount, mouseEvent, false);
1910
1911    if (m_lastScrollbarUnderMouse) {
1912        invalidateClick();
1913        m_lastScrollbarUnderMouse->mouseUp(mouseEvent);
1914        bool cancelable = true;
1915        bool setUnder = false;
1916        return !dispatchMouseEvent(eventNames().mouseupEvent, m_lastNodeUnderMouse.get(), cancelable, m_clickCount, mouseEvent, setUnder);
1917    }
1918
1919    HitTestRequest request(HitTestRequest::Release | HitTestRequest::DisallowShadowContent);
1920    MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
1921    Frame* subframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev);
1922    if (m_eventHandlerWillResetCapturingMouseEventsNode)
1923        m_capturingMouseEventsNode = 0;
1924    if (subframe && passMouseReleaseEventToSubframe(mev, subframe))
1925        return true;
1926
1927    bool swallowMouseUpEvent = !dispatchMouseEvent(eventNames().mouseupEvent, mev.targetNode(), true, m_clickCount, mouseEvent, false);
1928
1929    bool contextMenuEvent = mouseEvent.button() == RightButton;
1930
1931    bool swallowClickEvent = m_clickCount > 0 && !contextMenuEvent && mouseIsReleasedOnPressedElement(mev.targetNode(), m_clickNode.get()) && !dispatchMouseEvent(eventNames().clickEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
1932
1933    if (m_resizeLayer) {
1934        m_resizeLayer->setInResizeMode(false);
1935        m_resizeLayer = 0;
1936    }
1937
1938    bool swallowMouseReleaseEvent = false;
1939    if (!swallowMouseUpEvent)
1940        swallowMouseReleaseEvent = handleMouseReleaseEvent(mev);
1941
1942    invalidateClick();
1943
1944    return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
1945}
1946
1947bool EventHandler::handlePasteGlobalSelection(const PlatformMouseEvent& mouseEvent)
1948{
1949    // If the event was a middle click, attempt to copy global selection in after
1950    // the newly set caret position.
1951    //
1952    // This code is called from either the mouse up or mouse down handling. There
1953    // is some debate about when the global selection is pasted:
1954    //   xterm: pastes on up.
1955    //   GTK: pastes on down.
1956    //   Qt: pastes on up.
1957    //   Firefox: pastes on up.
1958    //   Chromium: pastes on up.
1959    //
1960    // There is something of a webcompat angle to this well, as highlighted by
1961    // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on
1962    // down then the text is pasted just before the onclick handler runs and
1963    // clears the text box. So it's important this happens after the event
1964    // handlers have been fired.
1965#if PLATFORM(GTK)
1966    if (mouseEvent.type() != PlatformEvent::MousePressed)
1967        return false;
1968#else
1969    if (mouseEvent.type() != PlatformEvent::MouseReleased)
1970        return false;
1971#endif
1972
1973    if (!m_frame->page())
1974        return false;
1975    Frame* focusFrame = m_frame->page()->focusController()->focusedOrMainFrame();
1976    // Do not paste here if the focus was moved somewhere else.
1977    if (m_frame == focusFrame && m_frame->editor().client()->supportsGlobalSelection())
1978        return m_frame->editor().command(ASCIILiteral("PasteGlobalSelection")).execute();
1979
1980    return false;
1981}
1982
1983
1984#if ENABLE(DRAG_SUPPORT)
1985bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard)
1986{
1987    FrameView* view = m_frame->view();
1988
1989    // FIXME: We might want to dispatch a dragleave even if the view is gone.
1990    if (!view)
1991        return false;
1992
1993    view->resetDeferredRepaintDelay();
1994    RefPtr<MouseEvent> me = MouseEvent::create(eventType,
1995        true, true, m_frame->document()->defaultView(),
1996        0, event.globalPosition().x(), event.globalPosition().y(), event.position().x(), event.position().y(),
1997#if ENABLE(POINTER_LOCK)
1998        event.movementDelta().x(), event.movementDelta().y(),
1999#endif
2000        event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
2001        0, 0, clipboard);
2002
2003    dragTarget->dispatchEvent(me.get(), IGNORE_EXCEPTION);
2004    return me->defaultPrevented();
2005}
2006
2007static bool targetIsFrame(Node* target, Frame*& frame)
2008{
2009    if (!target)
2010        return false;
2011
2012    if (!target->hasTagName(frameTag) && !target->hasTagName(iframeTag))
2013        return false;
2014
2015    frame = static_cast<HTMLFrameElementBase*>(target)->contentFrame();
2016
2017    return true;
2018}
2019
2020static bool findDropZone(Node* target, Clipboard* clipboard)
2021{
2022    Element* element = target->isElementNode() ? toElement(target) : target->parentElement();
2023    for (; element; element = element->parentElement()) {
2024        bool matched = false;
2025        String dropZoneStr = element->fastGetAttribute(webkitdropzoneAttr);
2026
2027        if (dropZoneStr.isEmpty())
2028            continue;
2029
2030        dropZoneStr.makeLower();
2031
2032        SpaceSplitString keywords(dropZoneStr, false);
2033        if (keywords.isNull())
2034            continue;
2035
2036        DragOperation dragOperation = DragOperationNone;
2037        for (unsigned int i = 0; i < keywords.size(); i++) {
2038            DragOperation op = convertDropZoneOperationToDragOperation(keywords[i]);
2039            if (op != DragOperationNone) {
2040                if (dragOperation == DragOperationNone)
2041                    dragOperation = op;
2042            } else
2043                matched = matched || clipboard->hasDropZoneType(keywords[i].string());
2044
2045            if (matched && dragOperation != DragOperationNone)
2046                break;
2047        }
2048        if (matched) {
2049            clipboard->setDropEffect(convertDragOperationToDropZoneOperation(dragOperation));
2050            return true;
2051        }
2052    }
2053    return false;
2054}
2055
2056bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
2057{
2058    bool accept = false;
2059
2060    if (!m_frame->view())
2061        return false;
2062
2063    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent);
2064    MouseEventWithHitTestResults mev = prepareMouseEvent(request, event);
2065
2066    // Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
2067    RefPtr<Node> newTarget = mev.targetNode();
2068    if (newTarget && newTarget->isTextNode())
2069        newTarget = EventPathWalker::parent(newTarget.get());
2070
2071    m_autoscrollController->updateDragAndDrop(newTarget.get(), event.position(), event.timestamp());
2072
2073    if (m_dragTarget != newTarget) {
2074        // FIXME: this ordering was explicitly chosen to match WinIE. However,
2075        // it is sometimes incorrect when dragging within subframes, as seen with
2076        // LayoutTests/fast/events/drag-in-frames.html.
2077        //
2078        // 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>.
2079        Frame* targetFrame;
2080        if (targetIsFrame(newTarget.get(), targetFrame)) {
2081            if (targetFrame)
2082                accept = targetFrame->eventHandler()->updateDragAndDrop(event, clipboard);
2083        } else if (newTarget) {
2084            // 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.
2085            if (dragState().source && dragState().shouldDispatchEvents) {
2086                // for now we don't care if event handler cancels default behavior, since there is none
2087                dispatchDragSrcEvent(eventNames().dragEvent, event);
2088            }
2089            accept = dispatchDragEvent(eventNames().dragenterEvent, newTarget.get(), event, clipboard);
2090            if (!accept)
2091                accept = findDropZone(newTarget.get(), clipboard);
2092        }
2093
2094        if (targetIsFrame(m_dragTarget.get(), targetFrame)) {
2095            if (targetFrame)
2096                accept = targetFrame->eventHandler()->updateDragAndDrop(event, clipboard);
2097        } else if (m_dragTarget)
2098            dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard);
2099
2100        if (newTarget) {
2101            // We do not explicitly call dispatchDragEvent here because it could ultimately result in the appearance that
2102            // two dragover events fired. So, we mark that we should only fire a dragover event on the next call to this function.
2103            m_shouldOnlyFireDragOverEvent = true;
2104        }
2105    } else {
2106        Frame* targetFrame;
2107        if (targetIsFrame(newTarget.get(), targetFrame)) {
2108            if (targetFrame)
2109                accept = targetFrame->eventHandler()->updateDragAndDrop(event, clipboard);
2110        } else if (newTarget) {
2111            // Note, when dealing with sub-frames, we may need to fire only a dragover event as a drag event may have been fired earlier.
2112            if (!m_shouldOnlyFireDragOverEvent && dragState().source && dragState().shouldDispatchEvents) {
2113                // for now we don't care if event handler cancels default behavior, since there is none
2114                dispatchDragSrcEvent(eventNames().dragEvent, event);
2115            }
2116            accept = dispatchDragEvent(eventNames().dragoverEvent, newTarget.get(), event, clipboard);
2117            if (!accept)
2118                accept = findDropZone(newTarget.get(), clipboard);
2119            m_shouldOnlyFireDragOverEvent = false;
2120        }
2121    }
2122    m_dragTarget = newTarget;
2123
2124    return accept;
2125}
2126
2127void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
2128{
2129    Frame* targetFrame;
2130    if (targetIsFrame(m_dragTarget.get(), targetFrame)) {
2131        if (targetFrame)
2132            targetFrame->eventHandler()->cancelDragAndDrop(event, clipboard);
2133    } else if (m_dragTarget.get()) {
2134        if (dragState().source && dragState().shouldDispatchEvents)
2135            dispatchDragSrcEvent(eventNames().dragEvent, event);
2136        dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard);
2137    }
2138    clearDragState();
2139}
2140
2141bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
2142{
2143    Frame* targetFrame;
2144    bool preventedDefault = false;
2145    if (targetIsFrame(m_dragTarget.get(), targetFrame)) {
2146        if (targetFrame)
2147            preventedDefault = targetFrame->eventHandler()->performDragAndDrop(event, clipboard);
2148    } else if (m_dragTarget.get())
2149        preventedDefault = dispatchDragEvent(eventNames().dropEvent, m_dragTarget.get(), event, clipboard);
2150    clearDragState();
2151    return preventedDefault;
2152}
2153
2154void EventHandler::clearDragState()
2155{
2156    stopAutoscrollTimer();
2157    m_dragTarget = 0;
2158    m_capturingMouseEventsNode = 0;
2159    m_shouldOnlyFireDragOverEvent = false;
2160#if PLATFORM(MAC)
2161    m_sendingEventToSubview = false;
2162#endif
2163}
2164#endif // ENABLE(DRAG_SUPPORT)
2165
2166void EventHandler::setCapturingMouseEventsNode(PassRefPtr<Node> n)
2167{
2168    m_capturingMouseEventsNode = n;
2169    m_eventHandlerWillResetCapturingMouseEventsNode = false;
2170}
2171
2172MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestRequest& request, const PlatformMouseEvent& mev)
2173{
2174    ASSERT(m_frame);
2175    ASSERT(m_frame->document());
2176
2177    return m_frame->document()->prepareMouseEvent(request, documentPointForWindowPoint(m_frame, mev.position()), mev);
2178}
2179
2180#if ENABLE(SVG)
2181static inline SVGElementInstance* instanceAssociatedWithShadowTreeElement(Node* referenceNode)
2182{
2183    if (!referenceNode || !referenceNode->isSVGElement())
2184        return 0;
2185
2186    ShadowRoot* shadowRoot = referenceNode->containingShadowRoot();
2187    if (!shadowRoot)
2188        return 0;
2189
2190    Element* shadowTreeParentElement = shadowRoot->host();
2191    if (!shadowTreeParentElement || !shadowTreeParentElement->hasTagName(useTag))
2192        return 0;
2193
2194    return static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode);
2195}
2196#endif
2197
2198void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMouseEvent& mouseEvent, bool fireMouseOverOut)
2199{
2200    Node* result = targetNode;
2201
2202    // If we're capturing, we always go right to that node.
2203    if (m_capturingMouseEventsNode)
2204        result = m_capturingMouseEventsNode.get();
2205    else {
2206        // If the target node is a text node, dispatch on the parent node - rdar://4196646
2207        if (result && result->isTextNode())
2208            result = EventPathWalker::parent(result);
2209    }
2210    m_nodeUnderMouse = result;
2211#if ENABLE(SVG)
2212    m_instanceUnderMouse = instanceAssociatedWithShadowTreeElement(result);
2213
2214    // <use> shadow tree elements may have been recloned, update node under mouse in any case
2215    if (m_lastInstanceUnderMouse) {
2216        SVGElement* lastCorrespondingElement = m_lastInstanceUnderMouse->correspondingElement();
2217        SVGElement* lastCorrespondingUseElement = m_lastInstanceUnderMouse->correspondingUseElement();
2218
2219        if (lastCorrespondingElement && lastCorrespondingUseElement) {
2220            HashSet<SVGElementInstance*> instances = lastCorrespondingElement->instancesForElement();
2221
2222            // Locate the recloned shadow tree element for our corresponding instance
2223            HashSet<SVGElementInstance*>::iterator end = instances.end();
2224            for (HashSet<SVGElementInstance*>::iterator it = instances.begin(); it != end; ++it) {
2225                SVGElementInstance* instance = (*it);
2226                ASSERT(instance->correspondingElement() == lastCorrespondingElement);
2227
2228                if (instance == m_lastInstanceUnderMouse)
2229                    continue;
2230
2231                if (instance->correspondingUseElement() != lastCorrespondingUseElement)
2232                    continue;
2233
2234                SVGElement* shadowTreeElement = instance->shadowTreeElement();
2235                if (!shadowTreeElement->inDocument() || m_lastNodeUnderMouse == shadowTreeElement)
2236                    continue;
2237
2238                m_lastNodeUnderMouse = shadowTreeElement;
2239                m_lastInstanceUnderMouse = instance;
2240                break;
2241            }
2242        }
2243    }
2244#endif
2245
2246    // Fire mouseout/mouseover if the mouse has shifted to a different node.
2247    if (fireMouseOverOut) {
2248        RenderLayer* layerForLastNode = layerForNode(m_lastNodeUnderMouse.get());
2249        RenderLayer* layerForNodeUnderMouse = layerForNode(m_nodeUnderMouse.get());
2250        Page* page = m_frame->page();
2251
2252        if (m_lastNodeUnderMouse && (!m_nodeUnderMouse || m_nodeUnderMouse->document() != m_frame->document())) {
2253            // The mouse has moved between frames.
2254            if (Frame* frame = m_lastNodeUnderMouse->document()->frame()) {
2255                if (FrameView* frameView = frame->view())
2256                    frameView->mouseExitedContentArea();
2257            }
2258        } else if (page && (layerForLastNode && (!layerForNodeUnderMouse || layerForNodeUnderMouse != layerForLastNode))) {
2259            // The mouse has moved between layers.
2260            if (Frame* frame = m_lastNodeUnderMouse->document()->frame()) {
2261                if (FrameView* frameView = frame->view()) {
2262                    if (frameView->containsScrollableArea(layerForLastNode))
2263                        layerForLastNode->mouseExitedContentArea();
2264                }
2265            }
2266        }
2267
2268        if (m_nodeUnderMouse && (!m_lastNodeUnderMouse || m_lastNodeUnderMouse->document() != m_frame->document())) {
2269            // The mouse has moved between frames.
2270            if (Frame* frame = m_nodeUnderMouse->document()->frame()) {
2271                if (FrameView* frameView = frame->view())
2272                    frameView->mouseEnteredContentArea();
2273            }
2274        } else if (page && (layerForNodeUnderMouse && (!layerForLastNode || layerForNodeUnderMouse != layerForLastNode))) {
2275            // The mouse has moved between layers.
2276            if (Frame* frame = m_nodeUnderMouse->document()->frame()) {
2277                if (FrameView* frameView = frame->view()) {
2278                    if (frameView->containsScrollableArea(layerForNodeUnderMouse))
2279                        layerForNodeUnderMouse->mouseEnteredContentArea();
2280                }
2281            }
2282        }
2283
2284        if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame->document()) {
2285            m_lastNodeUnderMouse = 0;
2286            m_lastScrollbarUnderMouse = 0;
2287#if ENABLE(SVG)
2288            m_lastInstanceUnderMouse = 0;
2289#endif
2290        }
2291
2292        if (m_lastNodeUnderMouse != m_nodeUnderMouse) {
2293            // send mouseout event to the old node
2294            if (m_lastNodeUnderMouse)
2295                m_lastNodeUnderMouse->dispatchMouseEvent(mouseEvent, eventNames().mouseoutEvent, 0, m_nodeUnderMouse.get());
2296            // send mouseover event to the new node
2297            if (m_nodeUnderMouse)
2298                m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventNames().mouseoverEvent, 0, m_lastNodeUnderMouse.get());
2299        }
2300        m_lastNodeUnderMouse = m_nodeUnderMouse;
2301#if ENABLE(SVG)
2302        m_lastInstanceUnderMouse = instanceAssociatedWithShadowTreeElement(m_nodeUnderMouse.get());
2303#endif
2304    }
2305}
2306
2307bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool /*cancelable*/, int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder)
2308{
2309    if (FrameView* view = m_frame->view())
2310        view->resetDeferredRepaintDelay();
2311
2312    updateMouseEventTargetNode(targetNode, mouseEvent, setUnder);
2313
2314    bool swallowEvent = false;
2315
2316    if (m_nodeUnderMouse)
2317        swallowEvent = !(m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventType, clickCount));
2318
2319    if (!swallowEvent && eventType == eventNames().mousedownEvent) {
2320
2321        // If clicking on a frame scrollbar, do not mess up with content focus.
2322        if (FrameView* view = m_frame->view()) {
2323            if (view->scrollbarAtPoint(mouseEvent.position()))
2324                return true;
2325        }
2326
2327        // The layout needs to be up to date to determine if an element is focusable.
2328        m_frame->document()->updateLayoutIgnorePendingStylesheets();
2329
2330        // Blur current focus node when a link/button is clicked; this
2331        // is expected by some sites that rely on onChange handlers running
2332        // from form fields before the button click is processed.
2333
2334        Element* element;
2335        if (m_nodeUnderMouse)
2336            element = m_nodeUnderMouse->isElementNode() ? toElement(m_nodeUnderMouse.get()) : m_nodeUnderMouse->parentOrShadowHostElement();
2337        else
2338            element = 0;
2339
2340        // Walk up the DOM tree to search for an element to focus.
2341        while (element) {
2342            if (element->isMouseFocusable()) {
2343                // To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus a
2344                // node on mouse down if it's selected and inside a focused node. It will be
2345                // focused if the user does a mouseup over it, however, because the mouseup
2346                // will set a selection inside it, which will call setFocuseNodeIfNeeded.
2347                if (m_frame->selection()->isRange()
2348                    && m_frame->selection()->toNormalizedRange()->compareNode(element, IGNORE_EXCEPTION) == Range::NODE_INSIDE
2349                    && element->isDescendantOf(m_frame->document()->focusedElement()))
2350                    return true;
2351
2352                break;
2353            }
2354            element = element->parentOrShadowHostElement();
2355        }
2356
2357        // Only change the focus when clicking scrollbars if it can transfered to a mouse focusable node.
2358        if ((!element || !element->isMouseFocusable()) && isInsideScrollbar(mouseEvent.position()))
2359            return false;
2360
2361        // If focus shift is blocked, we eat the event.  Note we should never clear swallowEvent
2362        // if the page already set it (e.g., by canceling default behavior).
2363        if (Page* page = m_frame->page()) {
2364            if (element && element->isMouseFocusable()) {
2365                if (!page->focusController()->setFocusedElement(element, m_frame))
2366                    swallowEvent = true;
2367            } else if (!element || !element->focused()) {
2368                if (!page->focusController()->setFocusedElement(0, m_frame))
2369                    swallowEvent = true;
2370            }
2371        }
2372    }
2373
2374    return !swallowEvent;
2375}
2376
2377bool EventHandler::isInsideScrollbar(const IntPoint& windowPoint) const
2378{
2379    if (RenderView* renderView = m_frame->contentRenderer()) {
2380        HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent);
2381        HitTestResult result(windowPoint);
2382        renderView->hitTest(request, result);
2383        return result.scrollbar();
2384    }
2385
2386    return false;
2387}
2388
2389#if !PLATFORM(GTK)
2390bool EventHandler::shouldTurnVerticalTicksIntoHorizontal(const HitTestResult&, const PlatformWheelEvent&) const
2391{
2392    return false;
2393}
2394#endif
2395
2396void EventHandler::recordWheelEventDelta(const PlatformWheelEvent& event)
2397{
2398    const size_t recentEventCount = 3;
2399
2400    m_recentWheelEventDeltas.append(FloatSize(event.deltaX(), event.deltaY()));
2401    if (m_recentWheelEventDeltas.size() > recentEventCount)
2402        m_recentWheelEventDeltas.removeFirst();
2403}
2404
2405static bool deltaIsPredominantlyVertical(const FloatSize& delta)
2406{
2407    return fabs(delta.height()) > fabs(delta.width());
2408}
2409
2410EventHandler::DominantScrollGestureDirection EventHandler::dominantScrollGestureDirection() const
2411{
2412    bool allVertical = m_recentWheelEventDeltas.size();
2413    bool allHorizontal = m_recentWheelEventDeltas.size();
2414
2415    Deque<FloatSize>::const_iterator end = m_recentWheelEventDeltas.end();
2416    for (Deque<FloatSize>::const_iterator it = m_recentWheelEventDeltas.begin(); it != end; ++it) {
2417        bool isVertical = deltaIsPredominantlyVertical(*it);
2418        allVertical &= isVertical;
2419        allHorizontal &= !isVertical;
2420    }
2421
2422    if (allVertical)
2423        return DominantScrollDirectionVertical;
2424
2425    if (allHorizontal)
2426        return DominantScrollDirectionHorizontal;
2427
2428    return DominantScrollDirectionNone;
2429}
2430
2431bool EventHandler::handleWheelEvent(const PlatformWheelEvent& e)
2432{
2433    Document* doc = m_frame->document();
2434
2435    RenderObject* docRenderer = doc->renderer();
2436    if (!docRenderer)
2437        return false;
2438
2439    RefPtr<FrameView> protector(m_frame->view());
2440
2441    FrameView* view = m_frame->view();
2442    if (!view)
2443        return false;
2444
2445    m_isHandlingWheelEvent = true;
2446    setFrameWasScrolledByUser();
2447    LayoutPoint vPoint = view->windowToContents(e.position());
2448
2449    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent);
2450    HitTestResult result(vPoint);
2451    doc->renderView()->hitTest(request, result);
2452
2453    bool useLatchedWheelEventNode = e.useLatchedEventNode();
2454
2455    // FIXME: Is the following code different from just calling innerElement?
2456    Node* node = result.innerNode();
2457    // Wheel events should not dispatch to text nodes.
2458    if (node && node->isTextNode())
2459        node = EventPathWalker::parent(node);
2460
2461    bool isOverWidget;
2462    if (useLatchedWheelEventNode) {
2463        if (!m_latchedWheelEventNode) {
2464            m_latchedWheelEventNode = node;
2465            m_widgetIsLatched = result.isOverWidget();
2466        } else
2467            node = m_latchedWheelEventNode.get();
2468
2469        isOverWidget = m_widgetIsLatched;
2470    } else {
2471        if (m_latchedWheelEventNode)
2472            m_latchedWheelEventNode = 0;
2473        if (m_previousWheelScrolledNode)
2474            m_previousWheelScrolledNode = 0;
2475
2476        isOverWidget = result.isOverWidget();
2477    }
2478
2479    // FIXME: It should not be necessary to do this mutation here.
2480    // Instead, the handlers should know convert vertical scrolls
2481    // appropriately.
2482    PlatformWheelEvent event = e;
2483    if (m_baseEventType == PlatformEvent::NoType && shouldTurnVerticalTicksIntoHorizontal(result, e))
2484        event = event.copyTurningVerticalTicksIntoHorizontalTicks();
2485
2486#if PLATFORM(MAC)
2487    switch (event.phase()) {
2488    case PlatformWheelEventPhaseBegan:
2489        m_recentWheelEventDeltas.clear();
2490        m_inTrackingScrollGesturePhase = true;
2491        break;
2492    case PlatformWheelEventPhaseEnded:
2493        m_inTrackingScrollGesturePhase = false;
2494        break;
2495    default:
2496        break;
2497    }
2498#endif
2499
2500    recordWheelEventDelta(event);
2501
2502    if (node) {
2503        // Figure out which view to send the event to.
2504        RenderObject* target = node->renderer();
2505
2506        if (isOverWidget && target && target->isWidget()) {
2507            Widget* widget = toRenderWidget(target)->widget();
2508            if (widget && passWheelEventToWidget(e, widget)) {
2509                m_isHandlingWheelEvent = false;
2510                return true;
2511            }
2512        }
2513
2514        if (node && !node->dispatchWheelEvent(event)) {
2515            m_isHandlingWheelEvent = false;
2516            return true;
2517        }
2518    }
2519
2520
2521    // We do another check on the frame view because the event handler can run JS which results in the frame getting destroyed.
2522    view = m_frame->view();
2523    bool didHandleEvent = view ? view->wheelEvent(event) : false;
2524    m_isHandlingWheelEvent = false;
2525    return didHandleEvent;
2526}
2527
2528void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEvent)
2529{
2530    if (!startNode || !wheelEvent)
2531        return;
2532
2533    Node* stopNode = m_previousWheelScrolledNode.get();
2534    ScrollGranularity granularity = wheelGranularityToScrollGranularity(wheelEvent->deltaMode());
2535
2536    DominantScrollGestureDirection dominantDirection = DominantScrollDirectionNone;
2537    // Workaround for scrolling issues in iTunes (<rdar://problem/14758615>).
2538    if (m_inTrackingScrollGesturePhase && applicationIsITunes())
2539        dominantDirection = dominantScrollGestureDirection();
2540
2541    // Break up into two scrolls if we need to.  Diagonal movement on
2542    // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
2543    if (dominantDirection != DominantScrollDirectionVertical && scrollNode(wheelEvent->rawDeltaX(), granularity, ScrollLeft, ScrollRight, startNode, &stopNode))
2544        wheelEvent->setDefaultHandled();
2545
2546    if (dominantDirection != DominantScrollDirectionHorizontal && scrollNode(wheelEvent->rawDeltaY(), granularity, ScrollUp, ScrollDown, startNode, &stopNode))
2547        wheelEvent->setDefaultHandled();
2548
2549    if (!m_latchedWheelEventNode)
2550        m_previousWheelScrolledNode = stopNode;
2551}
2552
2553#if ENABLE(GESTURE_EVENTS)
2554bool EventHandler::handleGestureTapDown()
2555{
2556    FrameView* view = m_frame->view();
2557    if (!view)
2558        return false;
2559    if (ScrollAnimator* scrollAnimator = view->existingScrollAnimator())
2560        scrollAnimator->cancelAnimations();
2561    const FrameView::ScrollableAreaSet* areas = view->scrollableAreas();
2562    if (!areas)
2563        return false;
2564    for (FrameView::ScrollableAreaSet::const_iterator it = areas->begin(); it != areas->end(); ++it) {
2565        ScrollableArea* sa = *it;
2566        ScrollAnimator* animator = sa->scrollAnimator();
2567        if (animator)
2568            animator->cancelAnimations();
2569    }
2570    return false;
2571}
2572
2573bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
2574{
2575    Node* eventTarget = 0;
2576    Scrollbar* scrollbar = 0;
2577    if (gestureEvent.type() == PlatformEvent::GestureScrollEnd
2578        || gestureEvent.type() == PlatformEvent::GestureScrollUpdate
2579        || gestureEvent.type() == PlatformEvent::GestureScrollUpdateWithoutPropagation) {
2580        scrollbar = m_scrollbarHandlingScrollGesture.get();
2581        eventTarget = m_scrollGestureHandlingNode.get();
2582    }
2583
2584    IntPoint adjustedPoint = gestureEvent.position();
2585    HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent;
2586    if (gestureEvent.type() == PlatformEvent::GestureTapDown) {
2587#if ENABLE(TOUCH_ADJUSTMENT)
2588        adjustGesturePosition(gestureEvent, adjustedPoint);
2589#endif
2590        hitType |= HitTestRequest::Active;
2591    } else if (gestureEvent.type() == PlatformEvent::GestureTapDownCancel)
2592        hitType |= HitTestRequest::Release;
2593    else if (gestureEvent.type() == PlatformEvent::GestureTap) {
2594        // The mouseup event synthesized for this gesture will clear the active state of the
2595        // targeted node, so performing a ReadOnly hit test here is fine.
2596        hitType |= HitTestRequest::ReadOnly;
2597    }
2598    else
2599        hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly;
2600
2601    if (!shouldGesturesTriggerActive())
2602        hitType |= HitTestRequest::ReadOnly;
2603
2604    if ((!scrollbar && !eventTarget) || !(hitType & HitTestRequest::ReadOnly)) {
2605        IntPoint hitTestPoint = m_frame->view()->windowToContents(adjustedPoint);
2606        HitTestResult result = hitTestResultAtPoint(hitTestPoint, hitType | HitTestRequest::AllowFrameScrollbars);
2607        eventTarget = result.targetNode();
2608        if (!scrollbar)
2609            scrollbar = result.scrollbar();
2610    }
2611
2612    if (scrollbar) {
2613        bool eventSwallowed = scrollbar->gestureEvent(gestureEvent);
2614        if (gestureEvent.type() == PlatformEvent::GestureScrollBegin && eventSwallowed)
2615            m_scrollbarHandlingScrollGesture = scrollbar;
2616        else if (gestureEvent.type() == PlatformEvent::GestureScrollEnd || !eventSwallowed)
2617            m_scrollbarHandlingScrollGesture = 0;
2618
2619        if (eventSwallowed)
2620            return true;
2621    }
2622
2623    if (eventTarget) {
2624        bool eventSwallowed = eventTarget->dispatchGestureEvent(gestureEvent);
2625        if (gestureEvent.type() == PlatformEvent::GestureScrollBegin || gestureEvent.type() == PlatformEvent::GestureScrollEnd) {
2626            if (eventSwallowed)
2627                m_scrollGestureHandlingNode = eventTarget;
2628        }
2629
2630        if (eventSwallowed)
2631            return true;
2632    }
2633
2634    // FIXME: A more general scroll system (https://bugs.webkit.org/show_bug.cgi?id=80596) will
2635    // eliminate the need for this.
2636    TemporaryChange<PlatformEvent::Type> baseEventType(m_baseEventType, gestureEvent.type());
2637
2638    switch (gestureEvent.type()) {
2639    case PlatformEvent::GestureScrollBegin:
2640        return handleGestureScrollBegin(gestureEvent);
2641    case PlatformEvent::GestureScrollUpdate:
2642    case PlatformEvent::GestureScrollUpdateWithoutPropagation:
2643        return handleGestureScrollUpdate(gestureEvent);
2644    case PlatformEvent::GestureScrollEnd:
2645        clearGestureScrollNodes();
2646        return true;
2647    case PlatformEvent::GestureTap:
2648        return handleGestureTap(gestureEvent);
2649    case PlatformEvent::GestureTapDown:
2650        return handleGestureTapDown();
2651    case PlatformEvent::GestureLongPress:
2652        return handleGestureLongPress(gestureEvent);
2653    case PlatformEvent::GestureLongTap:
2654        return handleGestureLongTap(gestureEvent);
2655    case PlatformEvent::GestureTwoFingerTap:
2656        return handleGestureTwoFingerTap(gestureEvent);
2657    case PlatformEvent::GesturePinchBegin:
2658    case PlatformEvent::GesturePinchEnd:
2659    case PlatformEvent::GesturePinchUpdate:
2660    case PlatformEvent::GestureTapDownCancel:
2661        break;
2662    default:
2663        ASSERT_NOT_REACHED();
2664    }
2665
2666    return false;
2667}
2668
2669bool EventHandler::handleGestureTap(const PlatformGestureEvent& gestureEvent)
2670{
2671    // FIXME: Refactor this code to not hit test multiple times. We use the adjusted position to ensure that the correct node is targeted by the later redundant hit tests.
2672    IntPoint adjustedPoint = gestureEvent.position();
2673#if ENABLE(TOUCH_ADJUSTMENT)
2674    adjustGesturePosition(gestureEvent, adjustedPoint);
2675#endif
2676
2677    PlatformMouseEvent fakeMouseMove(adjustedPoint, gestureEvent.globalPosition(),
2678        NoButton, PlatformEvent::MouseMoved, /* clickCount */ 0,
2679        gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp());
2680    mouseMoved(fakeMouseMove);
2681
2682    int tapCount = 1;
2683    // FIXME: deletaX is overloaded to mean different things for different gestures.
2684    // http://wkb.ug/93123
2685    if (gestureEvent.deltaX() > 0)
2686        tapCount = static_cast<int>(gestureEvent.deltaX());
2687
2688    bool defaultPrevented = false;
2689    PlatformMouseEvent fakeMouseDown(adjustedPoint, gestureEvent.globalPosition(),
2690        LeftButton, PlatformEvent::MousePressed, tapCount,
2691        gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp());
2692    defaultPrevented |= handleMousePressEvent(fakeMouseDown);
2693
2694    PlatformMouseEvent fakeMouseUp(adjustedPoint, gestureEvent.globalPosition(),
2695        LeftButton, PlatformEvent::MouseReleased, tapCount,
2696        gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp());
2697    defaultPrevented |= handleMouseReleaseEvent(fakeMouseUp);
2698
2699    return defaultPrevented;
2700}
2701
2702bool EventHandler::handleGestureLongPress(const PlatformGestureEvent& gestureEvent)
2703{
2704#if ENABLE(DRAG_SUPPORT)
2705    if (m_frame->settings() && m_frame->settings()->touchDragDropEnabled()) {
2706        IntPoint adjustedPoint = gestureEvent.position();
2707#if ENABLE(TOUCH_ADJUSTMENT)
2708        adjustGesturePosition(gestureEvent, adjustedPoint);
2709#endif
2710        PlatformMouseEvent mouseDownEvent(adjustedPoint, gestureEvent.globalPosition(), LeftButton, PlatformEvent::MousePressed, 0, false, false, false, false, WTF::currentTime());
2711        handleMousePressEvent(mouseDownEvent);
2712        PlatformMouseEvent mouseDragEvent(adjustedPoint, gestureEvent.globalPosition(), LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, WTF::currentTime());
2713        HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent);
2714        MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseDragEvent);
2715        m_didStartDrag = false;
2716        RefPtr<Frame> subframe = subframeForHitTestResult(mev);
2717        if (subframe && !m_mouseDownMayStartDrag) {
2718            if (subframe->eventHandler()->handleGestureLongPress(gestureEvent))
2719                return true;
2720        }
2721        handleDrag(mev, DontCheckDragHysteresis);
2722        if (m_didStartDrag)
2723            return true;
2724    }
2725#endif
2726    return handleGestureForTextSelectionOrContextMenu(gestureEvent);
2727}
2728
2729bool EventHandler::handleGestureLongTap(const PlatformGestureEvent& gestureEvent)
2730{
2731#if ENABLE(CONTEXT_MENUS)
2732    if (!m_didLongPressInvokeContextMenu)
2733        return sendContextMenuEventForGesture(gestureEvent);
2734#endif // ENABLE(CONTEXT_MENUS)
2735    return false;
2736}
2737
2738bool EventHandler::handleGestureForTextSelectionOrContextMenu(const PlatformGestureEvent& gestureEvent)
2739{
2740#if ENABLE(CONTEXT_MENUS)
2741    m_didLongPressInvokeContextMenu = (gestureEvent.type() == PlatformEvent::GestureLongPress);
2742    return sendContextMenuEventForGesture(gestureEvent);
2743#else
2744    return false;
2745#endif
2746}
2747
2748bool EventHandler::handleGestureTwoFingerTap(const PlatformGestureEvent& gestureEvent)
2749{
2750    return handleGestureForTextSelectionOrContextMenu(gestureEvent);
2751}
2752
2753bool EventHandler::passGestureEventToWidget(const PlatformGestureEvent& gestureEvent, Widget* widget)
2754{
2755    if (!widget)
2756        return false;
2757
2758    if (!widget->isFrameView())
2759        return false;
2760
2761    return toFrameView(widget)->frame()->eventHandler()->handleGestureEvent(gestureEvent);
2762}
2763
2764bool EventHandler::passGestureEventToWidgetIfPossible(const PlatformGestureEvent& gestureEvent, RenderObject* renderer)
2765{
2766    if (m_lastHitTestResultOverWidget && renderer && renderer->isWidget()) {
2767        Widget* widget = toRenderWidget(renderer)->widget();
2768        return widget && passGestureEventToWidget(gestureEvent, widget);
2769    }
2770    return false;
2771}
2772
2773bool EventHandler::handleGestureScrollBegin(const PlatformGestureEvent& gestureEvent)
2774{
2775    Document* document = m_frame->document();
2776    RenderObject* documentRenderer = document->renderer();
2777    if (!documentRenderer)
2778        return false;
2779
2780    FrameView* view = m_frame->view();
2781    if (!view)
2782        return false;
2783
2784    LayoutPoint viewPoint = view->windowToContents(gestureEvent.position());
2785    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent);
2786    HitTestResult result(viewPoint);
2787    document->renderView()->hitTest(request, result);
2788
2789    m_lastHitTestResultOverWidget = result.isOverWidget();
2790    m_scrollGestureHandlingNode = result.innerNode();
2791    m_previousGestureScrolledNode = 0;
2792
2793    Node* node = m_scrollGestureHandlingNode.get();
2794    if (node)
2795        passGestureEventToWidgetIfPossible(gestureEvent, node->renderer());
2796
2797    return node && node->renderer();
2798}
2799
2800bool EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gestureEvent)
2801{
2802    FloatSize delta(gestureEvent.deltaX(), gestureEvent.deltaY());
2803    if (delta.isZero())
2804        return false;
2805
2806    const float scaleFactor = m_frame->pageZoomFactor() * m_frame->frameScaleFactor();
2807    delta.scale(1 / scaleFactor, 1 / scaleFactor);
2808
2809    Node* node = m_scrollGestureHandlingNode.get();
2810    if (!node)
2811        return sendScrollEventToView(gestureEvent, delta);
2812
2813    // Ignore this event if the targeted node does not have a valid renderer.
2814    RenderObject* renderer = node->renderer();
2815    if (!renderer)
2816        return false;
2817
2818    RefPtr<FrameView> protector(m_frame->view());
2819
2820    // Try to send the event to the correct view.
2821    if (passGestureEventToWidgetIfPossible(gestureEvent, renderer))
2822        return true;
2823
2824    Node* stopNode = 0;
2825    bool scrollShouldNotPropagate = gestureEvent.type() == PlatformEvent::GestureScrollUpdateWithoutPropagation;
2826    if (scrollShouldNotPropagate)
2827        stopNode = m_previousGestureScrolledNode.get();
2828
2829    // First try to scroll the closest scrollable RenderBox ancestor of |node|.
2830    ScrollGranularity granularity = ScrollByPixel;
2831    bool horizontalScroll = scrollNode(delta.width(), granularity, ScrollLeft, ScrollRight, node, &stopNode);
2832    bool verticalScroll = scrollNode(delta.height(), granularity, ScrollUp, ScrollDown, node, &stopNode);
2833
2834    if (scrollShouldNotPropagate)
2835        m_previousGestureScrolledNode = stopNode;
2836
2837    if (horizontalScroll || verticalScroll) {
2838        setFrameWasScrolledByUser();
2839        return true;
2840    }
2841
2842    // Otherwise try to scroll the view.
2843    return sendScrollEventToView(gestureEvent, delta);
2844}
2845
2846bool EventHandler::sendScrollEventToView(const PlatformGestureEvent& gestureEvent, const FloatSize& scaledDelta)
2847{
2848    FrameView* view = m_frame->view();
2849    if (!view)
2850        return false;
2851
2852    const float tickDivisor = static_cast<float>(WheelEvent::TickMultiplier);
2853    IntPoint point(gestureEvent.position().x(), gestureEvent.position().y());
2854    IntPoint globalPoint(gestureEvent.globalPosition().x(), gestureEvent.globalPosition().y());
2855    PlatformWheelEvent syntheticWheelEvent(point, globalPoint,
2856        scaledDelta.width(), scaledDelta.height(),
2857        scaledDelta.width() / tickDivisor, scaledDelta.height() / tickDivisor,
2858        ScrollByPixelWheelEvent,
2859        gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey());
2860#if PLATFORM(MAC)
2861    syntheticWheelEvent.setHasPreciseScrollingDeltas(true);
2862#endif
2863
2864    bool scrolledFrame = view->wheelEvent(syntheticWheelEvent);
2865    if (scrolledFrame)
2866        setFrameWasScrolledByUser();
2867
2868    return scrolledFrame;
2869}
2870
2871void EventHandler::clearGestureScrollNodes()
2872{
2873    m_scrollGestureHandlingNode = 0;
2874    m_previousGestureScrolledNode = 0;
2875}
2876
2877bool EventHandler::isScrollbarHandlingGestures() const
2878{
2879    return m_scrollbarHandlingScrollGesture.get();
2880}
2881#endif // ENABLE(GESTURE_EVENTS)
2882
2883#if ENABLE(TOUCH_ADJUSTMENT)
2884bool EventHandler::shouldApplyTouchAdjustment(const PlatformGestureEvent& event) const
2885{
2886    if (m_frame->settings() && !m_frame->settings()->touchAdjustmentEnabled())
2887        return false;
2888    return !event.area().isEmpty();
2889}
2890
2891
2892bool EventHandler::bestClickableNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode)
2893{
2894    IntPoint hitTestPoint = m_frame->view()->windowToContents(touchCenter);
2895    HitTestResult result = hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active, touchRadius);
2896
2897    IntRect touchRect(touchCenter - touchRadius, touchRadius + touchRadius);
2898
2899    // FIXME: Should be able to handle targetNode being a shadow DOM node to avoid performing uncessary hit tests
2900    // in the case where further processing on the node is required. Returning the shadow ancestor prevents a
2901    // regression in touchadjustment/html-label.html. Some refinement is required to testing/internals to
2902    // handle targetNode being a shadow DOM node.
2903    bool success = findBestClickableCandidate(targetNode, targetPoint, touchCenter, touchRect, result.rectBasedTestResult());
2904    if (success && targetNode)
2905        targetNode = targetNode->deprecatedShadowAncestorNode();
2906    return success;
2907}
2908
2909bool EventHandler::bestContextMenuNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode)
2910{
2911    IntPoint hitTestPoint = m_frame->view()->windowToContents(touchCenter);
2912    HitTestResult result = hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active, touchRadius);
2913
2914    IntRect touchRect(touchCenter - touchRadius, touchRadius + touchRadius);
2915    return findBestContextMenuCandidate(targetNode, targetPoint, touchCenter, touchRect, result.rectBasedTestResult());
2916}
2917
2918bool EventHandler::bestZoomableAreaForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntRect& targetArea, Node*& targetNode)
2919{
2920    IntPoint hitTestPoint = m_frame->view()->windowToContents(touchCenter);
2921    HitTestResult result = hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent, touchRadius);
2922
2923    IntRect touchRect(touchCenter - touchRadius, touchRadius + touchRadius);
2924    return findBestZoomableArea(targetNode, targetArea, touchCenter, touchRect, result.rectBasedTestResult());
2925}
2926
2927bool EventHandler::adjustGesturePosition(const PlatformGestureEvent& gestureEvent, IntPoint& adjustedPoint)
2928{
2929    if (!shouldApplyTouchAdjustment(gestureEvent))
2930        return false;
2931
2932    Node* targetNode = 0;
2933    switch (gestureEvent.type()) {
2934    case PlatformEvent::GestureTap:
2935    case PlatformEvent::GestureTapDown:
2936        bestClickableNodeForTouchPoint(gestureEvent.position(), IntSize(gestureEvent.area().width() / 2, gestureEvent.area().height() / 2), adjustedPoint, targetNode);
2937        break;
2938    case PlatformEvent::GestureLongPress:
2939    case PlatformEvent::GestureLongTap:
2940    case PlatformEvent::GestureTwoFingerTap:
2941        bestContextMenuNodeForTouchPoint(gestureEvent.position(), IntSize(gestureEvent.area().width() / 2, gestureEvent.area().height() / 2), adjustedPoint, targetNode);
2942        break;
2943    default:
2944        // FIXME: Implement handling for other types as needed.
2945        ASSERT_NOT_REACHED();
2946    }
2947    return targetNode;
2948}
2949#endif
2950
2951#if ENABLE(CONTEXT_MENUS)
2952bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event)
2953{
2954    Document* doc = m_frame->document();
2955    FrameView* v = m_frame->view();
2956    if (!v)
2957        return false;
2958
2959    // Clear mouse press state to avoid initiating a drag while context menu is up.
2960    m_mousePressed = false;
2961    bool swallowEvent;
2962    LayoutPoint viewportPos = v->windowToContents(event.position());
2963    HitTestRequest request(HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
2964    MouseEventWithHitTestResults mev = doc->prepareMouseEvent(request, viewportPos, event);
2965
2966    if (m_frame->editor().behavior().shouldSelectOnContextualMenuClick()
2967        && !m_frame->selection()->contains(viewportPos)
2968        && !mev.scrollbar()
2969        // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse.
2970        // If the selection is non-editable, we do word selection to make it easier to use the contextual menu items
2971        // available for text selections.  But only if we're above text.
2972        && (m_frame->selection()->isContentEditable() || (mev.targetNode() && mev.targetNode()->isTextNode()))) {
2973        m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection
2974        selectClosestWordOrLinkFromMouseEvent(mev);
2975    }
2976
2977    swallowEvent = !dispatchMouseEvent(eventNames().contextmenuEvent, mev.targetNode(), true, 0, event, false);
2978
2979    return swallowEvent;
2980}
2981
2982bool EventHandler::sendContextMenuEventForKey()
2983{
2984    FrameView* view = m_frame->view();
2985    if (!view)
2986        return false;
2987
2988    Document* doc = m_frame->document();
2989    if (!doc)
2990        return false;
2991
2992    // Clear mouse press state to avoid initiating a drag while context menu is up.
2993    m_mousePressed = false;
2994
2995    static const int kContextMenuMargin = 1;
2996
2997#if OS(WINDOWS) && !OS(WINCE)
2998    int rightAligned = ::GetSystemMetrics(SM_MENUDROPALIGNMENT);
2999#else
3000    int rightAligned = 0;
3001#endif
3002    IntPoint location;
3003
3004    Element* focusedElement = doc->focusedElement();
3005    FrameSelection* selection = m_frame->selection();
3006    Position start = selection->selection().start();
3007
3008    if (start.deprecatedNode() && (selection->rootEditableElement() || selection->isRange())) {
3009        RefPtr<Range> selectionRange = selection->toNormalizedRange();
3010        IntRect firstRect = m_frame->editor().firstRectForRange(selectionRange.get());
3011
3012        int x = rightAligned ? firstRect.maxX() : firstRect.x();
3013        // In a multiline edit, firstRect.maxY() would endup on the next line, so -1.
3014        int y = firstRect.maxY() ? firstRect.maxY() - 1 : 0;
3015        location = IntPoint(x, y);
3016    } else if (focusedElement) {
3017        RenderBoxModelObject* box = focusedElement->renderBoxModelObject();
3018        if (!box)
3019            return false;
3020        IntRect clippedRect = box->pixelSnappedAbsoluteClippedOverflowRect();
3021        location = IntPoint(clippedRect.x(), clippedRect.maxY() - 1);
3022    } else {
3023        location = IntPoint(
3024            rightAligned ? view->contentsWidth() - kContextMenuMargin : kContextMenuMargin,
3025            kContextMenuMargin);
3026    }
3027
3028    m_frame->view()->setCursor(pointerCursor());
3029
3030    IntPoint position = view->contentsToRootView(location);
3031    IntPoint globalPosition = view->hostWindow()->rootViewToScreen(IntRect(position, IntSize())).location();
3032
3033    Node* targetNode = doc->focusedElement();
3034    if (!targetNode)
3035        targetNode = doc;
3036
3037    // Use the focused node as the target for hover and active.
3038    HitTestResult result(position);
3039    result.setInnerNode(targetNode);
3040    doc->updateHoverActiveState(HitTestRequest::Active | HitTestRequest::DisallowShadowContent, result.innerElement());
3041
3042    // The contextmenu event is a mouse event even when invoked using the keyboard.
3043    // This is required for web compatibility.
3044
3045#if OS(WINDOWS)
3046    PlatformEvent::Type eventType = PlatformEvent::MouseReleased;
3047#else
3048    PlatformEvent::Type eventType = PlatformEvent::MousePressed;
3049#endif
3050
3051    PlatformMouseEvent mouseEvent(position, globalPosition, RightButton, eventType, 1, false, false, false, false, WTF::currentTime());
3052
3053    return !dispatchMouseEvent(eventNames().contextmenuEvent, targetNode, true, 0, mouseEvent, false);
3054}
3055
3056#if ENABLE(GESTURE_EVENTS)
3057bool EventHandler::sendContextMenuEventForGesture(const PlatformGestureEvent& event)
3058{
3059#if OS(WINDOWS)
3060    PlatformEvent::Type eventType = PlatformEvent::MouseReleased;
3061#else
3062    PlatformEvent::Type eventType = PlatformEvent::MousePressed;
3063#endif
3064
3065    IntPoint adjustedPoint = event.position();
3066#if ENABLE(TOUCH_ADJUSTMENT)
3067    adjustGesturePosition(event, adjustedPoint);
3068#endif
3069    PlatformMouseEvent mouseEvent(adjustedPoint, event.globalPosition(), RightButton, eventType, 1, false, false, false, false, WTF::currentTime());
3070    // To simulate right-click behavior, we send a right mouse down and then
3071    // context menu event.
3072    handleMousePressEvent(mouseEvent);
3073    return sendContextMenuEvent(mouseEvent);
3074    // We do not need to send a corresponding mouse release because in case of
3075    // right-click, the context menu takes capture and consumes all events.
3076}
3077#endif // ENABLE(GESTURE_EVENTS)
3078#endif // ENABLE(CONTEXT_MENUS)
3079
3080void EventHandler::scheduleHoverStateUpdate()
3081{
3082    if (!m_hoverTimer.isActive())
3083        m_hoverTimer.startOneShot(0);
3084}
3085
3086void EventHandler::scheduleCursorUpdate()
3087{
3088    if (!m_cursorUpdateTimer.isActive())
3089        m_cursorUpdateTimer.startOneShot(cursorUpdateInterval);
3090}
3091
3092void EventHandler::dispatchFakeMouseMoveEventSoon()
3093{
3094    if (m_mousePressed)
3095        return;
3096
3097    if (m_mousePositionIsUnknown)
3098        return;
3099
3100    Settings* settings = m_frame->settings();
3101    if (settings && !settings->deviceSupportsMouse())
3102        return;
3103
3104    // If the content has ever taken longer than fakeMouseMoveShortInterval we
3105    // reschedule the timer and use a longer time. This will cause the content
3106    // to receive these moves only after the user is done scrolling, reducing
3107    // pauses during the scroll.
3108    if (m_maxMouseMovedDuration > fakeMouseMoveDurationThreshold) {
3109        if (m_fakeMouseMoveEventTimer.isActive())
3110            m_fakeMouseMoveEventTimer.stop();
3111        m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveLongInterval);
3112    } else {
3113        if (!m_fakeMouseMoveEventTimer.isActive())
3114            m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveShortInterval);
3115    }
3116}
3117
3118void EventHandler::dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad& quad)
3119{
3120    FrameView* view = m_frame->view();
3121    if (!view)
3122        return;
3123
3124    if (!quad.containsPoint(view->windowToContents(m_lastKnownMousePosition)))
3125        return;
3126
3127    dispatchFakeMouseMoveEventSoon();
3128}
3129
3130void EventHandler::cancelFakeMouseMoveEvent()
3131{
3132    m_fakeMouseMoveEventTimer.stop();
3133}
3134
3135void EventHandler::fakeMouseMoveEventTimerFired(Timer<EventHandler>* timer)
3136{
3137    ASSERT_UNUSED(timer, timer == &m_fakeMouseMoveEventTimer);
3138    ASSERT(!m_mousePressed);
3139
3140    Settings* settings = m_frame->settings();
3141    if (settings && !settings->deviceSupportsMouse())
3142        return;
3143
3144    FrameView* view = m_frame->view();
3145    if (!view)
3146        return;
3147
3148    if (!m_frame->page() || !m_frame->page()->isOnscreen() || !m_frame->page()->focusController()->isActive())
3149        return;
3150
3151    bool shiftKey;
3152    bool ctrlKey;
3153    bool altKey;
3154    bool metaKey;
3155    PlatformKeyboardEvent::getCurrentModifierState(shiftKey, ctrlKey, altKey, metaKey);
3156    PlatformMouseEvent fakeMouseMoveEvent(m_lastKnownMousePosition, m_lastKnownMouseGlobalPosition, NoButton, PlatformEvent::MouseMoved, 0, shiftKey, ctrlKey, altKey, metaKey, currentTime());
3157    mouseMoved(fakeMouseMoveEvent);
3158}
3159
3160void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet)
3161{
3162    m_frameSetBeingResized = frameSet;
3163}
3164
3165void EventHandler::resizeLayerDestroyed()
3166{
3167    ASSERT(m_resizeLayer);
3168    m_resizeLayer = 0;
3169}
3170
3171void EventHandler::hoverTimerFired(Timer<EventHandler>*)
3172{
3173    m_hoverTimer.stop();
3174
3175    ASSERT(m_frame);
3176    ASSERT(m_frame->document());
3177
3178    if (RenderView* renderer = m_frame->contentRenderer()) {
3179        if (FrameView* view = m_frame->view()) {
3180            HitTestRequest request(HitTestRequest::Move | HitTestRequest::DisallowShadowContent);
3181            HitTestResult result(view->windowToContents(m_lastKnownMousePosition));
3182            renderer->hitTest(request, result);
3183            m_frame->document()->updateHoverActiveState(request, result.innerElement());
3184        }
3185    }
3186}
3187
3188bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& evt)
3189{
3190    // FIXME: Ignoring the state of Shift key is what neither IE nor Firefox do.
3191    // IE matches lower and upper case access keys regardless of Shift key state - but if both upper and
3192    // lower case variants are present in a document, the correct element is matched based on Shift key state.
3193    // Firefox only matches an access key if Shift is not pressed, and does that case-insensitively.
3194    ASSERT(!(accessKeyModifiers() & PlatformEvent::ShiftKey));
3195    if ((evt.modifiers() & ~PlatformEvent::ShiftKey) != accessKeyModifiers())
3196        return false;
3197    String key = evt.unmodifiedText();
3198    Element* elem = m_frame->document()->getElementByAccessKey(key.lower());
3199    if (!elem)
3200        return false;
3201    elem->accessKeyAction(false);
3202    return true;
3203}
3204
3205#if !PLATFORM(MAC)
3206bool EventHandler::needsKeyboardEventDisambiguationQuirks() const
3207{
3208    return false;
3209}
3210#endif
3211
3212#if ENABLE(FULLSCREEN_API)
3213bool EventHandler::isKeyEventAllowedInFullScreen(const PlatformKeyboardEvent& keyEvent) const
3214{
3215    Document* document = m_frame->document();
3216    if (document->webkitFullScreenKeyboardInputAllowed())
3217        return true;
3218
3219    if (keyEvent.type() == PlatformKeyboardEvent::Char) {
3220        if (keyEvent.text().length() != 1)
3221            return false;
3222        UChar character = keyEvent.text()[0];
3223        return character == ' ';
3224    }
3225
3226    int keyCode = keyEvent.windowsVirtualKeyCode();
3227    return (keyCode >= VK_BACK && keyCode <= VK_CAPITAL)
3228        || (keyCode >= VK_SPACE && keyCode <= VK_DELETE)
3229        || (keyCode >= VK_OEM_1 && keyCode <= VK_OEM_PLUS)
3230        || (keyCode >= VK_MULTIPLY && keyCode <= VK_OEM_8);
3231}
3232#endif
3233
3234bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent)
3235{
3236    RefPtr<FrameView> protector(m_frame->view());
3237
3238#if ENABLE(FULLSCREEN_API)
3239    if (m_frame->document()->webkitIsFullScreen() && !isKeyEventAllowedInFullScreen(initialKeyEvent))
3240        return false;
3241#endif
3242
3243    if (initialKeyEvent.windowsVirtualKeyCode() == VK_CAPITAL)
3244        capsLockStateMayHaveChanged();
3245
3246#if ENABLE(PAN_SCROLLING)
3247    if (Page* page = m_frame->page()) {
3248        if (page->mainFrame()->eventHandler()->panScrollInProgress()) {
3249            // If a key is pressed while the panScroll is in progress then we want to stop
3250            if (initialKeyEvent.type() == PlatformEvent::KeyDown || initialKeyEvent.type() == PlatformEvent::RawKeyDown)
3251                stopAutoscrollTimer();
3252
3253            // If we were in panscroll mode, we swallow the key event
3254            return true;
3255        }
3256    }
3257#endif
3258
3259    // Check for cases where we are too early for events -- possible unmatched key up
3260    // from pressing return in the location bar.
3261    RefPtr<Node> node = eventTargetNodeForDocument(m_frame->document());
3262    if (!node)
3263        return false;
3264
3265    UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
3266    UserTypingGestureIndicator typingGestureIndicator(m_frame);
3267
3268    if (FrameView* view = m_frame->view())
3269        view->resetDeferredRepaintDelay();
3270
3271    // FIXME (bug 68185): this call should be made at another abstraction layer
3272    m_frame->loader()->resetMultipleFormSubmissionProtection();
3273
3274    // In IE, access keys are special, they are handled after default keydown processing, but cannot be canceled - this is hard to match.
3275    // On Mac OS X, we process them before dispatching keydown, as the default keydown handler implements Emacs key bindings, which may conflict
3276    // with access keys. Then we dispatch keydown, but suppress its default handling.
3277    // On Windows, WebKit explicitly calls handleAccessKey() instead of dispatching a keypress event for WM_SYSCHAR messages.
3278    // Other platforms currently match either Mac or Windows behavior, depending on whether they send combined KeyDown events.
3279    bool matchedAnAccessKey = false;
3280    if (initialKeyEvent.type() == PlatformEvent::KeyDown)
3281        matchedAnAccessKey = handleAccessKey(initialKeyEvent);
3282
3283    // FIXME: it would be fair to let an input method handle KeyUp events before DOM dispatch.
3284    if (initialKeyEvent.type() == PlatformEvent::KeyUp || initialKeyEvent.type() == PlatformEvent::Char)
3285        return !node->dispatchKeyEvent(initialKeyEvent);
3286
3287    bool backwardCompatibilityMode = needsKeyboardEventDisambiguationQuirks();
3288
3289    PlatformKeyboardEvent keyDownEvent = initialKeyEvent;
3290    if (keyDownEvent.type() != PlatformEvent::RawKeyDown)
3291        keyDownEvent.disambiguateKeyDownEvent(PlatformEvent::RawKeyDown, backwardCompatibilityMode);
3292    RefPtr<KeyboardEvent> keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->defaultView());
3293    if (matchedAnAccessKey)
3294        keydown->setDefaultPrevented(true);
3295    keydown->setTarget(node);
3296
3297    if (initialKeyEvent.type() == PlatformEvent::RawKeyDown) {
3298        node->dispatchEvent(keydown, IGNORE_EXCEPTION);
3299        // If frame changed as a result of keydown dispatch, then return true to avoid sending a subsequent keypress message to the new frame.
3300        bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController()->focusedOrMainFrame();
3301        return keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame;
3302    }
3303
3304    // Run input method in advance of DOM event handling.  This may result in the IM
3305    // modifying the page prior the keydown event, but this behaviour is necessary
3306    // in order to match IE:
3307    // 1. preventing default handling of keydown and keypress events has no effect on IM input;
3308    // 2. if an input method handles the event, its keyCode is set to 229 in keydown event.
3309    m_frame->editor().handleInputMethodKeydown(keydown.get());
3310
3311    bool handledByInputMethod = keydown->defaultHandled();
3312
3313    if (handledByInputMethod) {
3314        keyDownEvent.setWindowsVirtualKeyCode(CompositionEventKeyCode);
3315        keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->defaultView());
3316        keydown->setTarget(node);
3317        keydown->setDefaultHandled();
3318    }
3319
3320    node->dispatchEvent(keydown, IGNORE_EXCEPTION);
3321    // If frame changed as a result of keydown dispatch, then return early to avoid sending a subsequent keypress message to the new frame.
3322    bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController()->focusedOrMainFrame();
3323    bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame;
3324    if (handledByInputMethod || (keydownResult && !backwardCompatibilityMode))
3325        return keydownResult;
3326
3327    // Focus may have changed during keydown handling, so refetch node.
3328    // But if we are dispatching a fake backward compatibility keypress, then we pretend that the keypress happened on the original node.
3329    if (!keydownResult) {
3330        node = eventTargetNodeForDocument(m_frame->document());
3331        if (!node)
3332            return false;
3333    }
3334
3335    PlatformKeyboardEvent keyPressEvent = initialKeyEvent;
3336    keyPressEvent.disambiguateKeyDownEvent(PlatformEvent::Char, backwardCompatibilityMode);
3337    if (keyPressEvent.text().isEmpty())
3338        return keydownResult;
3339    RefPtr<KeyboardEvent> keypress = KeyboardEvent::create(keyPressEvent, m_frame->document()->defaultView());
3340    keypress->setTarget(node);
3341    if (keydownResult)
3342        keypress->setDefaultPrevented(true);
3343#if PLATFORM(MAC)
3344    keypress->keypressCommands() = keydown->keypressCommands();
3345#endif
3346    node->dispatchEvent(keypress, IGNORE_EXCEPTION);
3347
3348    return keydownResult || keypress->defaultPrevented() || keypress->defaultHandled();
3349}
3350
3351static FocusDirection focusDirectionForKey(const AtomicString& keyIdentifier)
3352{
3353    DEFINE_STATIC_LOCAL(AtomicString, Down, ("Down", AtomicString::ConstructFromLiteral));
3354    DEFINE_STATIC_LOCAL(AtomicString, Up, ("Up", AtomicString::ConstructFromLiteral));
3355    DEFINE_STATIC_LOCAL(AtomicString, Left, ("Left", AtomicString::ConstructFromLiteral));
3356    DEFINE_STATIC_LOCAL(AtomicString, Right, ("Right", AtomicString::ConstructFromLiteral));
3357
3358    FocusDirection retVal = FocusDirectionNone;
3359
3360    if (keyIdentifier == Down)
3361        retVal = FocusDirectionDown;
3362    else if (keyIdentifier == Up)
3363        retVal = FocusDirectionUp;
3364    else if (keyIdentifier == Left)
3365        retVal = FocusDirectionLeft;
3366    else if (keyIdentifier == Right)
3367        retVal = FocusDirectionRight;
3368
3369    return retVal;
3370}
3371
3372static void handleKeyboardSelectionMovement(FrameSelection* selection, KeyboardEvent* event)
3373{
3374    if (!event)
3375        return;
3376
3377    bool isOptioned = event->getModifierState("Alt");
3378    bool isCommanded = event->getModifierState("Meta");
3379
3380    SelectionDirection direction = DirectionForward;
3381    TextGranularity granularity = CharacterGranularity;
3382
3383    switch (focusDirectionForKey(event->keyIdentifier())) {
3384    case FocusDirectionNone:
3385        return;
3386    case FocusDirectionForward:
3387    case FocusDirectionBackward:
3388        ASSERT_NOT_REACHED();
3389        return;
3390    case FocusDirectionUp:
3391        direction = DirectionBackward;
3392        granularity = isCommanded ? DocumentBoundary : LineGranularity;
3393        break;
3394    case FocusDirectionDown:
3395        direction = DirectionForward;
3396        granularity = isCommanded ? DocumentBoundary : LineGranularity;
3397        break;
3398    case FocusDirectionLeft:
3399        direction = DirectionLeft;
3400        granularity = (isCommanded) ? LineBoundary : (isOptioned) ? WordGranularity : CharacterGranularity;
3401        break;
3402    case FocusDirectionRight:
3403        direction = DirectionRight;
3404        granularity = (isCommanded) ? LineBoundary : (isOptioned) ? WordGranularity : CharacterGranularity;
3405        break;
3406    }
3407
3408    FrameSelection::EAlteration alternation = event->getModifierState("Shift") ? FrameSelection::AlterationExtend : FrameSelection::AlterationMove;
3409    selection->modify(alternation, direction, granularity, UserTriggered);
3410    event->setDefaultHandled();
3411}
3412
3413void EventHandler::handleKeyboardSelectionMovementForAccessibility(KeyboardEvent* event)
3414{
3415    if (event->type() == eventNames().keydownEvent) {
3416        if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled())
3417            handleKeyboardSelectionMovement(m_frame->selection(), event);
3418    }
3419}
3420
3421void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event)
3422{
3423    if (event->type() == eventNames().keydownEvent) {
3424        m_frame->editor().handleKeyboardEvent(event);
3425        if (event->defaultHandled())
3426            return;
3427        if (event->keyIdentifier() == "U+0009")
3428            defaultTabEventHandler(event);
3429        else if (event->keyIdentifier() == "U+0008")
3430            defaultBackspaceEventHandler(event);
3431        else {
3432            FocusDirection direction = focusDirectionForKey(event->keyIdentifier());
3433            if (direction != FocusDirectionNone)
3434                defaultArrowEventHandler(direction, event);
3435        }
3436
3437        handleKeyboardSelectionMovementForAccessibility(event);
3438    }
3439    if (event->type() == eventNames().keypressEvent) {
3440        m_frame->editor().handleKeyboardEvent(event);
3441        if (event->defaultHandled())
3442            return;
3443        if (event->charCode() == ' ')
3444            defaultSpaceEventHandler(event);
3445    }
3446}
3447
3448#if ENABLE(DRAG_SUPPORT)
3449bool EventHandler::dragHysteresisExceeded(const IntPoint& floatDragViewportLocation) const
3450{
3451    FloatPoint dragViewportLocation(floatDragViewportLocation.x(), floatDragViewportLocation.y());
3452    return dragHysteresisExceeded(dragViewportLocation);
3453}
3454
3455bool EventHandler::dragHysteresisExceeded(const FloatPoint& dragViewportLocation) const
3456{
3457    FrameView* view = m_frame->view();
3458    if (!view)
3459        return false;
3460    IntPoint dragLocation = view->windowToContents(flooredIntPoint(dragViewportLocation));
3461    IntSize delta = dragLocation - m_mouseDownPos;
3462
3463    int threshold = GeneralDragHysteresis;
3464    switch (dragState().type) {
3465    case DragSourceActionSelection:
3466        threshold = TextDragHysteresis;
3467        break;
3468    case DragSourceActionImage:
3469        threshold = ImageDragHysteresis;
3470        break;
3471    case DragSourceActionLink:
3472        threshold = LinkDragHysteresis;
3473        break;
3474    case DragSourceActionDHTML:
3475        break;
3476    case DragSourceActionNone:
3477    case DragSourceActionAny:
3478        ASSERT_NOT_REACHED();
3479    }
3480
3481    return abs(delta.width()) >= threshold || abs(delta.height()) >= threshold;
3482}
3483
3484void EventHandler::freeClipboard()
3485{
3486    if (!dragState().clipboard)
3487        return;
3488    dragState().clipboard->setAccessPolicy(ClipboardNumb);
3489    dragState().clipboard = 0;
3490}
3491
3492void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, DragOperation operation)
3493{
3494    // Send a hit test request so that RenderLayer gets a chance to update the :hover and :active pseudoclasses.
3495    HitTestRequest request(HitTestRequest::Release | HitTestRequest::DisallowShadowContent);
3496    prepareMouseEvent(request, event);
3497
3498    if (dragState().source && dragState().shouldDispatchEvents) {
3499        dragState().clipboard->setDestinationOperation(operation);
3500        // For now we don't care if event handler cancels default behavior, since there is no default behavior.
3501        dispatchDragSrcEvent(eventNames().dragendEvent, event);
3502    }
3503    freeClipboard();
3504    dragState().source = 0;
3505    // In case the drag was ended due to an escape key press we need to ensure
3506    // that consecutive mousemove events don't reinitiate the drag and drop.
3507    m_mouseDownMayStartDrag = false;
3508}
3509
3510void EventHandler::updateDragStateAfterEditDragIfNeeded(Element* rootEditableElement)
3511{
3512    // If inserting the dragged contents removed the drag source, we still want to fire dragend at the root editable element.
3513    if (dragState().source && !dragState().source->inDocument())
3514        dragState().source = rootEditableElement;
3515}
3516
3517// Return value indicates if we should continue "default processing", i.e., whether event handler canceled.
3518bool EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent& event)
3519{
3520    return !dispatchDragEvent(eventType, dragState().source.get(), event, dragState().clipboard.get());
3521}
3522
3523static bool ExactlyOneBitSet(DragSourceAction n)
3524{
3525    return n && !(n & (n - 1));
3526}
3527
3528bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, CheckDragHysteresis checkDragHysteresis)
3529{
3530    if (event.event().button() != LeftButton || event.event().type() != PlatformEvent::MouseMoved) {
3531        // If we allowed the other side of the bridge to handle a drag
3532        // last time, then m_mousePressed might still be set. So we
3533        // clear it now to make sure the next move after a drag
3534        // doesn't look like a drag.
3535        m_mousePressed = false;
3536        return false;
3537    }
3538
3539    if (eventLoopHandleMouseDragged(event))
3540        return true;
3541
3542    // Careful that the drag starting logic stays in sync with eventMayStartDrag()
3543
3544    if (m_mouseDownMayStartDrag && !dragState().source) {
3545        dragState().shouldDispatchEvents = (updateDragSourceActionsAllowed() & DragSourceActionDHTML);
3546
3547        // try to find an element that wants to be dragged
3548        HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent);
3549        HitTestResult result(m_mouseDownPos);
3550        m_frame->contentRenderer()->hitTest(request, result);
3551        if (m_frame->page())
3552            dragState().source = m_frame->page()->dragController()->draggableElement(m_frame, result.innerElement(), m_mouseDownPos, dragState());
3553
3554        if (!dragState().source)
3555            m_mouseDownMayStartDrag = false; // no element is draggable
3556        else
3557            m_dragMayStartSelectionInstead = (dragState().type & DragSourceActionSelection);
3558    }
3559
3560    // For drags starting in the selection, the user must wait between the mousedown and mousedrag,
3561    // or else we bail on the dragging stuff and allow selection to occur
3562    if (m_mouseDownMayStartDrag && m_dragMayStartSelectionInstead && (dragState().type & DragSourceActionSelection) && event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay) {
3563        ASSERT(event.event().type() == PlatformEvent::MouseMoved);
3564        if ((dragState().type & DragSourceActionImage)) {
3565            // ... unless the mouse is over an image, then we start dragging just the image
3566            dragState().type = DragSourceActionImage;
3567        } else if (!(dragState().type & (DragSourceActionDHTML | DragSourceActionLink))) {
3568            // ... but only bail if we're not over an unselectable element.
3569            m_mouseDownMayStartDrag = false;
3570            dragState().source = 0;
3571            // ... but if this was the first click in the window, we don't even want to start selection
3572            if (eventActivatedView(event.event()))
3573                m_mouseDownMayStartSelect = false;
3574        } else {
3575            // Prevent the following case from occuring:
3576            // 1. User starts a drag immediately after mouse down over an unselectable element.
3577            // 2. We enter this block and decided that since we're over an unselectable element, don't cancel the drag.
3578            // 3. The drag gets resolved as a potential selection drag below /but/ we haven't exceeded the drag hysteresis yet.
3579            // 4. We enter this block again, and since it's now marked as a selection drag, we cancel the drag.
3580            m_dragMayStartSelectionInstead = false;
3581        }
3582    }
3583
3584    if (!m_mouseDownMayStartDrag)
3585        return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll;
3586
3587    if (!ExactlyOneBitSet(dragState().type)) {
3588        ASSERT((dragState().type & DragSourceActionSelection));
3589        ASSERT((dragState().type & ~DragSourceActionSelection) == DragSourceActionDHTML
3590            || (dragState().type & ~DragSourceActionSelection) == DragSourceActionImage
3591            || (dragState().type & ~DragSourceActionSelection) == DragSourceActionLink);
3592        dragState().type = DragSourceActionSelection;
3593    }
3594
3595    // We are starting a text/image/url drag, so the cursor should be an arrow
3596    if (FrameView* view = m_frame->view()) {
3597        // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and drop (default to pointer).
3598        view->setCursor(pointerCursor());
3599    }
3600
3601    if (checkDragHysteresis == ShouldCheckDragHysteresis && !dragHysteresisExceeded(event.event().position()))
3602        return true;
3603
3604    // Once we're past the hysteresis point, we don't want to treat this gesture as a click
3605    invalidateClick();
3606
3607    DragOperation srcOp = DragOperationNone;
3608
3609    // This does work only if we missed a dragEnd. Do it anyway, just to make sure the old clipboard gets numbed.
3610    freeClipboard();
3611
3612    dragState().clipboard = createDraggingClipboard();
3613
3614    if (dragState().shouldDispatchEvents) {
3615        // Check to see if the is a DOM based drag. If it is, get the DOM specified drag image and offset.
3616        if (dragState().type == DragSourceActionDHTML) {
3617            if (RenderObject* renderer = dragState().source->renderer()) {
3618                // FIXME: This doesn't work correctly with transforms.
3619                FloatPoint absPos = renderer->localToAbsolute();
3620                IntSize delta = m_mouseDownPos - roundedIntPoint(absPos);
3621                dragState().clipboard->setDragImage(dragState().source.get(), delta.width(), delta.height());
3622            } else {
3623                // The renderer has disappeared, this can happen if the onStartDrag handler has hidden
3624                // the element in some way.  In this case we just kill the drag.
3625                m_mouseDownMayStartDrag = false;
3626                goto cleanupDrag;
3627            }
3628        }
3629
3630        m_mouseDownMayStartDrag = dispatchDragSrcEvent(eventNames().dragstartEvent, m_mouseDown)
3631            && !m_frame->selection()->isInPasswordField();
3632
3633        // Invalidate clipboard here against anymore pasteboard writing for security.  The drag
3634        // image can still be changed as we drag, but not the pasteboard data.
3635        dragState().clipboard->setAccessPolicy(ClipboardImageWritable);
3636
3637        if (m_mouseDownMayStartDrag) {
3638            // Gather values from DHTML element, if it set any.
3639            srcOp = dragState().clipboard->sourceOperation();
3640
3641            // Yuck, a draggedImage:moveTo: message can be fired as a result of kicking off the
3642            // drag with dragImage! Because of that dumb reentrancy, we may think we've not
3643            // started the drag when that happens. So we have to assume it's started before we kick it off.
3644            dragState().clipboard->setDragHasStarted();
3645        }
3646    }
3647
3648    if (m_mouseDownMayStartDrag) {
3649        Page* page = m_frame->page();
3650        DragController* dragController = page ? page->dragController() : 0;
3651        m_didStartDrag = dragController && dragController->startDrag(m_frame, dragState(), srcOp, event.event(), m_mouseDownPos);
3652        // In WebKit2 we could re-enter this code and start another drag.
3653        // On OS X this causes problems with the ownership of the pasteboard and the promised types.
3654        if (m_didStartDrag) {
3655            m_mouseDownMayStartDrag = false;
3656            return true;
3657        }
3658        if (dragState().source && dragState().shouldDispatchEvents) {
3659            // Drag was canned at the last minute. We owe dragSource a dragend event.
3660            dispatchDragSrcEvent(eventNames().dragendEvent, event.event());
3661            m_mouseDownMayStartDrag = false;
3662        }
3663    }
3664
3665cleanupDrag:
3666    if (!m_mouseDownMayStartDrag) {
3667        // Something failed to start the drag, clean up.
3668        freeClipboard();
3669        dragState().source = 0;
3670    }
3671
3672    // No more default handling (like selection), whether we're past the hysteresis bounds or not
3673    return true;
3674}
3675#endif // ENABLE(DRAG_SUPPORT)
3676
3677bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEvent, TextEventInputType inputType)
3678{
3679    // Platforms should differentiate real commands like selectAll from text input in disguise (like insertNewline),
3680    // and avoid dispatching text input events from keydown default handlers.
3681    ASSERT(!underlyingEvent || !underlyingEvent->isKeyboardEvent() || static_cast<KeyboardEvent*>(underlyingEvent)->type() == eventNames().keypressEvent);
3682
3683    if (!m_frame)
3684        return false;
3685
3686    EventTarget* target;
3687    if (underlyingEvent)
3688        target = underlyingEvent->target();
3689    else
3690        target = eventTargetNodeForDocument(m_frame->document());
3691    if (!target)
3692        return false;
3693
3694    if (FrameView* view = m_frame->view())
3695        view->resetDeferredRepaintDelay();
3696
3697    RefPtr<TextEvent> event = TextEvent::create(m_frame->document()->domWindow(), text, inputType);
3698    event->setUnderlyingEvent(underlyingEvent);
3699
3700    target->dispatchEvent(event, IGNORE_EXCEPTION);
3701    return event->defaultHandled();
3702}
3703
3704bool EventHandler::isKeyboardOptionTab(KeyboardEvent* event)
3705{
3706    return event
3707        && (event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent)
3708        && event->altKey()
3709        && event->keyIdentifier() == "U+0009";
3710}
3711
3712bool EventHandler::eventInvertsTabsToLinksClientCallResult(KeyboardEvent* event)
3713{
3714#if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(EFL)
3715    return EventHandler::isKeyboardOptionTab(event);
3716#else
3717    return false;
3718#endif
3719}
3720
3721bool EventHandler::tabsToLinks(KeyboardEvent* event) const
3722{
3723    // FIXME: This function needs a better name. It can be called for keypresses other than Tab when spatial navigation is enabled.
3724
3725    Page* page = m_frame->page();
3726    if (!page)
3727        return false;
3728
3729    bool tabsToLinksClientCallResult = page->chrome().client()->keyboardUIMode() & KeyboardAccessTabsToLinks;
3730    return eventInvertsTabsToLinksClientCallResult(event) ? !tabsToLinksClientCallResult : tabsToLinksClientCallResult;
3731}
3732
3733void EventHandler::defaultTextInputEventHandler(TextEvent* event)
3734{
3735    if (m_frame->editor().handleTextEvent(event))
3736        event->setDefaultHandled();
3737}
3738
3739
3740void EventHandler::defaultSpaceEventHandler(KeyboardEvent* event)
3741{
3742    ASSERT(event->type() == eventNames().keypressEvent);
3743
3744    if (event->ctrlKey() || event->metaKey() || event->altKey() || event->altGraphKey())
3745        return;
3746
3747    ScrollLogicalDirection direction = event->shiftKey() ? ScrollBlockDirectionBackward : ScrollBlockDirectionForward;
3748    if (logicalScrollOverflow(direction, ScrollByPage)) {
3749        event->setDefaultHandled();
3750        return;
3751    }
3752
3753    FrameView* view = m_frame->view();
3754    if (!view)
3755        return;
3756
3757    if (view->logicalScroll(direction, ScrollByPage))
3758        event->setDefaultHandled();
3759}
3760
3761void EventHandler::defaultBackspaceEventHandler(KeyboardEvent* event)
3762{
3763    ASSERT(event->type() == eventNames().keydownEvent);
3764
3765    if (event->ctrlKey() || event->metaKey() || event->altKey() || event->altGraphKey())
3766        return;
3767
3768    if (!m_frame->editor().behavior().shouldNavigateBackOnBackspace())
3769        return;
3770
3771    Page* page = m_frame->page();
3772    if (!page)
3773        return;
3774
3775    if (!m_frame->settings()->backspaceKeyNavigationEnabled())
3776        return;
3777
3778    bool handledEvent = false;
3779
3780    if (event->shiftKey())
3781        handledEvent = page->goForward();
3782    else
3783        handledEvent = page->goBack();
3784
3785    if (handledEvent)
3786        event->setDefaultHandled();
3787}
3788
3789
3790void EventHandler::defaultArrowEventHandler(FocusDirection focusDirection, KeyboardEvent* event)
3791{
3792    ASSERT(event->type() == eventNames().keydownEvent);
3793
3794    if (event->ctrlKey() || event->metaKey() || event->altGraphKey() || event->shiftKey())
3795        return;
3796
3797    Page* page = m_frame->page();
3798    if (!page)
3799        return;
3800
3801    if (!isSpatialNavigationEnabled(m_frame))
3802        return;
3803
3804    // Arrows and other possible directional navigation keys can be used in design
3805    // mode editing.
3806    if (m_frame->document()->inDesignMode())
3807        return;
3808
3809    if (page->focusController()->advanceFocus(focusDirection, event))
3810        event->setDefaultHandled();
3811}
3812
3813void EventHandler::defaultTabEventHandler(KeyboardEvent* event)
3814{
3815    ASSERT(event->type() == eventNames().keydownEvent);
3816
3817    // We should only advance focus on tabs if no special modifier keys are held down.
3818    if (event->ctrlKey() || event->metaKey() || event->altGraphKey())
3819        return;
3820
3821    Page* page = m_frame->page();
3822    if (!page)
3823        return;
3824    if (!page->tabKeyCyclesThroughElements())
3825        return;
3826
3827    FocusDirection focusDirection = event->shiftKey() ? FocusDirectionBackward : FocusDirectionForward;
3828
3829    // Tabs can be used in design mode editing.
3830    if (m_frame->document()->inDesignMode())
3831        return;
3832
3833    if (page->focusController()->advanceFocus(focusDirection, event))
3834        event->setDefaultHandled();
3835}
3836
3837void EventHandler::capsLockStateMayHaveChanged()
3838{
3839    Document* d = m_frame->document();
3840    if (Element* element = d->focusedElement()) {
3841        if (RenderObject* r = element->renderer()) {
3842            if (r->isTextField())
3843                toRenderTextControlSingleLine(r)->capsLockStateMayHaveChanged();
3844        }
3845    }
3846}
3847
3848void EventHandler::sendScrollEvent()
3849{
3850    setFrameWasScrolledByUser();
3851    if (m_frame->view() && m_frame->document())
3852        m_frame->document()->eventQueue()->enqueueOrDispatchScrollEvent(m_frame->document(), DocumentEventQueue::ScrollEventDocumentTarget);
3853}
3854
3855void EventHandler::setFrameWasScrolledByUser()
3856{
3857    FrameView* v = m_frame->view();
3858    if (v)
3859        v->setWasScrolledByUser(true);
3860}
3861
3862bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults& mev, Scrollbar* scrollbar)
3863{
3864    if (!scrollbar || !scrollbar->enabled())
3865        return false;
3866    setFrameWasScrolledByUser();
3867    return scrollbar->mouseDown(mev.event());
3868}
3869
3870// If scrollbar (under mouse) is different from last, send a mouse exited. Set
3871// last to scrollbar if setLast is true; else set last to 0.
3872void EventHandler::updateLastScrollbarUnderMouse(Scrollbar* scrollbar, bool setLast)
3873{
3874    if (m_lastScrollbarUnderMouse != scrollbar) {
3875        // Send mouse exited to the old scrollbar.
3876        if (m_lastScrollbarUnderMouse)
3877            m_lastScrollbarUnderMouse->mouseExited();
3878
3879        // Send mouse entered if we're setting a new scrollbar.
3880        if (scrollbar && setLast)
3881            scrollbar->mouseEntered();
3882
3883        m_lastScrollbarUnderMouse = setLast ? scrollbar : 0;
3884    }
3885}
3886
3887#if ENABLE(TOUCH_EVENTS)
3888
3889static const AtomicString& eventNameForTouchPointState(PlatformTouchPoint::State state)
3890{
3891    switch (state) {
3892    case PlatformTouchPoint::TouchReleased:
3893        return eventNames().touchendEvent;
3894    case PlatformTouchPoint::TouchCancelled:
3895        return eventNames().touchcancelEvent;
3896    case PlatformTouchPoint::TouchPressed:
3897        return eventNames().touchstartEvent;
3898    case PlatformTouchPoint::TouchMoved:
3899        return eventNames().touchmoveEvent;
3900    case PlatformTouchPoint::TouchStationary:
3901        // TouchStationary state is not converted to touch events, so fall through to assert.
3902    default:
3903        ASSERT_NOT_REACHED();
3904        return emptyAtom;
3905    }
3906}
3907
3908HitTestResult EventHandler::hitTestResultInFrame(Frame* frame, const LayoutPoint& point, HitTestRequest::HitTestRequestType hitType)
3909{
3910    HitTestResult result(point);
3911
3912    if (!frame || !frame->contentRenderer())
3913        return result;
3914    if (frame->view()) {
3915        IntRect rect = frame->view()->visibleContentRect();
3916        if (!rect.contains(roundedIntPoint(point)))
3917            return result;
3918    }
3919    frame->contentRenderer()->hitTest(HitTestRequest(hitType), result);
3920    return result;
3921}
3922
3923bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
3924{
3925    // First build up the lists to use for the 'touches', 'targetTouches' and 'changedTouches' attributes
3926    // in the JS event. See http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/
3927    // for an overview of how these lists fit together.
3928
3929    // Holds the complete set of touches on the screen and will be used as the 'touches' list in the JS event.
3930    RefPtr<TouchList> touches = TouchList::create();
3931
3932    // A different view on the 'touches' list above, filtered and grouped by event target. Used for the
3933    // 'targetTouches' list in the JS event.
3934    typedef HashMap<EventTarget*, RefPtr<TouchList> > TargetTouchesMap;
3935    TargetTouchesMap touchesByTarget;
3936
3937    // Array of touches per state, used to assemble the 'changedTouches' list in the JS event.
3938    typedef HashSet<RefPtr<EventTarget> > EventTargetSet;
3939    struct {
3940        // The touches corresponding to the particular change state this struct instance represents.
3941        RefPtr<TouchList> m_touches;
3942        // Set of targets involved in m_touches.
3943        EventTargetSet m_targets;
3944    } changedTouches[PlatformTouchPoint::TouchStateEnd];
3945
3946    const Vector<PlatformTouchPoint>& points = event.touchPoints();
3947
3948    UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
3949
3950    unsigned i;
3951    bool freshTouchEvents = true;
3952    bool allTouchReleased = true;
3953    for (i = 0; i < points.size(); ++i) {
3954        const PlatformTouchPoint& point = points[i];
3955        if (point.state() != PlatformTouchPoint::TouchPressed)
3956            freshTouchEvents = false;
3957        if (point.state() != PlatformTouchPoint::TouchReleased && point.state() != PlatformTouchPoint::TouchCancelled)
3958            allTouchReleased = false;
3959    }
3960
3961    for (i = 0; i < points.size(); ++i) {
3962        const PlatformTouchPoint& point = points[i];
3963        PlatformTouchPoint::State pointState = point.state();
3964        LayoutPoint pagePoint = documentPointForWindowPoint(m_frame, point.pos());
3965
3966        HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent;
3967        // The HitTestRequest types used for mouse events map quite adequately
3968        // to touch events. Note that in addition to meaning that the hit test
3969        // should affect the active state of the current node if necessary,
3970        // HitTestRequest::Active signifies that the hit test is taking place
3971        // with the mouse (or finger in this case) being pressed.
3972        switch (pointState) {
3973        case PlatformTouchPoint::TouchPressed:
3974            hitType |= HitTestRequest::Active;
3975            break;
3976        case PlatformTouchPoint::TouchMoved:
3977            hitType |= HitTestRequest::Active | HitTestRequest::Move | HitTestRequest::ReadOnly;
3978            break;
3979        case PlatformTouchPoint::TouchReleased:
3980        case PlatformTouchPoint::TouchCancelled:
3981            hitType |= HitTestRequest::Release;
3982            break;
3983        case PlatformTouchPoint::TouchStationary:
3984            hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly;
3985            break;
3986        default:
3987            ASSERT_NOT_REACHED();
3988            break;
3989        }
3990
3991        if (shouldGesturesTriggerActive())
3992            hitType |= HitTestRequest::ReadOnly;
3993
3994        // Increment the platform touch id by 1 to avoid storing a key of 0 in the hashmap.
3995        unsigned touchPointTargetKey = point.id() + 1;
3996        RefPtr<EventTarget> touchTarget;
3997        if (pointState == PlatformTouchPoint::TouchPressed) {
3998            HitTestResult result;
3999            if (freshTouchEvents) {
4000                result = hitTestResultAtPoint(pagePoint, hitType);
4001                m_originatingTouchPointTargetKey = touchPointTargetKey;
4002            } else if (m_originatingTouchPointDocument.get() && m_originatingTouchPointDocument->frame()) {
4003                LayoutPoint pagePointInOriginatingDocument = documentPointForWindowPoint(m_originatingTouchPointDocument->frame(), point.pos());
4004                result = hitTestResultInFrame(m_originatingTouchPointDocument->frame(), pagePointInOriginatingDocument, hitType);
4005                if (!result.innerNode())
4006                    continue;
4007            } else
4008                continue;
4009
4010            // FIXME: Is the following code different from just calling innerElement?
4011            Node* node = result.innerNode();
4012            ASSERT(node);
4013            // Touch events should not go to text nodes
4014            if (node->isTextNode())
4015                node = EventPathWalker::parent(node);
4016
4017            if (InspectorInstrumentation::handleTouchEvent(m_frame->page(), node))
4018                return true;
4019
4020            Document* doc = node->document();
4021            // Record the originating touch document even if it does not have a touch listener.
4022            if (freshTouchEvents) {
4023                m_originatingTouchPointDocument = doc;
4024                freshTouchEvents = false;
4025            }
4026            if (!doc)
4027                continue;
4028            if (!doc->hasTouchEventHandlers())
4029                continue;
4030            m_originatingTouchPointTargets.set(touchPointTargetKey, node);
4031            touchTarget = node;
4032        } else if (pointState == PlatformTouchPoint::TouchReleased || pointState == PlatformTouchPoint::TouchCancelled) {
4033            // No need to perform a hit-test since we only need to unset :hover and :active states.
4034            if (!shouldGesturesTriggerActive() && allTouchReleased)
4035                m_frame->document()->updateHoverActiveState(hitType, 0);
4036            if (touchPointTargetKey == m_originatingTouchPointTargetKey)
4037                m_originatingTouchPointTargetKey = 0;
4038
4039            // The target should be the original target for this touch, so get it from the hashmap. As it's a release or cancel
4040            // we also remove it from the map.
4041            touchTarget = m_originatingTouchPointTargets.take(touchPointTargetKey);
4042        } else
4043            // No hittest is performed on move or stationary, since the target is not allowed to change anyway.
4044            touchTarget = m_originatingTouchPointTargets.get(touchPointTargetKey);
4045
4046        if (!touchTarget.get())
4047            continue;
4048        Document* doc = touchTarget->toNode()->document();
4049        if (!doc)
4050            continue;
4051        if (!doc->hasTouchEventHandlers())
4052            continue;
4053        Frame* targetFrame = doc->frame();
4054        if (!targetFrame)
4055            continue;
4056
4057        if (m_frame != targetFrame) {
4058            // pagePoint should always be relative to the target elements containing frame.
4059            pagePoint = documentPointForWindowPoint(targetFrame, point.pos());
4060        }
4061
4062        float scaleFactor = targetFrame->pageZoomFactor() * targetFrame->frameScaleFactor();
4063
4064        int adjustedPageX = lroundf(pagePoint.x() / scaleFactor);
4065        int adjustedPageY = lroundf(pagePoint.y() / scaleFactor);
4066
4067        RefPtr<Touch> touch = Touch::create(targetFrame, touchTarget.get(), point.id(),
4068                                            point.screenPos().x(), point.screenPos().y(),
4069                                            adjustedPageX, adjustedPageY,
4070                                            point.radiusX(), point.radiusY(), point.rotationAngle(), point.force());
4071
4072        // Ensure this target's touch list exists, even if it ends up empty, so it can always be passed to TouchEvent::Create below.
4073        TargetTouchesMap::iterator targetTouchesIterator = touchesByTarget.find(touchTarget.get());
4074        if (targetTouchesIterator == touchesByTarget.end())
4075            targetTouchesIterator = touchesByTarget.set(touchTarget.get(), TouchList::create()).iterator;
4076
4077        // touches and targetTouches should only contain information about touches still on the screen, so if this point is
4078        // released or cancelled it will only appear in the changedTouches list.
4079        if (pointState != PlatformTouchPoint::TouchReleased && pointState != PlatformTouchPoint::TouchCancelled) {
4080            touches->append(touch);
4081            targetTouchesIterator->value->append(touch);
4082        }
4083
4084        // Now build up the correct list for changedTouches.
4085        // Note that  any touches that are in the TouchStationary state (e.g. if
4086        // the user had several points touched but did not move them all) should
4087        // never be in the changedTouches list so we do not handle them explicitly here.
4088        // See https://bugs.webkit.org/show_bug.cgi?id=37609 for further discussion
4089        // about the TouchStationary state.
4090        if (pointState != PlatformTouchPoint::TouchStationary) {
4091            ASSERT(pointState < PlatformTouchPoint::TouchStateEnd);
4092            if (!changedTouches[pointState].m_touches)
4093                changedTouches[pointState].m_touches = TouchList::create();
4094            changedTouches[pointState].m_touches->append(touch);
4095            changedTouches[pointState].m_targets.add(touchTarget);
4096        }
4097    }
4098    m_touchPressed = touches->length() > 0;
4099    if (allTouchReleased)
4100        m_originatingTouchPointDocument.clear();
4101
4102    // Now iterate the changedTouches list and m_targets within it, sending events to the targets as required.
4103    bool swallowedEvent = false;
4104    RefPtr<TouchList> emptyList = TouchList::create();
4105    for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; ++state) {
4106        if (!changedTouches[state].m_touches)
4107            continue;
4108
4109        // When sending a touch cancel event, use empty touches and targetTouches lists.
4110        bool isTouchCancelEvent = (state == PlatformTouchPoint::TouchCancelled);
4111        RefPtr<TouchList>& effectiveTouches(isTouchCancelEvent ? emptyList : touches);
4112        const AtomicString& stateName(eventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state)));
4113        const EventTargetSet& targetsForState = changedTouches[state].m_targets;
4114
4115        for (EventTargetSet::const_iterator it = targetsForState.begin(); it != targetsForState.end(); ++it) {
4116            EventTarget* touchEventTarget = it->get();
4117            RefPtr<TouchList> targetTouches(isTouchCancelEvent ? emptyList : touchesByTarget.get(touchEventTarget));
4118            ASSERT(targetTouches);
4119
4120            RefPtr<TouchEvent> touchEvent =
4121                TouchEvent::create(effectiveTouches.get(), targetTouches.get(), changedTouches[state].m_touches.get(),
4122                                   stateName, touchEventTarget->toNode()->document()->defaultView(),
4123                                   0, 0, 0, 0, event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey());
4124            touchEventTarget->toNode()->dispatchTouchEvent(touchEvent.get());
4125            swallowedEvent = swallowedEvent || touchEvent->defaultPrevented() || touchEvent->defaultHandled();
4126        }
4127    }
4128
4129    return swallowedEvent;
4130}
4131
4132bool EventHandler::dispatchSyntheticTouchEventIfEnabled(const PlatformMouseEvent& event)
4133{
4134    if (!m_frame || !m_frame->settings() || !m_frame->settings()->isTouchEventEmulationEnabled())
4135        return false;
4136
4137    PlatformEvent::Type eventType = event.type();
4138    if (eventType != PlatformEvent::MouseMoved && eventType != PlatformEvent::MousePressed && eventType != PlatformEvent::MouseReleased)
4139        return false;
4140
4141    HitTestRequest request(HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
4142    MouseEventWithHitTestResults mev = prepareMouseEvent(request, event);
4143    if (mev.scrollbar() || subframeForHitTestResult(mev))
4144        return false;
4145
4146    // The order is important. This check should follow the subframe test: http://webkit.org/b/111292.
4147    if (eventType == PlatformEvent::MouseMoved && !m_touchPressed)
4148        return true;
4149
4150    SyntheticSingleTouchEvent touchEvent(event);
4151    return handleTouchEvent(touchEvent);
4152}
4153
4154#endif
4155
4156void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event)
4157{
4158    m_mousePositionIsUnknown = false;
4159    m_lastKnownMousePosition = event.position();
4160    m_lastKnownMouseGlobalPosition = event.globalPosition();
4161}
4162
4163} // namespace WebCore
4164