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