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