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