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