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