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