EventHandler.cpp revision 2bde8e466a4451c7319e3a072d118917957d6554
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 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "EventHandler.h"
29
30#include "AXObjectCache.h"
31#include "CachedImage.h"
32#include "Chrome.h"
33#include "ChromeClient.h"
34#include "Cursor.h"
35#include "CursorList.h"
36#include "Document.h"
37#include "DragController.h"
38#include "Editor.h"
39#include "EventNames.h"
40#include "EventQueue.h"
41#include "FloatPoint.h"
42#include "FloatRect.h"
43#include "FocusController.h"
44#include "Frame.h"
45#include "FrameLoader.h"
46#include "FrameTree.h"
47#include "FrameView.h"
48#include "htmlediting.h"
49#include "HTMLFrameElementBase.h"
50#include "HTMLFrameSetElement.h"
51#include "HTMLInputElement.h"
52#include "HTMLNames.h"
53#include "HitTestRequest.h"
54#include "HitTestResult.h"
55#include "Image.h"
56#include "InspectorInstrumentation.h"
57#include "KeyboardEvent.h"
58#include "MouseEvent.h"
59#include "MouseEventWithHitTestResults.h"
60#include "Page.h"
61#include "PlatformKeyboardEvent.h"
62#include "PlatformWheelEvent.h"
63#include "PluginDocument.h"
64#if defined(ANDROID_PLUGINS)
65#include "PluginView.h"
66#endif
67#include "RenderFrameSet.h"
68#include "RenderLayer.h"
69#include "RenderTextControlSingleLine.h"
70#include "RenderView.h"
71#include "RenderWidget.h"
72#include "ScrollAnimator.h"
73#include "Scrollbar.h"
74#include "SelectionController.h"
75#include "Settings.h"
76#include "StyleCachedImage.h"
77#include "TextEvent.h"
78#include "TextIterator.h"
79#include "UserGestureIndicator.h"
80#include "UserTypingGestureIndicator.h"
81#include "WheelEvent.h"
82#include <wtf/CurrentTime.h>
83#include <wtf/StdLibExtras.h>
84
85#if ENABLE(GESTURE_EVENTS)
86#include "PlatformGestureEvent.h"
87#endif
88
89#if ENABLE(SVG)
90#include "SVGDocument.h"
91#include "SVGElementInstance.h"
92#include "SVGNames.h"
93#include "SVGUseElement.h"
94#endif
95
96#if ENABLE(TOUCH_EVENTS)
97#include "PlatformTouchEvent.h"
98#include "TouchEvent.h"
99#endif
100
101<<<<<<< HEAD
102#if defined(ANDROID_PLUGINS)
103#include "WebViewCore.h"
104=======
105#if ENABLE(GESTURE_RECOGNIZER)
106#include "PlatformGestureRecognizer.h"
107>>>>>>> webkit.org at r82507
108#endif
109
110namespace WebCore {
111
112using namespace HTMLNames;
113
114#if ENABLE(DRAG_SUPPORT)
115// The link drag hysteresis is much larger than the others because there
116// needs to be enough space to cancel the link press without starting a link drag,
117// and because dragging links is rare.
118const int LinkDragHysteresis = 40;
119const int ImageDragHysteresis = 5;
120const int TextDragHysteresis = 3;
121const int GeneralDragHysteresis = 3;
122#endif // ENABLE(DRAG_SUPPORT)
123
124// Match key code of composition keydown event on windows.
125// IE sends VK_PROCESSKEY which has value 229;
126const int CompositionEventKeyCode = 229;
127
128#if ENABLE(SVG)
129using namespace SVGNames;
130#endif
131
132// When the autoscroll or the panScroll is triggered when do the scroll every 0.05s to make it smooth
133const double autoscrollInterval = 0.05;
134
135const double fakeMouseMoveInterval = 0.1;
136
137static Frame* subframeForHitTestResult(const MouseEventWithHitTestResults&);
138
139static inline bool scrollNode(float delta, WheelEvent::Granularity granularity, ScrollDirection positiveDirection, ScrollDirection negativeDirection, Node* node, Node** stopNode)
140{
141    if (!delta)
142        return false;
143
144    if (!node->renderer())
145        return false;
146
147    // Find the nearest enclosing box.
148    RenderBox* enclosingBox = node->renderer()->enclosingBox();
149
150    float absDelta = delta > 0 ? delta : -delta;
151
152    if (granularity == WheelEvent::Page)
153        return enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPage, absDelta, stopNode);
154
155    if (granularity == WheelEvent::Line)
156        return enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByLine, absDelta, stopNode);
157
158    if (granularity == WheelEvent::Pixel)
159        return enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, absDelta, stopNode);
160
161    return false;
162}
163
164#if !PLATFORM(MAC)
165
166inline bool EventHandler::eventLoopHandleMouseUp(const MouseEventWithHitTestResults&)
167{
168    return false;
169}
170
171#if ENABLE(DRAG_SUPPORT)
172inline bool EventHandler::eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&)
173{
174    return false;
175}
176#endif
177
178#endif
179
180EventHandler::EventHandler(Frame* frame)
181    : m_frame(frame)
182    , m_mousePressed(false)
183    , m_capturesDragging(false)
184    , m_mouseDownMayStartSelect(false)
185#if ENABLE(DRAG_SUPPORT)
186    , m_mouseDownMayStartDrag(false)
187#endif
188    , m_mouseDownWasSingleClickInSelection(false)
189    , m_beganSelectingText(false)
190    , m_panScrollInProgress(false)
191    , m_panScrollButtonPressed(false)
192    , m_springLoadedPanScrollInProgress(false)
193    , m_hoverTimer(this, &EventHandler::hoverTimerFired)
194    , m_autoscrollTimer(this, &EventHandler::autoscrollTimerFired)
195    , m_autoscrollRenderer(0)
196    , m_autoscrollInProgress(false)
197    , m_mouseDownMayStartAutoscroll(false)
198    , m_mouseDownWasInSubframe(false)
199    , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFired)
200#if ENABLE(SVG)
201    , m_svgPan(false)
202#endif
203    , m_resizeLayer(0)
204    , m_eventHandlerWillResetCapturingMouseEventsNode(0)
205    , m_clickCount(0)
206    , m_mouseDownTimestamp(0)
207    , m_useLatchedWheelEventNode(false)
208    , m_widgetIsLatched(false)
209#if PLATFORM(MAC)
210    , m_mouseDownView(nil)
211    , m_sendingEventToSubview(false)
212    , m_activationEventNumber(-1)
213#endif
214#if ENABLE(TOUCH_EVENTS)
215    , m_touchPressed(false)
216#endif
217#if ENABLE(GESTURE_RECOGNIZER)
218    , m_gestureRecognizer(PlatformGestureRecognizer::create())
219#endif
220{
221}
222
223EventHandler::~EventHandler()
224{
225    ASSERT(!m_fakeMouseMoveEventTimer.isActive());
226}
227
228#if ENABLE(DRAG_SUPPORT)
229EventHandler::EventHandlerDragState& EventHandler::dragState()
230{
231    DEFINE_STATIC_LOCAL(EventHandlerDragState, state, ());
232    return state;
233}
234#endif // ENABLE(DRAG_SUPPORT)
235
236void EventHandler::clear()
237{
238    m_hoverTimer.stop();
239    m_fakeMouseMoveEventTimer.stop();
240    m_resizeLayer = 0;
241    m_nodeUnderMouse = 0;
242    m_lastNodeUnderMouse = 0;
243#if ENABLE(SVG)
244    m_instanceUnderMouse = 0;
245    m_lastInstanceUnderMouse = 0;
246#endif
247    m_lastMouseMoveEventSubframe = 0;
248    m_lastScrollbarUnderMouse = 0;
249    m_clickCount = 0;
250    m_clickNode = 0;
251    m_frameSetBeingResized = 0;
252#if ENABLE(DRAG_SUPPORT)
253    m_dragTarget = 0;
254    m_shouldOnlyFireDragOverEvent = false;
255#endif
256    m_currentMousePosition = IntPoint();
257    m_mousePressNode = 0;
258    m_mousePressed = false;
259    m_capturesDragging = false;
260    m_capturingMouseEventsNode = 0;
261    m_latchedWheelEventNode = 0;
262    m_previousWheelScrolledNode = 0;
263#if ENABLE(TOUCH_EVENTS)
264    m_originatingTouchPointTargets.clear();
265#if PLATFORM(ANDROID)
266    m_capturingTouchEventsNode = 0;
267#endif
268#endif
269}
270
271static void setSelectionIfNeeded(SelectionController* selection, const VisibleSelection& newSelection)
272{
273    ASSERT(selection);
274    if (selection->selection() != newSelection && selection->shouldChangeSelection(newSelection))
275        selection->setSelection(newSelection);
276}
277
278static void setNonDirectionalSelectionIfNeeded(SelectionController* selection, const VisibleSelection& newSelection, TextGranularity granularity)
279{
280    ASSERT(selection);
281    if (selection->selection() != newSelection && selection->shouldChangeSelection(newSelection))
282        selection->setSelection(newSelection, granularity, MakeNonDirectionalSelection);
283}
284
285void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result)
286{
287    Node* innerNode = result.targetNode();
288    VisibleSelection newSelection;
289
290    if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
291        VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
292        TextGranularity granularity = CharacterGranularity;
293        if (pos.isNotNull()) {
294            newSelection = VisibleSelection(pos);
295            newSelection.expandUsingGranularity(WordGranularity);
296        }
297
298        if (newSelection.isRange()) {
299            granularity = WordGranularity;
300            m_beganSelectingText = true;
301            if (result.event().clickCount() == 2 && m_frame->editor()->isSelectTrailingWhitespaceEnabled())
302                newSelection.appendTrailingWhitespace();
303        }
304
305        setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, granularity);
306    }
307}
308
309void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults& result)
310{
311    if (!result.hitTestResult().isLiveLink())
312        return selectClosestWordFromMouseEvent(result);
313
314    Node* innerNode = result.targetNode();
315
316    if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
317        VisibleSelection newSelection;
318        Element* URLElement = result.hitTestResult().URLElement();
319        VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
320        if (pos.isNotNull() && pos.deepEquivalent().deprecatedNode()->isDescendantOf(URLElement))
321            newSelection = VisibleSelection::selectionFromContentsOfNode(URLElement);
322
323        TextGranularity granularity = CharacterGranularity;
324        if (newSelection.isRange()) {
325            granularity = WordGranularity;
326            m_beganSelectingText = true;
327        }
328
329        setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, granularity);
330    }
331}
332
333bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event)
334{
335    if (event.event().button() != LeftButton)
336        return false;
337
338    if (m_frame->selection()->isRange())
339        // A double-click when range is already selected
340        // should not change the selection.  So, do not call
341        // selectClosestWordFromMouseEvent, but do set
342        // m_beganSelectingText to prevent handleMouseReleaseEvent
343        // from setting caret selection.
344        m_beganSelectingText = true;
345    else
346        selectClosestWordFromMouseEvent(event);
347
348    return true;
349}
350
351bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event)
352{
353    if (event.event().button() != LeftButton)
354        return false;
355
356    Node* innerNode = event.targetNode();
357    if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
358        return false;
359
360    VisibleSelection newSelection;
361    VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint()));
362    if (pos.isNotNull()) {
363        newSelection = VisibleSelection(pos);
364        newSelection.expandUsingGranularity(ParagraphGranularity);
365    }
366
367    TextGranularity granularity = CharacterGranularity;
368    if (newSelection.isRange()) {
369        granularity = ParagraphGranularity;
370        m_beganSelectingText = true;
371    }
372
373    setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, granularity);
374
375    return true;
376}
377
378static int textDistance(const Position& start, const Position& end)
379{
380     RefPtr<Range> range = Range::create(start.anchorNode()->document(), start, end);
381     return TextIterator::rangeLength(range.get(), true);
382}
383
384bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
385{
386    Node* innerNode = event.targetNode();
387    if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
388        return false;
389
390    // Extend the selection if the Shift key is down, unless the click is in a link.
391    bool extendSelection = event.event().shiftKey() && !event.isOverLink();
392
393    // Don't restart the selection when the mouse is pressed on an
394    // existing selection so we can allow for text dragging.
395    if (FrameView* view = m_frame->view()) {
396        IntPoint vPoint = view->windowToContents(event.event().pos());
397        if (!extendSelection && m_frame->selection()->contains(vPoint)) {
398            m_mouseDownWasSingleClickInSelection = true;
399            return false;
400        }
401    }
402
403    VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(event.localPoint()));
404    if (visiblePos.isNull())
405        visiblePos = VisiblePosition(firstPositionInOrBeforeNode(innerNode), DOWNSTREAM);
406    Position pos = visiblePos.deepEquivalent();
407
408    VisibleSelection newSelection = m_frame->selection()->selection();
409    TextGranularity granularity = CharacterGranularity;
410
411    if (extendSelection && newSelection.isCaretOrRange()) {
412        m_frame->selection()->setIsDirectional(false);
413
414        ASSERT(m_frame->settings());
415        if (m_frame->settings()->editingBehaviorType() == EditingMacBehavior) {
416            // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection
417            // was created right-to-left
418            Position start = newSelection.start();
419            Position end = newSelection.end();
420            int distanceToStart = textDistance(start, pos);
421            int distanceToEnd = textDistance(pos, end);
422            if (distanceToStart <= distanceToEnd)
423                newSelection = VisibleSelection(end, pos);
424            else
425                newSelection = VisibleSelection(start, pos);
426        } else {
427            newSelection.setExtent(pos);
428        }
429
430        if (m_frame->selection()->granularity() != CharacterGranularity) {
431            granularity = m_frame->selection()->granularity();
432            newSelection.expandUsingGranularity(m_frame->selection()->granularity());
433        }
434
435        m_beganSelectingText = true;
436    } else
437        newSelection = VisibleSelection(visiblePos);
438
439    setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, granularity);
440
441    return true;
442}
443
444bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event)
445{
446#if ENABLE(DRAG_SUPPORT)
447    // Reset drag state.
448    dragState().m_dragSrc = 0;
449#endif
450
451    cancelFakeMouseMoveEvent();
452
453    if (ScrollView* scrollView = m_frame->view()) {
454        if (scrollView->isPointInScrollbarCorner(event.event().pos()))
455            return false;
456    }
457
458    bool singleClick = event.event().clickCount() <= 1;
459
460    // If we got the event back, that must mean it wasn't prevented,
461    // so it's allowed to start a drag or selection.
462    m_mouseDownMayStartSelect = canMouseDownStartSelect(event.targetNode());
463
464#if ENABLE(DRAG_SUPPORT)
465    // Careful that the drag starting logic stays in sync with eventMayStartDrag()
466    m_mouseDownMayStartDrag = singleClick;
467#endif
468
469    m_mouseDownWasSingleClickInSelection = false;
470
471    m_mouseDown = event.event();
472
473    if (event.isOverWidget() && passWidgetMouseDownEventToWidget(event))
474        return true;
475
476#if ENABLE(SVG)
477    if (m_frame->document()->isSVGDocument()
478        && static_cast<SVGDocument*>(m_frame->document())->zoomAndPanEnabled()) {
479        if (event.event().shiftKey() && singleClick) {
480            m_svgPan = true;
481            static_cast<SVGDocument*>(m_frame->document())->startPan(event.event().pos());
482            return true;
483        }
484    }
485#endif
486
487    // We don't do this at the start of mouse down handling,
488    // because we don't want to do it until we know we didn't hit a widget.
489    if (singleClick)
490        focusDocumentView();
491
492    Node* innerNode = event.targetNode();
493
494    m_mousePressNode = innerNode;
495#if ENABLE(DRAG_SUPPORT)
496    m_dragStartPos = event.event().pos();
497#endif
498
499    bool swallowEvent = false;
500    m_mousePressed = true;
501    m_beganSelectingText = false;
502
503    if (event.event().clickCount() == 2)
504        swallowEvent = handleMousePressEventDoubleClick(event);
505    else if (event.event().clickCount() >= 3)
506        swallowEvent = handleMousePressEventTripleClick(event);
507    else
508        swallowEvent = handleMousePressEventSingleClick(event);
509
510    m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect
511        || (m_mousePressNode && m_mousePressNode->renderBox() && m_mousePressNode->renderBox()->canBeProgramaticallyScrolled(true));
512
513    return swallowEvent;
514}
515
516// There are two kinds of renderer that can autoscroll.
517static bool canAutoscroll(RenderObject* renderer)
518{
519    if (!renderer->isBox())
520        return false;
521
522    // Check for a box that can be scrolled in its own right.
523    if (toRenderBox(renderer)->canBeScrolledAndHasScrollableArea())
524        return true;
525
526    // Check for a box that represents the top level of a web page.
527    // This can be scrolled by calling Chrome::scrollRectIntoView.
528    // This only has an effect on the Mac platform in applications
529    // that put web views into scrolling containers, such as Mac OS X Mail.
530    // The code for this is in RenderLayer::scrollRectToVisible.
531    if (renderer->node() != renderer->document())
532        return false;
533    Frame* frame = renderer->frame();
534    if (!frame)
535        return false;
536    Page* page = frame->page();
537    return page && page->mainFrame() == frame;
538}
539
540#if ENABLE(DRAG_SUPPORT)
541bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event)
542{
543    if (handleDrag(event))
544        return true;
545
546    if (!m_mousePressed)
547        return false;
548
549    Node* targetNode = event.targetNode();
550    if (event.event().button() != LeftButton || !targetNode || !targetNode->renderer())
551        return false;
552
553#if PLATFORM(MAC) // FIXME: Why does this assertion fire on other platforms?
554    ASSERT(m_mouseDownMayStartSelect || m_mouseDownMayStartAutoscroll);
555#endif
556
557    m_mouseDownMayStartDrag = false;
558
559    if (m_mouseDownMayStartAutoscroll && !m_panScrollInProgress) {
560        // Find a renderer that can autoscroll.
561        RenderObject* renderer = targetNode->renderer();
562        while (renderer && !canAutoscroll(renderer)) {
563            if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement())
564                renderer = renderer->document()->ownerElement()->renderer();
565            else
566                renderer = renderer->parent();
567        }
568
569        if (renderer) {
570            m_autoscrollInProgress = true;
571            handleAutoscroll(renderer);
572        }
573
574        m_mouseDownMayStartAutoscroll = false;
575    }
576
577    if (!m_beganSelectingText) {
578        HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
579        HitTestResult result(m_mouseDownPos);
580        m_frame->document()->renderView()->layer()->hitTest(request, result);
581        updateSelectionForMouseDrag(result.innerNode(), result.localPoint());
582    }
583    updateSelectionForMouseDrag(targetNode, event.localPoint());
584    return true;
585}
586
587bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const
588{
589    // This is a pre-flight check of whether the event might lead to a drag being started.  Be careful
590    // that its logic needs to stay in sync with handleMouseMoveEvent() and the way we setMouseDownMayStartDrag
591    // in handleMousePressEvent
592
593    if (!m_frame->contentRenderer() || !m_frame->contentRenderer()->hasLayer())
594        return false;
595
596    if (event.button() != LeftButton || event.clickCount() != 1)
597        return false;
598
599    bool DHTMLFlag;
600    bool UAFlag;
601    allowDHTMLDrag(DHTMLFlag, UAFlag);
602    if (!DHTMLFlag && !UAFlag)
603        return false;
604
605    FrameView* view = m_frame->view();
606    if (!view)
607        return false;
608
609    HitTestRequest request(HitTestRequest::ReadOnly);
610    HitTestResult result(view->windowToContents(event.pos()));
611    m_frame->contentRenderer()->layer()->hitTest(request, result);
612    bool srcIsDHTML;
613    return result.innerNode() && result.innerNode()->renderer()->draggableNode(DHTMLFlag, UAFlag, result.point().x(), result.point().y(), srcIsDHTML);
614}
615
616void EventHandler::updateSelectionForMouseDrag()
617{
618    FrameView* view = m_frame->view();
619    if (!view)
620        return;
621    RenderView* renderer = m_frame->contentRenderer();
622    if (!renderer)
623        return;
624    RenderLayer* layer = renderer->layer();
625    if (!layer)
626        return;
627
628    HitTestRequest request(HitTestRequest::ReadOnly |
629                           HitTestRequest::Active |
630                           HitTestRequest::MouseMove);
631    HitTestResult result(view->windowToContents(m_currentMousePosition));
632    layer->hitTest(request, result);
633    updateSelectionForMouseDrag(result.innerNode(), result.localPoint());
634}
635
636void EventHandler::updateSelectionForMouseDrag(Node* targetNode, const IntPoint& localPoint)
637{
638    if (!m_mouseDownMayStartSelect)
639        return;
640
641    if (!targetNode)
642        return;
643
644    if (!canMouseDragExtendSelect(targetNode))
645        return;
646
647    RenderObject* targetRenderer = targetNode->renderer();
648    if (!targetRenderer)
649        return;
650
651    VisiblePosition targetPosition(targetRenderer->positionForPoint(localPoint));
652
653    // Don't modify the selection if we're not on a node.
654    if (targetPosition.isNull())
655        return;
656
657    // Restart the selection if this is the first mouse move. This work is usually
658    // done in handleMousePressEvent, but not if the mouse press was on an existing selection.
659    VisibleSelection newSelection = m_frame->selection()->selection();
660
661#if ENABLE(SVG)
662    // Special case to limit selection to the containing block for SVG text.
663    // FIXME: Isn't there a better non-SVG-specific way to do this?
664    if (Node* selectionBaseNode = newSelection.base().deprecatedNode())
665        if (RenderObject* selectionBaseRenderer = selectionBaseNode->renderer())
666            if (selectionBaseRenderer->isSVGText())
667                if (targetNode->renderer()->containingBlock() != selectionBaseRenderer->containingBlock())
668                    return;
669#endif
670
671    if (!m_beganSelectingText) {
672        m_beganSelectingText = true;
673        newSelection = VisibleSelection(targetPosition);
674    }
675
676    newSelection.setExtent(targetPosition);
677    if (m_frame->selection()->granularity() != CharacterGranularity)
678        newSelection.expandUsingGranularity(m_frame->selection()->granularity());
679
680    setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, m_frame->selection()->granularity());
681}
682#endif // ENABLE(DRAG_SUPPORT)
683
684void EventHandler::lostMouseCapture()
685{
686    m_frame->selection()->setCaretBlinkingSuspended(false);
687}
688
689bool EventHandler::handleMouseUp(const MouseEventWithHitTestResults& event)
690{
691    if (eventLoopHandleMouseUp(event))
692        return true;
693
694    // If this was the first click in the window, we don't even want to clear the selection.
695    // This case occurs when the user clicks on a draggable element, since we have to process
696    // the mouse down and drag events to see if we might start a drag.  For other first clicks
697    // in a window, we just don't acceptFirstMouse, and the whole down-drag-up sequence gets
698    // ignored upstream of this layer.
699    return eventActivatedView(event.event());
700}
701
702bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
703{
704    if (m_autoscrollInProgress)
705        stopAutoscrollTimer();
706
707    if (handleMouseUp(event))
708        return true;
709
710    // Used to prevent mouseMoveEvent from initiating a drag before
711    // the mouse is pressed again.
712    m_frame->selection()->setCaretBlinkingSuspended(false);
713    m_mousePressed = false;
714    m_capturesDragging = false;
715#if ENABLE(DRAG_SUPPORT)
716    m_mouseDownMayStartDrag = false;
717#endif
718    m_mouseDownMayStartSelect = false;
719    m_mouseDownMayStartAutoscroll = false;
720    m_mouseDownWasInSubframe = false;
721
722    bool handled = false;
723
724    // Clear the selection if the mouse didn't move after the last mouse
725    // press and it's not a context menu click.  We do this so when clicking
726    // on the selection, the selection goes away.  However, if we are
727    // editing, place the caret.
728    if (m_mouseDownWasSingleClickInSelection && !m_beganSelectingText
729#if ENABLE(DRAG_SUPPORT)
730            && m_dragStartPos == event.event().pos()
731#endif
732            && m_frame->selection()->isRange()
733            && event.event().button() != RightButton) {
734        VisibleSelection newSelection;
735        Node* node = event.targetNode();
736        bool caretBrowsing = m_frame->settings()->caretBrowsingEnabled();
737        if (node && (caretBrowsing || node->rendererIsEditable()) && node->renderer()) {
738            VisiblePosition pos = node->renderer()->positionForPoint(event.localPoint());
739            newSelection = VisibleSelection(pos);
740        }
741
742        setSelectionIfNeeded(m_frame->selection(), newSelection);
743
744        handled = true;
745    }
746
747    m_frame->selection()->notifyRendererOfSelectionChange(true);
748
749    m_frame->selection()->selectFrameElementInParentIfFullySelected();
750
751    return handled;
752}
753
754void EventHandler::handleAutoscroll(RenderObject* renderer)
755{
756    // We don't want to trigger the autoscroll or the panScroll if it's already active
757    if (m_autoscrollTimer.isActive())
758        return;
759
760    setAutoscrollRenderer(renderer);
761
762#if ENABLE(PAN_SCROLLING)
763    if (m_panScrollInProgress) {
764        m_panScrollStartPos = currentMousePosition();
765        if (FrameView* view = m_frame->view())
766            view->addPanScrollIcon(m_panScrollStartPos);
767        // If we're not in the top frame we notify it that we doing a panScroll.
768        if (Page* page = m_frame->page()) {
769            Frame* mainFrame = page->mainFrame();
770            if (m_frame != mainFrame)
771                mainFrame->eventHandler()->setPanScrollInProgress(true);
772        }
773    }
774#endif
775
776    startAutoscrollTimer();
777}
778
779void EventHandler::autoscrollTimerFired(Timer<EventHandler>*)
780{
781    RenderObject* r = autoscrollRenderer();
782    if (!r || !r->isBox()) {
783        stopAutoscrollTimer();
784        return;
785    }
786
787    if (m_autoscrollInProgress) {
788        if (!m_mousePressed) {
789            stopAutoscrollTimer();
790            return;
791        }
792        toRenderBox(r)->autoscroll();
793    } else {
794        // we verify that the main frame hasn't received the order to stop the panScroll
795        if (Page* page = m_frame->page()) {
796            if (!page->mainFrame()->eventHandler()->panScrollInProgress()) {
797                stopAutoscrollTimer();
798                return;
799            }
800        }
801#if ENABLE(PAN_SCROLLING)
802        updatePanScrollState();
803        toRenderBox(r)->panScroll(m_panScrollStartPos);
804#endif
805    }
806}
807
808#if ENABLE(PAN_SCROLLING)
809
810void EventHandler::startPanScrolling(RenderObject* renderer)
811{
812    m_panScrollInProgress = true;
813    m_panScrollButtonPressed = true;
814    handleAutoscroll(renderer);
815    invalidateClick();
816}
817
818void EventHandler::updatePanScrollState()
819{
820    FrameView* view = m_frame->view();
821    if (!view)
822        return;
823
824    // At the original click location we draw a 4 arrowed icon. Over this icon there won't be any scroll
825    // So we don't want to change the cursor over this area
826    bool east = m_panScrollStartPos.x() < (m_currentMousePosition.x() - ScrollView::noPanScrollRadius);
827    bool west = m_panScrollStartPos.x() > (m_currentMousePosition.x() + ScrollView::noPanScrollRadius);
828    bool north = m_panScrollStartPos.y() > (m_currentMousePosition.y() + ScrollView::noPanScrollRadius);
829    bool south = m_panScrollStartPos.y() < (m_currentMousePosition.y() - ScrollView::noPanScrollRadius);
830
831    if ((east || west || north || south) && m_panScrollButtonPressed)
832        m_springLoadedPanScrollInProgress = true;
833
834    if (north) {
835        if (east)
836            view->setCursor(northEastPanningCursor());
837        else if (west)
838            view->setCursor(northWestPanningCursor());
839        else
840            view->setCursor(northPanningCursor());
841    } else if (south) {
842        if (east)
843            view->setCursor(southEastPanningCursor());
844        else if (west)
845            view->setCursor(southWestPanningCursor());
846        else
847            view->setCursor(southPanningCursor());
848    } else if (east)
849        view->setCursor(eastPanningCursor());
850    else if (west)
851        view->setCursor(westPanningCursor());
852    else
853        view->setCursor(middlePanningCursor());
854}
855
856#endif // ENABLE(PAN_SCROLLING)
857
858RenderObject* EventHandler::autoscrollRenderer() const
859{
860    return m_autoscrollRenderer;
861}
862
863void EventHandler::updateAutoscrollRenderer()
864{
865    if (!m_autoscrollRenderer)
866        return;
867
868    HitTestResult hitTest = hitTestResultAtPoint(m_panScrollStartPos, true);
869
870    if (Node* nodeAtPoint = hitTest.innerNode())
871        m_autoscrollRenderer = nodeAtPoint->renderer();
872
873    while (m_autoscrollRenderer && !canAutoscroll(m_autoscrollRenderer))
874        m_autoscrollRenderer = m_autoscrollRenderer->parent();
875}
876
877void EventHandler::setAutoscrollRenderer(RenderObject* renderer)
878{
879    m_autoscrollRenderer = renderer;
880}
881
882#if ENABLE(DRAG_SUPPORT)
883void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const
884{
885    flagDHTML = false;
886    flagUA = false;
887
888    if (!m_frame)
889        return;
890
891    Page* page = m_frame->page();
892    if (!page)
893        return;
894
895    FrameView* view = m_frame->view();
896    if (!view)
897        return;
898
899    unsigned mask = page->dragController()->delegateDragSourceAction(view->contentsToWindow(m_mouseDownPos));
900    flagDHTML = (mask & DragSourceActionDHTML) != DragSourceActionNone;
901    flagUA = ((mask & DragSourceActionImage) || (mask & DragSourceActionLink) || (mask & DragSourceActionSelection));
902}
903#endif // ENABLE(DRAG_SUPPORT)
904
905HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent, bool ignoreClipping, HitTestScrollbars testScrollbars, HitTestRequest::HitTestRequestType hitType, const IntSize& padding)
906{
907    HitTestResult result(point, padding.height(), padding.width(), padding.height(), padding.width());
908    if (!m_frame->contentRenderer())
909        return result;
910    if (ignoreClipping)
911        hitType |= HitTestRequest::IgnoreClipping;
912    m_frame->contentRenderer()->layer()->hitTest(HitTestRequest(hitType), result);
913
914    while (true) {
915        Node* n = result.innerNode();
916        if (!result.isOverWidget() || !n || !n->renderer() || !n->renderer()->isWidget())
917            break;
918        RenderWidget* renderWidget = toRenderWidget(n->renderer());
919        Widget* widget = renderWidget->widget();
920        if (!widget || !widget->isFrameView())
921            break;
922        Frame* frame = static_cast<HTMLFrameElementBase*>(n)->contentFrame();
923        if (!frame || !frame->contentRenderer())
924            break;
925        FrameView* view = static_cast<FrameView*>(widget);
926        IntPoint widgetPoint(result.localPoint().x() + view->scrollX() - renderWidget->borderLeft() - renderWidget->paddingLeft(),
927            result.localPoint().y() + view->scrollY() - renderWidget->borderTop() - renderWidget->paddingTop());
928        HitTestResult widgetHitTestResult(widgetPoint, padding.height(), padding.width(), padding.height(), padding.width());
929        frame->contentRenderer()->layer()->hitTest(HitTestRequest(hitType), widgetHitTestResult);
930        result = widgetHitTestResult;
931
932        if (testScrollbars == ShouldHitTestScrollbars) {
933            Scrollbar* eventScrollbar = view->scrollbarAtPoint(point);
934            if (eventScrollbar)
935                result.setScrollbar(eventScrollbar);
936        }
937    }
938
939    // If our HitTestResult is not visible, then we started hit testing too far down the frame chain.
940    // Another hit test at the main frame level should get us the correct visible result.
941    Frame* resultFrame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : 0;
942    if (Page* page = m_frame->page()) {
943        Frame* mainFrame = page->mainFrame();
944        if (m_frame != mainFrame && resultFrame && resultFrame != mainFrame && !resultFrame->editor()->insideVisibleArea(result.point())) {
945            FrameView* resultView = resultFrame->view();
946            FrameView* mainView = mainFrame->view();
947            if (resultView && mainView) {
948                IntPoint windowPoint = resultView->contentsToWindow(result.point());
949                IntPoint mainFramePoint = mainView->windowToContents(windowPoint);
950                result = mainFrame->eventHandler()->hitTestResultAtPoint(mainFramePoint, allowShadowContent, ignoreClipping, testScrollbars, hitType, padding);
951            }
952        }
953    }
954
955    if (!allowShadowContent)
956        result.setToNonShadowAncestor();
957
958    return result;
959}
960
961
962void EventHandler::startAutoscrollTimer()
963{
964    m_autoscrollTimer.startRepeating(autoscrollInterval);
965}
966
967void EventHandler::stopAutoscrollTimer(bool rendererIsBeingDestroyed)
968{
969    if (m_autoscrollInProgress) {
970        if (m_mouseDownWasInSubframe) {
971            if (Frame* subframe = subframeForTargetNode(m_mousePressNode.get()))
972                subframe->eventHandler()->stopAutoscrollTimer(rendererIsBeingDestroyed);
973            return;
974        }
975    }
976
977    if (autoscrollRenderer()) {
978        if (!rendererIsBeingDestroyed && (m_autoscrollInProgress || m_panScrollInProgress))
979            toRenderBox(autoscrollRenderer())->stopAutoscroll();
980#if ENABLE(PAN_SCROLLING)
981        if (m_panScrollInProgress) {
982            if (FrameView* view = m_frame->view()) {
983                view->removePanScrollIcon();
984                view->setCursor(pointerCursor());
985            }
986        }
987#endif
988
989        setAutoscrollRenderer(0);
990    }
991
992    m_autoscrollTimer.stop();
993
994    m_panScrollInProgress = false;
995    m_springLoadedPanScrollInProgress = false;
996
997    // If we're not in the top frame we notify it that we are not doing a panScroll any more.
998    if (Page* page = m_frame->page()) {
999        Frame* mainFrame = page->mainFrame();
1000        if (m_frame != mainFrame)
1001            mainFrame->eventHandler()->setPanScrollInProgress(false);
1002    }
1003
1004    m_autoscrollInProgress = false;
1005}
1006
1007Node* EventHandler::mousePressNode() const
1008{
1009    return m_mousePressNode.get();
1010}
1011
1012void EventHandler::setMousePressNode(PassRefPtr<Node> node)
1013{
1014    m_mousePressNode = node;
1015}
1016
1017bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode)
1018{
1019    Node* node = startingNode;
1020
1021    if (!node)
1022        node = m_frame->document()->focusedNode();
1023
1024    if (!node)
1025        node = m_mousePressNode.get();
1026
1027    if (node) {
1028        RenderObject* r = node->renderer();
1029        if (r && !r->isListBox() && r->enclosingBox()->scroll(direction, granularity)) {
1030            setFrameWasScrolledByUser();
1031            return true;
1032        }
1033    }
1034
1035    return false;
1036}
1037
1038bool EventHandler::logicalScrollOverflow(ScrollLogicalDirection direction, ScrollGranularity granularity, Node* startingNode)
1039{
1040    Node* node = startingNode;
1041
1042    if (!node)
1043        node = m_frame->document()->focusedNode();
1044
1045    if (!node)
1046        node = m_mousePressNode.get();
1047
1048    if (node) {
1049        RenderObject* r = node->renderer();
1050        if (r && !r->isListBox() && r->enclosingBox()->logicalScroll(direction, granularity)) {
1051            setFrameWasScrolledByUser();
1052            return true;
1053        }
1054    }
1055
1056    return false;
1057}
1058
1059bool EventHandler::scrollRecursively(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode)
1060{
1061    // The layout needs to be up to date to determine if we can scroll. We may be
1062    // here because of an onLoad event, in which case the final layout hasn't been performed yet.
1063    m_frame->document()->updateLayoutIgnorePendingStylesheets();
1064    if (scrollOverflow(direction, granularity, startingNode))
1065        return true;
1066    Frame* frame = m_frame;
1067    FrameView* view = frame->view();
1068    if (view && view->scroll(direction, granularity))
1069        return true;
1070    frame = frame->tree()->parent();
1071    if (!frame)
1072        return false;
1073    return frame->eventHandler()->scrollRecursively(direction, granularity, m_frame->ownerElement());
1074}
1075
1076bool EventHandler::logicalScrollRecursively(ScrollLogicalDirection direction, ScrollGranularity granularity, Node* startingNode)
1077{
1078    // The layout needs to be up to date to determine if we can scroll. We may be
1079    // here because of an onLoad event, in which case the final layout hasn't been performed yet.
1080    m_frame->document()->updateLayoutIgnorePendingStylesheets();
1081    if (logicalScrollOverflow(direction, granularity, startingNode))
1082        return true;
1083    Frame* frame = m_frame;
1084    FrameView* view = frame->view();
1085
1086    bool scrolled = false;
1087#if PLATFORM(MAC)
1088    // Mac also resets the scroll position in the inline direction.
1089    if (granularity == ScrollByDocument && view && view->logicalScroll(ScrollInlineDirectionBackward, ScrollByDocument))
1090        scrolled = true;
1091#endif
1092    if (view && view->logicalScroll(direction, granularity))
1093        scrolled = true;
1094
1095    if (scrolled)
1096        return true;
1097
1098    frame = frame->tree()->parent();
1099    if (!frame)
1100        return false;
1101
1102    return frame->eventHandler()->logicalScrollRecursively(direction, granularity, m_frame->ownerElement());
1103}
1104
1105IntPoint EventHandler::currentMousePosition() const
1106{
1107    return m_currentMousePosition;
1108}
1109
1110Frame* subframeForHitTestResult(const MouseEventWithHitTestResults& hitTestResult)
1111{
1112    if (!hitTestResult.isOverWidget())
1113        return 0;
1114    return EventHandler::subframeForTargetNode(hitTestResult.targetNode());
1115}
1116
1117Frame* EventHandler::subframeForTargetNode(Node* node)
1118{
1119    if (!node)
1120        return 0;
1121
1122    RenderObject* renderer = node->renderer();
1123    if (!renderer || !renderer->isWidget())
1124        return 0;
1125
1126    Widget* widget = toRenderWidget(renderer)->widget();
1127    if (!widget || !widget->isFrameView())
1128        return 0;
1129
1130    return static_cast<FrameView*>(widget)->frame();
1131}
1132
1133static bool isSubmitImage(Node* node)
1134{
1135    return node && node->hasTagName(inputTag) && static_cast<HTMLInputElement*>(node)->isImageButton();
1136}
1137
1138// Returns true if the node's editable block is not current focused for editing
1139static bool nodeIsNotBeingEdited(Node* node, Frame* frame)
1140{
1141    return frame->selection()->rootEditableElement() != node->rootEditableElement();
1142}
1143
1144Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Scrollbar* scrollbar)
1145{
1146    Node* node = event.targetNode();
1147    RenderObject* renderer = node ? node->renderer() : 0;
1148    RenderStyle* style = renderer ? renderer->style() : 0;
1149
1150    bool horizontalText = !style || style->isHorizontalWritingMode();
1151    const Cursor& iBeam = horizontalText ? iBeamCursor() : verticalTextCursor();
1152
1153    // During selection, use an I-beam no matter what we're over.
1154    // If you're capturing mouse events for a particular node, don't treat this as a selection.
1155    if (m_mousePressed && m_mouseDownMayStartSelect && m_frame->selection()->isCaretOrRange() && !m_capturingMouseEventsNode)
1156        return iBeam;
1157
1158    if (renderer && renderer->isFrameSet()) {
1159        RenderFrameSet* frameSetRenderer = toRenderFrameSet(renderer);
1160        if (frameSetRenderer->canResizeRow(event.localPoint()))
1161            return rowResizeCursor();
1162        if (frameSetRenderer->canResizeColumn(event.localPoint()))
1163            return columnResizeCursor();
1164    }
1165
1166    if (style && style->cursors()) {
1167        const CursorList* cursors = style->cursors();
1168        for (unsigned i = 0; i < cursors->size(); ++i) {
1169            const CachedImage* cimage = 0;
1170            StyleImage* image = (*cursors)[i].image();
1171            if (image && image->isCachedImage())
1172                cimage = static_cast<StyleCachedImage*>(image)->cachedImage();
1173            if (!cimage)
1174                continue;
1175            IntPoint hotSpot = (*cursors)[i].hotSpot();
1176            // Limit the size of cursors so that they cannot be used to cover UI elements in chrome.
1177            IntSize size = cimage->image()->size();
1178            if (size.width() > 128 || size.height() > 128)
1179                continue;
1180            if (cimage->image()->isNull())
1181                break;
1182            if (!cimage->errorOccurred())
1183                return Cursor(cimage->image(), hotSpot);
1184        }
1185    }
1186
1187    switch (style ? style->cursor() : CURSOR_AUTO) {
1188    case CURSOR_AUTO: {
1189        bool editable = (node && node->rendererIsEditable());
1190        bool editableLinkEnabled = false;
1191
1192        // If the link is editable, then we need to check the settings to see whether or not the link should be followed
1193        if (editable) {
1194            ASSERT(m_frame->settings());
1195            switch (m_frame->settings()->editableLinkBehavior()) {
1196            default:
1197            case EditableLinkDefaultBehavior:
1198            case EditableLinkAlwaysLive:
1199                editableLinkEnabled = true;
1200                break;
1201
1202            case EditableLinkNeverLive:
1203                editableLinkEnabled = false;
1204                break;
1205
1206            case EditableLinkLiveWhenNotFocused:
1207                editableLinkEnabled = nodeIsNotBeingEdited(node, m_frame) || event.event().shiftKey();
1208                break;
1209
1210            case EditableLinkOnlyLiveWithShiftKey:
1211                editableLinkEnabled = event.event().shiftKey();
1212                break;
1213            }
1214        }
1215
1216        if ((event.isOverLink() || isSubmitImage(node)) && (!editable || editableLinkEnabled))
1217            return handCursor();
1218        bool inResizer = false;
1219        if (renderer) {
1220            if (RenderLayer* layer = renderer->enclosingLayer()) {
1221                if (FrameView* view = m_frame->view())
1222                    inResizer = layer->isPointInResizeControl(view->windowToContents(event.event().pos()));
1223            }
1224        }
1225        if ((editable || (renderer && renderer->isText() && node->canStartSelection())) && !inResizer && !scrollbar)
1226            return iBeam;
1227        return pointerCursor();
1228    }
1229    case CURSOR_CROSS:
1230        return crossCursor();
1231    case CURSOR_POINTER:
1232        return handCursor();
1233    case CURSOR_MOVE:
1234        return moveCursor();
1235    case CURSOR_ALL_SCROLL:
1236        return moveCursor();
1237    case CURSOR_E_RESIZE:
1238        return eastResizeCursor();
1239    case CURSOR_W_RESIZE:
1240        return westResizeCursor();
1241    case CURSOR_N_RESIZE:
1242        return northResizeCursor();
1243    case CURSOR_S_RESIZE:
1244        return southResizeCursor();
1245    case CURSOR_NE_RESIZE:
1246        return northEastResizeCursor();
1247    case CURSOR_SW_RESIZE:
1248        return southWestResizeCursor();
1249    case CURSOR_NW_RESIZE:
1250        return northWestResizeCursor();
1251    case CURSOR_SE_RESIZE:
1252        return southEastResizeCursor();
1253    case CURSOR_NS_RESIZE:
1254        return northSouthResizeCursor();
1255    case CURSOR_EW_RESIZE:
1256        return eastWestResizeCursor();
1257    case CURSOR_NESW_RESIZE:
1258        return northEastSouthWestResizeCursor();
1259    case CURSOR_NWSE_RESIZE:
1260        return northWestSouthEastResizeCursor();
1261    case CURSOR_COL_RESIZE:
1262        return columnResizeCursor();
1263    case CURSOR_ROW_RESIZE:
1264        return rowResizeCursor();
1265    case CURSOR_TEXT:
1266        return iBeamCursor();
1267    case CURSOR_WAIT:
1268        return waitCursor();
1269    case CURSOR_HELP:
1270        return helpCursor();
1271    case CURSOR_VERTICAL_TEXT:
1272        return verticalTextCursor();
1273    case CURSOR_CELL:
1274        return cellCursor();
1275    case CURSOR_CONTEXT_MENU:
1276        return contextMenuCursor();
1277    case CURSOR_PROGRESS:
1278        return progressCursor();
1279    case CURSOR_NO_DROP:
1280        return noDropCursor();
1281    case CURSOR_ALIAS:
1282        return aliasCursor();
1283    case CURSOR_COPY:
1284        return copyCursor();
1285    case CURSOR_NONE:
1286        return noneCursor();
1287    case CURSOR_NOT_ALLOWED:
1288        return notAllowedCursor();
1289    case CURSOR_DEFAULT:
1290        return pointerCursor();
1291    case CURSOR_WEBKIT_ZOOM_IN:
1292        return zoomInCursor();
1293    case CURSOR_WEBKIT_ZOOM_OUT:
1294        return zoomOutCursor();
1295    case CURSOR_WEBKIT_GRAB:
1296        return grabCursor();
1297    case CURSOR_WEBKIT_GRABBING:
1298        return grabbingCursor();
1299    }
1300    return pointerCursor();
1301}
1302
1303static IntPoint documentPointForWindowPoint(Frame* frame, const IntPoint& windowPoint)
1304{
1305    FrameView* view = frame->view();
1306    // FIXME: Is it really OK to use the wrong coordinates here when view is 0?
1307    // Historically the code would just crash; this is clearly no worse than that.
1308    return view ? view->windowToContents(windowPoint) : windowPoint;
1309}
1310
1311bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
1312{
1313    RefPtr<FrameView> protector(m_frame->view());
1314
1315    UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
1316
1317    cancelFakeMouseMoveEvent();
1318    m_mousePressed = true;
1319    m_capturesDragging = true;
1320    m_currentMousePosition = mouseEvent.pos();
1321    m_mouseDownTimestamp = mouseEvent.timestamp();
1322#if ENABLE(DRAG_SUPPORT)
1323    m_mouseDownMayStartDrag = false;
1324#endif
1325    m_mouseDownMayStartSelect = false;
1326    m_mouseDownMayStartAutoscroll = false;
1327    if (FrameView* view = m_frame->view())
1328        m_mouseDownPos = view->windowToContents(mouseEvent.pos());
1329    else {
1330        invalidateClick();
1331        return false;
1332    }
1333    m_mouseDownWasInSubframe = false;
1334
1335#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
1336    // Add IgnoreClipping because fixed position elements are moved only on the
1337    // UI thread.  Nodes in fixed position elements are clipped out by the view
1338    // without IgnoreClipping.
1339    HitTestRequest request(HitTestRequest::Active | HitTestRequest::IgnoreClipping);
1340#else
1341    HitTestRequest request(HitTestRequest::Active);
1342#endif
1343    // Save the document point we generate in case the window coordinate is invalidated by what happens
1344    // when we dispatch the event.
1345    IntPoint documentPoint = documentPointForWindowPoint(m_frame, mouseEvent.pos());
1346    MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent);
1347
1348    if (!mev.targetNode()) {
1349        invalidateClick();
1350        return false;
1351    }
1352
1353    m_mousePressNode = mev.targetNode();
1354
1355    if (InspectorInstrumentation::handleMousePress(m_frame->page())) {
1356        invalidateClick();
1357        return true;
1358    }
1359
1360    Frame* subframe = subframeForHitTestResult(mev);
1361    if (subframe && passMousePressEventToSubframe(mev, subframe)) {
1362        // Start capturing future events for this frame.  We only do this if we didn't clear
1363        // the m_mousePressed flag, which may happen if an AppKit widget entered a modal event loop.
1364        m_capturesDragging = subframe->eventHandler()->capturesDragging();
1365        if (m_mousePressed && m_capturesDragging) {
1366            m_capturingMouseEventsNode = mev.targetNode();
1367            m_eventHandlerWillResetCapturingMouseEventsNode = true;
1368        }
1369        invalidateClick();
1370        return true;
1371    }
1372
1373#if ENABLE(PAN_SCROLLING)
1374    Page* page = m_frame->page();
1375    if ((page && page->mainFrame()->eventHandler()->panScrollInProgress()) || m_autoscrollInProgress) {
1376        stopAutoscrollTimer();
1377        invalidateClick();
1378        return true;
1379    }
1380#endif
1381
1382    m_clickCount = mouseEvent.clickCount();
1383    m_clickNode = mev.targetNode();
1384
1385    if (FrameView* view = m_frame->view()) {
1386        RenderLayer* layer = m_clickNode->renderer() ? m_clickNode->renderer()->enclosingLayer() : 0;
1387        IntPoint p = view->windowToContents(mouseEvent.pos());
1388        if (layer && layer->isPointInResizeControl(p)) {
1389            layer->setInResizeMode(true);
1390            m_resizeLayer = layer;
1391            m_offsetFromResizeCorner = layer->offsetFromResizeCorner(p);
1392            invalidateClick();
1393            return true;
1394        }
1395    }
1396
1397    m_frame->selection()->setCaretBlinkingSuspended(true);
1398
1399    bool swallowEvent = dispatchMouseEvent(eventNames().mousedownEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
1400    m_capturesDragging = !swallowEvent;
1401
1402    // If the hit testing originally determined the event was in a scrollbar, refetch the MouseEventWithHitTestResults
1403    // in case the scrollbar widget was destroyed when the mouse event was handled.
1404    if (mev.scrollbar()) {
1405        const bool wasLastScrollBar = mev.scrollbar() == m_lastScrollbarUnderMouse.get();
1406        HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
1407        mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent);
1408        if (wasLastScrollBar && mev.scrollbar() != m_lastScrollbarUnderMouse.get())
1409            m_lastScrollbarUnderMouse = 0;
1410    }
1411
1412    if (swallowEvent) {
1413        // scrollbars should get events anyway, even disabled controls might be scrollable
1414        Scrollbar* scrollbar = mev.scrollbar();
1415
1416        updateLastScrollbarUnderMouse(scrollbar, true);
1417
1418        if (scrollbar)
1419            passMousePressEventToScrollbar(mev, scrollbar);
1420    } else {
1421        // Refetch the event target node if it currently is the shadow node inside an <input> element.
1422        // If a mouse event handler changes the input element type to one that has a widget associated,
1423        // we'd like to EventHandler::handleMousePressEvent to pass the event to the widget and thus the
1424        // event target node can't still be the shadow node.
1425        if (mev.targetNode()->isShadowRoot() && mev.targetNode()->shadowHost()->hasTagName(inputTag)) {
1426            HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
1427            mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent);
1428        }
1429
1430        FrameView* view = m_frame->view();
1431        Scrollbar* scrollbar = view ? view->scrollbarAtPoint(mouseEvent.pos()) : 0;
1432        if (!scrollbar)
1433            scrollbar = mev.scrollbar();
1434
1435        updateLastScrollbarUnderMouse(scrollbar, true);
1436
1437        if (scrollbar && passMousePressEventToScrollbar(mev, scrollbar))
1438            swallowEvent = true;
1439        else
1440            swallowEvent = handleMousePressEvent(mev);
1441    }
1442
1443    return swallowEvent;
1444}
1445
1446// This method only exists for platforms that don't know how to deliver
1447bool EventHandler::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent)
1448{
1449    RefPtr<FrameView> protector(m_frame->view());
1450
1451    UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
1452
1453    // We get this instead of a second mouse-up
1454    m_mousePressed = false;
1455    m_currentMousePosition = mouseEvent.pos();
1456
1457    HitTestRequest request(HitTestRequest::Active);
1458    MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
1459    Frame* subframe = subframeForHitTestResult(mev);
1460    if (m_eventHandlerWillResetCapturingMouseEventsNode)
1461        m_capturingMouseEventsNode = 0;
1462    if (subframe && passMousePressEventToSubframe(mev, subframe))
1463        return true;
1464
1465    m_clickCount = mouseEvent.clickCount();
1466    bool swallowMouseUpEvent = dispatchMouseEvent(eventNames().mouseupEvent, mev.targetNode(), true, m_clickCount, mouseEvent, false);
1467
1468    bool swallowClickEvent = mouseEvent.button() != RightButton && mev.targetNode() == m_clickNode && dispatchMouseEvent(eventNames().clickEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
1469
1470    if (m_lastScrollbarUnderMouse)
1471        swallowMouseUpEvent = m_lastScrollbarUnderMouse->mouseUp();
1472
1473    bool swallowMouseReleaseEvent = !swallowMouseUpEvent && handleMouseReleaseEvent(mev);
1474
1475    invalidateClick();
1476
1477    return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
1478}
1479
1480static RenderLayer* layerForNode(Node* node)
1481{
1482    if (!node)
1483        return 0;
1484
1485    RenderObject* renderer = node->renderer();
1486    if (!renderer)
1487        return 0;
1488
1489    RenderLayer* layer = renderer->enclosingLayer();
1490    if (!layer)
1491        return 0;
1492
1493    return layer;
1494}
1495
1496bool EventHandler::mouseMoved(const PlatformMouseEvent& event)
1497{
1498    HitTestResult hoveredNode = HitTestResult(IntPoint());
1499    bool result = handleMouseMoveEvent(event, &hoveredNode);
1500
1501    Page* page = m_frame->page();
1502    if (!page)
1503        return result;
1504
1505    if (RenderLayer* layer = layerForNode(hoveredNode.innerNode())) {
1506        if (page->containsScrollableArea(layer))
1507            layer->scrollAnimator()->mouseMovedInContentArea();
1508    }
1509
1510    if (FrameView* frameView = m_frame->view())
1511        frameView->scrollAnimator()->mouseMovedInContentArea();
1512
1513    hoveredNode.setToNonShadowAncestor();
1514    page->chrome()->mouseDidMoveOverElement(hoveredNode, event.modifierFlags());
1515    page->chrome()->setToolTip(hoveredNode);
1516    return result;
1517}
1518
1519bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, HitTestResult* hoveredNode)
1520{
1521    // in Radar 3703768 we saw frequent crashes apparently due to the
1522    // part being null here, which seems impossible, so check for nil
1523    // but also assert so that we can try to figure this out in debug
1524    // builds, if it happens.
1525    ASSERT(m_frame);
1526    if (!m_frame)
1527        return false;
1528
1529    RefPtr<FrameView> protector(m_frame->view());
1530    m_currentMousePosition = mouseEvent.pos();
1531
1532    if (m_hoverTimer.isActive())
1533        m_hoverTimer.stop();
1534
1535    cancelFakeMouseMoveEvent();
1536
1537#if ENABLE(SVG)
1538    if (m_svgPan) {
1539        static_cast<SVGDocument*>(m_frame->document())->updatePan(m_currentMousePosition);
1540        return true;
1541    }
1542#endif
1543
1544    if (m_frameSetBeingResized)
1545        return dispatchMouseEvent(eventNames().mousemoveEvent, m_frameSetBeingResized.get(), false, 0, mouseEvent, false);
1546
1547    // Send events right to a scrollbar if the mouse is pressed.
1548    if (m_lastScrollbarUnderMouse && m_mousePressed)
1549        return m_lastScrollbarUnderMouse->mouseMoved(mouseEvent);
1550
1551    // Treat mouse move events while the mouse is pressed as "read-only" in prepareMouseEvent
1552    // if we are allowed to select.
1553    // This means that :hover and :active freeze in the state they were in when the mouse
1554    // was pressed, rather than updating for nodes the mouse moves over as you hold the mouse down.
1555    HitTestRequest::HitTestRequestType hitType = HitTestRequest::MouseMove;
1556    if (m_mousePressed && m_mouseDownMayStartSelect)
1557        hitType |= HitTestRequest::ReadOnly;
1558    if (m_mousePressed)
1559        hitType |= HitTestRequest::Active;
1560
1561#if ENABLE(TOUCH_EVENTS)
1562    // Treat any mouse move events as readonly if the user is currently touching the screen.
1563    if (m_touchPressed)
1564        hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly;
1565#endif
1566    HitTestRequest request(hitType);
1567    MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
1568    if (hoveredNode)
1569        *hoveredNode = mev.hitTestResult();
1570
1571    Scrollbar* scrollbar = 0;
1572
1573    if (m_resizeLayer && m_resizeLayer->inResizeMode())
1574        m_resizeLayer->resize(mouseEvent, m_offsetFromResizeCorner);
1575    else {
1576        if (FrameView* view = m_frame->view())
1577            scrollbar = view->scrollbarAtPoint(mouseEvent.pos());
1578
1579        if (!scrollbar)
1580            scrollbar = mev.scrollbar();
1581
1582        updateLastScrollbarUnderMouse(scrollbar, !m_mousePressed);
1583    }
1584
1585    bool swallowEvent = false;
1586    RefPtr<Frame> newSubframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev);
1587
1588    // 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.
1589    if (m_lastMouseMoveEventSubframe && m_lastMouseMoveEventSubframe->tree()->isDescendantOf(m_frame) && m_lastMouseMoveEventSubframe != newSubframe)
1590        passMouseMoveEventToSubframe(mev, m_lastMouseMoveEventSubframe.get());
1591
1592    if (newSubframe) {
1593        // Update over/out state before passing the event to the subframe.
1594        updateMouseEventTargetNode(mev.targetNode(), mouseEvent, true);
1595
1596        // Event dispatch in updateMouseEventTargetNode may have caused the subframe of the target
1597        // node to be detached from its FrameView, in which case the event should not be passed.
1598        if (newSubframe->view())
1599            swallowEvent |= passMouseMoveEventToSubframe(mev, newSubframe.get(), hoveredNode);
1600    } else {
1601        if (scrollbar && !m_mousePressed)
1602            scrollbar->mouseMoved(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
1603        if (Page* page = m_frame->page()) {
1604            if ((!m_resizeLayer || !m_resizeLayer->inResizeMode()) && !page->mainFrame()->eventHandler()->panScrollInProgress()) {
1605                // Plugins set cursor on their own. The only case WebKit intervenes is resetting cursor to arrow on mouse enter,
1606                // in case the particular plugin doesn't manipulate cursor at all. Thus,  even a CSS cursor set on body has no
1607                // effect on plugins (which matches Firefox).
1608                bool overPluginElement = false;
1609                if (mev.targetNode() && mev.targetNode()->isHTMLElement()) {
1610                    HTMLElement* el = toHTMLElement(mev.targetNode());
1611                    overPluginElement = el->hasTagName(appletTag) || el->hasTagName(objectTag) || el->hasTagName(embedTag);
1612                }
1613                if (!overPluginElement) {
1614                    if (FrameView* view = m_frame->view())
1615                        view->setCursor(selectCursor(mev, scrollbar));
1616                }
1617            }
1618        }
1619    }
1620
1621    m_lastMouseMoveEventSubframe = newSubframe;
1622
1623    if (swallowEvent)
1624        return true;
1625
1626    swallowEvent = dispatchMouseEvent(eventNames().mousemoveEvent, mev.targetNode(), false, 0, mouseEvent, true);
1627#if ENABLE(DRAG_SUPPORT)
1628    if (!swallowEvent)
1629        swallowEvent = handleMouseDraggedEvent(mev);
1630#endif // ENABLE(DRAG_SUPPORT)
1631
1632    return swallowEvent;
1633}
1634
1635void EventHandler::invalidateClick()
1636{
1637    m_clickCount = 0;
1638    m_clickNode = 0;
1639}
1640
1641bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
1642{
1643    RefPtr<FrameView> protector(m_frame->view());
1644
1645    UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
1646
1647#if ENABLE(PAN_SCROLLING)
1648    if (mouseEvent.button() == MiddleButton)
1649        m_panScrollButtonPressed = false;
1650    if (m_springLoadedPanScrollInProgress)
1651        stopAutoscrollTimer();
1652#endif
1653
1654    m_mousePressed = false;
1655    m_currentMousePosition = mouseEvent.pos();
1656
1657#if ENABLE(SVG)
1658    if (m_svgPan) {
1659        m_svgPan = false;
1660        static_cast<SVGDocument*>(m_frame->document())->updatePan(m_currentMousePosition);
1661        return true;
1662    }
1663#endif
1664
1665    if (m_frameSetBeingResized)
1666        return dispatchMouseEvent(eventNames().mouseupEvent, m_frameSetBeingResized.get(), true, m_clickCount, mouseEvent, false);
1667
1668    if (m_lastScrollbarUnderMouse) {
1669        invalidateClick();
1670        return m_lastScrollbarUnderMouse->mouseUp();
1671    }
1672
1673#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
1674    // Add IgnoreClipping because fixed position elements are moved only on the
1675    // UI thread.  Nodes in fixed position elements are clipped out by the view
1676    // without IgnoreClipping.
1677    HitTestRequest request(HitTestRequest::MouseUp | HitTestRequest::IgnoreClipping);
1678#else
1679    HitTestRequest request(HitTestRequest::MouseUp);
1680#endif
1681    MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
1682    Frame* subframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev);
1683    if (m_eventHandlerWillResetCapturingMouseEventsNode)
1684        m_capturingMouseEventsNode = 0;
1685    if (subframe && passMouseReleaseEventToSubframe(mev, subframe))
1686        return true;
1687
1688    bool swallowMouseUpEvent = dispatchMouseEvent(eventNames().mouseupEvent, mev.targetNode(), true, m_clickCount, mouseEvent, false);
1689
1690    bool swallowClickEvent = m_clickCount > 0 && mouseEvent.button() != RightButton && mev.targetNode() == m_clickNode && dispatchMouseEvent(eventNames().clickEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
1691
1692    if (m_resizeLayer) {
1693        m_resizeLayer->setInResizeMode(false);
1694        m_resizeLayer = 0;
1695    }
1696
1697    bool swallowMouseReleaseEvent = false;
1698    if (!swallowMouseUpEvent)
1699        swallowMouseReleaseEvent = handleMouseReleaseEvent(mev);
1700
1701    invalidateClick();
1702
1703    return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
1704}
1705
1706#if ENABLE(DRAG_SUPPORT)
1707bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard)
1708{
1709    FrameView* view = m_frame->view();
1710
1711    // FIXME: We might want to dispatch a dragleave even if the view is gone.
1712    if (!view)
1713        return false;
1714
1715    view->resetDeferredRepaintDelay();
1716    IntPoint contentsPos = view->windowToContents(event.pos());
1717
1718    RefPtr<MouseEvent> me = MouseEvent::create(eventType,
1719        true, true, m_frame->document()->defaultView(),
1720        0, event.globalX(), event.globalY(), contentsPos.x(), contentsPos.y(),
1721        event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
1722        0, 0, clipboard);
1723
1724    ExceptionCode ec;
1725    dragTarget->dispatchEvent(me.get(), ec);
1726    return me->defaultPrevented();
1727}
1728
1729bool EventHandler::canHandleDragAndDropForTarget(DragAndDropHandleType type, Node* target, const PlatformMouseEvent& event, Clipboard* clipboard, bool* accepted)
1730{
1731    bool canHandle = false;
1732    bool wasAccepted = false;
1733
1734    if (target->hasTagName(frameTag) || target->hasTagName(iframeTag)) {
1735        Frame* frame = static_cast<HTMLFrameElementBase*>(target)->contentFrame();
1736        if (frame) {
1737            switch (type) {
1738            case UpdateDragAndDrop:
1739                wasAccepted = frame->eventHandler()->updateDragAndDrop(event, clipboard);
1740                break;
1741            case CancelDragAndDrop:
1742                frame->eventHandler()->cancelDragAndDrop(event, clipboard);
1743                break;
1744            case PerformDragAndDrop:
1745                wasAccepted = frame->eventHandler()->performDragAndDrop(event, clipboard);
1746                break;
1747            }
1748        }
1749    } else
1750        canHandle = true;
1751
1752    if (accepted)
1753        *accepted = wasAccepted;
1754
1755    return canHandle;
1756}
1757
1758bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
1759{
1760    bool accept = false;
1761
1762    if (!m_frame->view())
1763        return false;
1764
1765    HitTestRequest request(HitTestRequest::ReadOnly);
1766    MouseEventWithHitTestResults mev = prepareMouseEvent(request, event);
1767
1768    // Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
1769    Node* newTarget = mev.targetNode();
1770    if (newTarget && newTarget->isTextNode())
1771        newTarget = newTarget->parentNode();
1772    if (newTarget)
1773        newTarget = newTarget->shadowAncestorNode();
1774
1775    if (m_dragTarget != newTarget) {
1776        // FIXME: this ordering was explicitly chosen to match WinIE. However,
1777        // it is sometimes incorrect when dragging within subframes, as seen with
1778        // LayoutTests/fast/events/drag-in-frames.html.
1779        //
1780        // 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>.
1781        if (newTarget && canHandleDragAndDropForTarget(UpdateDragAndDrop, newTarget, event, clipboard, &accept)) {
1782            // 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.
1783            if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) {
1784                // for now we don't care if event handler cancels default behavior, since there is none
1785                dispatchDragSrcEvent(eventNames().dragEvent, event);
1786            }
1787            accept = dispatchDragEvent(eventNames().dragenterEvent, newTarget, event, clipboard);
1788        }
1789
1790        if (m_dragTarget && canHandleDragAndDropForTarget(UpdateDragAndDrop, m_dragTarget.get(), event, clipboard, &accept))
1791            dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard);
1792
1793        if (newTarget) {
1794            // We do not explicitly call dispatchDragEvent here because it could ultimately result in the appearance that
1795            // two dragover events fired. So, we mark that we should only fire a dragover event on the next call to this function.
1796            m_shouldOnlyFireDragOverEvent = true;
1797        }
1798    } else {
1799        if (newTarget && canHandleDragAndDropForTarget(UpdateDragAndDrop, newTarget, event, clipboard, &accept)) {
1800            // Note, when dealing with sub-frames, we may need to fire only a dragover event as a drag event may have been fired earlier.
1801            if (!m_shouldOnlyFireDragOverEvent && dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) {
1802                // for now we don't care if event handler cancels default behavior, since there is none
1803                dispatchDragSrcEvent(eventNames().dragEvent, event);
1804            }
1805            accept = dispatchDragEvent(eventNames().dragoverEvent, newTarget, event, clipboard);
1806            m_shouldOnlyFireDragOverEvent = false;
1807        }
1808    }
1809    m_dragTarget = newTarget;
1810
1811    return accept;
1812}
1813
1814void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
1815{
1816    if (m_dragTarget && canHandleDragAndDropForTarget(CancelDragAndDrop, m_dragTarget.get(), event, clipboard)) {
1817        if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML)
1818            dispatchDragSrcEvent(eventNames().dragEvent, event);
1819        dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard);
1820    }
1821    clearDragState();
1822}
1823
1824bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
1825{
1826    bool accept = false;
1827    if (m_dragTarget && canHandleDragAndDropForTarget(PerformDragAndDrop, m_dragTarget.get(), event, clipboard, &accept))
1828        dispatchDragEvent(eventNames().dropEvent, m_dragTarget.get(), event, clipboard);
1829    clearDragState();
1830    return accept;
1831}
1832
1833void EventHandler::clearDragState()
1834{
1835    m_dragTarget = 0;
1836    m_capturingMouseEventsNode = 0;
1837    m_shouldOnlyFireDragOverEvent = false;
1838#if PLATFORM(MAC)
1839    m_sendingEventToSubview = false;
1840#endif
1841}
1842#endif // ENABLE(DRAG_SUPPORT)
1843
1844#if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS)
1845void EventHandler::setCapturingTouchEventsNode(PassRefPtr<Node> n)
1846{
1847    m_capturingTouchEventsNode = n;
1848}
1849#endif
1850
1851void EventHandler::setCapturingMouseEventsNode(PassRefPtr<Node> n)
1852{
1853    m_capturingMouseEventsNode = n;
1854    m_eventHandlerWillResetCapturingMouseEventsNode = false;
1855}
1856
1857MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestRequest& request, const PlatformMouseEvent& mev)
1858{
1859    ASSERT(m_frame);
1860    ASSERT(m_frame->document());
1861
1862    return m_frame->document()->prepareMouseEvent(request, documentPointForWindowPoint(m_frame, mev.pos()), mev);
1863}
1864
1865#if ENABLE(SVG)
1866static inline SVGElementInstance* instanceAssociatedWithShadowTreeElement(Node* referenceNode)
1867{
1868    if (!referenceNode || !referenceNode->isSVGElement())
1869        return 0;
1870
1871    Node* shadowTreeElement = referenceNode->shadowTreeRootNode();
1872    if (!shadowTreeElement)
1873        return 0;
1874
1875    Element* shadowTreeParentElement = shadowTreeElement->shadowHost();
1876    if (!shadowTreeParentElement)
1877        return 0;
1878
1879    ASSERT(shadowTreeParentElement->hasTagName(useTag));
1880    return static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode);
1881}
1882#endif
1883
1884void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMouseEvent& mouseEvent, bool fireMouseOverOut)
1885{
1886    Node* result = targetNode;
1887
1888    // If we're capturing, we always go right to that node.
1889    if (m_capturingMouseEventsNode)
1890        result = m_capturingMouseEventsNode.get();
1891    else {
1892        // If the target node is a text node, dispatch on the parent node - rdar://4196646
1893        if (result && result->isTextNode())
1894            result = result->parentNode();
1895    }
1896    m_nodeUnderMouse = result;
1897#if ENABLE(SVG)
1898    m_instanceUnderMouse = instanceAssociatedWithShadowTreeElement(result);
1899
1900    // <use> shadow tree elements may have been recloned, update node under mouse in any case
1901    if (m_lastInstanceUnderMouse) {
1902        SVGElement* lastCorrespondingElement = m_lastInstanceUnderMouse->correspondingElement();
1903        SVGElement* lastCorrespondingUseElement = m_lastInstanceUnderMouse->correspondingUseElement();
1904
1905        if (lastCorrespondingElement && lastCorrespondingUseElement) {
1906            HashSet<SVGElementInstance*> instances = lastCorrespondingElement->instancesForElement();
1907
1908            // Locate the recloned shadow tree element for our corresponding instance
1909            HashSet<SVGElementInstance*>::iterator end = instances.end();
1910            for (HashSet<SVGElementInstance*>::iterator it = instances.begin(); it != end; ++it) {
1911                SVGElementInstance* instance = (*it);
1912                ASSERT(instance->correspondingElement() == lastCorrespondingElement);
1913
1914                if (instance == m_lastInstanceUnderMouse)
1915                    continue;
1916
1917                if (instance->correspondingUseElement() != lastCorrespondingUseElement)
1918                    continue;
1919
1920                SVGElement* shadowTreeElement = instance->shadowTreeElement();
1921                if (!shadowTreeElement->inDocument() || m_lastNodeUnderMouse == shadowTreeElement)
1922                    continue;
1923
1924                m_lastNodeUnderMouse = shadowTreeElement;
1925                m_lastInstanceUnderMouse = instance;
1926                break;
1927            }
1928        }
1929    }
1930#endif
1931
1932    // Fire mouseout/mouseover if the mouse has shifted to a different node.
1933    if (fireMouseOverOut) {
1934        RenderLayer* layerForLastNode = layerForNode(m_lastNodeUnderMouse.get());
1935        RenderLayer* layerForNodeUnderMouse = layerForNode(m_nodeUnderMouse.get());
1936        Page* page = m_frame->page();
1937
1938        if (m_lastNodeUnderMouse && (!m_nodeUnderMouse || m_nodeUnderMouse->document() != m_frame->document())) {
1939            // The mouse has moved between frames.
1940            if (Frame* frame = m_lastNodeUnderMouse->document()->frame()) {
1941                if (FrameView* frameView = frame->view())
1942                    frameView->scrollAnimator()->mouseExitedContentArea();
1943            }
1944        } else if (page && (layerForLastNode && (!layerForNodeUnderMouse || layerForNodeUnderMouse != layerForLastNode))) {
1945            // The mouse has moved between layers.
1946            if (page->containsScrollableArea(layerForLastNode))
1947                layerForLastNode->scrollAnimator()->mouseExitedContentArea();
1948        }
1949
1950        if (m_nodeUnderMouse && (!m_lastNodeUnderMouse || m_lastNodeUnderMouse->document() != m_frame->document())) {
1951            // The mouse has moved between frames.
1952            if (Frame* frame = m_nodeUnderMouse->document()->frame()) {
1953                if (FrameView* frameView = frame->view())
1954                    frameView->scrollAnimator()->mouseEnteredContentArea();
1955            }
1956        } else if (page && (layerForNodeUnderMouse && (!layerForLastNode || layerForNodeUnderMouse != layerForLastNode))) {
1957            // The mouse has moved between layers.
1958            if (page->containsScrollableArea(layerForNodeUnderMouse))
1959                layerForNodeUnderMouse->scrollAnimator()->mouseEnteredContentArea();
1960        }
1961
1962        if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame->document()) {
1963            m_lastNodeUnderMouse = 0;
1964            m_lastScrollbarUnderMouse = 0;
1965#if ENABLE(SVG)
1966            m_lastInstanceUnderMouse = 0;
1967#endif
1968        }
1969
1970        if (m_lastNodeUnderMouse != m_nodeUnderMouse) {
1971            // send mouseout event to the old node
1972            if (m_lastNodeUnderMouse)
1973                m_lastNodeUnderMouse->dispatchMouseEvent(mouseEvent, eventNames().mouseoutEvent, 0, m_nodeUnderMouse.get());
1974            // send mouseover event to the new node
1975            if (m_nodeUnderMouse)
1976                m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventNames().mouseoverEvent, 0, m_lastNodeUnderMouse.get());
1977        }
1978        m_lastNodeUnderMouse = m_nodeUnderMouse;
1979#if ENABLE(SVG)
1980        m_lastInstanceUnderMouse = instanceAssociatedWithShadowTreeElement(m_nodeUnderMouse.get());
1981#endif
1982    }
1983}
1984
1985bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool /*cancelable*/, int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder)
1986{
1987    if (FrameView* view = m_frame->view())
1988        view->resetDeferredRepaintDelay();
1989
1990    updateMouseEventTargetNode(targetNode, mouseEvent, setUnder);
1991
1992    bool swallowEvent = false;
1993
1994    if (m_nodeUnderMouse)
1995        swallowEvent = m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventType, clickCount);
1996
1997    if (!swallowEvent && eventType == eventNames().mousedownEvent) {
1998
1999        // If clicking on a frame scrollbar, do not mess up with content focus.
2000        if (FrameView* view = m_frame->view()) {
2001            if (view->scrollbarAtPoint(mouseEvent.pos()))
2002                return false;
2003        }
2004
2005        // The layout needs to be up to date to determine if an element is focusable.
2006        m_frame->document()->updateLayoutIgnorePendingStylesheets();
2007
2008        // Blur current focus node when a link/button is clicked; this
2009        // is expected by some sites that rely on onChange handlers running
2010        // from form fields before the button click is processed.
2011        Node* node = m_nodeUnderMouse.get();
2012
2013        // Walk up the DOM tree to search for a node to focus.
2014        while (node) {
2015            if (node->isMouseFocusable()) {
2016                // To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus a
2017                // node on mouse down if it's selected and inside a focused node. It will be
2018                // focused if the user does a mouseup over it, however, because the mouseup
2019                // will set a selection inside it, which will call setFocuseNodeIfNeeded.
2020                ExceptionCode ec = 0;
2021                Node* n = node->isShadowRoot() ? node->shadowHost() : node;
2022                if (m_frame->selection()->isRange()
2023                    && m_frame->selection()->toNormalizedRange()->compareNode(n, ec) == Range::NODE_INSIDE
2024                    && n->isDescendantOf(m_frame->document()->focusedNode()))
2025                    return false;
2026
2027                break;
2028            }
2029            node = node->parentOrHostNode();
2030        }
2031
2032        // If focus shift is blocked, we eat the event.  Note we should never clear swallowEvent
2033        // if the page already set it (e.g., by canceling default behavior).
2034        if (Page* page = m_frame->page()) {
2035            if (node && node->isMouseFocusable()) {
2036                if (!page->focusController()->setFocusedNode(node, m_frame))
2037                    swallowEvent = true;
2038            } else if (!node || !node->focused()) {
2039                if (!page->focusController()->setFocusedNode(0, m_frame))
2040                    swallowEvent = true;
2041            }
2042        }
2043    }
2044
2045    return swallowEvent;
2046}
2047
2048#if !PLATFORM(GTK) && !(PLATFORM(CHROMIUM) && (OS(LINUX) || OS(FREEBSD)))
2049bool EventHandler::shouldTurnVerticalTicksIntoHorizontal(const HitTestResult&) const
2050{
2051    return false;
2052}
2053#endif
2054
2055bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
2056{
2057    Document* doc = m_frame->document();
2058
2059    RenderObject* docRenderer = doc->renderer();
2060    if (!docRenderer)
2061        return false;
2062
2063    RefPtr<FrameView> protector(m_frame->view());
2064
2065    FrameView* view = m_frame->view();
2066    if (!view)
2067        return false;
2068    setFrameWasScrolledByUser();
2069    IntPoint vPoint = view->windowToContents(e.pos());
2070
2071    Node* node;
2072    bool isOverWidget;
2073
2074    HitTestRequest request(HitTestRequest::ReadOnly);
2075    HitTestResult result(vPoint);
2076    doc->renderView()->layer()->hitTest(request, result);
2077
2078    if (m_useLatchedWheelEventNode) {
2079        if (!m_latchedWheelEventNode) {
2080            m_latchedWheelEventNode = result.innerNode();
2081            m_widgetIsLatched = result.isOverWidget();
2082        }
2083
2084        node = m_latchedWheelEventNode.get();
2085        isOverWidget = m_widgetIsLatched;
2086    } else {
2087        if (m_latchedWheelEventNode)
2088            m_latchedWheelEventNode = 0;
2089        if (m_previousWheelScrolledNode)
2090            m_previousWheelScrolledNode = 0;
2091
2092        node = result.innerNode();
2093        isOverWidget = result.isOverWidget();
2094    }
2095
2096    if (shouldTurnVerticalTicksIntoHorizontal(result))
2097        e.turnVerticalTicksIntoHorizontal();
2098
2099    if (node) {
2100        // Figure out which view to send the event to.
2101        RenderObject* target = node->renderer();
2102
2103        if (isOverWidget && target && target->isWidget()) {
2104            Widget* widget = toRenderWidget(target)->widget();
2105            if (widget && passWheelEventToWidget(e, widget)) {
2106                e.accept();
2107                return true;
2108            }
2109        }
2110
2111        node = node->shadowAncestorNode();
2112        node->dispatchWheelEvent(e);
2113        if (e.isAccepted())
2114            return true;
2115    }
2116
2117    if (e.isAccepted())
2118        return true;
2119
2120    view = m_frame->view();
2121    if (!view)
2122        return false;
2123
2124    view->wheelEvent(e);
2125    return e.isAccepted();
2126}
2127
2128void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEvent)
2129{
2130    if (!startNode || !wheelEvent)
2131        return;
2132
2133    Node* stopNode = m_previousWheelScrolledNode.get();
2134
2135    // Break up into two scrolls if we need to.  Diagonal movement on
2136    // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
2137    if (scrollNode(wheelEvent->rawDeltaX(), wheelEvent->granularity(), ScrollLeft, ScrollRight, startNode, &stopNode))
2138        wheelEvent->setDefaultHandled();
2139
2140    if (scrollNode(wheelEvent->rawDeltaY(), wheelEvent->granularity(), ScrollUp, ScrollDown, startNode, &stopNode))
2141        wheelEvent->setDefaultHandled();
2142
2143    if (!m_useLatchedWheelEventNode)
2144        m_previousWheelScrolledNode = stopNode;
2145}
2146
2147#if ENABLE(GESTURE_EVENTS)
2148bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
2149{
2150    // FIXME: This should hit test and go to the correct subframe rather than
2151    // always sending gestures to the main frame only. We should also ensure
2152    // that if a frame gets a gesture begin gesture, it gets the corresponding
2153    // end gesture as well.
2154
2155    FrameView* view = m_frame->view();
2156    if (!view)
2157        return false;
2158
2159    view->handleGestureEvent(gestureEvent);
2160    return true;
2161}
2162#endif
2163
2164#if ENABLE(CONTEXT_MENUS)
2165bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event)
2166{
2167    Document* doc = m_frame->document();
2168    FrameView* v = m_frame->view();
2169    if (!v)
2170        return false;
2171
2172    bool swallowEvent;
2173    IntPoint viewportPos = v->windowToContents(event.pos());
2174    HitTestRequest request(HitTestRequest::Active);
2175    MouseEventWithHitTestResults mev = doc->prepareMouseEvent(request, viewportPos, event);
2176
2177    if (m_frame->editor()->behavior().shouldSelectOnContextualMenuClick()
2178        && !m_frame->selection()->contains(viewportPos)
2179        // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse.
2180        // If the selection is non-editable, we do word selection to make it easier to use the contextual menu items
2181        // available for text selections.  But only if we're above text.
2182        && (m_frame->selection()->isContentEditable() || (mev.targetNode() && mev.targetNode()->isTextNode()))) {
2183        m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection
2184        selectClosestWordOrLinkFromMouseEvent(mev);
2185    }
2186
2187    swallowEvent = dispatchMouseEvent(eventNames().contextmenuEvent, mev.targetNode(), true, 0, event, false);
2188
2189    return swallowEvent;
2190}
2191
2192bool EventHandler::sendContextMenuEventForKey()
2193{
2194    FrameView* view = m_frame->view();
2195    if (!view)
2196        return false;
2197
2198    Document* doc = m_frame->document();
2199    if (!doc)
2200        return false;
2201
2202    static const int kContextMenuMargin = 1;
2203
2204#if OS(WINDOWS) && !OS(WINCE)
2205    int rightAligned = ::GetSystemMetrics(SM_MENUDROPALIGNMENT);
2206#else
2207    int rightAligned = 0;
2208#endif
2209    IntPoint location;
2210
2211    Node* focusedNode = doc->focusedNode();
2212    SelectionController* selectionController = m_frame->selection();
2213    Position start = selectionController->selection().start();
2214
2215    if (start.deprecatedNode() && (selectionController->rootEditableElement() || selectionController->isRange())) {
2216        RefPtr<Range> selection = selectionController->toNormalizedRange();
2217        IntRect firstRect = m_frame->editor()->firstRectForRange(selection.get());
2218
2219        int x = rightAligned ? firstRect.maxX() : firstRect.x();
2220        location = IntPoint(x, firstRect.maxY());
2221    } else if (focusedNode) {
2222        RenderBoxModelObject* box = focusedNode->renderBoxModelObject();
2223        if (!box)
2224            return false;
2225        IntRect clippedRect = box->absoluteClippedOverflowRect();
2226        location = IntPoint(clippedRect.x(), clippedRect.maxY() - 1);
2227    } else {
2228        location = IntPoint(
2229            rightAligned ? view->contentsWidth() - kContextMenuMargin : kContextMenuMargin,
2230            kContextMenuMargin);
2231    }
2232
2233    m_frame->view()->setCursor(pointerCursor());
2234
2235    IntPoint position = view->contentsToWindow(location);
2236    IntPoint globalPosition = view->contentsToScreen(IntRect(location, IntSize())).location();
2237
2238    Node* targetNode = doc->focusedNode();
2239    if (!targetNode)
2240        targetNode = doc;
2241
2242    // Use the focused node as the target for hover and active.
2243    HitTestResult result(position);
2244    result.setInnerNode(targetNode);
2245    HitTestRequest request(HitTestRequest::Active);
2246    doc->renderView()->layer()->updateHoverActiveState(request, result);
2247    doc->updateStyleIfNeeded();
2248
2249    // The contextmenu event is a mouse event even when invoked using the keyboard.
2250    // This is required for web compatibility.
2251
2252#if OS(WINDOWS)
2253    MouseEventType eventType = MouseEventReleased;
2254#else
2255    MouseEventType eventType = MouseEventPressed;
2256#endif
2257
2258    PlatformMouseEvent mouseEvent(position, globalPosition, RightButton, eventType, 1, false, false, false, false, WTF::currentTime());
2259
2260    return dispatchMouseEvent(eventNames().contextmenuEvent, targetNode, true, 0, mouseEvent, false);
2261}
2262
2263#endif // ENABLE(CONTEXT_MENUS)
2264
2265void EventHandler::scheduleHoverStateUpdate()
2266{
2267    if (!m_hoverTimer.isActive())
2268        m_hoverTimer.startOneShot(0);
2269}
2270
2271void EventHandler::dispatchFakeMouseMoveEventSoon()
2272{
2273    if (m_mousePressed)
2274        return;
2275
2276    if (!m_fakeMouseMoveEventTimer.isActive())
2277        m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveInterval);
2278}
2279
2280void EventHandler::dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad& quad)
2281{
2282    FrameView* view = m_frame->view();
2283    if (!view)
2284        return;
2285
2286    if (m_mousePressed || !quad.containsPoint(view->windowToContents(m_currentMousePosition)))
2287        return;
2288
2289    if (!m_fakeMouseMoveEventTimer.isActive())
2290        m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveInterval);
2291}
2292
2293void EventHandler::cancelFakeMouseMoveEvent()
2294{
2295    m_fakeMouseMoveEventTimer.stop();
2296}
2297
2298void EventHandler::fakeMouseMoveEventTimerFired(Timer<EventHandler>* timer)
2299{
2300    ASSERT_UNUSED(timer, timer == &m_fakeMouseMoveEventTimer);
2301    ASSERT(!m_mousePressed);
2302
2303    FrameView* view = m_frame->view();
2304    if (!view)
2305        return;
2306
2307    bool shiftKey;
2308    bool ctrlKey;
2309    bool altKey;
2310    bool metaKey;
2311    PlatformKeyboardEvent::getCurrentModifierState(shiftKey, ctrlKey, altKey, metaKey);
2312    IntPoint globalPoint = view->contentsToScreen(IntRect(view->windowToContents(m_currentMousePosition), IntSize())).location();
2313    PlatformMouseEvent fakeMouseMoveEvent(m_currentMousePosition, globalPoint, NoButton, MouseEventMoved, 0, shiftKey, ctrlKey, altKey, metaKey, currentTime());
2314    mouseMoved(fakeMouseMoveEvent);
2315}
2316
2317// Whether or not a mouse down can begin the creation of a selection.  Fires the selectStart event.
2318bool EventHandler::canMouseDownStartSelect(Node* node)
2319{
2320    if (!node || !node->renderer())
2321        return true;
2322
2323    // Some controls and images can't start a select on a mouse down.
2324    if (!node->canStartSelection())
2325        return false;
2326
2327    return node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true));
2328}
2329
2330#if ENABLE(DRAG_SUPPORT)
2331bool EventHandler::canMouseDragExtendSelect(Node* node)
2332{
2333    if (!node || !node->renderer())
2334        return true;
2335
2336    return node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true));
2337}
2338#endif // ENABLE(DRAG_SUPPORT)
2339
2340void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet)
2341{
2342    m_frameSetBeingResized = frameSet;
2343}
2344
2345void EventHandler::resizeLayerDestroyed()
2346{
2347    ASSERT(m_resizeLayer);
2348    m_resizeLayer = 0;
2349}
2350
2351void EventHandler::hoverTimerFired(Timer<EventHandler>*)
2352{
2353    m_hoverTimer.stop();
2354
2355    ASSERT(m_frame);
2356    ASSERT(m_frame->document());
2357
2358    if (RenderView* renderer = m_frame->contentRenderer()) {
2359        if (FrameView* view = m_frame->view()) {
2360            HitTestRequest request(HitTestRequest::MouseMove);
2361            HitTestResult result(view->windowToContents(m_currentMousePosition));
2362            renderer->layer()->hitTest(request, result);
2363            m_frame->document()->updateStyleIfNeeded();
2364        }
2365    }
2366}
2367
2368static Node* eventTargetNodeForDocument(Document* doc)
2369{
2370    if (!doc)
2371        return 0;
2372    Node* node = doc->focusedNode();
2373#if defined(ANDROID_PLUGINS)
2374    if (!node && doc->frame() && doc->frame()->view())
2375        node = android::WebViewCore::getWebViewCore(doc->frame()->view())
2376                                     ->cursorNodeIsPlugin();
2377#else
2378    if (!node && doc->isPluginDocument()) {
2379        PluginDocument* pluginDocument = static_cast<PluginDocument*>(doc);
2380        node =  pluginDocument->pluginNode();
2381    }
2382#endif
2383    if (!node && doc->isHTMLDocument())
2384        node = doc->body();
2385    if (!node)
2386        node = doc->documentElement();
2387    return node;
2388}
2389
2390bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& evt)
2391{
2392    // FIXME: Ignoring the state of Shift key is what neither IE nor Firefox do.
2393    // IE matches lower and upper case access keys regardless of Shift key state - but if both upper and
2394    // lower case variants are present in a document, the correct element is matched based on Shift key state.
2395    // Firefox only matches an access key if Shift is not pressed, and does that case-insensitively.
2396    ASSERT(!(accessKeyModifiers() & PlatformKeyboardEvent::ShiftKey));
2397    if ((evt.modifiers() & ~PlatformKeyboardEvent::ShiftKey) != accessKeyModifiers())
2398        return false;
2399    String key = evt.unmodifiedText();
2400    Element* elem = m_frame->document()->getElementByAccessKey(key.lower());
2401    if (!elem)
2402        return false;
2403    elem->accessKeyAction(false);
2404    return true;
2405}
2406
2407#if !PLATFORM(MAC)
2408bool EventHandler::needsKeyboardEventDisambiguationQuirks() const
2409{
2410    return false;
2411}
2412#endif
2413
2414bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent)
2415{
2416    RefPtr<FrameView> protector(m_frame->view());
2417
2418#if ENABLE(PAN_SCROLLING)
2419    if (Page* page = m_frame->page()) {
2420        if (page->mainFrame()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress) {
2421            // If a key is pressed while the autoscroll/panScroll is in progress then we want to stop
2422            if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyDown || initialKeyEvent.type() == PlatformKeyboardEvent::RawKeyDown)
2423                stopAutoscrollTimer();
2424
2425            // If we were in autoscroll/panscroll mode, we swallow the key event
2426            return true;
2427        }
2428    }
2429#endif
2430
2431    // Check for cases where we are too early for events -- possible unmatched key up
2432    // from pressing return in the location bar.
2433    RefPtr<Node> node = eventTargetNodeForDocument(m_frame->document());
2434    if (!node)
2435        return false;
2436
2437    UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
2438    UserTypingGestureIndicator typingGestureIndicator(m_frame);
2439
2440    if (FrameView* view = m_frame->view())
2441        view->resetDeferredRepaintDelay();
2442
2443    // FIXME: what is this doing here, in keyboard event handler?
2444    m_frame->loader()->resetMultipleFormSubmissionProtection();
2445
2446    // In IE, access keys are special, they are handled after default keydown processing, but cannot be canceled - this is hard to match.
2447    // On Mac OS X, we process them before dispatching keydown, as the default keydown handler implements Emacs key bindings, which may conflict
2448    // with access keys. Then we dispatch keydown, but suppress its default handling.
2449    // On Windows, WebKit explicitly calls handleAccessKey() instead of dispatching a keypress event for WM_SYSCHAR messages.
2450    // Other platforms currently match either Mac or Windows behavior, depending on whether they send combined KeyDown events.
2451    bool matchedAnAccessKey = false;
2452    if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyDown)
2453        matchedAnAccessKey = handleAccessKey(initialKeyEvent);
2454
2455    // FIXME: it would be fair to let an input method handle KeyUp events before DOM dispatch.
2456    if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyUp || initialKeyEvent.type() == PlatformKeyboardEvent::Char)
2457        return !node->dispatchKeyEvent(initialKeyEvent);
2458
2459    bool backwardCompatibilityMode = needsKeyboardEventDisambiguationQuirks();
2460
2461    ExceptionCode ec;
2462    PlatformKeyboardEvent keyDownEvent = initialKeyEvent;
2463    if (keyDownEvent.type() != PlatformKeyboardEvent::RawKeyDown)
2464        keyDownEvent.disambiguateKeyDownEvent(PlatformKeyboardEvent::RawKeyDown, backwardCompatibilityMode);
2465    RefPtr<KeyboardEvent> keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->defaultView());
2466    if (matchedAnAccessKey)
2467        keydown->setDefaultPrevented(true);
2468    keydown->setTarget(node);
2469
2470    if (initialKeyEvent.type() == PlatformKeyboardEvent::RawKeyDown) {
2471        node->dispatchEvent(keydown, ec);
2472        // If frame changed as a result of keydown dispatch, then return true to avoid sending a subsequent keypress message to the new frame.
2473        bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController()->focusedOrMainFrame();
2474        return keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame;
2475    }
2476
2477    // Run input method in advance of DOM event handling.  This may result in the IM
2478    // modifying the page prior the keydown event, but this behaviour is necessary
2479    // in order to match IE:
2480    // 1. preventing default handling of keydown and keypress events has no effect on IM input;
2481    // 2. if an input method handles the event, its keyCode is set to 229 in keydown event.
2482    m_frame->editor()->handleInputMethodKeydown(keydown.get());
2483
2484    bool handledByInputMethod = keydown->defaultHandled();
2485
2486    if (handledByInputMethod) {
2487        keyDownEvent.setWindowsVirtualKeyCode(CompositionEventKeyCode);
2488        keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->defaultView());
2489        keydown->setTarget(node);
2490        keydown->setDefaultHandled();
2491    }
2492
2493    node->dispatchEvent(keydown, ec);
2494    // If frame changed as a result of keydown dispatch, then return early to avoid sending a subsequent keypress message to the new frame.
2495    bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController()->focusedOrMainFrame();
2496    bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame;
2497    if (handledByInputMethod || (keydownResult && !backwardCompatibilityMode))
2498        return keydownResult;
2499
2500    // Focus may have changed during keydown handling, so refetch node.
2501    // But if we are dispatching a fake backward compatibility keypress, then we pretend that the keypress happened on the original node.
2502    if (!keydownResult) {
2503        node = eventTargetNodeForDocument(m_frame->document());
2504        if (!node)
2505            return false;
2506    }
2507
2508    PlatformKeyboardEvent keyPressEvent = initialKeyEvent;
2509    keyPressEvent.disambiguateKeyDownEvent(PlatformKeyboardEvent::Char, backwardCompatibilityMode);
2510    if (keyPressEvent.text().isEmpty())
2511        return keydownResult;
2512    RefPtr<KeyboardEvent> keypress = KeyboardEvent::create(keyPressEvent, m_frame->document()->defaultView());
2513    keypress->setTarget(node);
2514    if (keydownResult)
2515        keypress->setDefaultPrevented(true);
2516#if PLATFORM(MAC)
2517    keypress->keypressCommands() = keydown->keypressCommands();
2518#endif
2519    node->dispatchEvent(keypress, ec);
2520
2521    return keydownResult || keypress->defaultPrevented() || keypress->defaultHandled();
2522}
2523
2524void EventHandler::handleKeyboardSelectionMovement(KeyboardEvent* event)
2525{
2526    if (!event)
2527        return;
2528
2529    const String& key = event->keyIdentifier();
2530    bool isShifted = event->getModifierState("Shift");
2531    bool isOptioned = event->getModifierState("Alt");
2532    bool isCommanded = event->getModifierState("Meta");
2533
2534    if (key == "Up") {
2535        m_frame->selection()->modify((isShifted) ? SelectionController::AlterationExtend : SelectionController::AlterationMove, DirectionBackward, (isCommanded) ? DocumentBoundary : LineGranularity, true);
2536        event->setDefaultHandled();
2537    } else if (key == "Down") {
2538        m_frame->selection()->modify((isShifted) ? SelectionController::AlterationExtend : SelectionController::AlterationMove, DirectionForward, (isCommanded) ? DocumentBoundary : LineGranularity, true);
2539        event->setDefaultHandled();
2540    } else if (key == "Left") {
2541        m_frame->selection()->modify((isShifted) ? SelectionController::AlterationExtend : SelectionController::AlterationMove, DirectionLeft, (isCommanded) ? LineBoundary : (isOptioned) ? WordGranularity : CharacterGranularity, true);
2542        event->setDefaultHandled();
2543    } else if (key == "Right") {
2544        m_frame->selection()->modify((isShifted) ? SelectionController::AlterationExtend : SelectionController::AlterationMove, DirectionRight, (isCommanded) ? LineBoundary : (isOptioned) ? WordGranularity : CharacterGranularity, true);
2545        event->setDefaultHandled();
2546    }
2547}
2548
2549void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event)
2550{
2551    if (event->type() == eventNames().keydownEvent) {
2552        m_frame->editor()->handleKeyboardEvent(event);
2553        if (event->defaultHandled())
2554            return;
2555        if (event->keyIdentifier() == "U+0009")
2556            defaultTabEventHandler(event);
2557        else {
2558            FocusDirection direction = focusDirectionForKey(event->keyIdentifier());
2559            if (direction != FocusDirectionNone)
2560                defaultArrowEventHandler(direction, event);
2561        }
2562
2563        // provides KB navigation and selection for enhanced accessibility users
2564        if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled())
2565            handleKeyboardSelectionMovement(event);
2566    }
2567    if (event->type() == eventNames().keypressEvent) {
2568        m_frame->editor()->handleKeyboardEvent(event);
2569        if (event->defaultHandled())
2570            return;
2571        if (event->charCode() == ' ')
2572            defaultSpaceEventHandler(event);
2573    }
2574}
2575
2576FocusDirection EventHandler::focusDirectionForKey(const AtomicString& keyIdentifier) const
2577{
2578    DEFINE_STATIC_LOCAL(AtomicString, Down, ("Down"));
2579    DEFINE_STATIC_LOCAL(AtomicString, Up, ("Up"));
2580    DEFINE_STATIC_LOCAL(AtomicString, Left, ("Left"));
2581    DEFINE_STATIC_LOCAL(AtomicString, Right, ("Right"));
2582
2583    FocusDirection retVal = FocusDirectionNone;
2584
2585    if (keyIdentifier == Down)
2586        retVal = FocusDirectionDown;
2587    else if (keyIdentifier == Up)
2588        retVal = FocusDirectionUp;
2589    else if (keyIdentifier == Left)
2590        retVal = FocusDirectionLeft;
2591    else if (keyIdentifier == Right)
2592        retVal = FocusDirectionRight;
2593
2594    return retVal;
2595}
2596
2597#if ENABLE(DRAG_SUPPORT)
2598bool EventHandler::dragHysteresisExceeded(const FloatPoint& floatDragViewportLocation) const
2599{
2600    IntPoint dragViewportLocation((int)floatDragViewportLocation.x(), (int)floatDragViewportLocation.y());
2601    return dragHysteresisExceeded(dragViewportLocation);
2602}
2603
2604bool EventHandler::dragHysteresisExceeded(const IntPoint& dragViewportLocation) const
2605{
2606    FrameView* view = m_frame->view();
2607    if (!view)
2608        return false;
2609    IntPoint dragLocation = view->windowToContents(dragViewportLocation);
2610    IntSize delta = dragLocation - m_mouseDownPos;
2611
2612    int threshold = GeneralDragHysteresis;
2613    if (dragState().m_dragSrcIsImage)
2614        threshold = ImageDragHysteresis;
2615    else if (dragState().m_dragSrcIsLink)
2616        threshold = LinkDragHysteresis;
2617    else if (dragState().m_dragSrcInSelection)
2618        threshold = TextDragHysteresis;
2619
2620    return abs(delta.width()) >= threshold || abs(delta.height()) >= threshold;
2621}
2622
2623void EventHandler::freeClipboard()
2624{
2625    if (dragState().m_dragClipboard)
2626        dragState().m_dragClipboard->setAccessPolicy(ClipboardNumb);
2627}
2628
2629bool EventHandler::shouldDragAutoNode(Node* node, const IntPoint& point) const
2630{
2631    if (!node || !m_frame->view())
2632        return false;
2633    Page* page = m_frame->page();
2634    return page && page->dragController()->mayStartDragAtEventLocation(m_frame, point, node);
2635}
2636
2637void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, DragOperation operation)
2638{
2639    if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) {
2640        dragState().m_dragClipboard->setDestinationOperation(operation);
2641        // for now we don't care if event handler cancels default behavior, since there is none
2642        dispatchDragSrcEvent(eventNames().dragendEvent, event);
2643    }
2644    freeClipboard();
2645    dragState().m_dragSrc = 0;
2646    // In case the drag was ended due to an escape key press we need to ensure
2647    // that consecutive mousemove events don't reinitiate the drag and drop.
2648    m_mouseDownMayStartDrag = false;
2649}
2650
2651// returns if we should continue "default processing", i.e., whether eventhandler canceled
2652bool EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent& event)
2653{
2654    return !dispatchDragEvent(eventType, dragState().m_dragSrc.get(), event, dragState().m_dragClipboard.get());
2655}
2656
2657bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event)
2658{
2659    if (event.event().button() != LeftButton || event.event().eventType() != MouseEventMoved) {
2660        // If we allowed the other side of the bridge to handle a drag
2661        // last time, then m_mousePressed might still be set. So we
2662        // clear it now to make sure the next move after a drag
2663        // doesn't look like a drag.
2664        m_mousePressed = false;
2665        return false;
2666    }
2667
2668    if (eventLoopHandleMouseDragged(event))
2669        return true;
2670
2671    // Careful that the drag starting logic stays in sync with eventMayStartDrag()
2672
2673    if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
2674        allowDHTMLDrag(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA);
2675        if (!dragState().m_dragSrcMayBeDHTML && !dragState().m_dragSrcMayBeUA)
2676            m_mouseDownMayStartDrag = false; // no element is draggable
2677    }
2678
2679    if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
2680        // try to find an element that wants to be dragged
2681        HitTestRequest request(HitTestRequest::ReadOnly);
2682        HitTestResult result(m_mouseDownPos);
2683        m_frame->contentRenderer()->layer()->hitTest(request, result);
2684        Node* node = result.innerNode();
2685        if (node && node->renderer())
2686            dragState().m_dragSrc = node->renderer()->draggableNode(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA,
2687                                                                    m_mouseDownPos.x(), m_mouseDownPos.y(), dragState().m_dragSrcIsDHTML);
2688        else
2689            dragState().m_dragSrc = 0;
2690
2691        if (!dragState().m_dragSrc)
2692            m_mouseDownMayStartDrag = false; // no element is draggable
2693        else {
2694            // remember some facts about this source, while we have a HitTestResult handy
2695            node = result.URLElement();
2696            dragState().m_dragSrcIsLink = node && node->isLink();
2697
2698            node = result.innerNonSharedNode();
2699            dragState().m_dragSrcIsImage = node && node->renderer() && node->renderer()->isImage();
2700
2701            dragState().m_dragSrcInSelection = m_frame->selection()->contains(m_mouseDownPos);
2702        }
2703    }
2704
2705    // For drags starting in the selection, the user must wait between the mousedown and mousedrag,
2706    // or else we bail on the dragging stuff and allow selection to occur
2707    if (m_mouseDownMayStartDrag && !dragState().m_dragSrcIsImage && dragState().m_dragSrcInSelection && event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay) {
2708        m_mouseDownMayStartDrag = false;
2709        dragState().m_dragSrc = 0;
2710        // ...but if this was the first click in the window, we don't even want to start selection
2711        if (eventActivatedView(event.event()))
2712            m_mouseDownMayStartSelect = false;
2713    }
2714
2715    if (!m_mouseDownMayStartDrag)
2716        return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll;
2717
2718    // We are starting a text/image/url drag, so the cursor should be an arrow
2719    if (FrameView* view = m_frame->view()) {
2720        // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and drop (default to pointer).
2721        view->setCursor(pointerCursor());
2722    }
2723
2724    if (!dragHysteresisExceeded(event.event().pos()))
2725        return true;
2726
2727    // Once we're past the hysteresis point, we don't want to treat this gesture as a click
2728    invalidateClick();
2729
2730    DragOperation srcOp = DragOperationNone;
2731
2732    freeClipboard(); // would only happen if we missed a dragEnd.  Do it anyway, just
2733                     // to make sure it gets numbified
2734    dragState().m_dragClipboard = createDraggingClipboard();
2735
2736    if (dragState().m_dragSrcMayBeDHTML) {
2737        // Check to see if the is a DOM based drag, if it is get the DOM specified drag
2738        // image and offset
2739        if (dragState().m_dragSrcIsDHTML) {
2740            if (RenderObject* renderer = dragState().m_dragSrc->renderer()) {
2741                // FIXME: This doesn't work correctly with transforms.
2742                FloatPoint absPos = renderer->localToAbsolute();
2743                IntSize delta = m_mouseDownPos - roundedIntPoint(absPos);
2744                dragState().m_dragClipboard->setDragImageElement(dragState().m_dragSrc.get(), toPoint(delta));
2745            } else {
2746                // The renderer has disappeared, this can happen if the onStartDrag handler has hidden
2747                // the element in some way.  In this case we just kill the drag.
2748                m_mouseDownMayStartDrag = false;
2749                goto cleanupDrag;
2750            }
2751        }
2752
2753        m_mouseDownMayStartDrag = dispatchDragSrcEvent(eventNames().dragstartEvent, m_mouseDown)
2754            && !m_frame->selection()->isInPasswordField();
2755
2756        // Invalidate clipboard here against anymore pasteboard writing for security.  The drag
2757        // image can still be changed as we drag, but not the pasteboard data.
2758        dragState().m_dragClipboard->setAccessPolicy(ClipboardImageWritable);
2759
2760        if (m_mouseDownMayStartDrag) {
2761            // gather values from DHTML element, if it set any
2762            srcOp = dragState().m_dragClipboard->sourceOperation();
2763
2764            // Yuck, a draggedImage:moveTo: message can be fired as a result of kicking off the
2765            // drag with dragImage!  Because of that dumb reentrancy, we may think we've not
2766            // started the drag when that happens.  So we have to assume it's started before we
2767            // kick it off.
2768            dragState().m_dragClipboard->setDragHasStarted();
2769        }
2770    }
2771
2772    if (m_mouseDownMayStartDrag) {
2773        Page* page = m_frame->page();
2774        DragController* dragController = page ? page->dragController() : 0;
2775        bool startedDrag = dragController && dragController->startDrag(m_frame, dragState().m_dragClipboard.get(), srcOp, event.event(), m_mouseDownPos, dragState().m_dragSrcIsDHTML);
2776        if (!startedDrag && dragState().m_dragSrcMayBeDHTML) {
2777            // Drag was canned at the last minute - we owe m_dragSrc a DRAGEND event
2778            dispatchDragSrcEvent(eventNames().dragendEvent, event.event());
2779            m_mouseDownMayStartDrag = false;
2780        }
2781    }
2782
2783cleanupDrag:
2784    if (!m_mouseDownMayStartDrag) {
2785        // something failed to start the drag, cleanup
2786        freeClipboard();
2787        dragState().m_dragSrc = 0;
2788    }
2789
2790    // No more default handling (like selection), whether we're past the hysteresis bounds or not
2791    return true;
2792}
2793#endif // ENABLE(DRAG_SUPPORT)
2794
2795bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEvent, TextEventInputType inputType)
2796{
2797    // Platforms should differentiate real commands like selectAll from text input in disguise (like insertNewline),
2798    // and avoid dispatching text input events from keydown default handlers.
2799    ASSERT(!underlyingEvent || !underlyingEvent->isKeyboardEvent() || static_cast<KeyboardEvent*>(underlyingEvent)->type() == eventNames().keypressEvent);
2800
2801    if (!m_frame)
2802        return false;
2803
2804    EventTarget* target;
2805    if (underlyingEvent)
2806        target = underlyingEvent->target();
2807    else
2808        target = eventTargetNodeForDocument(m_frame->document());
2809    if (!target)
2810        return false;
2811
2812    if (FrameView* view = m_frame->view())
2813        view->resetDeferredRepaintDelay();
2814
2815    RefPtr<TextEvent> event = TextEvent::create(m_frame->domWindow(), text, inputType);
2816    event->setUnderlyingEvent(underlyingEvent);
2817
2818    ExceptionCode ec;
2819    target->dispatchEvent(event, ec);
2820    return event->defaultHandled();
2821}
2822
2823bool EventHandler::isKeyboardOptionTab(KeyboardEvent* event)
2824{
2825    return event
2826        && (event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent)
2827        && event->altKey()
2828        && event->keyIdentifier() == "U+0009";
2829}
2830
2831static bool eventInvertsTabsToLinksClientCallResult(KeyboardEvent* event)
2832{
2833#if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(HAIKU) || PLATFORM(EFL)
2834    return EventHandler::isKeyboardOptionTab(event);
2835#else
2836    return false;
2837#endif
2838}
2839
2840bool EventHandler::tabsToLinks(KeyboardEvent* event) const
2841{
2842    // FIXME: This function needs a better name. It can be called for keypresses other than Tab when spatial navigation is enabled.
2843
2844    Page* page = m_frame->page();
2845    if (!page)
2846        return false;
2847
2848    bool tabsToLinksClientCallResult = page->chrome()->client()->keyboardUIMode() & KeyboardAccessTabsToLinks;
2849    return eventInvertsTabsToLinksClientCallResult(event) ? !tabsToLinksClientCallResult : tabsToLinksClientCallResult;
2850}
2851
2852void EventHandler::defaultTextInputEventHandler(TextEvent* event)
2853{
2854    if (m_frame->editor()->handleTextEvent(event))
2855        event->setDefaultHandled();
2856}
2857
2858#if PLATFORM(QT) || PLATFORM(MAC) || PLATFORM(ANDROID)
2859
2860// These two platforms handle the space event in the platform-specific WebKit code.
2861// Eventually it would be good to eliminate that and use the code here instead, but
2862// the Qt version is inside an ifdef and the Mac version has some extra behavior
2863// so we can't unify everything yet.
2864void EventHandler::defaultSpaceEventHandler(KeyboardEvent*)
2865{
2866}
2867
2868#else
2869
2870void EventHandler::defaultSpaceEventHandler(KeyboardEvent* event)
2871{
2872    ScrollLogicalDirection direction = event->shiftKey() ? ScrollBlockDirectionBackward : ScrollBlockDirectionForward;
2873    if (logicalScrollOverflow(direction, ScrollByPage)) {
2874        event->setDefaultHandled();
2875        return;
2876    }
2877
2878    FrameView* view = m_frame->view();
2879    if (!view)
2880        return;
2881
2882    if (view->logicalScroll(direction, ScrollByPage))
2883        event->setDefaultHandled();
2884}
2885
2886#endif
2887
2888void EventHandler::defaultArrowEventHandler(FocusDirection focusDirection, KeyboardEvent* event)
2889{
2890    if (event->ctrlKey() || event->metaKey() || event->altGraphKey() || event->shiftKey())
2891        return;
2892
2893    Page* page = m_frame->page();
2894    if (!page)
2895        return;
2896
2897    if (!isSpatialNavigationEnabled(m_frame))
2898        return;
2899
2900    // Arrows and other possible directional navigation keys can be used in design
2901    // mode editing.
2902    if (m_frame->document()->inDesignMode())
2903        return;
2904
2905    if (page->focusController()->advanceFocus(focusDirection, event))
2906        event->setDefaultHandled();
2907}
2908
2909void EventHandler::defaultTabEventHandler(KeyboardEvent* event)
2910{
2911    // We should only advance focus on tabs if no special modifier keys are held down.
2912    if (event->ctrlKey() || event->metaKey() || event->altGraphKey())
2913        return;
2914
2915    Page* page = m_frame->page();
2916    if (!page)
2917        return;
2918    if (!page->tabKeyCyclesThroughElements())
2919        return;
2920
2921    FocusDirection focusDirection = event->shiftKey() ? FocusDirectionBackward : FocusDirectionForward;
2922
2923    // Tabs can be used in design mode editing.
2924    if (m_frame->document()->inDesignMode())
2925        return;
2926
2927    if (page->focusController()->advanceFocus(focusDirection, event))
2928        event->setDefaultHandled();
2929}
2930
2931void EventHandler::capsLockStateMayHaveChanged()
2932{
2933    Document* d = m_frame->document();
2934    if (Node* node = d->focusedNode()) {
2935        if (RenderObject* r = node->renderer()) {
2936            if (r->isTextField())
2937                toRenderTextControlSingleLine(r)->capsLockStateMayHaveChanged();
2938        }
2939    }
2940}
2941
2942void EventHandler::sendResizeEvent()
2943{
2944    m_frame->document()->enqueueWindowEvent(Event::create(eventNames().resizeEvent, false, false));
2945}
2946
2947void EventHandler::sendScrollEvent()
2948{
2949    setFrameWasScrolledByUser();
2950    if (m_frame->view() && m_frame->document())
2951        m_frame->document()->eventQueue()->enqueueScrollEvent(m_frame->document(), EventQueue::ScrollEventDocumentTarget);
2952}
2953
2954void EventHandler::setFrameWasScrolledByUser()
2955{
2956    FrameView* v = m_frame->view();
2957    if (v)
2958        v->setWasScrolledByUser(true);
2959}
2960
2961bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults& mev, Scrollbar* scrollbar)
2962{
2963    if (!scrollbar || !scrollbar->enabled())
2964        return false;
2965    setFrameWasScrolledByUser();
2966    return scrollbar->mouseDown(mev.event());
2967}
2968
2969// If scrollbar (under mouse) is different from last, send a mouse exited. Set
2970// last to scrollbar if setLast is true; else set last to 0.
2971void EventHandler::updateLastScrollbarUnderMouse(Scrollbar* scrollbar, bool setLast)
2972{
2973    if (m_lastScrollbarUnderMouse != scrollbar) {
2974        // Send mouse exited to the old scrollbar.
2975        if (m_lastScrollbarUnderMouse)
2976            m_lastScrollbarUnderMouse->mouseExited();
2977        m_lastScrollbarUnderMouse = setLast ? scrollbar : 0;
2978    }
2979}
2980
2981#if ENABLE(TOUCH_EVENTS)
2982
2983static const AtomicString& eventNameForTouchPointState(PlatformTouchPoint::State state)
2984{
2985    switch (state) {
2986    case PlatformTouchPoint::TouchReleased:
2987        return eventNames().touchendEvent;
2988    case PlatformTouchPoint::TouchCancelled:
2989        return eventNames().touchcancelEvent;
2990    case PlatformTouchPoint::TouchPressed:
2991        return eventNames().touchstartEvent;
2992    case PlatformTouchPoint::TouchMoved:
2993        return eventNames().touchmoveEvent;
2994    default:
2995        ASSERT_NOT_REACHED();
2996        return emptyAtom;
2997    }
2998}
2999
3000bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
3001{
3002    // First build up the lists to use for the 'touches', 'targetTouches' and 'changedTouches' attributes
3003    // in the JS event. See http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/
3004    // for an overview of how these lists fit together.
3005
3006    // Holds the complete set of touches on the screen and will be used as the 'touches' list in the JS event.
3007    RefPtr<TouchList> touches = TouchList::create();
3008
3009    // A different view on the 'touches' list above, filtered and grouped by event target. Used for the
3010    // 'targetTouches' list in the JS event.
3011    typedef HashMap<EventTarget*, RefPtr<TouchList> > TargetTouchesMap;
3012    TargetTouchesMap touchesByTarget;
3013
3014    // Array of touches per state, used to assemble the 'changedTouches' list in the JS event.
3015    typedef HashSet<RefPtr<EventTarget> > EventTargetSet;
3016    struct {
3017        // The touches corresponding to the particular change state this struct instance represents.
3018        RefPtr<TouchList> m_touches;
3019        // Set of targets involved in m_touches.
3020        EventTargetSet m_targets;
3021    } changedTouches[PlatformTouchPoint::TouchStateEnd];
3022
3023    const Vector<PlatformTouchPoint>& points = event.touchPoints();
3024
3025    UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
3026
3027    for (unsigned i = 0; i < points.size(); ++i) {
3028        const PlatformTouchPoint& point = points[i];
3029        PlatformTouchPoint::State pointState = point.state();
3030        IntPoint pagePoint = documentPointForWindowPoint(m_frame, point.pos());
3031
3032        HitTestRequest::HitTestRequestType hitType = HitTestRequest::Active | HitTestRequest::ReadOnly;
3033        // The HitTestRequest types used for mouse events map quite adequately
3034        // to touch events. Note that in addition to meaning that the hit test
3035        // should affect the active state of the current node if necessary,
3036        // HitTestRequest::Active signifies that the hit test is taking place
3037        // with the mouse (or finger in this case) being pressed.
3038        switch (pointState) {
3039        case PlatformTouchPoint::TouchPressed:
3040            hitType = HitTestRequest::Active;
3041            break;
3042        case PlatformTouchPoint::TouchMoved:
3043            hitType = HitTestRequest::Active | HitTestRequest::MouseMove | HitTestRequest::ReadOnly;
3044            break;
3045        case PlatformTouchPoint::TouchReleased:
3046        case PlatformTouchPoint::TouchCancelled:
3047            hitType = HitTestRequest::MouseUp;
3048            break;
3049        default:
3050            break;
3051        }
3052#if PLATFORM(ANDROID)
3053        Node* node = 0;
3054        if (m_capturingTouchEventsNode)
3055            node = m_capturingTouchEventsNode.get();
3056        else {
3057            HitTestResult result = hitTestResultAtPoint(pagePoint, /*allowShadowContent*/ false, false, DontHitTestScrollbars, hitType);
3058            node = result.innerNode();
3059            ASSERT(node);
3060
3061            // Touch events should not go to text nodes
3062            if (node->isTextNode())
3063                node = node->parentNode();
3064        }
3065#else
3066        HitTestResult result = hitTestResultAtPoint(pagePoint, /*allowShadowContent*/ false, false, DontHitTestScrollbars, hitType);
3067        Node* node = result.innerNode();
3068        ASSERT(node);
3069
3070        // Touch events should not go to text nodes
3071        if (node->isTextNode())
3072            node = node->parentNode();
3073#endif
3074
3075
3076        Document* doc = node->document();
3077        if (!doc)
3078            continue;
3079        if (!doc->hasListenerType(Document::TOUCH_LISTENER))
3080            continue;
3081
3082        if (m_frame != doc->frame()) {
3083            // pagePoint should always be relative to the target elements containing frame.
3084            pagePoint = documentPointForWindowPoint(doc->frame(), point.pos());
3085        }
3086
3087        int adjustedPageX = lroundf(pagePoint.x() / m_frame->pageZoomFactor());
3088        int adjustedPageY = lroundf(pagePoint.y() / m_frame->pageZoomFactor());
3089
3090        // Increment the platform touch id by 1 to avoid storing a key of 0 in the hashmap.
3091        unsigned touchPointTargetKey = point.id() + 1;
3092        RefPtr<EventTarget> touchTarget;
3093#if PLATFORM(ANDROID)
3094        if (m_capturingTouchEventsNode)
3095            touchTarget = node;
3096        else {
3097#endif
3098        if (pointState == PlatformTouchPoint::TouchPressed) {
3099            m_originatingTouchPointTargets.set(touchPointTargetKey, node);
3100            touchTarget = node;
3101        } else if (pointState == PlatformTouchPoint::TouchReleased || pointState == PlatformTouchPoint::TouchCancelled) {
3102            // The target should be the original target for this touch, so get it from the hashmap. As it's a release or cancel
3103            // we also remove it from the map.
3104            touchTarget = m_originatingTouchPointTargets.take(touchPointTargetKey);
3105        } else
3106            touchTarget = m_originatingTouchPointTargets.get(touchPointTargetKey);
3107#if PLATFORM(ANDROID)
3108        }
3109#endif
3110        if (!touchTarget.get())
3111            continue;
3112
3113        RefPtr<Touch> touch = Touch::create(doc->frame(), touchTarget.get(), point.id(),
3114                                            point.screenPos().x(), point.screenPos().y(),
3115                                            adjustedPageX, adjustedPageY);
3116
3117        // Ensure this target's touch list exists, even if it ends up empty, so it can always be passed to TouchEvent::Create below.
3118        TargetTouchesMap::iterator targetTouchesIterator = touchesByTarget.find(touchTarget.get());
3119        if (targetTouchesIterator == touchesByTarget.end())
3120            targetTouchesIterator = touchesByTarget.set(touchTarget.get(), TouchList::create()).first;
3121
3122        // touches and targetTouches should only contain information about touches still on the screen, so if this point is
3123        // released or cancelled it will only appear in the changedTouches list.
3124        if (pointState != PlatformTouchPoint::TouchReleased && pointState != PlatformTouchPoint::TouchCancelled) {
3125            touches->append(touch);
3126            targetTouchesIterator->second->append(touch);
3127        }
3128
3129        // Now build up the correct list for changedTouches.
3130        // Note that  any touches that are in the TouchStationary state (e.g. if
3131        // the user had several points touched but did not move them all) should
3132        // never be in the changedTouches list so we do not handle them explicitly here.
3133        // See https://bugs.webkit.org/show_bug.cgi?id=37609 for further discussion
3134        // about the TouchStationary state.
3135        if (pointState != PlatformTouchPoint::TouchStationary) {
3136            ASSERT(pointState < PlatformTouchPoint::TouchStateEnd);
3137            if (!changedTouches[pointState].m_touches)
3138                changedTouches[pointState].m_touches = TouchList::create();
3139            changedTouches[pointState].m_touches->append(touch);
3140            changedTouches[pointState].m_targets.add(touchTarget);
3141        }
3142    }
3143    m_touchPressed = touches->length() > 0;
3144
3145    // Now iterate the changedTouches list and m_targets within it, sending events to the tagets as required.
3146    bool defaultPrevented = false;
3147    RefPtr<TouchList> emptyList = TouchList::create();
3148    for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; ++state) {
3149        if (!changedTouches[state].m_touches)
3150            continue;
3151
3152        // When sending a touch cancel event, use empty touches and targetTouches lists.
3153        bool isTouchCancelEvent = (state == PlatformTouchPoint::TouchCancelled);
3154        RefPtr<TouchList>& effectiveTouches(isTouchCancelEvent ? emptyList : touches);
3155#if PLATFORM(ANDROID)
3156        AtomicString stateName(eventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state)));
3157        if (event.type() == TouchLongPress)
3158            stateName = eventNames().touchlongpressEvent;
3159        else if (event.type() == TouchDoubleTap)
3160            stateName = eventNames().touchdoubletapEvent;
3161#else
3162        const AtomicString& stateName(eventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state)));
3163#endif
3164        const EventTargetSet& targetsForState = changedTouches[state].m_targets;
3165
3166        for (EventTargetSet::const_iterator it = targetsForState.begin(); it != targetsForState.end(); ++it) {
3167            EventTarget* touchEventTarget = it->get();
3168            RefPtr<TouchList> targetTouches(isTouchCancelEvent ? emptyList : touchesByTarget.get(touchEventTarget));
3169            ASSERT(targetTouches);
3170
3171            RefPtr<TouchEvent> touchEvent =
3172                TouchEvent::create(effectiveTouches.get(), targetTouches.get(), changedTouches[state].m_touches.get(),
3173                                   stateName, touchEventTarget->toNode()->document()->defaultView(),
3174                                   0, 0, 0, 0, event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey());
3175            ExceptionCode ec = 0;
3176            touchEventTarget->dispatchEvent(touchEvent.get(), ec);
3177            defaultPrevented |= touchEvent->defaultPrevented();
3178        }
3179    }
3180
3181#if ENABLE(GESTURE_RECOGNIZER)
3182    if (m_gestureRecognizer)
3183        m_gestureRecognizer->processTouchEventForGesture(event, this, defaultPrevented);
3184#endif
3185
3186    return defaultPrevented;
3187}
3188#endif
3189
3190}
3191