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