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