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