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