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