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