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