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