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