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->webkitFullScreenKeyboardInputAllowed())
   2862         return true;
   2863 
   2864     if (keyEvent.type() == PlatformKeyboardEvent::Char) {
   2865         if (keyEvent.text().length() != 1)
   2866             return false;
   2867         UChar character = keyEvent.text()[0];
   2868         return character == ' ';
   2869     }
   2870 
   2871     int keyCode = keyEvent.windowsVirtualKeyCode();
   2872     return (keyCode >= VK_BACK && keyCode <= VK_CAPITAL)
   2873         || (keyCode >= VK_SPACE && keyCode <= VK_DELETE)
   2874         || (keyCode >= VK_OEM_1 && keyCode <= VK_OEM_PLUS)
   2875         || (keyCode >= VK_MULTIPLY && keyCode <= VK_OEM_8);
   2876 }
   2877 
   2878 bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent)
   2879 {
   2880     RefPtr<FrameView> protector(m_frame->view());
   2881 
   2882     ASSERT(m_frame->document());
   2883     if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(*m_frame->document())) {
   2884         if (fullscreen->webkitIsFullScreen() && !isKeyEventAllowedInFullScreen(fullscreen, initialKeyEvent))
   2885             return false;
   2886     }
   2887 
   2888     if (initialKeyEvent.windowsVirtualKeyCode() == VK_CAPITAL)
   2889         capsLockStateMayHaveChanged();
   2890 
   2891 #if OS(WIN)
   2892     if (panScrollInProgress()) {
   2893         // If a key is pressed while the panScroll is in progress then we want to stop
   2894         if (initialKeyEvent.type() == PlatformEvent::KeyDown || initialKeyEvent.type() == PlatformEvent::RawKeyDown)
   2895             stopAutoscroll();
   2896 
   2897         // If we were in panscroll mode, we swallow the key event
   2898         return true;
   2899     }
   2900 #endif
   2901 
   2902     // Check for cases where we are too early for events -- possible unmatched key up
   2903     // from pressing return in the location bar.
   2904     RefPtrWillBeRawPtr<Node> node = eventTargetNodeForDocument(m_frame->document());
   2905     if (!node)
   2906         return false;
   2907 
   2908     UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
   2909 
   2910     // In IE, access keys are special, they are handled after default keydown processing, but cannot be canceled - this is hard to match.
   2911     // On Mac OS X, we process them before dispatching keydown, as the default keydown handler implements Emacs key bindings, which may conflict
   2912     // with access keys. Then we dispatch keydown, but suppress its default handling.
   2913     // On Windows, WebKit explicitly calls handleAccessKey() instead of dispatching a keypress event for WM_SYSCHAR messages.
   2914     // Other platforms currently match either Mac or Windows behavior, depending on whether they send combined KeyDown events.
   2915     bool matchedAnAccessKey = false;
   2916     if (initialKeyEvent.type() == PlatformEvent::KeyDown)
   2917         matchedAnAccessKey = handleAccessKey(initialKeyEvent);
   2918 
   2919     // FIXME: it would be fair to let an input method handle KeyUp events before DOM dispatch.
   2920     if (initialKeyEvent.type() == PlatformEvent::KeyUp || initialKeyEvent.type() == PlatformEvent::Char)
   2921         return !node->dispatchKeyEvent(initialKeyEvent);
   2922 
   2923     PlatformKeyboardEvent keyDownEvent = initialKeyEvent;
   2924     if (keyDownEvent.type() != PlatformEvent::RawKeyDown)
   2925         keyDownEvent.disambiguateKeyDownEvent(PlatformEvent::RawKeyDown);
   2926     RefPtrWillBeRawPtr<KeyboardEvent> keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->domWindow());
   2927     if (matchedAnAccessKey)
   2928         keydown->setDefaultPrevented(true);
   2929     keydown->setTarget(node);
   2930 
   2931     if (initialKeyEvent.type() == PlatformEvent::RawKeyDown) {
   2932         node->dispatchEvent(keydown, IGNORE_EXCEPTION);
   2933         // If frame changed as a result of keydown dispatch, then return true to avoid sending a subsequent keypress message to the new frame.
   2934         bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController().focusedOrMainFrame();
   2935         return keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame;
   2936     }
   2937 
   2938     node->dispatchEvent(keydown, IGNORE_EXCEPTION);
   2939     // If frame changed as a result of keydown dispatch, then return early to avoid sending a subsequent keypress message to the new frame.
   2940     bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController().focusedOrMainFrame();
   2941     bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame;
   2942     if (keydownResult)
   2943         return keydownResult;
   2944 
   2945     // Focus may have changed during keydown handling, so refetch node.
   2946     // But if we are dispatching a fake backward compatibility keypress, then we pretend that the keypress happened on the original node.
   2947     node = eventTargetNodeForDocument(m_frame->document());
   2948     if (!node)
   2949         return false;
   2950 
   2951     PlatformKeyboardEvent keyPressEvent = initialKeyEvent;
   2952     keyPressEvent.disambiguateKeyDownEvent(PlatformEvent::Char);
   2953     if (keyPressEvent.text().isEmpty())
   2954         return keydownResult;
   2955     RefPtrWillBeRawPtr<KeyboardEvent> keypress = KeyboardEvent::create(keyPressEvent, m_frame->document()->domWindow());
   2956     keypress->setTarget(node);
   2957     if (keydownResult)
   2958         keypress->setDefaultPrevented(true);
   2959     node->dispatchEvent(keypress, IGNORE_EXCEPTION);
   2960 
   2961     return keydownResult || keypress->defaultPrevented() || keypress->defaultHandled();
   2962 }
   2963 
   2964 static FocusType focusDirectionForKey(const AtomicString& keyIdentifier)
   2965 {
   2966     DEFINE_STATIC_LOCAL(AtomicString, Down, ("Down", AtomicString::ConstructFromLiteral));
   2967     DEFINE_STATIC_LOCAL(AtomicString, Up, ("Up", AtomicString::ConstructFromLiteral));
   2968     DEFINE_STATIC_LOCAL(AtomicString, Left, ("Left", AtomicString::ConstructFromLiteral));
   2969     DEFINE_STATIC_LOCAL(AtomicString, Right, ("Right", AtomicString::ConstructFromLiteral));
   2970 
   2971     FocusType retVal = FocusTypeNone;
   2972 
   2973     if (keyIdentifier == Down)
   2974         retVal = FocusTypeDown;
   2975     else if (keyIdentifier == Up)
   2976         retVal = FocusTypeUp;
   2977     else if (keyIdentifier == Left)
   2978         retVal = FocusTypeLeft;
   2979     else if (keyIdentifier == Right)
   2980         retVal = FocusTypeRight;
   2981 
   2982     return retVal;
   2983 }
   2984 
   2985 void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event)
   2986 {
   2987     if (event->type() == EventTypeNames::keydown) {
   2988         m_frame->editor().handleKeyboardEvent(event);
   2989         if (event->defaultHandled())
   2990             return;
   2991         if (event->keyIdentifier() == "U+0009")
   2992             defaultTabEventHandler(event);
   2993         else if (event->keyIdentifier() == "U+0008")
   2994             defaultBackspaceEventHandler(event);
   2995         else if (event->keyIdentifier() == "U+001B")
   2996             defaultEscapeEventHandler(event);
   2997         else {
   2998             FocusType type = focusDirectionForKey(AtomicString(event->keyIdentifier()));
   2999             if (type != FocusTypeNone)
   3000                 defaultArrowEventHandler(type, event);
   3001         }
   3002     }
   3003     if (event->type() == EventTypeNames::keypress) {
   3004         m_frame->editor().handleKeyboardEvent(event);
   3005         if (event->defaultHandled())
   3006             return;
   3007         if (event->charCode() == ' ')
   3008             defaultSpaceEventHandler(event);
   3009     }
   3010 }
   3011 
   3012 bool EventHandler::dragHysteresisExceeded(const FloatPoint& floatDragViewportLocation) const
   3013 {
   3014     return dragHysteresisExceeded(flooredIntPoint(floatDragViewportLocation));
   3015 }
   3016 
   3017 bool EventHandler::dragHysteresisExceeded(const IntPoint& dragViewportLocation) const
   3018 {
   3019     FrameView* view = m_frame->view();
   3020     if (!view)
   3021         return false;
   3022     IntPoint dragLocation = view->windowToContents(dragViewportLocation);
   3023     IntSize delta = dragLocation - m_mouseDownPos;
   3024 
   3025     int threshold = GeneralDragHysteresis;
   3026     switch (dragState().m_dragType) {
   3027     case DragSourceActionSelection:
   3028         threshold = TextDragHysteresis;
   3029         break;
   3030     case DragSourceActionImage:
   3031         threshold = ImageDragHysteresis;
   3032         break;
   3033     case DragSourceActionLink:
   3034         threshold = LinkDragHysteresis;
   3035         break;
   3036     case DragSourceActionDHTML:
   3037         break;
   3038     case DragSourceActionNone:
   3039         ASSERT_NOT_REACHED();
   3040     }
   3041 
   3042     return abs(delta.width()) >= threshold || abs(delta.height()) >= threshold;
   3043 }
   3044 
   3045 void EventHandler::freeClipboard()
   3046 {
   3047     if (dragState().m_dragClipboard) {
   3048         dragState().m_dragClipboard->clearDragImage();
   3049         dragState().m_dragClipboard->setAccessPolicy(ClipboardNumb);
   3050     }
   3051 }
   3052 
   3053 void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, DragOperation operation)
   3054 {
   3055     // Send a hit test request so that RenderLayer gets a chance to update the :hover and :active pseudoclasses.
   3056     HitTestRequest request(HitTestRequest::Release | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
   3057     prepareMouseEvent(request, event);
   3058 
   3059     if (dragState().m_dragSrc) {
   3060         dragState().m_dragClipboard->setDestinationOperation(operation);
   3061         // for now we don't care if event handler cancels default behavior, since there is none
   3062         dispatchDragSrcEvent(EventTypeNames::dragend, event);
   3063     }
   3064     freeClipboard();
   3065     dragState().m_dragSrc = nullptr;
   3066     // In case the drag was ended due to an escape key press we need to ensure
   3067     // that consecutive mousemove events don't reinitiate the drag and drop.
   3068     m_mouseDownMayStartDrag = false;
   3069 }
   3070 
   3071 void EventHandler::updateDragStateAfterEditDragIfNeeded(Element* rootEditableElement)
   3072 {
   3073     // If inserting the dragged contents removed the drag source, we still want to fire dragend at the root editble element.
   3074     if (dragState().m_dragSrc && !dragState().m_dragSrc->inDocument())
   3075         dragState().m_dragSrc = rootEditableElement;
   3076 }
   3077 
   3078 // returns if we should continue "default processing", i.e., whether eventhandler canceled
   3079 bool EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent& event)
   3080 {
   3081     return !dispatchDragEvent(eventType, dragState().m_dragSrc.get(), event, dragState().m_dragClipboard.get());
   3082 }
   3083 
   3084 bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, CheckDragHysteresis checkDragHysteresis)
   3085 {
   3086     ASSERT(event.event().type() == PlatformEvent::MouseMoved);
   3087     // Callers must protect the reference to FrameView, since this function may dispatch DOM
   3088     // events, causing page/FrameView to go away.
   3089     ASSERT(m_frame);
   3090     ASSERT(m_frame->view());
   3091     if (!m_frame->page())
   3092         return false;
   3093 
   3094     if (event.event().button() != LeftButton || event.event().type() != PlatformEvent::MouseMoved) {
   3095         // If we allowed the other side of the bridge to handle a drag
   3096         // last time, then m_mousePressed might still be set. So we
   3097         // clear it now to make sure the next move after a drag
   3098         // doesn't look like a drag.
   3099         m_mousePressed = false;
   3100         return false;
   3101     }
   3102 
   3103     if (m_mouseDownMayStartDrag) {
   3104         HitTestRequest request(HitTestRequest::ReadOnly);
   3105         HitTestResult result(m_mouseDownPos);
   3106         m_frame->contentRenderer()->hitTest(request, result);
   3107         Node* node = result.innerNode();
   3108         if (node) {
   3109             DragController::SelectionDragPolicy selectionDragPolicy = event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay
   3110                 ? DragController::DelayedSelectionDragResolution
   3111                 : DragController::ImmediateSelectionDragResolution;
   3112             dragState().m_dragSrc = m_frame->page()->dragController().draggableNode(m_frame, node, m_mouseDownPos, selectionDragPolicy, dragState().m_dragType);
   3113         } else {
   3114             dragState().m_dragSrc = nullptr;
   3115         }
   3116 
   3117         if (!dragState().m_dragSrc)
   3118             m_mouseDownMayStartDrag = false; // no element is draggable
   3119     }
   3120 
   3121     if (!m_mouseDownMayStartDrag)
   3122         return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll;
   3123 
   3124     // We are starting a text/image/url drag, so the cursor should be an arrow
   3125     // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and drop (default to pointer).
   3126     m_frame->view()->setCursor(pointerCursor());
   3127 
   3128     if (checkDragHysteresis == ShouldCheckDragHysteresis && !dragHysteresisExceeded(event.event().position()))
   3129         return true;
   3130 
   3131     // Once we're past the hysteresis point, we don't want to treat this gesture as a click
   3132     invalidateClick();
   3133 
   3134     if (!tryStartDrag(event)) {
   3135         // Something failed to start the drag, clean up.
   3136         freeClipboard();
   3137         dragState().m_dragSrc = nullptr;
   3138     }
   3139 
   3140     m_mouseDownMayStartDrag = false;
   3141     // Whether or not the drag actually started, no more default handling (like selection).
   3142     return true;
   3143 }
   3144 
   3145 bool EventHandler::tryStartDrag(const MouseEventWithHitTestResults& event)
   3146 {
   3147     freeClipboard(); // would only happen if we missed a dragEnd.  Do it anyway, just
   3148                      // to make sure it gets numbified
   3149     dragState().m_dragClipboard = createDraggingClipboard();
   3150 
   3151     // Check to see if this a DOM based drag, if it is get the DOM specified drag
   3152     // image and offset
   3153     if (dragState().m_dragType == DragSourceActionDHTML) {
   3154         if (RenderObject* renderer = dragState().m_dragSrc->renderer()) {
   3155             FloatPoint absPos = renderer->localToAbsolute(FloatPoint(), UseTransforms);
   3156             IntSize delta = m_mouseDownPos - roundedIntPoint(absPos);
   3157             dragState().m_dragClipboard->setDragImageElement(dragState().m_dragSrc.get(), IntPoint(delta));
   3158         } else {
   3159             // The renderer has disappeared, this can happen if the onStartDrag handler has hidden
   3160             // the element in some way. In this case we just kill the drag.
   3161             return false;
   3162         }
   3163     }
   3164 
   3165     DragController& dragController = m_frame->page()->dragController();
   3166     if (!dragController.populateDragClipboard(m_frame, dragState(), m_mouseDownPos))
   3167         return false;
   3168     m_mouseDownMayStartDrag = dispatchDragSrcEvent(EventTypeNames::dragstart, m_mouseDown)
   3169         && !m_frame->selection().isInPasswordField();
   3170 
   3171     // Invalidate clipboard here against anymore pasteboard writing for security. The drag
   3172     // image can still be changed as we drag, but not the pasteboard data.
   3173     dragState().m_dragClipboard->setAccessPolicy(ClipboardImageWritable);
   3174 
   3175     if (m_mouseDownMayStartDrag) {
   3176         // Dispatching the event could cause Page to go away. Make sure it's still valid before trying to use DragController.
   3177         m_didStartDrag = m_frame->page() && dragController.startDrag(m_frame, dragState(), event.event(), m_mouseDownPos);
   3178         // FIXME: This seems pretty useless now. The gesture code uses this as a signal for
   3179         // whether or not the drag started, but perhaps it can simply use the return value from
   3180         // handleDrag(), even though it doesn't mean exactly the same thing.
   3181         if (m_didStartDrag)
   3182             return true;
   3183         // Drag was canned at the last minute - we owe m_dragSrc a DRAGEND event
   3184         dispatchDragSrcEvent(EventTypeNames::dragend, event.event());
   3185     }
   3186 
   3187     return false;
   3188 }
   3189 
   3190 bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEvent, TextEventInputType inputType)
   3191 {
   3192     // Platforms should differentiate real commands like selectAll from text input in disguise (like insertNewline),
   3193     // and avoid dispatching text input events from keydown default handlers.
   3194     ASSERT(!underlyingEvent || !underlyingEvent->isKeyboardEvent() || toKeyboardEvent(underlyingEvent)->type() == EventTypeNames::keypress);
   3195 
   3196     if (!m_frame)
   3197         return false;
   3198 
   3199     EventTarget* target;
   3200     if (underlyingEvent)
   3201         target = underlyingEvent->target();
   3202     else
   3203         target = eventTargetNodeForDocument(m_frame->document());
   3204     if (!target)
   3205         return false;
   3206 
   3207     RefPtrWillBeRawPtr<TextEvent> event = TextEvent::create(m_frame->domWindow(), text, inputType);
   3208     event->setUnderlyingEvent(underlyingEvent);
   3209 
   3210     target->dispatchEvent(event, IGNORE_EXCEPTION);
   3211     return event->defaultHandled();
   3212 }
   3213 
   3214 void EventHandler::defaultTextInputEventHandler(TextEvent* event)
   3215 {
   3216     if (m_frame->editor().handleTextEvent(event))
   3217         event->setDefaultHandled();
   3218 }
   3219 
   3220 void EventHandler::defaultSpaceEventHandler(KeyboardEvent* event)
   3221 {
   3222     ASSERT(event->type() == EventTypeNames::keypress);
   3223 
   3224     if (event->ctrlKey() || event->metaKey() || event->altKey() || event->altGraphKey())
   3225         return;
   3226 
   3227     ScrollDirection direction = event->shiftKey() ? ScrollBlockDirectionBackward : ScrollBlockDirectionForward;
   3228     if (scroll(direction, ScrollByPage)) {
   3229         event->setDefaultHandled();
   3230         return;
   3231     }
   3232 
   3233     FrameView* view = m_frame->view();
   3234     if (!view)
   3235         return;
   3236 
   3237     if (view->scroll(direction, ScrollByPage))
   3238         event->setDefaultHandled();
   3239 }
   3240 
   3241 void EventHandler::defaultBackspaceEventHandler(KeyboardEvent* event)
   3242 {
   3243     ASSERT(event->type() == EventTypeNames::keydown);
   3244 
   3245     if (event->ctrlKey() || event->metaKey() || event->altKey() || event->altGraphKey())
   3246         return;
   3247 
   3248     if (!m_frame->editor().behavior().shouldNavigateBackOnBackspace())
   3249         return;
   3250 
   3251     Page* page = m_frame->page();
   3252     if (!page || !page->mainFrame()->isLocalFrame())
   3253         return;
   3254     bool handledEvent = page->deprecatedLocalMainFrame()->loader().client()->navigateBackForward(event->shiftKey() ? 1 : -1);
   3255     if (handledEvent)
   3256         event->setDefaultHandled();
   3257 }
   3258 
   3259 void EventHandler::defaultArrowEventHandler(FocusType focusType, KeyboardEvent* event)
   3260 {
   3261     ASSERT(event->type() == EventTypeNames::keydown);
   3262 
   3263     if (event->ctrlKey() || event->metaKey() || event->altGraphKey() || event->shiftKey())
   3264         return;
   3265 
   3266     Page* page = m_frame->page();
   3267     if (!page)
   3268         return;
   3269 
   3270     if (!isSpatialNavigationEnabled(m_frame))
   3271         return;
   3272 
   3273     // Arrows and other possible directional navigation keys can be used in design
   3274     // mode editing.
   3275     if (m_frame->document()->inDesignMode())
   3276         return;
   3277 
   3278     if (page->focusController().advanceFocus(focusType))
   3279         event->setDefaultHandled();
   3280 }
   3281 
   3282 void EventHandler::defaultTabEventHandler(KeyboardEvent* event)
   3283 {
   3284     ASSERT(event->type() == EventTypeNames::keydown);
   3285 
   3286     // We should only advance focus on tabs if no special modifier keys are held down.
   3287     if (event->ctrlKey() || event->metaKey() || event->altGraphKey())
   3288         return;
   3289 
   3290     Page* page = m_frame->page();
   3291     if (!page)
   3292         return;
   3293     if (!page->tabKeyCyclesThroughElements())
   3294         return;
   3295 
   3296     FocusType focusType = event->shiftKey() ? FocusTypeBackward : FocusTypeForward;
   3297 
   3298     // Tabs can be used in design mode editing.
   3299     if (m_frame->document()->inDesignMode())
   3300         return;
   3301 
   3302     if (page->focusController().advanceFocus(focusType))
   3303         event->setDefaultHandled();
   3304 }
   3305 
   3306 void EventHandler::defaultEscapeEventHandler(KeyboardEvent* event)
   3307 {
   3308     if (HTMLDialogElement* dialog = m_frame->document()->activeModalDialog())
   3309         dialog->dispatchEvent(Event::createCancelable(EventTypeNames::cancel));
   3310 }
   3311 
   3312 void EventHandler::capsLockStateMayHaveChanged()
   3313 {
   3314     if (Element* element = m_frame->document()->focusedElement()) {
   3315         if (RenderObject* r = element->renderer()) {
   3316             if (r->isTextField())
   3317                 toRenderTextControlSingleLine(r)->capsLockStateMayHaveChanged();
   3318         }
   3319     }
   3320 }
   3321 
   3322 void EventHandler::setFrameWasScrolledByUser()
   3323 {
   3324     if (FrameView* view = m_frame->view())
   3325         view->setWasScrolledByUser(true);
   3326 }
   3327 
   3328 bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults& mev)
   3329 {
   3330     // First try to use the frame scrollbar.
   3331     FrameView* view = m_frame->view();
   3332     Scrollbar* scrollbar = view ? view->scrollbarAtPoint(mev.event().position()) : 0;
   3333 
   3334     // Then try the scrollbar in the hit test.
   3335     if (!scrollbar)
   3336         scrollbar = mev.scrollbar();
   3337 
   3338     updateLastScrollbarUnderMouse(scrollbar, true);
   3339 
   3340     if (!scrollbar || !scrollbar->enabled())
   3341         return false;
   3342     setFrameWasScrolledByUser();
   3343     scrollbar->mouseDown(mev.event());
   3344     return true;
   3345 }
   3346 
   3347 // If scrollbar (under mouse) is different from last, send a mouse exited. Set
   3348 // last to scrollbar if setLast is true; else set last to 0.
   3349 void EventHandler::updateLastScrollbarUnderMouse(Scrollbar* scrollbar, bool setLast)
   3350 {
   3351     if (m_lastScrollbarUnderMouse != scrollbar) {
   3352         // Send mouse exited to the old scrollbar.
   3353         if (m_lastScrollbarUnderMouse)
   3354             m_lastScrollbarUnderMouse->mouseExited();
   3355 
   3356         // Send mouse entered if we're setting a new scrollbar.
   3357         if (scrollbar && setLast)
   3358             scrollbar->mouseEntered();
   3359 
   3360         m_lastScrollbarUnderMouse = setLast ? scrollbar : 0;
   3361     }
   3362 }
   3363 
   3364 static const AtomicString& eventNameForTouchPointState(PlatformTouchPoint::State state)
   3365 {
   3366     switch (state) {
   3367     case PlatformTouchPoint::TouchReleased:
   3368         return EventTypeNames::touchend;
   3369     case PlatformTouchPoint::TouchCancelled:
   3370         return EventTypeNames::touchcancel;
   3371     case PlatformTouchPoint::TouchPressed:
   3372         return EventTypeNames::touchstart;
   3373     case PlatformTouchPoint::TouchMoved:
   3374         return EventTypeNames::touchmove;
   3375     case PlatformTouchPoint::TouchStationary:
   3376         // TouchStationary state is not converted to touch events, so fall through to assert.
   3377     default:
   3378         ASSERT_NOT_REACHED();
   3379         return emptyAtom;
   3380     }
   3381 }
   3382 
   3383 HitTestResult EventHandler::hitTestResultInFrame(LocalFrame* frame, const LayoutPoint& point, HitTestRequest::HitTestRequestType hitType)
   3384 {
   3385     HitTestResult result(point);
   3386 
   3387     if (!frame || !frame->contentRenderer())
   3388         return result;
   3389     if (frame->view()) {
   3390         IntRect rect = frame->view()->visibleContentRect();
   3391         if (!rect.contains(roundedIntPoint(point)))
   3392             return result;
   3393     }
   3394     frame->contentRenderer()->hitTest(HitTestRequest(hitType), result);
   3395     return result;
   3396 }
   3397 
   3398 bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
   3399 {
   3400     TRACE_EVENT0("webkit", "EventHandler::handleTouchEvent");
   3401 
   3402     const Vector<PlatformTouchPoint>& points = event.touchPoints();
   3403 
   3404     unsigned i;
   3405     bool freshTouchEvents = true;
   3406     bool allTouchReleased = true;
   3407     for (i = 0; i < points.size(); ++i) {
   3408         const PlatformTouchPoint& point = points[i];
   3409         if (point.state() != PlatformTouchPoint::TouchPressed)
   3410             freshTouchEvents = false;
   3411         if (point.state() != PlatformTouchPoint::TouchReleased && point.state() != PlatformTouchPoint::TouchCancelled)
   3412             allTouchReleased = false;
   3413     }
   3414     if (freshTouchEvents) {
   3415         // Ideally we'd ASSERT !m_touchSequenceDocument here since we should
   3416         // have cleared the active document when we saw the last release. But we
   3417         // have some tests that violate this, ClusterFuzz could trigger it, and
   3418         // there may be cases where the browser doesn't reliably release all
   3419         // touches. http://crbug.com/345372 tracks this.
   3420         m_touchSequenceDocument.clear();
   3421         m_touchSequenceUserGestureToken.clear();
   3422     }
   3423 
   3424     OwnPtr<UserGestureIndicator> gestureIndicator;
   3425 
   3426     if (m_touchSequenceUserGestureToken)
   3427         gestureIndicator = adoptPtr(new UserGestureIndicator(m_touchSequenceUserGestureToken.release()));
   3428     else
   3429         gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProcessingUserGesture));
   3430 
   3431     m_touchSequenceUserGestureToken = gestureIndicator->currentToken();
   3432 
   3433     ASSERT(m_frame->view());
   3434     if (m_touchSequenceDocument && (!m_touchSequenceDocument->frame() || !m_touchSequenceDocument->frame()->view())) {
   3435         // If the active touch document has no frame or view, it's probably being destroyed
   3436         // so we can't dispatch events.
   3437         return false;
   3438     }
   3439 
   3440     // First do hit tests for any new touch points.
   3441     for (i = 0; i < points.size(); ++i) {
   3442         const PlatformTouchPoint& point = points[i];
   3443 
   3444         // Touch events implicitly capture to the touched node, and don't change
   3445         // active/hover states themselves (Gesture events do). So we only need
   3446         // to hit-test on touchstart, and it can be read-only.
   3447         if (point.state() == PlatformTouchPoint::TouchPressed) {
   3448             HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent | HitTestRequest::ReadOnly | HitTestRequest::Active;
   3449             LayoutPoint pagePoint = roundedLayoutPoint(m_frame->view()->windowToContents(point.pos()));
   3450             HitTestResult result;
   3451             if (!m_touchSequenceDocument) {
   3452                 result = hitTestResultAtPoint(pagePoint, hitType);
   3453             } else if (m_touchSequenceDocument->frame()) {
   3454                 LayoutPoint framePoint = roundedLayoutPoint(m_touchSequenceDocument->frame()->view()->windowToContents(point.pos()));
   3455                 result = hitTestResultInFrame(m_touchSequenceDocument->frame(), framePoint, hitType);
   3456             } else
   3457                 continue;
   3458 
   3459             Node* node = result.innerNode();
   3460             if (!node)
   3461                 continue;
   3462 
   3463             // Touch events should not go to text nodes
   3464             if (node->isTextNode())
   3465                 node = NodeRenderingTraversal::parent(node);
   3466 
   3467             if (!m_touchSequenceDocument) {
   3468                 // Keep track of which document should receive all touch events
   3469                 // in the active sequence. This must be a single document to
   3470                 // ensure we don't leak Nodes between documents.
   3471                 m_touchSequenceDocument = &(result.innerNode()->document());
   3472                 ASSERT(m_touchSequenceDocument->frame()->view());
   3473             }
   3474 
   3475             // Ideally we'd ASSERT(!m_targetForTouchID.contains(point.id())
   3476             // since we shouldn't get a touchstart for a touch that's already
   3477             // down. However EventSender allows this to be violated and there's
   3478             // some tests that take advantage of it. There may also be edge
   3479             // cases in the browser where this happens.
   3480             // See http://crbug.com/345372.
   3481             m_targetForTouchID.set(point.id(), node);
   3482 
   3483             TouchAction effectiveTouchAction = computeEffectiveTouchAction(*node);
   3484             if (effectiveTouchAction != TouchActionAuto)
   3485                 m_frame->page()->chrome().client().setTouchAction(effectiveTouchAction);
   3486         }
   3487     }
   3488 
   3489     m_touchPressed = !allTouchReleased;
   3490 
   3491     // If there's no document receiving touch events, or no handlers on the
   3492     // document set to receive the events, then we can skip all the rest of
   3493     // this work.
   3494     if (!m_touchSequenceDocument || !m_touchSequenceDocument->hasTouchEventHandlers() || !m_touchSequenceDocument->frame()) {
   3495         if (allTouchReleased) {
   3496             m_touchSequenceDocument.clear();
   3497             m_touchSequenceUserGestureToken.clear();
   3498         }
   3499         return false;
   3500     }
   3501 
   3502     // Build up the lists to use for the 'touches', 'targetTouches' and
   3503     // 'changedTouches' attributes in the JS event. See
   3504     // http://www.w3.org/TR/touch-events/#touchevent-interface for how these
   3505     // lists fit together.
   3506 
   3507     // Holds the complete set of touches on the screen.
   3508     RefPtrWillBeRawPtr<TouchList> touches = TouchList::create();
   3509 
   3510     // A different view on the 'touches' list above, filtered and grouped by
   3511     // event target. Used for the 'targetTouches' list in the JS event.
   3512     typedef WillBeHeapHashMap<EventTarget*, RefPtrWillBeMember<TouchList> > TargetTouchesHeapMap;
   3513     TargetTouchesHeapMap touchesByTarget;
   3514 
   3515     // Array of touches per state, used to assemble the 'changedTouches' list.
   3516     typedef WillBeHeapHashSet<RefPtrWillBeMember<EventTarget> > EventTargetSet;
   3517     struct {
   3518         // The touches corresponding to the particular change state this struct
   3519         // instance represents.
   3520         RefPtrWillBeMember<TouchList> m_touches;
   3521         // Set of targets involved in m_touches.
   3522         EventTargetSet m_targets;
   3523     } changedTouches[PlatformTouchPoint::TouchStateEnd];
   3524 
   3525     for (i = 0; i < points.size(); ++i) {
   3526         const PlatformTouchPoint& point = points[i];
   3527         PlatformTouchPoint::State pointState = point.state();
   3528         RefPtrWillBeRawPtr<EventTarget> touchTarget = nullptr;
   3529 
   3530         if (pointState == PlatformTouchPoint::TouchReleased || pointState == PlatformTouchPoint::TouchCancelled) {
   3531             // The target should be the original target for this touch, so get
   3532             // it from the hashmap. As it's a release or cancel we also remove
   3533             // it from the map.
   3534             touchTarget = m_targetForTouchID.take(point.id());
   3535         } else {
   3536             // No hittest is performed on move or stationary, since the target
   3537             // is not allowed to change anyway.
   3538             touchTarget = m_targetForTouchID.get(point.id());
   3539         }
   3540 
   3541         LocalFrame* targetFrame = 0;
   3542         bool knownTarget = false;
   3543         if (touchTarget) {
   3544             Document& doc = touchTarget->toNode()->document();
   3545             // If the target node has moved to a new document while it was being touched,
   3546             // we can't send events to the new document because that could leak nodes
   3547             // from one document to another. See http://crbug.com/394339.
   3548             if (&doc == m_touchSequenceDocument.get()) {
   3549                 targetFrame = doc.frame();
   3550                 knownTarget = true;
   3551             }
   3552         }
   3553         if (!knownTarget) {
   3554             // If we don't have a target registered for the point it means we've
   3555             // missed our opportunity to do a hit test for it (due to some
   3556             // optimization that prevented blink from ever seeing the
   3557             // touchstart), or that the touch started outside the active touch
   3558             // sequence document. We should still include the touch in the
   3559             // Touches list reported to the application (eg. so it can
   3560             // differentiate between a one and two finger gesture), but we won't
   3561             // actually dispatch any events for it. Set the target to the
   3562             // Document so that there's some valid node here. Perhaps this
   3563             // should really be LocalDOMWindow, but in all other cases the target of
   3564             // a Touch is a Node so using the window could be a breaking change.
   3565             // Since we know there was no handler invoked, the specific target
   3566             // should be completely irrelevant to the application.
   3567             // FIXME: Oilpan: We can remove the following .get() if EventTarget
   3568             // is on-heap.
   3569             touchTarget = m_touchSequenceDocument.get();
   3570             targetFrame = m_touchSequenceDocument->frame();
   3571         }
   3572         ASSERT(targetFrame);
   3573 
   3574         // pagePoint should always be relative to the target elements
   3575         // containing frame.
   3576         FloatPoint pagePoint = targetFrame->view()->windowToContents(point.pos());
   3577 
   3578         float scaleFactor = 1.0f / targetFrame->pageZoomFactor();
   3579 
   3580         FloatPoint adjustedPagePoint = pagePoint.scaledBy(scaleFactor);
   3581         FloatSize adjustedRadius = point.radius().scaledBy(scaleFactor);
   3582 
   3583         RefPtrWillBeRawPtr<Touch> touch = Touch::create(
   3584             targetFrame, touchTarget.get(), point.id(), point.screenPos(), adjustedPagePoint, adjustedRadius, point.rotationAngle(), point.force());
   3585 
   3586         // Ensure this target's touch list exists, even if it ends up empty, so
   3587         // it can always be passed to TouchEvent::Create below.
   3588         TargetTouchesHeapMap::iterator targetTouchesIterator = touchesByTarget.find(touchTarget.get());
   3589         if (targetTouchesIterator == touchesByTarget.end()) {
   3590             touchesByTarget.set(touchTarget.get(), TouchList::create());
   3591             targetTouchesIterator = touchesByTarget.find(touchTarget.get());
   3592         }
   3593 
   3594         // touches and targetTouches should only contain information about
   3595         // touches still on the screen, so if this point is released or
   3596         // cancelled it will only appear in the changedTouches list.
   3597         if (pointState != PlatformTouchPoint::TouchReleased && pointState != PlatformTouchPoint::TouchCancelled) {
   3598             touches->append(touch);
   3599             targetTouchesIterator->value->append(touch);
   3600         }
   3601 
   3602         // Now build up the correct list for changedTouches.
   3603         // Note that  any touches that are in the TouchStationary state (e.g. if
   3604         // the user had several points touched but did not move them all) should
   3605         // never be in the changedTouches list so we do not handle them
   3606         // explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609
   3607         // for further discussion about the TouchStationary state.
   3608         if (pointState != PlatformTouchPoint::TouchStationary && knownTarget) {
   3609             ASSERT(pointState < PlatformTouchPoint::TouchStateEnd);
   3610             if (!changedTouches[pointState].m_touches)
   3611                 changedTouches[pointState].m_touches = TouchList::create();
   3612             changedTouches[pointState].m_touches->append(touch);
   3613             changedTouches[pointState].m_targets.add(touchTarget);
   3614         }
   3615     }
   3616     if (allTouchReleased) {
   3617         m_touchSequenceDocument.clear();
   3618         m_touchSequenceUserGestureToken.clear();
   3619     }
   3620 
   3621     // Now iterate the changedTouches list and m_targets within it, sending
   3622     // events to the targets as required.
   3623     bool swallowedEvent = false;
   3624     for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; ++state) {
   3625         if (!changedTouches[state].m_touches)
   3626             continue;
   3627 
   3628         const AtomicString& stateName(eventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state)));
   3629         const EventTargetSet& targetsForState = changedTouches[state].m_targets;
   3630         for (EventTargetSet::const_iterator it = targetsForState.begin(); it != targetsForState.end(); ++it) {
   3631             EventTarget* touchEventTarget = it->get();
   3632             RefPtrWillBeRawPtr<TouchEvent> touchEvent = TouchEvent::create(
   3633                 touches.get(), touchesByTarget.get(touchEventTarget), changedTouches[state].m_touches.get(),
   3634                 stateName, touchEventTarget->toNode()->document().domWindow(),
   3635                 event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), event.cancelable());
   3636             touchEventTarget->toNode()->dispatchTouchEvent(touchEvent.get());
   3637             swallowedEvent = swallowedEvent || touchEvent->defaultPrevented() || touchEvent->defaultHandled();
   3638         }
   3639     }
   3640 
   3641     return swallowedEvent;
   3642 }
   3643 
   3644 TouchAction EventHandler::intersectTouchAction(TouchAction action1, TouchAction action2)
   3645 {
   3646     if (action1 == TouchActionNone || action2 == TouchActionNone)
   3647         return TouchActionNone;
   3648     if (action1 == TouchActionAuto)
   3649         return action2;
   3650     if (action2 == TouchActionAuto)
   3651         return action1;
   3652     if (!(action1 & action2))
   3653         return TouchActionNone;
   3654     return action1 & action2;
   3655 }
   3656 
   3657 TouchAction EventHandler::computeEffectiveTouchAction(const Node& node)
   3658 {
   3659     // Optimization to minimize risk of this new feature (behavior should be identical
   3660     // since there's no way to get non-default touch-action values).
   3661     if (!RuntimeEnabledFeatures::cssTouchActionEnabled())
   3662         return TouchActionAuto;
   3663 
   3664     // Start by permitting all actions, then walk the elements supporting
   3665     // touch-action from the target node up to the nearest scrollable ancestor
   3666     // and exclude any prohibited actions.
   3667     TouchAction effectiveTouchAction = TouchActionAuto;
   3668     for (const Node* curNode = &node; curNode; curNode = NodeRenderingTraversal::parent(curNode)) {
   3669         if (RenderObject* renderer = curNode->renderer()) {
   3670             if (renderer->supportsTouchAction()) {
   3671                 TouchAction action = renderer->style()->touchAction();
   3672                 effectiveTouchAction = intersectTouchAction(action, effectiveTouchAction);
   3673                 if (effectiveTouchAction == TouchActionNone)
   3674                     break;
   3675             }
   3676 
   3677             // If we've reached an ancestor that supports a touch action, search no further.
   3678             if (renderer->isBox() && toRenderBox(renderer)->scrollsOverflow())
   3679                 break;
   3680         }
   3681     }
   3682     return effectiveTouchAction;
   3683 }
   3684 
   3685 void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event)
   3686 {
   3687     m_mousePositionIsUnknown = false;
   3688     m_lastKnownMousePosition = event.position();
   3689     m_lastKnownMouseGlobalPosition = event.globalPosition();
   3690 }
   3691 
   3692 bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, LocalFrame* subframe)
   3693 {
   3694     // If we're clicking into a frame that is selected, the frame will appear
   3695     // greyed out even though we're clicking on the selection.  This looks
   3696     // really strange (having the whole frame be greyed out), so we deselect the
   3697     // selection.
   3698     IntPoint p = m_frame->view()->windowToContents(mev.event().position());
   3699     if (m_frame->selection().contains(p)) {
   3700         VisiblePosition visiblePos(
   3701             mev.targetNode()->renderer()->positionForPoint(mev.localPoint()));
   3702         VisibleSelection newSelection(visiblePos);
   3703         m_frame->selection().setSelection(newSelection);
   3704     }
   3705 
   3706     subframe->eventHandler().handleMousePressEvent(mev.event());
   3707     return true;
   3708 }
   3709 
   3710 bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& mev, LocalFrame* subframe, HitTestResult* hoveredNode)
   3711 {
   3712     if (m_mouseDownMayStartDrag && !m_mouseDownWasInSubframe)
   3713         return false;
   3714     subframe->eventHandler().handleMouseMoveOrLeaveEvent(mev.event(), hoveredNode);
   3715     return true;
   3716 }
   3717 
   3718 bool EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& mev, LocalFrame* subframe)
   3719 {
   3720     subframe->eventHandler().handleMouseReleaseEvent(mev.event());
   3721     return true;
   3722 }
   3723 
   3724 bool EventHandler::passWheelEventToWidget(const PlatformWheelEvent& wheelEvent, Widget* widget)
   3725 {
   3726     // We can sometimes get a null widget!  EventHandlerMac handles a null
   3727     // widget by returning false, so we do the same.
   3728     if (!widget)
   3729         return false;
   3730 
   3731     // If not a FrameView, then probably a plugin widget.  Those will receive
   3732     // the event via an EventTargetNode dispatch when this returns false.
   3733     if (!widget->isFrameView())
   3734         return false;
   3735 
   3736     return toFrameView(widget)->frame().eventHandler().handleWheelEvent(wheelEvent);
   3737 }
   3738 
   3739 bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event)
   3740 {
   3741     // Figure out which view to send the event to.
   3742     if (!event.targetNode() || !event.targetNode()->renderer() || !event.targetNode()->renderer()->isWidget())
   3743         return false;
   3744     return false;
   3745 }
   3746 
   3747 PassRefPtrWillBeRawPtr<Clipboard> EventHandler::createDraggingClipboard() const
   3748 {
   3749     return Clipboard::create(Clipboard::DragAndDrop, ClipboardWritable, DataObject::create());
   3750 }
   3751 
   3752 void EventHandler::focusDocumentView()
   3753 {
   3754     Page* page = m_frame->page();
   3755     if (!page)
   3756         return;
   3757     page->focusController().focusDocumentView(m_frame);
   3758 }
   3759 
   3760 unsigned EventHandler::accessKeyModifiers()
   3761 {
   3762 #if OS(MACOSX)
   3763     return PlatformEvent::CtrlKey | PlatformEvent::AltKey;
   3764 #else
   3765     return PlatformEvent::AltKey;
   3766 #endif
   3767 }
   3768 
   3769 } // namespace WebCore
   3770