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