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