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