Home | History | Annotate | Download | only in page
      1 /*
      2  * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
      3  * Copyright (C) 2006 Alexey Proskuryakov (ap (at) webkit.org)
      4  * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies)
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include "config.h"
     29 #include "core/page/EventHandler.h"
     30 
     31 #include "bindings/v8/ExceptionStatePlaceholder.h"
     32 #include "core/HTMLNames.h"
     33 #include "core/SVGNames.h"
     34 #include "core/clipboard/Clipboard.h"
     35 #include "core/clipboard/DataObject.h"
     36 #include "core/dom/Document.h"
     37 #include "core/dom/DocumentMarkerController.h"
     38 #include "core/dom/FullscreenElementStack.h"
     39 #include "core/dom/NodeRenderingTraversal.h"
     40 #include "core/dom/TouchList.h"
     41 #include "core/dom/shadow/ShadowRoot.h"
     42 #include "core/editing/Editor.h"
     43 #include "core/editing/FrameSelection.h"
     44 #include "core/editing/TextIterator.h"
     45 #include "core/editing/htmlediting.h"
     46 #include "core/events/DOMWindowEventQueue.h"
     47 #include "core/events/EventPath.h"
     48 #include "core/events/KeyboardEvent.h"
     49 #include "core/events/MouseEvent.h"
     50 #include "core/events/TextEvent.h"
     51 #include "core/events/TouchEvent.h"
     52 #include "core/events/WheelEvent.h"
     53 #include "core/fetch/ImageResource.h"
     54 #include "core/frame/FrameView.h"
     55 #include "core/frame/LocalFrame.h"
     56 #include "core/html/HTMLDialogElement.h"
     57 #include "core/html/HTMLFrameElementBase.h"
     58 #include "core/html/HTMLFrameSetElement.h"
     59 #include "core/html/HTMLInputElement.h"
     60 #include "core/loader/FrameLoader.h"
     61 #include "core/loader/FrameLoaderClient.h"
     62 #include "core/page/AutoscrollController.h"
     63 #include "core/page/BackForwardClient.h"
     64 #include "core/page/Chrome.h"
     65 #include "core/page/ChromeClient.h"
     66 #include "core/page/DragController.h"
     67 #include "core/page/DragState.h"
     68 #include "core/page/EditorClient.h"
     69 #include "core/page/FocusController.h"
     70 #include "core/page/FrameTree.h"
     71 #include "core/inspector/InspectorController.h"
     72 #include "core/page/MouseEventWithHitTestResults.h"
     73 #include "core/page/Page.h"
     74 #include "core/frame/Settings.h"
     75 #include "core/page/SpatialNavigation.h"
     76 #include "core/page/TouchAdjustment.h"
     77 #include "core/rendering/HitTestRequest.h"
     78 #include "core/rendering/HitTestResult.h"
     79 #include "core/rendering/RenderFlowThread.h"
     80 #include "core/rendering/RenderLayer.h"
     81 #include "core/rendering/RenderTextControlSingleLine.h"
     82 #include "core/rendering/RenderView.h"
     83 #include "core/rendering/RenderWidget.h"
     84 #include "core/rendering/style/RenderStyle.h"
     85 #include "core/svg/SVGDocumentExtensions.h"
     86 #include "platform/PlatformGestureEvent.h"
     87 #include "platform/PlatformKeyboardEvent.h"
     88 #include "platform/PlatformTouchEvent.h"
     89 #include "platform/PlatformWheelEvent.h"
     90 #include "platform/RuntimeEnabledFeatures.h"
     91 #include "platform/TraceEvent.h"
     92 #include "platform/WindowsKeyboardCodes.h"
     93 #include "platform/geometry/FloatPoint.h"
     94 #include "platform/graphics/Image.h"
     95 #include "platform/heap/Handle.h"
     96 #include "platform/scroll/ScrollAnimator.h"
     97 #include "platform/scroll/Scrollbar.h"
     98 #include "wtf/Assertions.h"
     99 #include "wtf/CurrentTime.h"
    100 #include "wtf/StdLibExtras.h"
    101 #include "wtf/TemporaryChange.h"
    102 
    103 namespace WebCore {
    104 
    105 using namespace HTMLNames;
    106 
    107 // The link drag hysteresis is much larger than the others because there
    108 // needs to be enough space to cancel the link press without starting a link drag,
    109 // and because dragging links is rare.
    110 static const int LinkDragHysteresis = 40;
    111 static const int ImageDragHysteresis = 5;
    112 static const int TextDragHysteresis = 3;
    113 static const int GeneralDragHysteresis = 3;
    114 
    115 // The amount of time to wait before sending a fake mouse event, triggered
    116 // during a scroll. The short interval is used if the content responds to the mouse events quickly enough,
    117 // otherwise the long interval is used.
    118 static const double fakeMouseMoveShortInterval = 0.1;
    119 static const double fakeMouseMoveLongInterval = 0.250;
    120 
    121 // The amount of time to wait for a cursor update on style and layout changes
    122 // Set to 50Hz, no need to be faster than common screen refresh rate
    123 static const double cursorUpdateInterval = 0.02;
    124 
    125 static const int maximumCursorSize = 128;
    126 
    127 // It's pretty unlikely that a scale of less than one would ever be used. But all we really
    128 // need to ensure here is that the scale isn't so small that integer overflow can occur when
    129 // dividing cursor sizes (limited above) by the scale.
    130 static const double minimumCursorScale = 0.001;
    131 
    132 // The minimum amount of time an element stays active after a ShowPress
    133 // This is roughly 9 frames, which should be long enough to be noticeable.
    134 static const double minimumActiveInterval = 0.15;
    135 
    136 #if OS(MACOSX)
    137 static const double TextDragDelay = 0.15;
    138 #else
    139 static const double TextDragDelay = 0.0;
    140 #endif
    141 
    142 enum NoCursorChangeType { NoCursorChange };
    143 
    144 class OptionalCursor {
    145 public:
    146     OptionalCursor(NoCursorChangeType) : m_isCursorChange(false) { }
    147     OptionalCursor(const Cursor& cursor) : m_isCursorChange(true), m_cursor(cursor) { }
    148 
    149     bool isCursorChange() const { return m_isCursorChange; }
    150     const Cursor& cursor() const { ASSERT(m_isCursorChange); return m_cursor; }
    151 
    152 private:
    153     bool m_isCursorChange;
    154     Cursor m_cursor;
    155 };
    156 
    157 class MaximumDurationTracker {
    158 public:
    159     explicit MaximumDurationTracker(double *maxDuration)
    160         : m_maxDuration(maxDuration)
    161         , m_start(monotonicallyIncreasingTime())
    162     {
    163     }
    164 
    165     ~MaximumDurationTracker()
    166     {
    167         *m_maxDuration = max(*m_maxDuration, monotonicallyIncreasingTime() - m_start);
    168     }
    169 
    170 private:
    171     double* m_maxDuration;
    172     double m_start;
    173 };
    174 
    175 static inline ScrollGranularity wheelGranularityToScrollGranularity(unsigned deltaMode)
    176 {
    177     switch (deltaMode) {
    178     case WheelEvent::DOM_DELTA_PAGE:
    179         return ScrollByPage;
    180     case WheelEvent::DOM_DELTA_LINE:
    181         return ScrollByLine;
    182     case WheelEvent::DOM_DELTA_PIXEL:
    183         return ScrollByPixel;
    184     default:
    185         return ScrollByPixel;
    186     }
    187 }
    188 
    189 // Refetch the event target node if it is removed or currently is the shadow node inside an <input> element.
    190 // If a mouse event handler changes the input element type to one that has a widget associated,
    191 // we'd like to EventHandler::handleMousePressEvent to pass the event to the widget and thus the
    192 // event target node can't still be the shadow node.
    193 static inline bool shouldRefetchEventTarget(const MouseEventWithHitTestResults& mev)
    194 {
    195     Node* targetNode = mev.targetNode();
    196     if (!targetNode || !targetNode->parentNode())
    197         return true;
    198     return targetNode->isShadowRoot() && isHTMLInputElement(*toShadowRoot(targetNode)->host());
    199 }
    200 
    201 EventHandler::EventHandler(LocalFrame* frame)
    202     : m_frame(frame)
    203     , m_mousePressed(false)
    204     , m_capturesDragging(false)
    205     , m_mouseDownMayStartSelect(false)
    206     , m_mouseDownMayStartDrag(false)
    207     , m_mouseDownWasSingleClickInSelection(false)
    208     , m_selectionInitiationState(HaveNotStartedSelection)
    209     , m_hoverTimer(this, &EventHandler::hoverTimerFired)
    210     , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired)
    211     , m_mouseDownMayStartAutoscroll(false)
    212     , m_mouseDownWasInSubframe(false)
    213     , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFired)
    214     , m_svgPan(false)
    215     , m_resizeScrollableArea(0)
    216     , m_eventHandlerWillResetCapturingMouseEventsNode(0)
    217     , m_clickCount(0)
    218     , m_shouldOnlyFireDragOverEvent(false)
    219     , m_mousePositionIsUnknown(true)
    220     , m_mouseDownTimestamp(0)
    221     , m_widgetIsLatched(false)
    222     , m_touchPressed(false)
    223     , m_scrollGestureHandlingNode(nullptr)
    224     , m_lastHitTestResultOverWidget(false)
    225     , m_maxMouseMovedDuration(0)
    226     , m_baseEventType(PlatformEvent::NoType)
    227     , m_didStartDrag(false)
    228     , m_longTapShouldInvokeContextMenu(false)
    229     , m_activeIntervalTimer(this, &EventHandler::activeIntervalTimerFired)
    230     , m_lastShowPressTimestamp(0)
    231 {
    232 }
    233 
    234 EventHandler::~EventHandler()
    235 {
    236     ASSERT(!m_fakeMouseMoveEventTimer.isActive());
    237 }
    238 
    239 void EventHandler::trace(Visitor* visitor)
    240 {
    241     visitor->trace(m_mousePressNode);
    242     visitor->trace(m_capturingMouseEventsNode);
    243     visitor->trace(m_nodeUnderMouse);
    244     visitor->trace(m_lastNodeUnderMouse);
    245     visitor->trace(m_clickNode);
    246     visitor->trace(m_dragTarget);
    247     visitor->trace(m_frameSetBeingResized);
    248     visitor->trace(m_latchedWheelEventNode);
    249     visitor->trace(m_previousWheelScrolledNode);
    250     visitor->trace(m_targetForTouchID);
    251     visitor->trace(m_touchSequenceDocument);
    252     visitor->trace(m_scrollGestureHandlingNode);
    253     visitor->trace(m_previousGestureScrolledNode);
    254     visitor->trace(m_lastDeferredTapElement);
    255 }
    256 
    257 DragState& EventHandler::dragState()
    258 {
    259 #if ENABLE(OILPAN)
    260     DEFINE_STATIC_LOCAL(Persistent<DragState>, state, (new DragState()));
    261     return *state;
    262 #else
    263     DEFINE_STATIC_LOCAL(DragState, state, ());
    264     return state;
    265 #endif
    266 }
    267 
    268 void EventHandler::clear()
    269 {
    270     m_hoverTimer.stop();
    271     m_cursorUpdateTimer.stop();
    272     m_fakeMouseMoveEventTimer.stop();
    273     m_activeIntervalTimer.stop();
    274     m_resizeScrollableArea = 0;
    275     m_nodeUnderMouse = nullptr;
    276     m_lastNodeUnderMouse = nullptr;
    277     m_lastMouseMoveEventSubframe = nullptr;
    278     m_lastScrollbarUnderMouse = nullptr;
    279     m_clickCount = 0;
    280     m_clickNode = nullptr;
    281     m_frameSetBeingResized = nullptr;
    282     m_dragTarget = nullptr;
    283     m_shouldOnlyFireDragOverEvent = false;
    284     m_mousePositionIsUnknown = true;
    285     m_lastKnownMousePosition = IntPoint();
    286     m_lastKnownMouseGlobalPosition = IntPoint();
    287     m_lastMouseDownUserGestureToken.clear();
    288     m_mousePressNode = nullptr;
    289     m_mousePressed = false;
    290     m_capturesDragging = false;
    291     m_capturingMouseEventsNode = nullptr;
    292     m_latchedWheelEventNode = nullptr;
    293     m_previousWheelScrolledNode = nullptr;
    294     m_targetForTouchID.clear();
    295     m_touchSequenceDocument.clear();
    296     m_touchSequenceUserGestureToken.clear();
    297     m_scrollGestureHandlingNode = nullptr;
    298     m_lastHitTestResultOverWidget = false;
    299     m_previousGestureScrolledNode = nullptr;
    300     m_scrollbarHandlingScrollGesture = nullptr;
    301     m_maxMouseMovedDuration = 0;
    302     m_baseEventType = PlatformEvent::NoType;
    303     m_didStartDrag = false;
    304     m_touchPressed = false;
    305     m_mouseDownMayStartSelect = false;
    306     m_mouseDownMayStartDrag = false;
    307     m_lastShowPressTimestamp = 0;
    308     m_lastDeferredTapElement = nullptr;
    309 }
    310 
    311 void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved)
    312 {
    313     if (!nodeToBeRemoved.containsIncludingShadowDOM(m_clickNode.get()))
    314         return;
    315     if (nodeToBeRemoved.isInShadowTree()) {
    316         m_clickNode = nodeToBeRemoved.parentOrShadowHostNode();
    317     } else {
    318         // We don't dispatch click events if the mousedown node is removed
    319         // before a mouseup event. It is compatible with IE and Firefox.
    320         m_clickNode = nullptr;
    321     }
    322 }
    323 
    324 static void setSelectionIfNeeded(FrameSelection& selection, const VisibleSelection& newSelection)
    325 {
    326     if (selection.selection() != newSelection)
    327         selection.setSelection(newSelection);
    328 }
    329 
    330 static inline bool dispatchSelectStart(Node* node)
    331 {
    332     if (!node || !node->renderer())
    333         return true;
    334 
    335     return node->dispatchEvent(Event::createCancelableBubble(EventTypeNames::selectstart));
    336 }
    337 
    338 static VisibleSelection expandSelectionToRespectUserSelectAll(Node* targetNode, const VisibleSelection& selection)
    339 {
    340     Node* rootUserSelectAll = Position::rootUserSelectAllForNode(targetNode);
    341     if (!rootUserSelectAll)
    342         return selection;
    343 
    344     VisibleSelection newSelection(selection);
    345     newSelection.setBase(positionBeforeNode(rootUserSelectAll).upstream(CanCrossEditingBoundary));
    346     newSelection.setExtent(positionAfterNode(rootUserSelectAll).downstream(CanCrossEditingBoundary));
    347 
    348     return newSelection;
    349 }
    350 
    351 bool EventHandler::updateSelectionForMouseDownDispatchingSelectStart(Node* targetNode, const VisibleSelection& selection, TextGranularity granularity)
    352 {
    353     if (Position::nodeIsUserSelectNone(targetNode))
    354         return false;
    355 
    356     if (!dispatchSelectStart(targetNode))
    357         return false;
    358 
    359     if (selection.isRange())
    360         m_selectionInitiationState = ExtendedSelection;
    361     else {
    362         granularity = CharacterGranularity;
    363         m_selectionInitiationState = PlacedCaret;
    364     }
    365 
    366     m_frame->selection().setNonDirectionalSelectionIfNeeded(selection, granularity);
    367 
    368     return true;
    369 }
    370 
    371 void EventHandler::selectClosestWordFromHitTestResult(const HitTestResult& result, AppendTrailingWhitespace appendTrailingWhitespace)
    372 {
    373     Node* innerNode = result.targetNode();
    374     VisibleSelection newSelection;
    375 
    376     if (innerNode && innerNode->renderer()) {
    377         VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
    378         if (pos.isNotNull()) {
    379             newSelection = VisibleSelection(pos);
    380             newSelection.expandUsingGranularity(WordGranularity);
    381         }
    382 
    383         if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSelection.isRange())
    384             newSelection.appendTrailingWhitespace();
    385 
    386         updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), WordGranularity);
    387     }
    388 }
    389 
    390 void EventHandler::selectClosestMisspellingFromHitTestResult(const HitTestResult& result, AppendTrailingWhitespace appendTrailingWhitespace)
    391 {
    392     Node* innerNode = result.targetNode();
    393     VisibleSelection newSelection;
    394 
    395     if (innerNode && innerNode->renderer()) {
    396         VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
    397         Position start = pos.deepEquivalent();
    398         Position end = pos.deepEquivalent();
    399         if (pos.isNotNull()) {
    400             WillBeHeapVector<DocumentMarker*> markers = innerNode->document().markers().markersInRange(makeRange(pos, pos).get(), DocumentMarker::MisspellingMarkers());
    401             if (markers.size() == 1) {
    402                 start.moveToOffset(markers[0]->startOffset());
    403                 end.moveToOffset(markers[0]->endOffset());
    404                 newSelection = VisibleSelection(start, end);
    405             }
    406         }
    407 
    408         if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSelection.isRange())
    409             newSelection.appendTrailingWhitespace();
    410 
    411         updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), WordGranularity);
    412     }
    413 }
    414 
    415 void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result)
    416 {
    417     if (m_mouseDownMayStartSelect) {
    418         selectClosestWordFromHitTestResult(result.hitTestResult(),
    419             (result.event().clickCount() == 2 && m_frame->editor().isSelectTrailingWhitespaceEnabled()) ? ShouldAppendTrailingWhitespace : DontAppendTrailingWhitespace);
    420     }
    421 }
    422 
    423 void EventHandler::selectClosestMisspellingFromMouseEvent(const MouseEventWithHitTestResults& result)
    424 {
    425     if (m_mouseDownMayStartSelect) {
    426         selectClosestMisspellingFromHitTestResult(result.hitTestResult(),
    427             (result.event().clickCount() == 2 && m_frame->editor().isSelectTrailingWhitespaceEnabled()) ? ShouldAppendTrailingWhitespace : DontAppendTrailingWhitespace);
    428     }
    429 }
    430 
    431 void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults& result)
    432 {
    433     if (!result.hitTestResult().isLiveLink())
    434         return selectClosestWordFromMouseEvent(result);
    435 
    436     Node* innerNode = result.targetNode();
    437 
    438     if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
    439         VisibleSelection newSelection;
    440         Element* URLElement = result.hitTestResult().URLElement();
    441         VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
    442         if (pos.isNotNull() && pos.deepEquivalent().deprecatedNode()->isDescendantOf(URLElement))
    443             newSelection = VisibleSelection::selectionFromContentsOfNode(URLElement);
    444 
    445         updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), WordGranularity);
    446     }
    447 }
    448 
    449 bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event)
    450 {
    451     TRACE_EVENT0("webkit", "EventHandler::handleMousePressEventDoubleClick");
    452 
    453     if (event.event().button() != LeftButton)
    454         return false;
    455 
    456     if (m_frame->selection().isRange()) {
    457         // A double-click when range is already selected
    458         // should not change the selection.  So, do not call
    459         // selectClosestWordFromMouseEvent, but do set
    460         // m_beganSelectingText to prevent handleMouseReleaseEvent
    461         // from setting caret selection.
    462         m_selectionInitiationState = ExtendedSelection;
    463     } else {
    464         selectClosestWordFromMouseEvent(event);
    465     }
    466     return true;
    467 }
    468 
    469 bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event)
    470 {
    471     TRACE_EVENT0("webkit", "EventHandler::handleMousePressEventTripleClick");
    472 
    473     if (event.event().button() != LeftButton)
    474         return false;
    475 
    476     Node* innerNode = event.targetNode();
    477     if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
    478         return false;
    479 
    480     VisibleSelection newSelection;
    481     VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint()));
    482     if (pos.isNotNull()) {
    483         newSelection = VisibleSelection(pos);
    484         newSelection.expandUsingGranularity(ParagraphGranularity);
    485     }
    486 
    487     return updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), ParagraphGranularity);
    488 }
    489 
    490 static int textDistance(const Position& start, const Position& end)
    491 {
    492     RefPtrWillBeRawPtr<Range> range = Range::create(*start.document(), start, end);
    493     return TextIterator::rangeLength(range.get(), true);
    494 }
    495 
    496 bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
    497 {
    498     TRACE_EVENT0("webkit", "EventHandler::handleMousePressEventSingleClick");
    499 
    500     m_frame->document()->updateLayoutIgnorePendingStylesheets();
    501     Node* innerNode = event.targetNode();
    502     if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
    503         return false;
    504 
    505     // Extend the selection if the Shift key is down, unless the click is in a link.
    506     bool extendSelection = event.event().shiftKey() && !event.isOverLink();
    507 
    508     // Don't restart the selection when the mouse is pressed on an
    509     // existing selection so we can allow for text dragging.
    510     if (FrameView* view = m_frame->view()) {
    511         LayoutPoint vPoint = view->windowToContents(event.event().position());
    512         if (!extendSelection && m_frame->selection().contains(vPoint)) {
    513             m_mouseDownWasSingleClickInSelection = true;
    514             return false;
    515         }
    516     }
    517 
    518     VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(event.localPoint()));
    519     if (visiblePos.isNull())
    520         visiblePos = VisiblePosition(firstPositionInOrBeforeNode(innerNode), DOWNSTREAM);
    521     Position pos = visiblePos.deepEquivalent();
    522 
    523     VisibleSelection newSelection = m_frame->selection().selection();
    524     TextGranularity granularity = CharacterGranularity;
    525 
    526     if (extendSelection && newSelection.isCaretOrRange()) {
    527         VisibleSelection selectionInUserSelectAll(expandSelectionToRespectUserSelectAll(innerNode, VisibleSelection(VisiblePosition(pos))));
    528         if (selectionInUserSelectAll.isRange()) {
    529             if (comparePositions(selectionInUserSelectAll.start(), newSelection.start()) < 0)
    530                 pos = selectionInUserSelectAll.start();
    531             else if (comparePositions(newSelection.end(), selectionInUserSelectAll.end()) < 0)
    532                 pos = selectionInUserSelectAll.end();
    533         }
    534 
    535         if (!m_frame->editor().behavior().shouldConsiderSelectionAsDirectional()) {
    536             if (pos.isNotNull()) {
    537                 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection
    538                 // was created right-to-left
    539                 Position start = newSelection.start();
    540                 Position end = newSelection.end();
    541                 int distanceToStart = textDistance(start, pos);
    542                 int distanceToEnd = textDistance(pos, end);
    543                 if (distanceToStart <= distanceToEnd)
    544                     newSelection = VisibleSelection(end, pos);
    545                 else
    546                     newSelection = VisibleSelection(start, pos);
    547             }
    548         } else
    549             newSelection.setExtent(pos);
    550 
    551         if (m_frame->selection().granularity() != CharacterGranularity) {
    552             granularity = m_frame->selection().granularity();
    553             newSelection.expandUsingGranularity(m_frame->selection().granularity());
    554         }
    555     } else {
    556         newSelection = expandSelectionToRespectUserSelectAll(innerNode, VisibleSelection(visiblePos));
    557     }
    558 
    559     // Updating the selection is considered side-effect of the event and so it doesn't impact the handled state.
    560     updateSelectionForMouseDownDispatchingSelectStart(innerNode, newSelection, granularity);
    561     return false;
    562 }
    563 
    564 static inline bool canMouseDownStartSelect(Node* node)
    565 {
    566     if (!node || !node->renderer())
    567         return true;
    568 
    569     if (!node->canStartSelection())
    570         return false;
    571 
    572     return true;
    573 }
    574 
    575 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event)
    576 {
    577     TRACE_EVENT0("webkit", "EventHandler::handleMousePressEvent");
    578 
    579     // Reset drag state.
    580     dragState().m_dragSrc = nullptr;
    581 
    582     cancelFakeMouseMoveEvent();
    583 
    584     m_frame->document()->updateLayoutIgnorePendingStylesheets();
    585 
    586     if (ScrollView* scrollView = m_frame->view()) {
    587         if (scrollView->isPointInScrollbarCorner(event.event().position()))
    588             return false;
    589     }
    590 
    591     bool singleClick = event.event().clickCount() <= 1;
    592 
    593     // If we got the event back, that must mean it wasn't prevented,
    594     // so it's allowed to start a drag or selection if it wasn't in a scrollbar.
    595     m_mouseDownMayStartSelect = canMouseDownStartSelect(event.targetNode()) && !event.scrollbar();
    596 
    597     m_mouseDownMayStartDrag = singleClick;
    598 
    599     m_mouseDownWasSingleClickInSelection = false;
    600 
    601     m_mouseDown = event.event();
    602 
    603     if (event.isOverWidget() && passWidgetMouseDownEventToWidget(event))
    604         return true;
    605 
    606     if (m_frame->document()->isSVGDocument() && m_frame->document()->accessSVGExtensions().zoomAndPanEnabled()) {
    607         if (event.event().shiftKey() && singleClick) {
    608             m_svgPan = true;
    609             m_frame->document()->accessSVGExtensions().startPan(m_frame->view()->windowToContents(event.event().position()));
    610             return true;
    611         }
    612     }
    613 
    614     // We don't do this at the start of mouse down handling,
    615     // because we don't want to do it until we know we didn't hit a widget.
    616     if (singleClick)
    617         focusDocumentView();
    618 
    619     Node* innerNode = event.targetNode();
    620 
    621     m_mousePressNode = innerNode;
    622     m_dragStartPos = event.event().position();
    623 
    624     bool swallowEvent = false;
    625     m_mousePressed = true;
    626     m_selectionInitiationState = HaveNotStartedSelection;
    627 
    628     if (event.event().clickCount() == 2)
    629         swallowEvent = handleMousePressEventDoubleClick(event);
    630     else if (event.event().clickCount() >= 3)
    631         swallowEvent = handleMousePressEventTripleClick(event);
    632     else
    633         swallowEvent = handleMousePressEventSingleClick(event);
    634 
    635     m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect
    636         || (m_mousePressNode && m_mousePressNode->renderBox() && m_mousePressNode->renderBox()->canBeProgramaticallyScrolled());
    637 
    638     return swallowEvent;
    639 }
    640 
    641 bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event)
    642 {
    643     TRACE_EVENT0("webkit", "EventHandler::handleMouseDraggedEvent");
    644 
    645     if (!m_mousePressed)
    646         return false;
    647 
    648     if (handleDrag(event, ShouldCheckDragHysteresis))
    649         return true;
    650 
    651     Node* targetNode = event.targetNode();
    652     if (event.event().button() != LeftButton || !targetNode)
    653         return false;
    654 
    655     RenderObject* renderer = targetNode->renderer();
    656     if (!renderer) {
    657         Node* parent = NodeRenderingTraversal::parent(targetNode);
    658         if (!parent)
    659             return false;
    660 
    661         renderer = parent->renderer();
    662         if (!renderer || !renderer->isListBox())
    663             return false;
    664     }
    665 
    666     m_mouseDownMayStartDrag = false;
    667 
    668     if (m_mouseDownMayStartAutoscroll && !panScrollInProgress()) {
    669         if (AutoscrollController* controller = autoscrollController()) {
    670             controller->startAutoscrollForSelection(renderer);
    671             m_mouseDownMayStartAutoscroll = false;
    672         }
    673     }
    674 
    675     if (m_selectionInitiationState != ExtendedSelection) {
    676         HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
    677         HitTestResult result(m_mouseDownPos);
    678         m_frame->document()->renderView()->hitTest(request, result);
    679 
    680         updateSelectionForMouseDrag(result);
    681     }
    682     updateSelectionForMouseDrag(event.hitTestResult());
    683     return true;
    684 }
    685 
    686 void EventHandler::updateSelectionForMouseDrag()
    687 {
    688     FrameView* view = m_frame->view();
    689     if (!view)
    690         return;
    691     RenderView* renderer = m_frame->contentRenderer();
    692     if (!renderer)
    693         return;
    694 
    695     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::Move | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
    696     HitTestResult result(view->windowToContents(m_lastKnownMousePosition));
    697     renderer->hitTest(request, result);
    698     updateSelectionForMouseDrag(result);
    699 }
    700 
    701 void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResult)
    702 {
    703     if (!m_mouseDownMayStartSelect)
    704         return;
    705 
    706     Node* target = hitTestResult.targetNode();
    707     if (!target)
    708         return;
    709 
    710     VisiblePosition targetPosition = m_frame->selection().selection().visiblePositionRespectingEditingBoundary(hitTestResult.localPoint(), target);
    711     // Don't modify the selection if we're not on a node.
    712     if (targetPosition.isNull())
    713         return;
    714 
    715     // Restart the selection if this is the first mouse move. This work is usually
    716     // done in handleMousePressEvent, but not if the mouse press was on an existing selection.
    717     VisibleSelection newSelection = m_frame->selection().selection();
    718 
    719     // Special case to limit selection to the containing block for SVG text.
    720     // FIXME: Isn't there a better non-SVG-specific way to do this?
    721     if (Node* selectionBaseNode = newSelection.base().deprecatedNode())
    722         if (RenderObject* selectionBaseRenderer = selectionBaseNode->renderer())
    723             if (selectionBaseRenderer->isSVGText())
    724                 if (target->renderer()->containingBlock() != selectionBaseRenderer->containingBlock())
    725                     return;
    726 
    727     if (m_selectionInitiationState == HaveNotStartedSelection && !dispatchSelectStart(target))
    728         return;
    729 
    730     if (m_selectionInitiationState != ExtendedSelection) {
    731         // Always extend selection here because it's caused by a mouse drag
    732         m_selectionInitiationState = ExtendedSelection;
    733         newSelection = VisibleSelection(targetPosition);
    734     }
    735 
    736     if (RuntimeEnabledFeatures::userSelectAllEnabled()) {
    737         Node* rootUserSelectAllForMousePressNode = Position::rootUserSelectAllForNode(m_mousePressNode.get());
    738         if (rootUserSelectAllForMousePressNode && rootUserSelectAllForMousePressNode == Position::rootUserSelectAllForNode(target)) {
    739             newSelection.setBase(positionBeforeNode(rootUserSelectAllForMousePressNode).upstream(CanCrossEditingBoundary));
    740             newSelection.setExtent(positionAfterNode(rootUserSelectAllForMousePressNode).downstream(CanCrossEditingBoundary));
    741         } else {
    742             // Reset base for user select all when base is inside user-select-all area and extent < base.
    743             if (rootUserSelectAllForMousePressNode && comparePositions(target->renderer()->positionForPoint(hitTestResult.localPoint()), m_mousePressNode->renderer()->positionForPoint(m_dragStartPos)) < 0)
    744                 newSelection.setBase(positionAfterNode(rootUserSelectAllForMousePressNode).downstream(CanCrossEditingBoundary));
    745 
    746             Node* rootUserSelectAllForTarget = Position::rootUserSelectAllForNode(target);
    747             if (rootUserSelectAllForTarget && m_mousePressNode->renderer() && comparePositions(target->renderer()->positionForPoint(hitTestResult.localPoint()), m_mousePressNode->renderer()->positionForPoint(m_dragStartPos)) < 0)
    748                 newSelection.setExtent(positionBeforeNode(rootUserSelectAllForTarget).upstream(CanCrossEditingBoundary));
    749             else if (rootUserSelectAllForTarget && m_mousePressNode->renderer())
    750                 newSelection.setExtent(positionAfterNode(rootUserSelectAllForTarget).downstream(CanCrossEditingBoundary));
    751             else
    752                 newSelection.setExtent(targetPosition);
    753         }
    754     } else {
    755         newSelection.setExtent(targetPosition);
    756     }
    757 
    758     if (m_frame->selection().granularity() != CharacterGranularity)
    759         newSelection.expandUsingGranularity(m_frame->selection().granularity());
    760 
    761     m_frame->selection().setNonDirectionalSelectionIfNeeded(newSelection, m_frame->selection().granularity(),
    762         FrameSelection::AdjustEndpointsAtBidiBoundary);
    763 }
    764 
    765 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
    766 {
    767     AutoscrollController* controller = autoscrollController();
    768     if (controller && controller->autoscrollInProgress())
    769         stopAutoscroll();
    770 
    771     // Used to prevent mouseMoveEvent from initiating a drag before
    772     // the mouse is pressed again.
    773     m_mousePressed = false;
    774     m_capturesDragging = false;
    775     m_mouseDownMayStartDrag = false;
    776     m_mouseDownMayStartSelect = false;
    777     m_mouseDownMayStartAutoscroll = false;
    778     m_mouseDownWasInSubframe = false;
    779 
    780     bool handled = false;
    781 
    782     // Clear the selection if the mouse didn't move after the last mouse
    783     // press and it's not a context menu click.  We do this so when clicking
    784     // on the selection, the selection goes away.  However, if we are
    785     // editing, place the caret.
    786     if (m_mouseDownWasSingleClickInSelection && m_selectionInitiationState != ExtendedSelection
    787             && m_dragStartPos == event.event().position()
    788             && m_frame->selection().isRange()
    789             && event.event().button() != RightButton) {
    790         VisibleSelection newSelection;
    791         Node* node = event.targetNode();
    792         bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled();
    793         if (node && node->renderer() && (caretBrowsing || node->rendererIsEditable())) {
    794             VisiblePosition pos = VisiblePosition(node->renderer()->positionForPoint(event.localPoint()));
    795             newSelection = VisibleSelection(pos);
    796         }
    797 
    798         setSelectionIfNeeded(m_frame->selection(), newSelection);
    799 
    800         handled = true;
    801     }
    802 
    803     m_frame->selection().notifyRendererOfSelectionChange(UserTriggered);
    804 
    805     m_frame->selection().selectFrameElementInParentIfFullySelected();
    806 
    807     if (event.event().button() == MiddleButton && !event.isOverLink()) {
    808         // Ignore handled, since we want to paste to where the caret was placed anyway.
    809         handled = handlePasteGlobalSelection(event.event()) || handled;
    810     }
    811 
    812     return handled;
    813 }
    814 
    815 #if OS(WIN)
    816 
    817 void EventHandler::startPanScrolling(RenderObject* renderer)
    818 {
    819     if (!renderer->isBox())
    820         return;
    821     AutoscrollController* controller = autoscrollController();
    822     if (!controller)
    823         return;
    824     controller->startPanScrolling(toRenderBox(renderer), lastKnownMousePosition());
    825     invalidateClick();
    826 }
    827 
    828 #endif // OS(WIN)
    829 
    830 AutoscrollController* EventHandler::autoscrollController() const
    831 {
    832     if (Page* page = m_frame->page())
    833         return &page->autoscrollController();
    834     return 0;
    835 }
    836 
    837 bool EventHandler::panScrollInProgress() const
    838 {
    839     return autoscrollController() && autoscrollController()->panScrollInProgress();
    840 }
    841 
    842 HitTestResult EventHandler::hitTestResultAtPoint(const LayoutPoint& point, HitTestRequest::HitTestRequestType hitType, const LayoutSize& padding)
    843 {
    844     TRACE_EVENT0("webkit", "EventHandler::hitTestResultAtPoint");
    845 
    846     // We always send hitTestResultAtPoint to the main frame if we have one,
    847     // otherwise we might hit areas that are obscured by higher frames.
    848     if (Page* page = m_frame->page()) {
    849         LocalFrame* mainFrame = page->mainFrame()->isLocalFrame() ? page->deprecatedLocalMainFrame() : 0;
    850         if (mainFrame && m_frame != mainFrame) {
    851             FrameView* frameView = m_frame->view();
    852             FrameView* mainView = mainFrame->view();
    853             if (frameView && mainView) {
    854                 IntPoint mainFramePoint = mainView->rootViewToContents(frameView->contentsToRootView(roundedIntPoint(point)));
    855                 return mainFrame->eventHandler().hitTestResultAtPoint(mainFramePoint, hitType, padding);
    856             }
    857         }
    858     }
    859 
    860     HitTestResult result(point, padding.height(), padding.width(), padding.height(), padding.width());
    861 
    862     // RenderView::hitTest causes a layout, and we don't want to hit that until the first
    863     // layout because until then, there is nothing shown on the screen - the user can't
    864     // have intentionally clicked on something belonging to this page. Furthermore,
    865     // mousemove events before the first layout should not lead to a premature layout()
    866     // happening, which could show a flash of white.
    867     // See also the similar code in Document::prepareMouseEvent.
    868     if (!m_frame->contentRenderer() || !m_frame->view() || !m_frame->view()->didFirstLayout())
    869         return result;
    870 
    871     // hitTestResultAtPoint is specifically used to hitTest into all frames, thus it always allows child frame content.
    872     HitTestRequest request(hitType | HitTestRequest::AllowChildFrameContent);
    873     m_frame->contentRenderer()->hitTest(request, result);
    874     if (!request.readOnly())
    875         m_frame->document()->updateHoverActiveState(request, result.innerElement());
    876 
    877     if (request.disallowsShadowContent())
    878         result.setToNodesInDocumentTreeScope();
    879 
    880     return result;
    881 }
    882 
    883 void EventHandler::stopAutoscroll()
    884 {
    885     if (AutoscrollController* controller = autoscrollController())
    886         controller->stopAutoscroll();
    887 }
    888 
    889 Node* EventHandler::mousePressNode() const
    890 {
    891     return m_mousePressNode.get();
    892 }
    893 
    894 bool EventHandler::scroll(ScrollDirection direction, ScrollGranularity granularity, Node* startNode, Node** stopNode, float delta, IntPoint absolutePoint)
    895 {
    896     if (!delta)
    897         return false;
    898 
    899     Node* node = startNode;
    900 
    901     if (!node)
    902         node = m_frame->document()->focusedElement();
    903 
    904     if (!node)
    905         node = m_mousePressNode.get();
    906 
    907     if (!node || !node->renderer())
    908         return false;
    909 
    910     RenderBox* curBox = node->renderer()->enclosingBox();
    911     while (curBox && !curBox->isRenderView()) {
    912         ScrollDirection physicalDirection = toPhysicalDirection(
    913             direction, curBox->isHorizontalWritingMode(), curBox->style()->isFlippedBlocksWritingMode());
    914 
    915         // If we're at the stopNode, we should try to scroll it but we shouldn't bubble past it
    916         bool shouldStopBubbling = stopNode && *stopNode && curBox->node() == *stopNode;
    917         bool didScroll = curBox->scroll(physicalDirection, granularity, delta);
    918 
    919         if (didScroll && stopNode)
    920             *stopNode = curBox->node();
    921 
    922         if (didScroll || shouldStopBubbling) {
    923             setFrameWasScrolledByUser();
    924             return true;
    925         }
    926 
    927         curBox = curBox->containingBlock();
    928     }
    929 
    930     return false;
    931 }
    932 
    933 bool EventHandler::bubblingScroll(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode)
    934 {
    935     // The layout needs to be up to date to determine if we can scroll. We may be
    936     // here because of an onLoad event, in which case the final layout hasn't been performed yet.
    937     m_frame->document()->updateLayoutIgnorePendingStylesheets();
    938     if (scroll(direction, granularity, startingNode))
    939         return true;
    940     LocalFrame* frame = m_frame;
    941     FrameView* view = frame->view();
    942     if (view && view->scroll(direction, granularity))
    943         return true;
    944     Frame* parentFrame = frame->tree().parent();
    945     if (!parentFrame || !parentFrame->isLocalFrame())
    946         return false;
    947     // FIXME: Broken for OOPI.
    948     return toLocalFrame(parentFrame)->eventHandler().bubblingScroll(direction, granularity, m_frame->deprecatedLocalOwner());
    949 }
    950 
    951 IntPoint EventHandler::lastKnownMousePosition() const
    952 {
    953     return m_lastKnownMousePosition;
    954 }
    955 
    956 static LocalFrame* subframeForTargetNode(Node* node)
    957 {
    958     if (!node)
    959         return 0;
    960 
    961     RenderObject* renderer = node->renderer();
    962     if (!renderer || !renderer->isWidget())
    963         return 0;
    964 
    965     // FIXME: This explicit check is needed only until RemoteFrames have RemoteFrameViews.
    966     if (isHTMLFrameElementBase(node) && toHTMLFrameElementBase(node)->contentFrame() && toHTMLFrameElementBase(node)->contentFrame()->isRemoteFrameTemporary())
    967         return 0;
    968 
    969     Widget* widget = toRenderWidget(renderer)->widget();
    970     if (!widget || !widget->isFrameView())
    971         return 0;
    972 
    973     return &toFrameView(widget)->frame();
    974 }
    975 
    976 static LocalFrame* subframeForHitTestResult(const MouseEventWithHitTestResults& hitTestResult)
    977 {
    978     if (!hitTestResult.isOverWidget())
    979         return 0;
    980     return subframeForTargetNode(hitTestResult.targetNode());
    981 }
    982 
    983 static bool isSubmitImage(Node* node)
    984 {
    985     return isHTMLInputElement(node) && toHTMLInputElement(node)->isImageButton();
    986 }
    987 
    988 bool EventHandler::useHandCursor(Node* node, bool isOverLink)
    989 {
    990     if (!node)
    991         return false;
    992 
    993     return ((isOverLink || isSubmitImage(node)) && !node->rendererIsEditable());
    994 }
    995 
    996 void EventHandler::cursorUpdateTimerFired(Timer<EventHandler>*)
    997 {
    998     ASSERT(m_frame);
    999     ASSERT(m_frame->document());
   1000 
   1001     updateCursor();
   1002 }
   1003 
   1004 void EventHandler::updateCursor()
   1005 {
   1006     if (m_mousePositionIsUnknown)
   1007         return;
   1008 
   1009     FrameView* view = m_frame->view();
   1010     if (!view || !view->shouldSetCursor())
   1011         return;
   1012 
   1013     RenderView* renderView = view->renderView();
   1014     if (!renderView)
   1015         return;
   1016 
   1017     m_frame->document()->updateLayout();
   1018 
   1019     HitTestRequest request(HitTestRequest::ReadOnly);
   1020     HitTestResult result(view->windowToContents(m_lastKnownMousePosition));
   1021     renderView->hitTest(request, result);
   1022 
   1023     OptionalCursor optionalCursor = selectCursor(result);
   1024     if (optionalCursor.isCursorChange()) {
   1025         m_currentMouseCursor = optionalCursor.cursor();
   1026         view->setCursor(m_currentMouseCursor);
   1027     }
   1028 }
   1029 
   1030 OptionalCursor EventHandler::selectCursor(const HitTestResult& result)
   1031 {
   1032     if (m_resizeScrollableArea && m_resizeScrollableArea->inResizeMode())
   1033         return NoCursorChange;
   1034 
   1035     Page* page = m_frame->page();
   1036     if (!page)
   1037         return NoCursorChange;
   1038 #if OS(WIN)
   1039     if (panScrollInProgress())
   1040         return NoCursorChange;
   1041 #endif
   1042 
   1043     Node* node = result.innerPossiblyPseudoNode();
   1044     if (!node)
   1045         return selectAutoCursor(result, node, iBeamCursor());
   1046 
   1047     RenderObject* renderer = node->renderer();
   1048     RenderStyle* style = renderer ? renderer->style() : 0;
   1049 
   1050     if (renderer) {
   1051         Cursor overrideCursor;
   1052         switch (renderer->getCursor(roundedIntPoint(result.localPoint()), overrideCursor)) {
   1053         case SetCursorBasedOnStyle:
   1054             break;
   1055         case SetCursor:
   1056             return overrideCursor;
   1057         case DoNotSetCursor:
   1058             return NoCursorChange;
   1059         }
   1060     }
   1061 
   1062     if (style && style->cursors()) {
   1063         const CursorList* cursors = style->cursors();
   1064         for (unsigned i = 0; i < cursors->size(); ++i) {
   1065             StyleImage* styleImage = (*cursors)[i].image();
   1066             if (!styleImage)
   1067                 continue;
   1068             ImageResource* cachedImage = styleImage->cachedImage();
   1069             if (!cachedImage)
   1070                 continue;
   1071             float scale = styleImage->imageScaleFactor();
   1072             // Get hotspot and convert from logical pixels to physical pixels.
   1073             IntPoint hotSpot = (*cursors)[i].hotSpot();
   1074             hotSpot.scale(scale, scale);
   1075             IntSize size = cachedImage->imageForRenderer(renderer)->size();
   1076             if (cachedImage->errorOccurred())
   1077                 continue;
   1078             // Limit the size of cursors (in UI pixels) so that they cannot be
   1079             // used to cover UI elements in chrome.
   1080             size.scale(1 / scale);
   1081             if (size.width() > maximumCursorSize || size.height() > maximumCursorSize)
   1082                 continue;
   1083 
   1084             Image* image = cachedImage->imageForRenderer(renderer);
   1085             // Ensure no overflow possible in calculations above.
   1086             if (scale < minimumCursorScale)
   1087                 continue;
   1088             return Cursor(image, hotSpot, scale);
   1089         }
   1090     }
   1091 
   1092     switch (style ? style->cursor() : CURSOR_AUTO) {
   1093     case CURSOR_AUTO: {
   1094         bool horizontalText = !style || style->isHorizontalWritingMode();
   1095         const Cursor& iBeam = horizontalText ? iBeamCursor() : verticalTextCursor();
   1096         return selectAutoCursor(result, node, iBeam);
   1097     }
   1098     case CURSOR_CROSS:
   1099         return crossCursor();
   1100     case CURSOR_POINTER:
   1101         return handCursor();
   1102     case CURSOR_MOVE:
   1103         return moveCursor();
   1104     case CURSOR_ALL_SCROLL:
   1105         return moveCursor();
   1106     case CURSOR_E_RESIZE:
   1107         return eastResizeCursor();
   1108     case CURSOR_W_RESIZE:
   1109         return westResizeCursor();
   1110     case CURSOR_N_RESIZE:
   1111         return northResizeCursor();
   1112     case CURSOR_S_RESIZE:
   1113         return southResizeCursor();
   1114     case CURSOR_NE_RESIZE:
   1115         return northEastResizeCursor();
   1116     case CURSOR_SW_RESIZE:
   1117         return southWestResizeCursor();
   1118     case CURSOR_NW_RESIZE:
   1119         return northWestResizeCursor();
   1120     case CURSOR_SE_RESIZE:
   1121         return southEastResizeCursor();
   1122     case CURSOR_NS_RESIZE:
   1123         return northSouthResizeCursor();
   1124     case CURSOR_EW_RESIZE:
   1125         return eastWestResizeCursor();
   1126     case CURSOR_NESW_RESIZE:
   1127         return northEastSouthWestResizeCursor();
   1128     case CURSOR_NWSE_RESIZE:
   1129         return northWestSouthEastResizeCursor();
   1130     case CURSOR_COL_RESIZE:
   1131         return columnResizeCursor();
   1132     case CURSOR_ROW_RESIZE:
   1133         return rowResizeCursor();
   1134     case CURSOR_TEXT:
   1135         return iBeamCursor();
   1136     case CURSOR_WAIT:
   1137         return waitCursor();
   1138     case CURSOR_HELP:
   1139         return helpCursor();
   1140     case CURSOR_VERTICAL_TEXT:
   1141         return verticalTextCursor();
   1142     case CURSOR_CELL:
   1143         return cellCursor();
   1144     case CURSOR_CONTEXT_MENU:
   1145         return contextMenuCursor();
   1146     case CURSOR_PROGRESS:
   1147         return progressCursor();
   1148     case CURSOR_NO_DROP:
   1149         return noDropCursor();
   1150     case CURSOR_ALIAS:
   1151         return aliasCursor();
   1152     case CURSOR_COPY:
   1153         return copyCursor();
   1154     case CURSOR_NONE:
   1155         return noneCursor();
   1156     case CURSOR_NOT_ALLOWED:
   1157         return notAllowedCursor();
   1158     case CURSOR_DEFAULT:
   1159         return pointerCursor();
   1160     case CURSOR_ZOOM_IN:
   1161         return zoomInCursor();
   1162     case CURSOR_ZOOM_OUT:
   1163         return zoomOutCursor();
   1164     case CURSOR_WEBKIT_GRAB:
   1165         return grabCursor();
   1166     case CURSOR_WEBKIT_GRABBING:
   1167         return grabbingCursor();
   1168     }
   1169     return pointerCursor();
   1170 }
   1171 
   1172 OptionalCursor EventHandler::selectAutoCursor(const HitTestResult& result, Node* node, const Cursor& iBeam)
   1173 {
   1174     bool editable = (node && node->rendererIsEditable());
   1175 
   1176     if (useHandCursor(node, result.isOverLink()))
   1177         return handCursor();
   1178 
   1179     bool inResizer = false;
   1180     RenderObject* renderer = node ? node->renderer() : 0;
   1181     if (renderer && m_frame->view()) {
   1182         RenderLayer* layer = renderer->enclosingLayer();
   1183         inResizer = layer->scrollableArea() && layer->scrollableArea()->isPointInResizeControl(result.roundedPointInMainFrame(), ResizerForPointer);
   1184     }
   1185 
   1186     // During selection, use an I-beam no matter what we're over.
   1187     // If a drag may be starting or we're capturing mouse events for a particular node, don't treat this as a selection.
   1188     if (m_mousePressed && m_mouseDownMayStartSelect
   1189         && !m_mouseDownMayStartDrag
   1190         && m_frame->selection().isCaretOrRange()
   1191         && !m_capturingMouseEventsNode) {
   1192         return iBeam;
   1193     }
   1194 
   1195     if ((editable || (renderer && renderer->isText() && node->canStartSelection())) && !inResizer && !result.scrollbar())
   1196         return iBeam;
   1197     return pointerCursor();
   1198 }
   1199 
   1200 static LayoutPoint documentPointForWindowPoint(LocalFrame* frame, const IntPoint& windowPoint)
   1201 {
   1202     FrameView* view = frame->view();
   1203     // FIXME: Is it really OK to use the wrong coordinates here when view is 0?
   1204     // Historically the code would just crash; this is clearly no worse than that.
   1205     return view ? view->windowToContents(windowPoint) : windowPoint;
   1206 }
   1207 
   1208 bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
   1209 {
   1210     TRACE_EVENT0("webkit", "EventHandler::handleMousePressEvent");
   1211 
   1212     RefPtr<FrameView> protector(m_frame->view());
   1213 
   1214     UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
   1215     m_frame->localFrameRoot()->eventHandler().m_lastMouseDownUserGestureToken = gestureIndicator.currentToken();
   1216 
   1217     cancelFakeMouseMoveEvent();
   1218     if (m_eventHandlerWillResetCapturingMouseEventsNode)
   1219         m_capturingMouseEventsNode = nullptr;
   1220     m_mousePressed = true;
   1221     m_capturesDragging = true;
   1222     setLastKnownMousePosition(mouseEvent);
   1223     m_mouseDownTimestamp = mouseEvent.timestamp();
   1224     m_mouseDownMayStartDrag = false;
   1225     m_mouseDownMayStartSelect = false;
   1226     m_mouseDownMayStartAutoscroll = false;
   1227     if (FrameView* view = m_frame->view())
   1228         m_mouseDownPos = view->windowToContents(mouseEvent.position());
   1229     else {
   1230         invalidateClick();
   1231         return false;
   1232     }
   1233     m_mouseDownWasInSubframe = false;
   1234 
   1235     HitTestRequest::HitTestRequestType hitType = HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent;
   1236     if (mouseEvent.fromTouch())
   1237         hitType |= HitTestRequest::ReadOnly;
   1238     HitTestRequest request(hitType);
   1239     // Save the document point we generate in case the window coordinate is invalidated by what happens
   1240     // when we dispatch the event.
   1241     LayoutPoint documentPoint = documentPointForWindowPoint(m_frame, mouseEvent.position());
   1242     MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent);
   1243 
   1244     if (!mev.targetNode()) {
   1245         invalidateClick();
   1246         return false;
   1247     }
   1248 
   1249     m_mousePressNode = mev.targetNode();
   1250 
   1251     RefPtr<LocalFrame> subframe = subframeForHitTestResult(mev);
   1252     if (subframe && passMousePressEventToSubframe(mev, subframe.get())) {
   1253         // Start capturing future events for this frame.  We only do this if we didn't clear
   1254         // the m_mousePressed flag, which may happen if an AppKit widget entered a modal event loop.
   1255         m_capturesDragging = subframe->eventHandler().capturesDragging();
   1256         if (m_mousePressed && m_capturesDragging) {
   1257             m_capturingMouseEventsNode = mev.targetNode();
   1258             m_eventHandlerWillResetCapturingMouseEventsNode = true;
   1259         }
   1260         invalidateClick();
   1261         return true;
   1262     }
   1263 
   1264 #if OS(WIN)
   1265     // We store whether pan scrolling is in progress before calling stopAutoscroll()
   1266     // because it will set m_autoscrollType to NoAutoscroll on return.
   1267     bool isPanScrollInProgress = panScrollInProgress();
   1268     stopAutoscroll();
   1269     if (isPanScrollInProgress) {
   1270         // We invalidate the click when exiting pan scrolling so that we don't inadvertently navigate
   1271         // away from the current page (e.g. the click was on a hyperlink). See <rdar://problem/6095023>.
   1272         invalidateClick();
   1273         return true;
   1274     }
   1275 #endif
   1276 
   1277     m_clickCount = mouseEvent.clickCount();
   1278     m_clickNode = mev.targetNode()->isTextNode() ?  NodeRenderingTraversal::parent(mev.targetNode()) : mev.targetNode();
   1279 
   1280     if (FrameView* view = m_frame->view()) {
   1281         RenderLayer* layer = mev.targetNode()->renderer() ? mev.targetNode()->renderer()->enclosingLayer() : 0;
   1282         IntPoint p = view->windowToContents(mouseEvent.position());
   1283         if (layer && layer->scrollableArea() && layer->scrollableArea()->isPointInResizeControl(p, ResizerForPointer)) {
   1284             m_resizeScrollableArea = layer->scrollableArea();
   1285             m_resizeScrollableArea->setInResizeMode(true);
   1286             m_offsetFromResizeCorner = m_resizeScrollableArea->offsetFromResizeCorner(p);
   1287             invalidateClick();
   1288             return true;
   1289         }
   1290     }
   1291 
   1292     m_frame->selection().setCaretBlinkingSuspended(true);
   1293 
   1294     bool swallowEvent = !dispatchMouseEvent(EventTypeNames::mousedown, mev.targetNode(), m_clickCount, mouseEvent, true);
   1295     swallowEvent = swallowEvent || !handleMouseFocus(mouseEvent);
   1296     m_capturesDragging = !swallowEvent || mev.scrollbar();
   1297 
   1298     // If the hit testing originally determined the event was in a scrollbar, refetch the MouseEventWithHitTestResults
   1299     // in case the scrollbar widget was destroyed when the mouse event was handled.
   1300     if (mev.scrollbar()) {
   1301         const bool wasLastScrollBar = mev.scrollbar() == m_lastScrollbarUnderMouse.get();
   1302         HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
   1303         mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent);
   1304         if (wasLastScrollBar && mev.scrollbar() != m_lastScrollbarUnderMouse.get())
   1305             m_lastScrollbarUnderMouse = nullptr;
   1306     }
   1307 
   1308     if (swallowEvent) {
   1309         // scrollbars should get events anyway, even disabled controls might be scrollable
   1310         passMousePressEventToScrollbar(mev);
   1311     } else {
   1312         if (shouldRefetchEventTarget(mev)) {
   1313             HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
   1314             mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent);
   1315         }
   1316 
   1317         if (passMousePressEventToScrollbar(mev))
   1318             swallowEvent = true;
   1319         else
   1320             swallowEvent = handleMousePressEvent(mev);
   1321     }
   1322 
   1323     return swallowEvent;
   1324 }
   1325 
   1326 static RenderLayer* layerForNode(Node* node)
   1327 {
   1328     if (!node)
   1329         return 0;
   1330 
   1331     RenderObject* renderer = node->renderer();
   1332     if (!renderer)
   1333         return 0;
   1334 
   1335     RenderLayer* layer = renderer->enclosingLayer();
   1336     if (!layer)
   1337         return 0;
   1338 
   1339     return layer;
   1340 }
   1341 
   1342 ScrollableArea* EventHandler::associatedScrollableArea(const RenderLayer* layer) const
   1343 {
   1344     if (RenderLayerScrollableArea* scrollableArea = layer->scrollableArea()) {
   1345         if (scrollableArea->scrollsOverflow())
   1346             return scrollableArea;
   1347     }
   1348 
   1349     return 0;
   1350 }
   1351 
   1352 bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& event)
   1353 {
   1354     TRACE_EVENT0("webkit", "EventHandler::handleMouseMoveEvent");
   1355 
   1356     RefPtr<FrameView> protector(m_frame->view());
   1357     MaximumDurationTracker maxDurationTracker(&m_maxMouseMovedDuration);
   1358 
   1359     HitTestResult hoveredNode = HitTestResult(LayoutPoint());
   1360     bool result = handleMouseMoveOrLeaveEvent(event, &hoveredNode);
   1361 
   1362     Page* page = m_frame->page();
   1363     if (!page)
   1364         return result;
   1365 
   1366     if (RenderLayer* layer = layerForNode(hoveredNode.innerNode())) {
   1367         if (ScrollableArea* layerScrollableArea = associatedScrollableArea(layer))
   1368             layerScrollableArea->mouseMovedInContentArea();
   1369     }
   1370 
   1371     if (FrameView* frameView = m_frame->view())
   1372         frameView->mouseMovedInContentArea();
   1373 
   1374     hoveredNode.setToShadowHostIfInUserAgentShadowRoot();
   1375     page->chrome().mouseDidMoveOverElement(hoveredNode, event.modifierFlags());
   1376     page->chrome().setToolTip(hoveredNode);
   1377 
   1378     return result;
   1379 }
   1380 
   1381 void EventHandler::handleMouseLeaveEvent(const PlatformMouseEvent& event)
   1382 {
   1383     TRACE_EVENT0("webkit", "EventHandler::handleMouseLeaveEvent");
   1384 
   1385     RefPtr<FrameView> protector(m_frame->view());
   1386     handleMouseMoveOrLeaveEvent(event);
   1387 }
   1388 
   1389 bool EventHandler::handleMouseMoveOrLeaveEvent(const PlatformMouseEvent& mouseEvent, HitTestResult* hoveredNode, bool onlyUpdateScrollbars)
   1390 {
   1391     ASSERT(m_frame);
   1392     ASSERT(m_frame->view());
   1393 
   1394     setLastKnownMousePosition(mouseEvent);
   1395 
   1396     if (m_hoverTimer.isActive())
   1397         m_hoverTimer.stop();
   1398 
   1399     m_cursorUpdateTimer.stop();
   1400 
   1401     cancelFakeMouseMoveEvent();
   1402 
   1403     if (m_svgPan) {
   1404         m_frame->document()->accessSVGExtensions().updatePan(m_frame->view()->windowToContents(m_lastKnownMousePosition));
   1405         return true;
   1406     }
   1407 
   1408     if (m_frameSetBeingResized)
   1409         return !dispatchMouseEvent(EventTypeNames::mousemove, m_frameSetBeingResized.get(), 0, mouseEvent, false);
   1410 
   1411     // Send events right to a scrollbar if the mouse is pressed.
   1412     if (m_lastScrollbarUnderMouse && m_mousePressed) {
   1413         m_lastScrollbarUnderMouse->mouseMoved(mouseEvent);
   1414         return true;
   1415     }
   1416 
   1417     HitTestRequest::HitTestRequestType hitType = HitTestRequest::Move | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent;
   1418     if (mouseEvent.fromTouch())
   1419         hitType |= HitTestRequest::ReadOnly;
   1420 
   1421     if (m_mousePressed)
   1422         hitType |= HitTestRequest::Active;
   1423     else if (onlyUpdateScrollbars) {
   1424         // Mouse events should be treated as "read-only" if we're updating only scrollbars. This
   1425         // means that :hover and :active freeze in the state they were in, rather than updating
   1426         // for nodes the mouse moves while the window is not key (which will be the case if
   1427         // onlyUpdateScrollbars is true).
   1428         hitType |= HitTestRequest::ReadOnly;
   1429     }
   1430 
   1431     // Treat any mouse move events as readonly if the user is currently touching the screen.
   1432     if (m_touchPressed)
   1433         hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly;
   1434     HitTestRequest request(hitType);
   1435     MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
   1436     if (hoveredNode)
   1437         *hoveredNode = mev.hitTestResult();
   1438 
   1439     Scrollbar* scrollbar = 0;
   1440 
   1441     if (m_resizeScrollableArea && m_resizeScrollableArea->inResizeMode())
   1442         m_resizeScrollableArea->resize(mouseEvent, m_offsetFromResizeCorner);
   1443     else {
   1444         if (FrameView* view = m_frame->view())
   1445             scrollbar = view->scrollbarAtPoint(mouseEvent.position());
   1446 
   1447         if (!scrollbar)
   1448             scrollbar = mev.scrollbar();
   1449 
   1450         updateLastScrollbarUnderMouse(scrollbar, !m_mousePressed);
   1451         if (onlyUpdateScrollbars)
   1452             return true;
   1453     }
   1454 
   1455     bool swallowEvent = false;
   1456     RefPtr<LocalFrame> newSubframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev);
   1457 
   1458     // We want mouseouts to happen first, from the inside out.  First send a move event to the last subframe so that it will fire mouseouts.
   1459     if (m_lastMouseMoveEventSubframe && m_lastMouseMoveEventSubframe->tree().isDescendantOf(m_frame) && m_lastMouseMoveEventSubframe != newSubframe)
   1460         passMouseMoveEventToSubframe(mev, m_lastMouseMoveEventSubframe.get());
   1461 
   1462     if (newSubframe) {
   1463         // Update over/out state before passing the event to the subframe.
   1464         updateMouseEventTargetNode(mev.targetNode(), mouseEvent, true);
   1465 
   1466         // Event dispatch in updateMouseEventTargetNode may have caused the subframe of the target
   1467         // node to be detached from its FrameView, in which case the event should not be passed.
   1468         if (newSubframe->view())
   1469             swallowEvent |= passMouseMoveEventToSubframe(mev, newSubframe.get(), hoveredNode);
   1470     } else {
   1471         if (scrollbar && !m_mousePressed)
   1472             scrollbar->mouseMoved(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
   1473         if (FrameView* view = m_frame->view()) {
   1474             OptionalCursor optionalCursor = selectCursor(mev.hitTestResult());
   1475             if (optionalCursor.isCursorChange()) {
   1476                 m_currentMouseCursor = optionalCursor.cursor();
   1477                 view->setCursor(m_currentMouseCursor);
   1478             }
   1479         }
   1480     }
   1481 
   1482     m_lastMouseMoveEventSubframe = newSubframe;
   1483 
   1484     if (swallowEvent)
   1485         return true;
   1486 
   1487     swallowEvent = !dispatchMouseEvent(EventTypeNames::mousemove, mev.targetNode(), 0, mouseEvent, true);
   1488     if (!swallowEvent)
   1489         swallowEvent = handleMouseDraggedEvent(mev);
   1490 
   1491     return swallowEvent;
   1492 }
   1493 
   1494 void EventHandler::invalidateClick()
   1495 {
   1496     m_clickCount = 0;
   1497     m_clickNode = nullptr;
   1498 }
   1499 
   1500 static Node* parentForClickEvent(const Node& node)
   1501 {
   1502     // IE doesn't dispatch click events for mousedown/mouseup events across form
   1503     // controls.
   1504     if (node.isHTMLElement() && toHTMLElement(node).isInteractiveContent())
   1505         return 0;
   1506     return NodeRenderingTraversal::parent(&node);
   1507 }
   1508 
   1509 bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
   1510 {
   1511     TRACE_EVENT0("webkit", "EventHandler::handleMouseReleaseEvent");
   1512 
   1513     RefPtr<FrameView> protector(m_frame->view());
   1514 
   1515     m_frame->selection().setCaretBlinkingSuspended(false);
   1516 
   1517     OwnPtr<UserGestureIndicator> gestureIndicator;
   1518 
   1519     if (m_frame->localFrameRoot()->eventHandler().m_lastMouseDownUserGestureToken)
   1520         gestureIndicator = adoptPtr(new UserGestureIndicator(m_frame->localFrameRoot()->eventHandler().m_lastMouseDownUserGestureToken.release()));
   1521     else
   1522         gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProcessingUserGesture));
   1523 
   1524 #if OS(WIN)
   1525     if (Page* page = m_frame->page())
   1526         page->autoscrollController().handleMouseReleaseForPanScrolling(m_frame, mouseEvent);
   1527 #endif
   1528 
   1529     m_mousePressed = false;
   1530     setLastKnownMousePosition(mouseEvent);
   1531 
   1532     if (m_svgPan) {
   1533         m_svgPan = false;
   1534         m_frame->document()->accessSVGExtensions().updatePan(m_frame->view()->windowToContents(m_lastKnownMousePosition));
   1535         return true;
   1536     }
   1537 
   1538     if (m_frameSetBeingResized)
   1539         return !dispatchMouseEvent(EventTypeNames::mouseup, m_frameSetBeingResized.get(), m_clickCount, mouseEvent, false);
   1540 
   1541     if (m_lastScrollbarUnderMouse) {
   1542         invalidateClick();
   1543         m_lastScrollbarUnderMouse->mouseUp(mouseEvent);
   1544         bool setUnder = false;
   1545         return !dispatchMouseEvent(EventTypeNames::mouseup, m_lastNodeUnderMouse.get(), m_clickCount, mouseEvent, setUnder);
   1546     }
   1547 
   1548     HitTestRequest::HitTestRequestType hitType = HitTestRequest::Release | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent;
   1549     if (mouseEvent.fromTouch())
   1550         hitType |= HitTestRequest::ReadOnly;
   1551     HitTestRequest request(hitType);
   1552     MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
   1553     LocalFrame* subframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev);
   1554     if (m_eventHandlerWillResetCapturingMouseEventsNode)
   1555         m_capturingMouseEventsNode = nullptr;
   1556     if (subframe && passMouseReleaseEventToSubframe(mev, subframe))
   1557         return true;
   1558 
   1559     bool swallowMouseUpEvent = !dispatchMouseEvent(EventTypeNames::mouseup, mev.targetNode(), m_clickCount, mouseEvent, false);
   1560 
   1561     bool contextMenuEvent = mouseEvent.button() == RightButton;
   1562 #if OS(MACOSX)
   1563     // FIXME: The Mac port achieves the same behavior by checking whether the context menu is currently open in WebPage::mouseEvent(). Consider merging the implementations.
   1564     if (mouseEvent.button() == LeftButton && mouseEvent.modifiers() & PlatformEvent::CtrlKey)
   1565         contextMenuEvent = true;
   1566 #endif
   1567 
   1568     bool swallowClickEvent = false;
   1569     if (m_clickCount > 0 && !contextMenuEvent && mev.targetNode() && m_clickNode) {
   1570         if (Node* clickTargetNode = mev.targetNode()->commonAncestor(*m_clickNode, parentForClickEvent))
   1571             swallowClickEvent = !dispatchMouseEvent(EventTypeNames::click, clickTargetNode, m_clickCount, mouseEvent, true);
   1572     }
   1573 
   1574     if (m_resizeScrollableArea) {
   1575         m_resizeScrollableArea->setInResizeMode(false);
   1576         m_resizeScrollableArea = 0;
   1577     }
   1578 
   1579     bool swallowMouseReleaseEvent = false;
   1580     if (!swallowMouseUpEvent)
   1581         swallowMouseReleaseEvent = handleMouseReleaseEvent(mev);
   1582 
   1583     invalidateClick();
   1584 
   1585     return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
   1586 }
   1587 
   1588 bool EventHandler::handlePasteGlobalSelection(const PlatformMouseEvent& mouseEvent)
   1589 {
   1590     // If the event was a middle click, attempt to copy global selection in after
   1591     // the newly set caret position.
   1592     //
   1593     // This code is called from either the mouse up or mouse down handling. There
   1594     // is some debate about when the global selection is pasted:
   1595     //   xterm: pastes on up.
   1596     //   GTK: pastes on down.
   1597     //   Qt: pastes on up.
   1598     //   Firefox: pastes on up.
   1599     //   Chromium: pastes on up.
   1600     //
   1601     // There is something of a webcompat angle to this well, as highlighted by
   1602     // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on
   1603     // down then the text is pasted just before the onclick handler runs and
   1604     // clears the text box. So it's important this happens after the event
   1605     // handlers have been fired.
   1606     if (mouseEvent.type() != PlatformEvent::MouseReleased)
   1607         return false;
   1608 
   1609     if (!m_frame->page())
   1610         return false;
   1611     Frame* focusFrame = m_frame->page()->focusController().focusedOrMainFrame();
   1612     // Do not paste here if the focus was moved somewhere else.
   1613     if (m_frame == focusFrame && m_frame->editor().behavior().supportsGlobalSelection())
   1614         return m_frame->editor().command("PasteGlobalSelection").execute();
   1615 
   1616     return false;
   1617 }
   1618 
   1619 
   1620 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard)
   1621 {
   1622     FrameView* view = m_frame->view();
   1623 
   1624     // FIXME: We might want to dispatch a dragleave even if the view is gone.
   1625     if (!view)
   1626         return false;
   1627 
   1628     RefPtrWillBeRawPtr<MouseEvent> me = MouseEvent::create(eventType,
   1629         true, true, m_frame->document()->domWindow(),
   1630         0, event.globalPosition().x(), event.globalPosition().y(), event.position().x(), event.position().y(),
   1631         event.movementDelta().x(), event.movementDelta().y(),
   1632         event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
   1633         0, nullptr, clipboard);
   1634 
   1635     dragTarget->dispatchEvent(me.get(), IGNORE_EXCEPTION);
   1636     return me->defaultPrevented();
   1637 }
   1638 
   1639 static bool targetIsFrame(Node* target, LocalFrame*& frame)
   1640 {
   1641     if (!isHTMLFrameElementBase(target))
   1642         return false;
   1643 
   1644     // Cross-process drag and drop is not yet supported.
   1645     if (toHTMLFrameElementBase(target)->contentFrame() && !toHTMLFrameElementBase(target)->contentFrame()->isLocalFrame())
   1646         return false;
   1647 
   1648     frame = toLocalFrame(toHTMLFrameElementBase(target)->contentFrame());
   1649     return true;
   1650 }
   1651 
   1652 static bool findDropZone(Node* target, Clipboard* clipboard)
   1653 {
   1654     Element* element = target->isElementNode() ? toElement(target) : target->parentElement();
   1655     for (; element; element = element->parentElement()) {
   1656         bool matched = false;
   1657         AtomicString dropZoneStr = element->fastGetAttribute(webkitdropzoneAttr);
   1658 
   1659         if (dropZoneStr.isEmpty())
   1660             continue;
   1661 
   1662         dropZoneStr = dropZoneStr.lower();
   1663 
   1664         SpaceSplitString keywords(dropZoneStr, false);
   1665         if (keywords.isNull())
   1666             continue;
   1667 
   1668         DragOperation dragOperation = DragOperationNone;
   1669         for (unsigned i = 0; i < keywords.size(); i++) {
   1670             DragOperation op = convertDropZoneOperationToDragOperation(keywords[i]);
   1671             if (op != DragOperationNone) {
   1672                 if (dragOperation == DragOperationNone)
   1673                     dragOperation = op;
   1674             } else
   1675                 matched = matched || clipboard->hasDropZoneType(keywords[i].string());
   1676 
   1677             if (matched && dragOperation != DragOperationNone)
   1678                 break;
   1679         }
   1680         if (matched) {
   1681             clipboard->setDropEffect(convertDragOperationToDropZoneOperation(dragOperation));
   1682             return true;
   1683         }
   1684     }
   1685     return false;
   1686 }
   1687 
   1688 bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
   1689 {
   1690     bool accept = false;
   1691 
   1692     if (!m_frame->view())
   1693         return false;
   1694 
   1695     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
   1696     MouseEventWithHitTestResults mev = prepareMouseEvent(request, event);
   1697 
   1698     // Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
   1699     RefPtrWillBeRawPtr<Node> newTarget = mev.targetNode();
   1700     if (newTarget && newTarget->isTextNode())
   1701         newTarget = NodeRenderingTraversal::parent(newTarget.get());
   1702 
   1703     if (AutoscrollController* controller = autoscrollController())
   1704         controller->updateDragAndDrop(newTarget.get(), event.position(), event.timestamp());
   1705 
   1706     if (m_dragTarget != newTarget) {
   1707         // FIXME: this ordering was explicitly chosen to match WinIE. However,
   1708         // it is sometimes incorrect when dragging within subframes, as seen with
   1709         // LayoutTests/fast/events/drag-in-frames.html.
   1710         //
   1711         // Moreover, this ordering conforms to section 7.9.4 of the HTML 5 spec. <http://dev.w3.org/html5/spec/Overview.html#drag-and-drop-processing-model>.
   1712         LocalFrame* targetFrame;
   1713         if (targetIsFrame(newTarget.get(), targetFrame)) {
   1714             if (targetFrame)
   1715                 accept = targetFrame->eventHandler().updateDragAndDrop(event, clipboard);
   1716         } else if (newTarget) {
   1717             // As per section 7.9.4 of the HTML 5 spec., we must always fire a drag event before firing a dragenter, dragleave, or dragover event.
   1718             if (dragState().m_dragSrc) {
   1719                 // for now we don't care if event handler cancels default behavior, since there is none
   1720                 dispatchDragSrcEvent(EventTypeNames::drag, event);
   1721             }
   1722             accept = dispatchDragEvent(EventTypeNames::dragenter, newTarget.get(), event, clipboard);
   1723             if (!accept)
   1724                 accept = findDropZone(newTarget.get(), clipboard);
   1725         }
   1726 
   1727         if (targetIsFrame(m_dragTarget.get(), targetFrame)) {
   1728             if (targetFrame)
   1729                 accept = targetFrame->eventHandler().updateDragAndDrop(event, clipboard);
   1730         } else if (m_dragTarget)
   1731             dispatchDragEvent(EventTypeNames::dragleave, m_dragTarget.get(), event, clipboard);
   1732 
   1733         if (newTarget) {
   1734             // We do not explicitly call dispatchDragEvent here because it could ultimately result in the appearance that
   1735             // two dragover events fired. So, we mark that we should only fire a dragover event on the next call to this function.
   1736             m_shouldOnlyFireDragOverEvent = true;
   1737         }
   1738     } else {
   1739         LocalFrame* targetFrame;
   1740         if (targetIsFrame(newTarget.get(), targetFrame)) {
   1741             if (targetFrame)
   1742                 accept = targetFrame->eventHandler().updateDragAndDrop(event, clipboard);
   1743         } else if (newTarget) {
   1744             // Note, when dealing with sub-frames, we may need to fire only a dragover event as a drag event may have been fired earlier.
   1745             if (!m_shouldOnlyFireDragOverEvent && dragState().m_dragSrc) {
   1746                 // for now we don't care if event handler cancels default behavior, since there is none
   1747                 dispatchDragSrcEvent(EventTypeNames::drag, event);
   1748             }
   1749             accept = dispatchDragEvent(EventTypeNames::dragover, newTarget.get(), event, clipboard);
   1750             if (!accept)
   1751                 accept = findDropZone(newTarget.get(), clipboard);
   1752             m_shouldOnlyFireDragOverEvent = false;
   1753         }
   1754     }
   1755     m_dragTarget = newTarget;
   1756 
   1757     return accept;
   1758 }
   1759 
   1760 void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
   1761 {
   1762     LocalFrame* targetFrame;
   1763     if (targetIsFrame(m_dragTarget.get(), targetFrame)) {
   1764         if (targetFrame)
   1765             targetFrame->eventHandler().cancelDragAndDrop(event, clipboard);
   1766     } else if (m_dragTarget.get()) {
   1767         if (dragState().m_dragSrc)
   1768             dispatchDragSrcEvent(EventTypeNames::drag, event);
   1769         dispatchDragEvent(EventTypeNames::dragleave, m_dragTarget.get(), event, clipboard);
   1770     }
   1771     clearDragState();
   1772 }
   1773 
   1774 bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
   1775 {
   1776     LocalFrame* targetFrame;
   1777     bool preventedDefault = false;
   1778     if (targetIsFrame(m_dragTarget.get(), targetFrame)) {
   1779         if (targetFrame)
   1780             preventedDefault = targetFrame->eventHandler().performDragAndDrop(event, clipboard);
   1781     } else if (m_dragTarget.get())
   1782         preventedDefault = dispatchDragEvent(EventTypeNames::drop, m_dragTarget.get(), event, clipboard);
   1783     clearDragState();
   1784     return preventedDefault;
   1785 }
   1786 
   1787 void EventHandler::clearDragState()
   1788 {
   1789     stopAutoscroll();
   1790     m_dragTarget = nullptr;
   1791     m_capturingMouseEventsNode = nullptr;
   1792     m_shouldOnlyFireDragOverEvent = false;
   1793 }
   1794 
   1795 void EventHandler::setCapturingMouseEventsNode(PassRefPtrWillBeRawPtr<Node> n)
   1796 {
   1797     m_capturingMouseEventsNode = n;
   1798     m_eventHandlerWillResetCapturingMouseEventsNode = false;
   1799 }
   1800 
   1801 MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestRequest& request, const PlatformMouseEvent& mev)
   1802 {
   1803     ASSERT(m_frame);
   1804     ASSERT(m_frame->document());
   1805 
   1806     return m_frame->document()->prepareMouseEvent(request, documentPointForWindowPoint(m_frame, mev.position()), mev);
   1807 }
   1808 
   1809 void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMouseEvent& mouseEvent, bool fireMouseOverOut)
   1810 {
   1811     Node* result = targetNode;
   1812 
   1813     // If we're capturing, we always go right to that node.
   1814     if (m_capturingMouseEventsNode)
   1815         result = m_capturingMouseEventsNode.get();
   1816     else {
   1817         // If the target node is a text node, dispatch on the parent node - rdar://4196646
   1818         if (result && result->isTextNode())
   1819             result = NodeRenderingTraversal::parent(result);
   1820     }
   1821     m_nodeUnderMouse = result;
   1822 
   1823     // Fire mouseout/mouseover if the mouse has shifted to a different node.
   1824     if (fireMouseOverOut) {
   1825         RenderLayer* layerForLastNode = layerForNode(m_lastNodeUnderMouse.get());
   1826         RenderLayer* layerForNodeUnderMouse = layerForNode(m_nodeUnderMouse.get());
   1827         Page* page = m_frame->page();
   1828 
   1829         if (m_lastNodeUnderMouse && (!m_nodeUnderMouse || m_nodeUnderMouse->document() != m_frame->document())) {
   1830             // The mouse has moved between frames.
   1831             if (LocalFrame* frame = m_lastNodeUnderMouse->document().frame()) {
   1832                 if (FrameView* frameView = frame->view())
   1833                     frameView->mouseExitedContentArea();
   1834             }
   1835         } else if (page && (layerForLastNode && (!layerForNodeUnderMouse || layerForNodeUnderMouse != layerForLastNode))) {
   1836             // The mouse has moved between layers.
   1837             if (ScrollableArea* scrollableAreaForLastNode = associatedScrollableArea(layerForLastNode))
   1838                 scrollableAreaForLastNode->mouseExitedContentArea();
   1839         }
   1840 
   1841         if (m_nodeUnderMouse && (!m_lastNodeUnderMouse || m_lastNodeUnderMouse->document() != m_frame->document())) {
   1842             // The mouse has moved between frames.
   1843             if (LocalFrame* frame = m_nodeUnderMouse->document().frame()) {
   1844                 if (FrameView* frameView = frame->view())
   1845                     frameView->mouseEnteredContentArea();
   1846             }
   1847         } else if (page && (layerForNodeUnderMouse && (!layerForLastNode || layerForNodeUnderMouse != layerForLastNode))) {
   1848             // The mouse has moved between layers.
   1849             if (ScrollableArea* scrollableAreaForNodeUnderMouse = associatedScrollableArea(layerForNodeUnderMouse))
   1850                 scrollableAreaForNodeUnderMouse->mouseEnteredContentArea();
   1851         }
   1852 
   1853         if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame->document()) {
   1854             m_lastNodeUnderMouse = nullptr;
   1855             m_lastScrollbarUnderMouse = nullptr;
   1856         }
   1857 
   1858         if (m_lastNodeUnderMouse != m_nodeUnderMouse) {
   1859             // send mouseout event to the old node
   1860             if (m_lastNodeUnderMouse)
   1861                 m_lastNodeUnderMouse->dispatchMouseEvent(mouseEvent, EventTypeNames::mouseout, 0, m_nodeUnderMouse.get());
   1862             // send mouseover event to the new node
   1863             if (m_nodeUnderMouse)
   1864                 m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, EventTypeNames::mouseover, 0, m_lastNodeUnderMouse.get());
   1865         }
   1866         m_lastNodeUnderMouse = m_nodeUnderMouse;
   1867     }
   1868 }
   1869 
   1870 // The return value means 'continue default handling.'
   1871 bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder)
   1872 {
   1873     updateMouseEventTargetNode(targetNode, mouseEvent, setUnder);
   1874     return !m_nodeUnderMouse || m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventType, clickCount);
   1875 }
   1876 
   1877 // The return value means 'continue default handling.'
   1878 bool EventHandler::handleMouseFocus(const PlatformMouseEvent& mouseEvent)
   1879 {
   1880     // If clicking on a frame scrollbar, do not mess up with content focus.
   1881     if (FrameView* view = m_frame->view()) {
   1882         if (view->scrollbarAtPoint(mouseEvent.position()))
   1883             return true;
   1884     }
   1885 
   1886     // The layout needs to be up to date to determine if an element is focusable.
   1887     m_frame->document()->updateLayoutIgnorePendingStylesheets();
   1888 
   1889     Element* element = 0;
   1890     if (m_nodeUnderMouse)
   1891         element = m_nodeUnderMouse->isElementNode() ? toElement(m_nodeUnderMouse) : m_nodeUnderMouse->parentOrShadowHostElement();
   1892     for (; element; element = element->parentOrShadowHostElement()) {
   1893         if (element->isFocusable() && element->focused())
   1894             return true;
   1895         if (element->isMouseFocusable())
   1896             break;
   1897     }
   1898     ASSERT(!element || element->isMouseFocusable());
   1899 
   1900     // To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus
   1901     // a node on mouse down if it's selected and inside a focused node. It will
   1902     // be focused if the user does a mouseup over it, however, because the
   1903     // mouseup will set a selection inside it, which will call
   1904     // FrameSelection::setFocusedNodeIfNeeded.
   1905     if (element
   1906         && m_frame->selection().isRange()
   1907         && m_frame->selection().toNormalizedRange()->compareNode(element, IGNORE_EXCEPTION) == Range::NODE_INSIDE
   1908         && element->isDescendantOf(m_frame->document()->focusedElement()))
   1909         return true;
   1910 
   1911     // Only change the focus when clicking scrollbars if it can transfered to a
   1912     // mouse focusable node.
   1913     if (!element && isInsideScrollbar(mouseEvent.position()))
   1914         return false;
   1915 
   1916     if (Page* page = m_frame->page()) {
   1917         // If focus shift is blocked, we eat the event. Note we should never
   1918         // clear swallowEvent if the page already set it (e.g., by canceling
   1919         // default behavior).
   1920         if (element) {
   1921             if (!page->focusController().setFocusedElement(element, m_frame, FocusTypeMouse))
   1922                 return false;
   1923         } else {
   1924             // We call setFocusedElement even with !element in order to blur
   1925             // current focus element when a link is clicked; this is expected by
   1926             // some sites that rely on onChange handlers running from form
   1927             // fields before the button click is processed.
   1928             if (!page->focusController().setFocusedElement(0, m_frame))
   1929                 return false;
   1930         }
   1931     }
   1932 
   1933     return true;
   1934 }
   1935 
   1936 bool EventHandler::isInsideScrollbar(const IntPoint& windowPoint) const
   1937 {
   1938     if (RenderView* renderView = m_frame->contentRenderer()) {
   1939         HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
   1940         HitTestResult result(windowPoint);
   1941         renderView->hitTest(request, result);
   1942         return result.scrollbar();
   1943     }
   1944 
   1945     return false;
   1946 }
   1947 
   1948 bool EventHandler::handleWheelEvent(const PlatformWheelEvent& event)
   1949 {
   1950 #define RETURN_WHEEL_EVENT_HANDLED() \
   1951     { \
   1952         setFrameWasScrolledByUser(); \
   1953         return true; \
   1954     }
   1955 
   1956     Document* doc = m_frame->document();
   1957 
   1958     if (!doc->renderView())
   1959         return false;
   1960 
   1961     RefPtr<FrameView> protector(m_frame->view());
   1962 
   1963     FrameView* view = m_frame->view();
   1964     if (!view)
   1965         return false;
   1966 
   1967     LayoutPoint vPoint = view->windowToContents(event.position());
   1968 
   1969     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
   1970     HitTestResult result(vPoint);
   1971     doc->renderView()->hitTest(request, result);
   1972 
   1973     Node* node = result.innerNode();
   1974     // Wheel events should not dispatch to text nodes.
   1975     if (node && node->isTextNode())
   1976         node = NodeRenderingTraversal::parent(node);
   1977 
   1978     bool isOverWidget;
   1979     if (event.useLatchedEventNode()) {
   1980         if (!m_latchedWheelEventNode) {
   1981             m_latchedWheelEventNode = node;
   1982             m_widgetIsLatched = result.isOverWidget();
   1983         } else
   1984             node = m_latchedWheelEventNode.get();
   1985 
   1986         isOverWidget = m_widgetIsLatched;
   1987     } else {
   1988         if (m_latchedWheelEventNode)
   1989             m_latchedWheelEventNode = nullptr;
   1990         if (m_previousWheelScrolledNode)
   1991             m_previousWheelScrolledNode = nullptr;
   1992 
   1993         isOverWidget = result.isOverWidget();
   1994     }
   1995 
   1996     if (node) {
   1997         // Figure out which view to send the event to.
   1998         RenderObject* target = node->renderer();
   1999 
   2000         if (isOverWidget && target && target->isWidget()) {
   2001             Widget* widget = toRenderWidget(target)->widget();
   2002             if (widget && passWheelEventToWidget(event, widget))
   2003                 RETURN_WHEEL_EVENT_HANDLED();
   2004         }
   2005 
   2006         if (node && !node->dispatchWheelEvent(event))
   2007             RETURN_WHEEL_EVENT_HANDLED();
   2008     }
   2009 
   2010     // We do another check on the frame view because the event handler can run JS which results in the frame getting destroyed.
   2011     view = m_frame->view();
   2012     if (!view || !view->wheelEvent(event))
   2013         return false;
   2014 
   2015     RETURN_WHEEL_EVENT_HANDLED();
   2016 
   2017 #undef RETURN_WHEEL_EVENT_HANDLED
   2018 }
   2019 
   2020 void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEvent)
   2021 {
   2022     if (!startNode || !wheelEvent)
   2023         return;
   2024 
   2025     // Ctrl + scrollwheel is reserved for triggering zoom in/out actions in Chromium.
   2026     if (wheelEvent->ctrlKey())
   2027         return;
   2028 
   2029     Node* stopNode = m_previousWheelScrolledNode.get();
   2030     ScrollGranularity granularity = wheelGranularityToScrollGranularity(wheelEvent->deltaMode());
   2031 
   2032     // Break up into two scrolls if we need to.  Diagonal movement on
   2033     // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
   2034     if (scroll(ScrollRight, granularity, startNode, &stopNode, wheelEvent->deltaX(), roundedIntPoint(wheelEvent->absoluteLocation())))
   2035         wheelEvent->setDefaultHandled();
   2036 
   2037     if (scroll(ScrollDown, granularity, startNode, &stopNode, wheelEvent->deltaY(), roundedIntPoint(wheelEvent->absoluteLocation())))
   2038         wheelEvent->setDefaultHandled();
   2039 
   2040     if (!m_latchedWheelEventNode)
   2041         m_previousWheelScrolledNode = stopNode;
   2042 }
   2043 
   2044 bool EventHandler::handleGestureShowPress()
   2045 {
   2046     m_lastShowPressTimestamp = WTF::currentTime();
   2047 
   2048     FrameView* view = m_frame->view();
   2049     if (!view)
   2050         return false;
   2051     if (ScrollAnimator* scrollAnimator = view->existingScrollAnimator())
   2052         scrollAnimator->cancelAnimations();
   2053     const FrameView::ScrollableAreaSet* areas = view->scrollableAreas();
   2054     if (!areas)
   2055         return false;
   2056     for (FrameView::ScrollableAreaSet::const_iterator it = areas->begin(); it != areas->end(); ++it) {
   2057         ScrollableArea* sa = *it;
   2058         ScrollAnimator* animator = sa->scrollAnimator();
   2059         if (animator)
   2060             animator->cancelAnimations();
   2061     }
   2062     return false;
   2063 }
   2064 
   2065 bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
   2066 {
   2067     IntPoint adjustedPoint = gestureEvent.position();
   2068     RefPtr<LocalFrame> subframe = nullptr;
   2069     switch (gestureEvent.type()) {
   2070     case PlatformEvent::GestureScrollBegin:
   2071     case PlatformEvent::GestureScrollUpdate:
   2072     case PlatformEvent::GestureScrollUpdateWithoutPropagation:
   2073     case PlatformEvent::GestureScrollEnd:
   2074     case PlatformEvent::GestureFlingStart:
   2075         // Handle directly in main frame
   2076         break;
   2077 
   2078     case PlatformEvent::GestureTap:
   2079     case PlatformEvent::GestureTapUnconfirmed:
   2080     case PlatformEvent::GestureTapDown:
   2081     case PlatformEvent::GestureShowPress:
   2082     case PlatformEvent::GestureTapDownCancel:
   2083     case PlatformEvent::GestureTwoFingerTap:
   2084     case PlatformEvent::GestureLongPress:
   2085     case PlatformEvent::GestureLongTap:
   2086     case PlatformEvent::GesturePinchBegin:
   2087     case PlatformEvent::GesturePinchEnd:
   2088     case PlatformEvent::GesturePinchUpdate:
   2089         adjustGesturePosition(gestureEvent, adjustedPoint);
   2090         subframe = getSubFrameForGestureEvent(adjustedPoint, gestureEvent);
   2091         if (subframe)
   2092             return subframe->eventHandler().handleGestureEvent(gestureEvent);
   2093         break;
   2094 
   2095     default:
   2096         ASSERT_NOT_REACHED();
   2097     }
   2098 
   2099     RefPtrWillBeRawPtr<Node> eventTarget = nullptr;
   2100     RefPtr<Scrollbar> scrollbar;
   2101     if (gestureEvent.type() == PlatformEvent::GestureScrollEnd
   2102         || gestureEvent.type() == PlatformEvent::GestureScrollUpdate
   2103         || gestureEvent.type() == PlatformEvent::GestureScrollUpdateWithoutPropagation
   2104         || gestureEvent.type() == PlatformEvent::GestureFlingStart) {
   2105         scrollbar = m_scrollbarHandlingScrollGesture.get();
   2106         eventTarget = m_scrollGestureHandlingNode.get();
   2107     }
   2108 
   2109     HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent;
   2110     double activeInterval = 0;
   2111     bool shouldKeepActiveForMinInterval = false;
   2112     if (gestureEvent.type() == PlatformEvent::GestureShowPress
   2113         || gestureEvent.type() == PlatformEvent::GestureTapUnconfirmed) {
   2114         hitType |= HitTestRequest::Active;
   2115     } else if (gestureEvent.type() == PlatformEvent::GestureTapDownCancel) {
   2116         hitType |= HitTestRequest::Release;
   2117         // A TapDownCancel received when no element is active shouldn't really be changing hover state.
   2118         if (!m_frame->document()->activeHoverElement())
   2119             hitType |= HitTestRequest::ReadOnly;
   2120     } else if (gestureEvent.type() == PlatformEvent::GestureTap) {
   2121         hitType |= HitTestRequest::Release;
   2122         // If the Tap is received very shortly after ShowPress, we want to
   2123         // delay clearing of the active state so that it's visible to the user
   2124         // for at least a couple of frames.
   2125         activeInterval = WTF::currentTime() - m_lastShowPressTimestamp;
   2126         shouldKeepActiveForMinInterval = m_lastShowPressTimestamp && activeInterval < minimumActiveInterval;
   2127         if (shouldKeepActiveForMinInterval)
   2128             hitType |= HitTestRequest::ReadOnly;
   2129     }
   2130     else
   2131         hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly;
   2132 
   2133     if ((!scrollbar && !eventTarget) || !(hitType & HitTestRequest::ReadOnly)) {
   2134         IntPoint hitTestPoint = m_frame->view()->windowToContents(adjustedPoint);
   2135         HitTestResult result = hitTestResultAtPoint(hitTestPoint, hitType | HitTestRequest::AllowFrameScrollbars);
   2136 
   2137         if (shouldKeepActiveForMinInterval) {
   2138             m_lastDeferredTapElement = result.innerElement();
   2139             m_activeIntervalTimer.startOneShot(minimumActiveInterval - activeInterval, FROM_HERE);
   2140         }
   2141 
   2142         eventTarget = result.targetNode();
   2143         if (!scrollbar) {
   2144             FrameView* view = m_frame->view();
   2145             scrollbar = view ? view->scrollbarAtPoint(gestureEvent.position()) : 0;
   2146         }
   2147         if (!scrollbar)
   2148             scrollbar = result.scrollbar();
   2149     }
   2150 
   2151     if (scrollbar) {
   2152         bool eventSwallowed = scrollbar->gestureEvent(gestureEvent);
   2153         if (gestureEvent.type() == PlatformEvent::GestureTapDown && eventSwallowed) {
   2154             m_scrollbarHandlingScrollGesture = scrollbar;
   2155         } else if (gestureEvent.type() == PlatformEvent::GestureScrollEnd
   2156             || gestureEvent.type() == PlatformEvent::GestureFlingStart
   2157             || !eventSwallowed) {
   2158             m_scrollbarHandlingScrollGesture = nullptr;
   2159         }
   2160 
   2161         if (eventSwallowed)
   2162             return true;
   2163     }
   2164 
   2165     if (eventTarget) {
   2166         bool eventSwallowed = false;
   2167         if (handleScrollGestureOnResizer(eventTarget.get(), gestureEvent))
   2168             eventSwallowed = true;
   2169         else
   2170             eventSwallowed = eventTarget->dispatchGestureEvent(gestureEvent);
   2171         if (gestureEvent.type() == PlatformEvent::GestureScrollBegin || gestureEvent.type() == PlatformEvent::GestureScrollEnd) {
   2172             if (eventSwallowed)
   2173                 m_scrollGestureHandlingNode = eventTarget;
   2174         }
   2175 
   2176         if (eventSwallowed)
   2177             return true;
   2178     }
   2179 
   2180     // FIXME: A more general scroll system (https://bugs.webkit.org/show_bug.cgi?id=80596) will
   2181     // eliminate the need for this.
   2182     TemporaryChange<PlatformEvent::Type> baseEventType(m_baseEventType, gestureEvent.type());
   2183 
   2184     switch (gestureEvent.type()) {
   2185     case PlatformEvent::GestureScrollBegin:
   2186         return handleGestureScrollBegin(gestureEvent);
   2187     case PlatformEvent::GestureScrollUpdate:
   2188     case PlatformEvent::GestureScrollUpdateWithoutPropagation:
   2189         return handleGestureScrollUpdate(gestureEvent);
   2190     case PlatformEvent::GestureScrollEnd:
   2191         return handleGestureScrollEnd(gestureEvent);
   2192     case PlatformEvent::GestureTap:
   2193         return handleGestureTap(gestureEvent, adjustedPoint);
   2194     case PlatformEvent::GestureShowPress:
   2195         return handleGestureShowPress();
   2196     case PlatformEvent::GestureLongPress:
   2197         return handleGestureLongPress(gestureEvent, adjustedPoint);
   2198     case PlatformEvent::GestureLongTap:
   2199         return handleGestureLongTap(gestureEvent, adjustedPoint);
   2200     case PlatformEvent::GestureTwoFingerTap:
   2201         return handleGestureTwoFingerTap(gestureEvent, adjustedPoint);
   2202     case PlatformEvent::GestureTapDown:
   2203     case PlatformEvent::GesturePinchBegin:
   2204     case PlatformEvent::GesturePinchEnd:
   2205     case PlatformEvent::GesturePinchUpdate:
   2206     case PlatformEvent::GestureTapDownCancel:
   2207     case PlatformEvent::GestureTapUnconfirmed:
   2208     case PlatformEvent::GestureFlingStart:
   2209         break;
   2210     default:
   2211         ASSERT_NOT_REACHED();
   2212     }
   2213 
   2214     return false;
   2215 }
   2216 
   2217 bool EventHandler::handleGestureTap(const PlatformGestureEvent& gestureEvent, const IntPoint& adjustedPoint)
   2218 {
   2219     // FIXME: Refactor this code to not hit test multiple times. We use the adjusted position to ensure that the correct node is targeted by the later redundant hit tests.
   2220 
   2221     unsigned modifierFlags = 0;
   2222     if (gestureEvent.altKey())
   2223         modifierFlags |= PlatformEvent::AltKey;
   2224     if (gestureEvent.ctrlKey())
   2225         modifierFlags |= PlatformEvent::CtrlKey;
   2226     if (gestureEvent.metaKey())
   2227         modifierFlags |= PlatformEvent::MetaKey;
   2228     if (gestureEvent.shiftKey())
   2229         modifierFlags |= PlatformEvent::ShiftKey;
   2230     PlatformEvent::Modifiers modifiers = static_cast<PlatformEvent::Modifiers>(modifierFlags);
   2231 
   2232     PlatformMouseEvent fakeMouseMove(adjustedPoint, gestureEvent.globalPosition(),
   2233         NoButton, PlatformEvent::MouseMoved, /* clickCount */ 0,
   2234         modifiers, PlatformMouseEvent::FromTouch, gestureEvent.timestamp());
   2235     handleMouseMoveEvent(fakeMouseMove);
   2236 
   2237     bool defaultPrevented = false;
   2238     PlatformMouseEvent fakeMouseDown(adjustedPoint, gestureEvent.globalPosition(),
   2239         LeftButton, PlatformEvent::MousePressed, gestureEvent.tapCount(),
   2240         modifiers, PlatformMouseEvent::FromTouch,  gestureEvent.timestamp());
   2241     defaultPrevented |= handleMousePressEvent(fakeMouseDown);
   2242 
   2243     PlatformMouseEvent fakeMouseUp(adjustedPoint, gestureEvent.globalPosition(),
   2244         LeftButton, PlatformEvent::MouseReleased, gestureEvent.tapCount(),
   2245         modifiers, PlatformMouseEvent::FromTouch,  gestureEvent.timestamp());
   2246     defaultPrevented |= handleMouseReleaseEvent(fakeMouseUp);
   2247 
   2248     return defaultPrevented;
   2249 }
   2250 
   2251 bool EventHandler::handleGestureLongPress(const PlatformGestureEvent& gestureEvent, const IntPoint& adjustedPoint)
   2252 {
   2253     m_longTapShouldInvokeContextMenu = false;
   2254     if (m_frame->settings() && m_frame->settings()->touchDragDropEnabled() && m_frame->view()) {
   2255         PlatformMouseEvent mouseDownEvent(adjustedPoint, gestureEvent.globalPosition(), LeftButton, PlatformEvent::MousePressed, 1,
   2256             gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), WTF::currentTime());
   2257         m_mouseDown = mouseDownEvent;
   2258 
   2259         PlatformMouseEvent mouseDragEvent(adjustedPoint, gestureEvent.globalPosition(), LeftButton, PlatformEvent::MouseMoved, 1,
   2260             gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), WTF::currentTime());
   2261         HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
   2262         MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseDragEvent);
   2263         m_didStartDrag = false;
   2264         m_mouseDownMayStartDrag = true;
   2265         dragState().m_dragSrc = nullptr;
   2266         m_mouseDownPos = m_frame->view()->windowToContents(mouseDragEvent.position());
   2267         RefPtr<FrameView> protector(m_frame->view());
   2268         handleDrag(mev, DontCheckDragHysteresis);
   2269         if (m_didStartDrag) {
   2270             m_longTapShouldInvokeContextMenu = true;
   2271             return true;
   2272         }
   2273     }
   2274 #if OS(ANDROID)
   2275     bool shouldLongPressSelectWord = true;
   2276 #else
   2277     bool shouldLongPressSelectWord = m_frame->settings() && m_frame->settings()->touchEditingEnabled();
   2278 #endif
   2279     if (shouldLongPressSelectWord) {
   2280         IntPoint hitTestPoint = m_frame->view()->windowToContents(gestureEvent.position());
   2281         HitTestResult result = hitTestResultAtPoint(hitTestPoint);
   2282         Node* innerNode = result.targetNode();
   2283         if (!result.isLiveLink() && innerNode && (innerNode->isContentEditable() || innerNode->isTextNode())) {
   2284             selectClosestWordFromHitTestResult(result, DontAppendTrailingWhitespace);
   2285             if (m_frame->selection().isRange()) {
   2286                 focusDocumentView();
   2287                 return true;
   2288             }
   2289         }
   2290     }
   2291     return sendContextMenuEventForGesture(gestureEvent);
   2292 }
   2293 
   2294 bool EventHandler::handleGestureLongTap(const PlatformGestureEvent& gestureEvent, const IntPoint& adjustedPoint)
   2295 {
   2296 #if !OS(ANDROID)
   2297     if (m_longTapShouldInvokeContextMenu) {
   2298         m_longTapShouldInvokeContextMenu = false;
   2299         return sendContextMenuEventForGesture(gestureEvent);
   2300     }
   2301 #endif
   2302     return false;
   2303 }
   2304 
   2305 bool EventHandler::handleScrollGestureOnResizer(Node* eventTarget, const PlatformGestureEvent& gestureEvent) {
   2306     if (gestureEvent.type() == PlatformEvent::GestureScrollBegin) {
   2307         RenderLayer* layer = eventTarget->renderer() ? eventTarget->renderer()->enclosingLayer() : 0;
   2308         IntPoint p = m_frame->view()->windowToContents(gestureEvent.position());
   2309         if (layer && layer->scrollableArea() && layer->scrollableArea()->isPointInResizeControl(p, ResizerForTouch)) {
   2310             m_resizeScrollableArea = layer->scrollableArea();
   2311             m_resizeScrollableArea->setInResizeMode(true);
   2312             m_offsetFromResizeCorner = m_resizeScrollableArea->offsetFromResizeCorner(p);
   2313             return true;
   2314         }
   2315     } else if (gestureEvent.type() == PlatformEvent::GestureScrollUpdate ||
   2316                gestureEvent.type() == PlatformEvent::GestureScrollUpdateWithoutPropagation) {
   2317         if (m_resizeScrollableArea && m_resizeScrollableArea->inResizeMode()) {
   2318             m_resizeScrollableArea->resize(gestureEvent, m_offsetFromResizeCorner);
   2319             return true;
   2320         }
   2321     } else if (gestureEvent.type() == PlatformEvent::GestureScrollEnd) {
   2322         if (m_resizeScrollableArea && m_resizeScrollableArea->inResizeMode()) {
   2323             m_resizeScrollableArea->setInResizeMode(false);
   2324             m_resizeScrollableArea = 0;
   2325             return false;
   2326         }
   2327     }
   2328 
   2329     return false;
   2330 }
   2331 
   2332 bool EventHandler::handleGestureTwoFingerTap(const PlatformGestureEvent& gestureEvent, const IntPoint& adjustedPoint)
   2333 {
   2334     return sendContextMenuEventForGesture(gestureEvent);
   2335 }
   2336 
   2337 bool EventHandler::passGestureEventToWidget(const PlatformGestureEvent& gestureEvent, Widget* widget)
   2338 {
   2339     if (!widget)
   2340         return false;
   2341 
   2342     if (!widget->isFrameView())
   2343         return false;
   2344 
   2345     return toFrameView(widget)->frame().eventHandler().handleGestureEvent(gestureEvent);
   2346 }
   2347 
   2348 bool EventHandler::passGestureEventToWidgetIfPossible(const PlatformGestureEvent& gestureEvent, RenderObject* renderer)
   2349 {
   2350     if (m_lastHitTestResultOverWidget && renderer && renderer->isWidget()) {
   2351         Widget* widget = toRenderWidget(renderer)->widget();
   2352         return widget && passGestureEventToWidget(gestureEvent, widget);
   2353     }
   2354     return false;
   2355 }
   2356 
   2357 bool EventHandler::handleGestureScrollEnd(const PlatformGestureEvent& gestureEvent) {
   2358     RefPtrWillBeRawPtr<Node> node = m_scrollGestureHandlingNode;
   2359     clearGestureScrollNodes();
   2360 
   2361     if (node)
   2362         passGestureEventToWidgetIfPossible(gestureEvent, node->renderer());
   2363 
   2364     return false;
   2365 }
   2366 
   2367 bool EventHandler::handleGestureScrollBegin(const PlatformGestureEvent& gestureEvent)
   2368 {
   2369     Document* document = m_frame->document();
   2370     if (!document->renderView())
   2371         return false;
   2372 
   2373     FrameView* view = m_frame->view();
   2374     if (!view)
   2375         return false;
   2376 
   2377     LayoutPoint viewPoint = view->windowToContents(gestureEvent.position());
   2378     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
   2379     HitTestResult result(viewPoint);
   2380     document->renderView()->hitTest(request, result);
   2381 
   2382     m_lastHitTestResultOverWidget = result.isOverWidget();
   2383     m_scrollGestureHandlingNode = result.innerNode();
   2384     m_previousGestureScrolledNode = nullptr;
   2385 
   2386     // If there's no renderer on the node, send the event to the nearest ancestor with a renderer.
   2387     // Needed for <option> and <optgroup> elements so we can touch scroll <select>s
   2388     while (m_scrollGestureHandlingNode && !m_scrollGestureHandlingNode->renderer())
   2389         m_scrollGestureHandlingNode = m_scrollGestureHandlingNode->parentOrShadowHostNode();
   2390 
   2391     if (!m_scrollGestureHandlingNode)
   2392         return false;
   2393 
   2394     passGestureEventToWidgetIfPossible(gestureEvent, m_scrollGestureHandlingNode->renderer());
   2395 
   2396     return true;
   2397 }
   2398 
   2399 bool EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gestureEvent)
   2400 {
   2401     FloatSize delta(gestureEvent.deltaX(), gestureEvent.deltaY());
   2402     if (delta.isZero())
   2403         return false;
   2404 
   2405     const float scaleFactor = m_frame->pageZoomFactor();
   2406     delta.scale(1 / scaleFactor, 1 / scaleFactor);
   2407 
   2408     Node* node = m_scrollGestureHandlingNode.get();
   2409     if (!node)
   2410         return sendScrollEventToView(gestureEvent, delta);
   2411 
   2412     // Ignore this event if the targeted node does not have a valid renderer.
   2413     RenderObject* renderer = node->renderer();
   2414     if (!renderer)
   2415         return false;
   2416 
   2417     RefPtr<FrameView> protector(m_frame->view());
   2418 
   2419     Node* stopNode = 0;
   2420     bool scrollShouldNotPropagate = gestureEvent.type() == PlatformEvent::GestureScrollUpdateWithoutPropagation;
   2421 
   2422     // Try to send the event to the correct view.
   2423     if (passGestureEventToWidgetIfPossible(gestureEvent, renderer)) {
   2424         if(scrollShouldNotPropagate)
   2425               m_previousGestureScrolledNode = m_scrollGestureHandlingNode;
   2426 
   2427         return true;
   2428     }
   2429 
   2430     if (scrollShouldNotPropagate)
   2431         stopNode = m_previousGestureScrolledNode.get();
   2432 
   2433     // First try to scroll the closest scrollable RenderBox ancestor of |node|.
   2434     ScrollGranularity granularity = ScrollByPixel;
   2435     bool horizontalScroll = scroll(ScrollLeft, granularity, node, &stopNode, delta.width());
   2436     bool verticalScroll = scroll(ScrollUp, granularity, node, &stopNode, delta.height());
   2437 
   2438     if (scrollShouldNotPropagate)
   2439         m_previousGestureScrolledNode = stopNode;
   2440 
   2441     if (horizontalScroll || verticalScroll) {
   2442         setFrameWasScrolledByUser();
   2443         return true;
   2444     }
   2445 
   2446     // Otherwise try to scroll the view.
   2447     return sendScrollEventToView(gestureEvent, delta);
   2448 }
   2449 
   2450 bool EventHandler::sendScrollEventToView(const PlatformGestureEvent& gestureEvent, const FloatSize& scaledDelta)
   2451 {
   2452     FrameView* view = m_frame->view();
   2453     if (!view)
   2454         return false;
   2455 
   2456     const float tickDivisor = static_cast<float>(WheelEvent::TickMultiplier);
   2457     IntPoint point(gestureEvent.position().x(), gestureEvent.position().y());
   2458     IntPoint globalPoint(gestureEvent.globalPosition().x(), gestureEvent.globalPosition().y());
   2459     PlatformWheelEvent syntheticWheelEvent(point, globalPoint,
   2460         scaledDelta.width(), scaledDelta.height(),
   2461         scaledDelta.width() / tickDivisor, scaledDelta.height() / tickDivisor,
   2462         ScrollByPixelWheelEvent,
   2463         gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey());
   2464     syntheticWheelEvent.setHasPreciseScrollingDeltas(true);
   2465 
   2466     bool scrolledFrame = view->wheelEvent(syntheticWheelEvent);
   2467     if (scrolledFrame)
   2468         setFrameWasScrolledByUser();
   2469 
   2470     return scrolledFrame;
   2471 }
   2472 
   2473 LocalFrame* EventHandler::getSubFrameForGestureEvent(const IntPoint& touchAdjustedPoint, const PlatformGestureEvent& gestureEvent)
   2474 {
   2475     PlatformMouseEvent mouseDown(touchAdjustedPoint, gestureEvent.globalPosition(), LeftButton, PlatformEvent::MousePressed, 1,
   2476         gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp());
   2477     HitTestRequest request(HitTestRequest::ReadOnly);
   2478     MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseDown);
   2479     return subframeForHitTestResult(mev);
   2480 }
   2481 
   2482 void EventHandler::clearGestureScrollNodes()
   2483 {
   2484     m_scrollGestureHandlingNode = nullptr;
   2485     m_previousGestureScrolledNode = nullptr;
   2486 }
   2487 
   2488 bool EventHandler::isScrollbarHandlingGestures() const
   2489 {
   2490     return m_scrollbarHandlingScrollGesture.get();
   2491 }
   2492 
   2493 bool EventHandler::shouldApplyTouchAdjustment(const PlatformGestureEvent& event) const
   2494 {
   2495     if (m_frame->settings() && !m_frame->settings()->touchAdjustmentEnabled())
   2496         return false;
   2497     return !event.area().isEmpty();
   2498 }
   2499 
   2500 bool EventHandler::bestClickableNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode)
   2501 {
   2502     IntPoint hitTestPoint = m_frame->view()->windowToContents(touchCenter);
   2503     HitTestResult result = hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active, touchRadius);
   2504 
   2505     // If the touch is over a scrollbar, don't adjust the touch point since touch adjustment only takes into account
   2506     // DOM nodes so a touch over a scrollbar will be adjusted towards nearby nodes. This leads to things like textarea
   2507     // scrollbars being untouchable.
   2508     if (result.scrollbar())
   2509         return false;
   2510 
   2511     IntRect touchRect(touchCenter - touchRadius, touchRadius + touchRadius);
   2512     WillBeHeapVector<RefPtrWillBeMember<Node>, 11> nodes;
   2513     copyToVector(result.rectBasedTestResult(), nodes);
   2514 
   2515     // FIXME: Should be able to handle targetNode being a shadow DOM node to avoid performing uncessary hit tests
   2516     // in the case where further processing on the node is required. Returning the shadow ancestor prevents a
   2517     // regression in touchadjustment/html-label.html. Some refinement is required to testing/internals to
   2518     // handle targetNode being a shadow DOM node.
   2519 
   2520     // FIXME: the explicit Vector conversion copies into a temporary and is wasteful.
   2521     // FIXME: targetNode and success are only used by Internals functions. We should
   2522     // instead have dedicated test methods so we only do this work in tests.
   2523     bool success = findBestClickableCandidate(targetNode, targetPoint, touchCenter, touchRect, WillBeHeapVector<RefPtrWillBeMember<Node> > (nodes));
   2524     if (success && targetNode)
   2525         targetNode = targetNode->deprecatedShadowAncestorNode();
   2526     return success;
   2527 }
   2528 
   2529 bool EventHandler::bestContextMenuNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode)
   2530 {
   2531     IntPoint hitTestPoint = m_frame->view()->windowToContents(touchCenter);
   2532     HitTestResult result = hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active, touchRadius);
   2533 
   2534     IntRect touchRect(touchCenter - touchRadius, touchRadius + touchRadius);
   2535     WillBeHeapVector<RefPtrWillBeMember<Node>, 11> nodes;
   2536     copyToVector(result.rectBasedTestResult(), nodes);
   2537 
   2538     // FIXME: the explicit Vector conversion copies into a temporary and is wasteful.
   2539     return findBestContextMenuCandidate(targetNode, targetPoint, touchCenter, touchRect, WillBeHeapVector<RefPtrWillBeMember<Node> >(nodes));
   2540 }
   2541 
   2542 bool EventHandler::bestZoomableAreaForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntRect& targetArea, Node*& targetNode)
   2543 {
   2544     IntPoint hitTestPoint = m_frame->view()->windowToContents(touchCenter);
   2545     HitTestResult result = hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent, touchRadius);
   2546 
   2547     IntRect touchRect(touchCenter - touchRadius, touchRadius + touchRadius);
   2548     WillBeHeapVector<RefPtrWillBeMember<Node>, 11> nodes;
   2549     copyToVector(result.rectBasedTestResult(), nodes);
   2550 
   2551     // FIXME: the explicit Vector conversion copies into a temporary and is wasteful.
   2552     return findBestZoomableArea(targetNode, targetArea, touchCenter, touchRect, WillBeHeapVector<RefPtrWillBeMember<Node> >(nodes));
   2553 }
   2554 
   2555 void EventHandler::adjustGesturePosition(const PlatformGestureEvent& gestureEvent, IntPoint& adjustedPoint)
   2556 {
   2557     if (!shouldApplyTouchAdjustment(gestureEvent))
   2558         return;
   2559 
   2560     Node* targetNode = 0;
   2561     switch (gestureEvent.type()) {
   2562     case PlatformEvent::GestureTap:
   2563     case PlatformEvent::GestureTapUnconfirmed:
   2564     case PlatformEvent::GestureTapDown:
   2565     case PlatformEvent::GestureShowPress:
   2566         bestClickableNodeForTouchPoint(gestureEvent.position(), IntSize(gestureEvent.area().width() / 2, gestureEvent.area().height() / 2), adjustedPoint, targetNode);
   2567         break;
   2568     case PlatformEvent::GestureLongPress:
   2569     case PlatformEvent::GestureLongTap:
   2570     case PlatformEvent::GestureTwoFingerTap:
   2571         bestContextMenuNodeForTouchPoint(gestureEvent.position(), IntSize(gestureEvent.area().width() / 2, gestureEvent.area().height() / 2), adjustedPoint, targetNode);
   2572         break;
   2573     default:
   2574         // FIXME: Implement handling for other types as needed.
   2575         ASSERT_NOT_REACHED();
   2576     }
   2577 }
   2578 
   2579 bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event)
   2580 {
   2581     Document* doc = m_frame->document();
   2582     FrameView* v = m_frame->view();
   2583     if (!v)
   2584         return false;
   2585 
   2586     // Clear mouse press state to avoid initiating a drag while context menu is up.
   2587     m_mousePressed = false;
   2588     LayoutPoint viewportPos = v->windowToContents(event.position());
   2589     HitTestRequest request(HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
   2590     MouseEventWithHitTestResults mev = doc->prepareMouseEvent(request, viewportPos, event);
   2591 
   2592     if (!m_frame->selection().contains(viewportPos)
   2593         && !mev.scrollbar()
   2594         // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse.
   2595         // If the selection is non-editable, we do word selection to make it easier to use the contextual menu items
   2596         // available for text selections.  But only if we're above text.
   2597         && (m_frame->selection().isContentEditable() || (mev.targetNode() && mev.targetNode()->isTextNode()))) {
   2598         m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection
   2599 
   2600         if (mev.hitTestResult().isMisspelled())
   2601             selectClosestMisspellingFromMouseEvent(mev);
   2602         else if (m_frame->editor().behavior().shouldSelectOnContextualMenuClick())
   2603             selectClosestWordOrLinkFromMouseEvent(mev);
   2604     }
   2605 
   2606     return !dispatchMouseEvent(EventTypeNames::contextmenu, mev.targetNode(), 0, event, false);
   2607 }
   2608 
   2609 bool EventHandler::sendContextMenuEventForKey()
   2610 {
   2611     FrameView* view = m_frame->view();
   2612     if (!view)
   2613         return false;
   2614 
   2615     Document* doc = m_frame->document();
   2616     if (!doc)
   2617         return false;
   2618 
   2619     // Clear mouse press state to avoid initiating a drag while context menu is up.
   2620     m_mousePressed = false;
   2621 
   2622     static const int kContextMenuMargin = 1;
   2623 
   2624 #if OS(WIN)
   2625     int rightAligned = ::GetSystemMetrics(SM_MENUDROPALIGNMENT);
   2626 #else
   2627     int rightAligned = 0;
   2628 #endif
   2629     IntPoint location;
   2630 
   2631     Element* focusedElement = doc->focusedElement();
   2632     FrameSelection& selection = m_frame->selection();
   2633     Position start = selection.selection().start();
   2634     bool shouldTranslateToRootView = true;
   2635 
   2636     if (start.deprecatedNode() && (selection.rootEditableElement() || selection.isRange())) {
   2637         RefPtrWillBeRawPtr<Range> selectionRange = selection.toNormalizedRange();
   2638         IntRect firstRect = m_frame->editor().firstRectForRange(selectionRange.get());
   2639 
   2640         int x = rightAligned ? firstRect.maxX() : firstRect.x();
   2641         // In a multiline edit, firstRect.maxY() would endup on the next line, so -1.
   2642         int y = firstRect.maxY() ? firstRect.maxY() - 1 : 0;
   2643         location = IntPoint(x, y);
   2644     } else if (focusedElement) {
   2645         IntRect clippedRect = focusedElement->boundsInRootViewSpace();
   2646         location = IntPoint(clippedRect.center());
   2647     } else {
   2648         location = IntPoint(
   2649             rightAligned ? view->contentsWidth() - kContextMenuMargin : kContextMenuMargin,
   2650             kContextMenuMargin);
   2651         shouldTranslateToRootView = false;
   2652     }
   2653 
   2654     m_frame->view()->setCursor(pointerCursor());
   2655 
   2656     IntPoint position = shouldTranslateToRootView ? view->contentsToRootView(location) : location;
   2657     IntPoint globalPosition = view->hostWindow()->rootViewToScreen(IntRect(position, IntSize())).location();
   2658 
   2659     Node* targetNode = doc->focusedElement();
   2660     if (!targetNode)
   2661         targetNode = doc;
   2662 
   2663     // Use the focused node as the target for hover and active.
   2664     HitTestResult result(position);
   2665     result.setInnerNode(targetNode);
   2666     doc->updateHoverActiveState(HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent, result.innerElement());
   2667 
   2668     // The contextmenu event is a mouse event even when invoked using the keyboard.
   2669     // This is required for web compatibility.
   2670 
   2671 #if OS(WIN)
   2672     PlatformEvent::Type eventType = PlatformEvent::MouseReleased;
   2673 #else
   2674     PlatformEvent::Type eventType = PlatformEvent::MousePressed;
   2675 #endif
   2676 
   2677     PlatformMouseEvent mouseEvent(position, globalPosition, RightButton, eventType, 1, false, false, false, false, WTF::currentTime());
   2678 
   2679     handleMousePressEvent(mouseEvent);
   2680     return sendContextMenuEvent(mouseEvent);
   2681 }
   2682 
   2683 bool EventHandler::sendContextMenuEventForGesture(const PlatformGestureEvent& event)
   2684 {
   2685 #if OS(WIN)
   2686     PlatformEvent::Type eventType = PlatformEvent::MouseReleased;
   2687 #else
   2688     PlatformEvent::Type eventType = PlatformEvent::MousePressed;
   2689 #endif
   2690 
   2691     IntPoint adjustedPoint = event.position();
   2692     adjustGesturePosition(event, adjustedPoint);
   2693     PlatformMouseEvent mouseEvent(adjustedPoint, event.globalPosition(), RightButton, eventType, 1, false, false, false, false, WTF::currentTime());
   2694     // To simulate right-click behavior, we send a right mouse down and then
   2695     // context menu event.
   2696     handleMousePressEvent(mouseEvent);
   2697     return sendContextMenuEvent(mouseEvent);
   2698     // We do not need to send a corresponding mouse release because in case of
   2699     // right-click, the context menu takes capture and consumes all events.
   2700 }
   2701 
   2702 void EventHandler::scheduleHoverStateUpdate()
   2703 {
   2704     if (!m_hoverTimer.isActive())
   2705         m_hoverTimer.startOneShot(0, FROM_HERE);
   2706 }
   2707 
   2708 void EventHandler::scheduleCursorUpdate()
   2709 {
   2710     if (!m_cursorUpdateTimer.isActive())
   2711         m_cursorUpdateTimer.startOneShot(cursorUpdateInterval, FROM_HERE);
   2712 }
   2713 
   2714 void EventHandler::dispatchFakeMouseMoveEventSoon()
   2715 {
   2716     if (m_mousePressed)
   2717         return;
   2718 
   2719     if (m_mousePositionIsUnknown)
   2720         return;
   2721 
   2722     Settings* settings = m_frame->settings();
   2723     if (settings && !settings->deviceSupportsMouse())
   2724         return;
   2725 
   2726     // If the content has ever taken longer than fakeMouseMoveShortInterval we
   2727     // reschedule the timer and use a longer time. This will cause the content
   2728     // to receive these moves only after the user is done scrolling, reducing
   2729     // pauses during the scroll.
   2730     if (m_maxMouseMovedDuration > fakeMouseMoveShortInterval) {
   2731         if (m_fakeMouseMoveEventTimer.isActive())
   2732             m_fakeMouseMoveEventTimer.stop();
   2733         m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveLongInterval, FROM_HERE);
   2734     } else {
   2735         if (!m_fakeMouseMoveEventTimer.isActive())
   2736             m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveShortInterval, FROM_HERE);
   2737     }
   2738 }
   2739 
   2740 void EventHandler::dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad& quad)
   2741 {
   2742     FrameView* view = m_frame->view();
   2743     if (!view)
   2744         return;
   2745 
   2746     if (!quad.containsPoint(view->windowToContents(m_lastKnownMousePosition)))
   2747         return;
   2748 
   2749     dispatchFakeMouseMoveEventSoon();
   2750 }
   2751 
   2752 void EventHandler::fakeMouseMoveEventTimerFired(Timer<EventHandler>* timer)
   2753 {
   2754     ASSERT_UNUSED(timer, timer == &m_fakeMouseMoveEventTimer);
   2755     ASSERT(!m_mousePressed);
   2756 
   2757     Settings* settings = m_frame->settings();
   2758     if (settings && !settings->deviceSupportsMouse())
   2759         return;
   2760 
   2761     FrameView* view = m_frame->view();
   2762     if (!view)
   2763         return;
   2764 
   2765     if (!m_frame->page() || !m_frame->page()->focusController().isActive())
   2766         return;
   2767 
   2768     // Don't dispatch a synthetic mouse move event if the mouse cursor is not visible to the user.
   2769     if (!isCursorVisible())
   2770         return;
   2771 
   2772     bool shiftKey;
   2773     bool ctrlKey;
   2774     bool altKey;
   2775     bool metaKey;
   2776     PlatformKeyboardEvent::getCurrentModifierState(shiftKey, ctrlKey, altKey, metaKey);
   2777     PlatformMouseEvent fakeMouseMoveEvent(m_lastKnownMousePosition, m_lastKnownMouseGlobalPosition, NoButton, PlatformEvent::MouseMoved, 0, shiftKey, ctrlKey, altKey, metaKey, currentTime());
   2778     handleMouseMoveEvent(fakeMouseMoveEvent);
   2779 }
   2780 
   2781 void EventHandler::cancelFakeMouseMoveEvent()
   2782 {
   2783     m_fakeMouseMoveEventTimer.stop();
   2784 }
   2785 
   2786 bool EventHandler::isCursorVisible() const
   2787 {
   2788     return m_frame->page()->isCursorVisible();
   2789 }
   2790 
   2791 void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet)
   2792 {
   2793     m_frameSetBeingResized = frameSet;
   2794 }
   2795 
   2796 void EventHandler::resizeScrollableAreaDestroyed()
   2797 {
   2798     ASSERT(m_resizeScrollableArea);
   2799     m_resizeScrollableArea = 0;
   2800 }
   2801 
   2802 void EventHandler::hoverTimerFired(Timer<EventHandler>*)
   2803 {
   2804     m_hoverTimer.stop();
   2805 
   2806     ASSERT(m_frame);
   2807     ASSERT(m_frame->document());
   2808 
   2809     if (RenderView* renderer = m_frame->contentRenderer()) {
   2810         if (FrameView* view = m_frame->view()) {
   2811             HitTestRequest request(HitTestRequest::Move | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
   2812             HitTestResult result(view->windowToContents(m_lastKnownMousePosition));
   2813             renderer->hitTest(request, result);
   2814             m_frame->document()->updateHoverActiveState(request, result.innerElement());
   2815         }
   2816     }
   2817 }
   2818 
   2819 void EventHandler::activeIntervalTimerFired(Timer<EventHandler>*)
   2820 {
   2821     m_activeIntervalTimer.stop();
   2822 
   2823     if (m_frame
   2824         && m_frame->document()
   2825         && m_lastDeferredTapElement) {
   2826         // FIXME: Enable condition when http://crbug.com/226842 lands
   2827         // m_lastDeferredTapElement.get() == m_frame->document()->activeElement()
   2828         HitTestRequest request(HitTestRequest::TouchEvent | HitTestRequest::Release);
   2829         m_frame->document()->updateHoverActiveState(request, m_lastDeferredTapElement.get());
   2830     }
   2831     m_lastDeferredTapElement = nullptr;
   2832 }
   2833 
   2834 void EventHandler::notifyElementActivated()
   2835 {
   2836     // Since another element has been set to active, stop current timer and clear reference.
   2837     if (m_activeIntervalTimer.isActive())
   2838         m_activeIntervalTimer.stop();
   2839     m_lastDeferredTapElement = nullptr;
   2840 }
   2841 
   2842 bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& evt)
   2843 {
   2844     // FIXME: Ignoring the state of Shift key is what neither IE nor Firefox do.
   2845     // IE matches lower and upper case access keys regardless of Shift key state - but if both upper and
   2846     // lower case variants are present in a document, the correct element is matched based on Shift key state.
   2847     // Firefox only matches an access key if Shift is not pressed, and does that case-insensitively.
   2848     ASSERT(!(accessKeyModifiers() & PlatformEvent::ShiftKey));
   2849     if ((evt.modifiers() & ~PlatformEvent::ShiftKey) != accessKeyModifiers())
   2850         return false;
   2851     String key = evt.unmodifiedText();
   2852     Element* elem = m_frame->document()->getElementByAccessKey(key.lower());
   2853     if (!elem)
   2854         return false;
   2855     elem->accessKeyAction(false);
   2856     return true;
   2857 }
   2858 
   2859 bool EventHandler::isKeyEventAllowedInFullScreen(FullscreenElementStack* fullscreen, const PlatformKeyboardEvent& keyEvent) const
   2860 {
   2861     if (fullscreen