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