LayoutTests:
[WebKit-https.git] / WebCore / page / EventHandler.cpp
1 /*
2  * Copyright (C) 2006, 2007 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 "CachedImage.h"
31 #include "ChromeClient.h"
32 #include "Cursor.h"
33 #include "Document.h"
34 #include "DragController.h"
35 #include "Editor.h"
36 #include "EventNames.h"
37 #include "FloatPoint.h"
38 #include "FocusController.h"
39 #include "Frame.h"
40 #include "FrameLoader.h"
41 #include "FrameTree.h"
42 #include "FrameView.h"
43 #include "HitTestRequest.h"
44 #include "HitTestResult.h"
45 #include "HTMLFrameSetElement.h"
46 #include "HTMLFrameElementBase.h"
47 #include "HTMLInputElement.h"
48 #include "HTMLNames.h"
49 #include "Image.h"
50 #include "KeyboardEvent.h"
51 #include "MouseEvent.h"
52 #include "MouseEventWithHitTestResults.h"
53 #include "Page.h"
54 #include "PlatformKeyboardEvent.h"
55 #include "PlatformScrollBar.h"
56 #include "PlatformWheelEvent.h"
57 #include "RenderWidget.h"
58 #include "SelectionController.h"
59 #include "Settings.h"
60 #include "TextEvent.h"
61
62 #if ENABLE(SVG)
63 #include "SVGCursorElement.h"
64 #include "SVGLength.h"
65 #include "SVGNames.h"
66 #endif
67
68 namespace WebCore {
69
70 using namespace EventNames;
71 using namespace HTMLNames;
72
73 // The link drag hysteresis is much larger than the others because there
74 // needs to be enough space to cancel the link press without starting a link drag,
75 // and because dragging links is rare.
76 const int LinkDragHysteresis = 40;
77 const int ImageDragHysteresis = 5;
78 const int TextDragHysteresis = 3;
79 const int GeneralDragHysteresis = 3;
80 const double TextDragDelay = 0.15;
81
82 #if ENABLE(SVG)
83 using namespace SVGNames;
84 #endif
85
86 const double autoscrollInterval = 0.1;
87
88 static Frame* subframeForTargetNode(Node* node);
89
90 EventHandler::EventHandler(Frame* frame)
91     : m_frame(frame)
92     , m_mousePressed(false)
93     , m_mouseDownMayStartSelect(false)
94     , m_mouseDownMayStartDrag(false)
95     , m_mouseDownWasSingleClickInSelection(false)
96     , m_beganSelectingText(false)
97     , m_hoverTimer(this, &EventHandler::hoverTimerFired)
98     , m_autoscrollTimer(this, &EventHandler::autoscrollTimerFired)
99     , m_autoscrollRenderer(0)
100     , m_mouseDownMayStartAutoscroll(false)
101     , m_mouseDownWasInSubframe(false)
102     , m_resizeLayer(0)
103     , m_capturingMouseEventsNode(0)
104     , m_clickCount(0)
105     , m_mouseDownTimestamp(0)
106 #if PLATFORM(MAC)
107     , m_mouseDownView(nil)
108     , m_sendingEventToSubview(false)
109     , m_activationEventNumber(0)
110 #endif
111 {
112 }
113
114 EventHandler::~EventHandler()
115 {
116 }
117     
118 EventHandler::EventHandlerDragState& EventHandler::dragState()
119 {
120     static EventHandlerDragState state;
121     return state;
122 }
123     
124 void EventHandler::clear()
125 {
126     m_hoverTimer.stop();
127     m_resizeLayer = 0;
128     m_nodeUnderMouse = 0;
129     m_lastNodeUnderMouse = 0;
130     m_lastMouseMoveEventSubframe = 0;
131     m_lastScrollbarUnderMouse = 0;
132     m_clickCount = 0;
133     m_clickNode = 0;
134     m_frameSetBeingResized = 0;
135     m_dragTarget = 0;
136     m_currentMousePosition = IntPoint();
137     m_mousePressNode = 0;
138     m_mousePressed = false;
139 }
140
141 void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result)
142 {
143     Node* innerNode = result.targetNode();
144     Selection newSelection;
145
146     if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect && innerNode->renderer()->shouldSelect()) {
147         VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
148         if (pos.isNotNull()) {
149             newSelection = Selection(pos);
150             newSelection.expandUsingGranularity(WordGranularity);
151         }
152     
153         if (newSelection.isRange()) {
154             m_frame->setSelectionGranularity(WordGranularity);
155             m_beganSelectingText = true;
156         }
157         
158         if (m_frame->shouldChangeSelection(newSelection))
159             m_frame->selectionController()->setSelection(newSelection);
160     }
161 }
162
163 bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event)
164 {
165     if (event.event().button() != LeftButton)
166         return false;
167
168     if (m_frame->selectionController()->isRange())
169         // A double-click when range is already selected
170         // should not change the selection.  So, do not call
171         // selectClosestWordFromMouseEvent, but do set
172         // m_beganSelectingText to prevent handleMouseReleaseEvent
173         // from setting caret selection.
174         m_beganSelectingText = true;
175     else
176         selectClosestWordFromMouseEvent(event);
177
178     return true;
179 }
180
181 bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event)
182 {
183     if (event.event().button() != LeftButton)
184         return false;
185     
186     Node* innerNode = event.targetNode();
187     if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect
188           && innerNode->renderer()->shouldSelect()))
189         return false;
190
191     Selection newSelection;
192     VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint()));
193     if (pos.isNotNull()) {
194         newSelection = Selection(pos);
195         newSelection.expandUsingGranularity(ParagraphGranularity);
196     }
197     if (newSelection.isRange()) {
198         m_frame->setSelectionGranularity(ParagraphGranularity);
199         m_beganSelectingText = true;
200     }
201     
202     if (m_frame->shouldChangeSelection(newSelection))
203         m_frame->selectionController()->setSelection(newSelection);
204
205     return true;
206 }
207
208 bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
209 {
210     if (event.event().button() != LeftButton)
211         return false;
212     
213     Node* innerNode = event.targetNode();
214     if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect
215           && innerNode->renderer()->shouldSelect()))
216         return false;
217
218     // Extend the selection if the Shift key is down, unless the click is in a link.
219     bool extendSelection = event.event().shiftKey() && !event.isOverLink();
220
221     // Don't restart the selection when the mouse is pressed on an
222     // existing selection so we can allow for text dragging.
223     IntPoint vPoint = m_frame->view()->windowToContents(event.event().pos());
224     if (!extendSelection && m_frame->selectionController()->contains(vPoint)) {
225         m_mouseDownWasSingleClickInSelection = true;
226         return false;
227     }
228
229     VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(event.localPoint()));
230     if (visiblePos.isNull())
231         visiblePos = VisiblePosition(innerNode, innerNode->caretMinOffset(), DOWNSTREAM);
232     Position pos = visiblePos.deepEquivalent();
233     
234     Selection newSelection = m_frame->selectionController()->selection();
235     if (extendSelection && newSelection.isCaretOrRange()) {
236         m_frame->selectionController()->clearModifyBias();
237         
238         // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection 
239         // was created right-to-left
240         Position start = newSelection.start();
241         Position end = newSelection.end();
242         short before = Range::compareBoundaryPoints(pos.node(), pos.offset(), start.node(), start.offset());
243         if (before <= 0)
244             newSelection = Selection(pos, end);
245         else
246             newSelection = Selection(start, pos);
247
248         if (m_frame->selectionGranularity() != CharacterGranularity)
249             newSelection.expandUsingGranularity(m_frame->selectionGranularity());
250         m_beganSelectingText = true;
251     } else {
252         newSelection = Selection(visiblePos);
253         m_frame->setSelectionGranularity(CharacterGranularity);
254     }
255     
256     if (m_frame->shouldChangeSelection(newSelection))
257         m_frame->selectionController()->setSelection(newSelection);
258
259     return true;
260 }
261
262 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event)
263 {
264     bool singleClick = event.event().clickCount() <= 1;
265
266     // If we got the event back, that must mean it wasn't prevented,
267     // so it's allowed to start a drag or selection.
268     m_mouseDownMayStartSelect = canMouseDownStartSelect(event.targetNode());
269     
270     // Careful that the drag starting logic stays in sync with eventMayStartDrag()
271     m_mouseDownMayStartDrag = singleClick;
272
273     m_mouseDownWasSingleClickInSelection = false;
274
275     if (passWidgetMouseDownEventToWidget(event))
276         return true;
277
278     // We don't do this at the start of mouse down handling,
279     // because we don't want to do it until we know we didn't hit a widget.
280     if (singleClick)
281         focusDocumentView();
282
283     Node* innerNode = event.targetNode();
284
285     m_mousePressNode = innerNode;
286     m_dragStartPos = event.event().pos();
287
288     bool swallowEvent = false;
289     if (event.event().button() == LeftButton || event.event().button() == MiddleButton) {
290         m_frame->selectionController()->setCaretBlinkingSuspended(true);
291         m_mousePressed = true;
292         m_beganSelectingText = false;
293
294         if (event.event().clickCount() == 2)
295             swallowEvent = handleMousePressEventDoubleClick(event);
296         else if (event.event().clickCount() >= 3)
297             swallowEvent = handleMousePressEventTripleClick(event);
298         else
299             swallowEvent = handleMousePressEventSingleClick(event);
300     }
301     
302    m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect || 
303         (m_mousePressNode && m_mousePressNode->renderer() && m_mousePressNode->renderer()->shouldAutoscroll());
304
305    return swallowEvent;
306 }
307
308 bool EventHandler::handleMouseMoveEvent(const MouseEventWithHitTestResults& event)
309 {
310     if (handleDrag(event))
311         return true;
312
313     // Mouse not pressed. Do nothing.
314     if (!m_mousePressed)
315         return false;
316
317     Node* innerNode = event.targetNode();
318
319     if (event.event().button() != LeftButton || !innerNode || !innerNode->renderer())
320         return false;
321
322 #if PLATFORM(MAC) // FIXME: Why does this assertion fire on other platforms?
323     ASSERT(m_mouseDownMayStartSelect || m_mouseDownMayStartAutoscroll);
324 #endif
325
326     m_mouseDownMayStartDrag = false;
327
328     if (m_mouseDownMayStartAutoscroll) {            
329         // If the selection is contained in a layer that can scroll, that layer should handle the autoscroll
330         // Otherwise, let the bridge handle it so the view can scroll itself.
331         RenderObject* renderer = innerNode->renderer();
332         while (renderer && !renderer->shouldAutoscroll())
333             renderer = renderer->parent();
334         if (renderer)
335             handleAutoscroll(renderer);
336     }
337     
338     if (!(m_mouseDownMayStartSelect && innerNode->renderer()->shouldSelect()))
339         return false;
340
341 #if ENABLE(SVG)
342     Selection curSelection = m_frame->selectionController()->selection();
343     if (!curSelection.isNone()
344         && curSelection.base().node()->renderer()
345         && curSelection.base().node()->renderer()->isSVGText()
346         && innerNode->renderer()->containingBlock() != curSelection.base().node()->renderer()->containingBlock())
347         return false;
348 #endif
349
350     // handle making selection
351     VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint()));
352
353     updateSelectionForMouseDragOverPosition(pos);
354
355     return true;
356 }
357     
358 bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const
359 {
360     // This is a pre-flight check of whether the event might lead to a drag being started.  Be careful
361     // that its logic needs to stay in sync with handleMouseMoveEvent() and the way we setMouseDownMayStartDrag
362     // in handleMousePressEvent
363     
364     if (!m_frame->renderer() || !m_frame->renderer()->layer()
365         || event.button() != LeftButton || event.clickCount() != 1)
366         return false;
367     
368     bool DHTMLFlag;
369     bool UAFlag;
370     allowDHTMLDrag(DHTMLFlag, UAFlag);
371     if (!DHTMLFlag && !UAFlag)
372         return false;
373     
374     HitTestRequest request(true, false);
375     HitTestResult result(event.pos());
376     m_frame->renderer()->layer()->hitTest(request, result);
377     bool srcIsDHTML;
378     return result.innerNode() && result.innerNode()->renderer()->draggableNode(DHTMLFlag, UAFlag, event.x(), event.y(), srcIsDHTML);
379 }
380
381 void EventHandler::updateSelectionForMouseDragOverPosition(const VisiblePosition& pos)
382 {
383     // Don't modify the selection if we're not on a node.
384     if (pos.isNull())
385         return;
386
387     // Restart the selection if this is the first mouse move. This work is usually
388     // done in handleMousePressEvent, but not if the mouse press was on an existing selection.
389     Selection newSelection = m_frame->selectionController()->selection();
390     m_frame->selectionController()->clearModifyBias();
391     
392     if (!m_beganSelectingText) {
393         m_beganSelectingText = true;
394         newSelection = Selection(pos);
395     }
396
397     newSelection.setExtent(pos);
398     if (m_frame->selectionGranularity() != CharacterGranularity)
399         newSelection.expandUsingGranularity(m_frame->selectionGranularity());
400
401     if (m_frame->shouldChangeSelection(newSelection))
402         m_frame->selectionController()->setSelection(newSelection);
403 }
404     
405 bool EventHandler::handleMouseUp(const MouseEventWithHitTestResults& event)
406 {
407     if (eventLoopHandleMouseUp(event))
408         return true;
409     
410     // If this was the first click in the window, we don't even want to clear the selection.
411     // This case occurs when the user clicks on a draggable element, since we have to process
412     // the mouse down and drag events to see if we might start a drag.  For other first clicks
413     // in a window, we just don't acceptFirstMouse, and the whole down-drag-up sequence gets
414     // ignored upstream of this layer.
415     return eventActivatedView(event.event());
416 }    
417
418 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
419 {
420     stopAutoscrollTimer();
421
422     if (handleMouseUp(event))
423         return true;
424
425     // Used to prevent mouseMoveEvent from initiating a drag before
426     // the mouse is pressed again.
427     m_frame->selectionController()->setCaretBlinkingSuspended(false);
428     m_mousePressed = false;
429     m_mouseDownMayStartDrag = false;
430     m_mouseDownMayStartSelect = false;
431     m_mouseDownMayStartAutoscroll = false;
432     m_mouseDownWasInSubframe = false;
433   
434     bool handled = false;
435
436     // Clear the selection if the mouse didn't move after the last mouse press.
437     // We do this so when clicking on the selection, the selection goes away.
438     // However, if we are editing, place the caret.
439     if (m_mouseDownWasSingleClickInSelection && !m_beganSelectingText
440             && m_dragStartPos == event.event().pos()
441             && m_frame->selectionController()->isRange()) {
442         Selection newSelection;
443         Node *node = event.targetNode();
444         if (node && node->isContentEditable() && node->renderer()) {
445             VisiblePosition pos = node->renderer()->positionForPoint(event.localPoint());
446             newSelection = Selection(pos);
447         }
448         if (m_frame->shouldChangeSelection(newSelection))
449             m_frame->selectionController()->setSelection(newSelection);
450
451         handled = true;
452     }
453
454     m_frame->notifyRendererOfSelectionChange(true);
455
456     m_frame->selectionController()->selectFrameElementInParentIfFullySelected();
457
458     return handled;
459 }
460
461 void EventHandler::handleAutoscroll(RenderObject* renderer)
462 {
463     if (m_autoscrollTimer.isActive())
464         return;
465     setAutoscrollRenderer(renderer);
466     startAutoscrollTimer();
467 }
468
469 void EventHandler::autoscrollTimerFired(Timer<EventHandler>*)
470 {
471     if (!m_mousePressed) {
472         stopAutoscrollTimer();
473         return;
474     }
475     if (RenderObject* r = autoscrollRenderer())
476         r->autoscroll();
477 }
478
479 RenderObject* EventHandler::autoscrollRenderer() const
480 {
481     return m_autoscrollRenderer;
482 }
483
484 void EventHandler::setAutoscrollRenderer(RenderObject* renderer)
485 {
486     m_autoscrollRenderer = renderer;
487 }
488
489 void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const
490 {
491     if (!m_frame || !m_frame->document()) {
492         flagDHTML = false;
493         flagUA = false;
494     }
495     
496     unsigned mask = m_frame->page()->dragController()->delegateDragSourceAction(m_frame->view()->contentsToWindow(m_mouseDownPos));
497     flagDHTML = (mask & DragSourceActionDHTML) != DragSourceActionNone;
498     flagUA = ((mask & DragSourceActionImage) || (mask & DragSourceActionLink) || (mask & DragSourceActionSelection));
499 }
500     
501 HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent)
502 {
503     HitTestResult result(point);
504     if (!m_frame->renderer())
505         return result;
506     m_frame->renderer()->layer()->hitTest(HitTestRequest(true, true), result);
507
508     IntPoint widgetPoint(point);
509     while (true) {
510         Node* n = result.innerNode();
511         if (!n || !n->renderer() || !n->renderer()->isWidget())
512             break;
513         Widget* widget = static_cast<RenderWidget*>(n->renderer())->widget();
514         if (!widget || !widget->isFrameView())
515             break;
516         Frame* frame = static_cast<HTMLFrameElementBase*>(n)->contentFrame();
517         if (!frame || !frame->renderer())
518             break;
519         int absX, absY;
520         n->renderer()->absolutePosition(absX, absY, true);
521         FrameView* view = static_cast<FrameView*>(widget);
522         widgetPoint.move(view->contentsX() - absX, view->contentsY() - absY);
523         HitTestResult widgetHitTestResult(widgetPoint);
524         frame->renderer()->layer()->hitTest(HitTestRequest(true, true), widgetHitTestResult);
525         result = widgetHitTestResult;
526     }
527
528     if (!allowShadowContent) {
529         Node* node = result.innerNode();
530         if (node)
531             node = node->shadowAncestorNode();
532         result.setInnerNode(node);
533         node = result.innerNonSharedNode();
534         if (node)
535             node = node->shadowAncestorNode();
536         result.setInnerNonSharedNode(node); 
537     }
538
539     return result;
540 }
541
542
543 void EventHandler::startAutoscrollTimer()
544 {
545     m_autoscrollTimer.startRepeating(autoscrollInterval);
546 }
547
548 void EventHandler::stopAutoscrollTimer(bool rendererIsBeingDestroyed)
549 {
550     if (m_mouseDownWasInSubframe) {
551         if (Frame* subframe = subframeForTargetNode(m_mousePressNode.get()))
552             subframe->eventHandler()->stopAutoscrollTimer(rendererIsBeingDestroyed);
553         return;
554     }
555
556     if (!rendererIsBeingDestroyed && autoscrollRenderer())
557         autoscrollRenderer()->stopAutoscroll();
558     setAutoscrollRenderer(0);
559     m_autoscrollTimer.stop();
560 }
561
562 Node* EventHandler::mousePressNode() const
563 {
564     return m_mousePressNode.get();
565 }
566
567 void EventHandler::setMousePressNode(PassRefPtr<Node> node)
568 {
569     m_mousePressNode = node;
570 }
571
572 bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity)
573 {
574     if (!m_frame->document())
575         return false;
576     
577     Node* node = m_frame->document()->focusedNode();
578     if (!node)
579         node = m_mousePressNode.get();
580     
581     if (node) {
582         RenderObject *r = node->renderer();
583         if (r && !r->isListBox())
584             return r->scroll(direction, granularity);
585     }
586
587     return false;
588 }
589
590 IntPoint EventHandler::currentMousePosition() const
591 {
592     return m_currentMousePosition;
593 }
594
595 static Frame* subframeForTargetNode(Node* node)
596 {
597     if (!node)
598         return 0;
599
600     RenderObject* renderer = node->renderer();
601     if (!renderer || !renderer->isWidget())
602         return 0;
603
604     Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
605     if (!widget || !widget->isFrameView())
606         return 0;
607
608     return static_cast<FrameView*>(widget)->frame();
609 }
610
611 static bool isSubmitImage(Node* node)
612 {
613     return node && node->hasTagName(inputTag)
614         && static_cast<HTMLInputElement*>(node)->inputType() == HTMLInputElement::IMAGE;
615 }
616
617 // Returns true if the node's editable block is not current focused for editing
618 static bool nodeIsNotBeingEdited(Node* node, Frame* frame)
619 {
620     return frame->selectionController()->rootEditableElement() != node->rootEditableElement();
621 }
622
623 static Cursor selectCursor(const MouseEventWithHitTestResults& event, Frame* frame, bool mousePressed, PlatformScrollbar* scrollbar)
624 {
625     // During selection, use an I-beam no matter what we're over.
626     if (mousePressed && frame->selectionController()->isCaretOrRange())
627         return iBeamCursor();
628
629     Node* node = event.targetNode();
630     RenderObject* renderer = node ? node->renderer() : 0;
631     RenderStyle* style = renderer ? renderer->style() : 0;
632
633     if (style && style->cursors()) {
634         const CursorList* cursors = style->cursors();
635         for (unsigned i = 0; i < cursors->size(); ++i) {
636             CachedImage* cimage = (*cursors)[i].cursorImage;
637             IntPoint hotSpot = (*cursors)[i].hotSpot;
638 #if ENABLE(SVG)
639             if (!cimage) {
640                 Element* e = node->document()->getElementById((*cursors)[i].cursorFragmentId);
641                 if (e && e->hasTagName(cursorTag)) {
642                     hotSpot.setX(int(static_cast<SVGCursorElement*>(e)->x().value()));
643                     hotSpot.setY(int(static_cast<SVGCursorElement*>(e)->y().value()));
644                     cimage = static_cast<SVGCursorElement*>(e)->cachedImage();
645                 }
646             }
647 #endif
648             if (!cimage)
649                 continue;
650             if (cimage->image()->isNull())
651                 break;
652             if (!cimage->errorOccurred())
653                 return Cursor(cimage->image(), hotSpot);
654         }
655     }
656
657     switch (style ? style->cursor() : CURSOR_AUTO) {
658         case CURSOR_AUTO: {
659             bool editable = (node && node->isContentEditable());
660             bool editableLinkEnabled = false;
661
662             // If the link is editable, then we need to check the settings to see whether or not the link should be followed
663             if (editable) {
664                 switch(frame->settings()->editableLinkBehavior()) {
665                     default:
666                     case EditableLinkDefaultBehavior:
667                     case EditableLinkAlwaysLive:
668                         editableLinkEnabled = true;
669                         break;
670
671                     case EditableLinkNeverLive:
672                         editableLinkEnabled = false;
673                         break;
674
675                     case EditableLinkLiveWhenNotFocused:
676                         editableLinkEnabled = nodeIsNotBeingEdited(node, frame) || event.event().shiftKey();
677                         break;
678                     
679                     case EditableLinkOnlyLiveWithShiftKey:
680                         editableLinkEnabled = event.event().shiftKey();
681                         break;
682                 }
683             }
684             
685             if ((event.isOverLink() || isSubmitImage(node)) && (!editable || editableLinkEnabled))
686                 return handCursor();
687             RenderLayer* layer = renderer ? renderer->enclosingLayer() : 0;
688             bool inResizer = false;
689             if (frame->view() && layer && layer->isPointInResizeControl(frame->view()->windowToContents(event.event().pos())))
690                 inResizer = true;
691             if ((editable || (renderer && renderer->isText() && renderer->canSelect())) && !inResizer && !scrollbar)
692                 return iBeamCursor();
693             return pointerCursor();
694         }
695         case CURSOR_CROSS:
696             return crossCursor();
697         case CURSOR_POINTER:
698             return handCursor();
699         case CURSOR_MOVE:
700             return moveCursor();
701         case CURSOR_ALL_SCROLL:
702             return moveCursor();
703         case CURSOR_E_RESIZE:
704             return eastResizeCursor();
705         case CURSOR_W_RESIZE:
706             return westResizeCursor();
707         case CURSOR_N_RESIZE:
708             return northResizeCursor();
709         case CURSOR_S_RESIZE:
710             return southResizeCursor();
711         case CURSOR_NE_RESIZE:
712             return northEastResizeCursor();
713         case CURSOR_SW_RESIZE:
714             return southWestResizeCursor();
715         case CURSOR_NW_RESIZE:
716             return northWestResizeCursor();
717         case CURSOR_SE_RESIZE:
718             return southEastResizeCursor();
719         case CURSOR_NS_RESIZE:
720             return northSouthResizeCursor();
721         case CURSOR_EW_RESIZE:
722             return eastWestResizeCursor();
723         case CURSOR_NESW_RESIZE:
724             return northEastSouthWestResizeCursor();
725         case CURSOR_NWSE_RESIZE:
726             return northWestSouthEastResizeCursor();
727         case CURSOR_COL_RESIZE:
728             return columnResizeCursor();
729         case CURSOR_ROW_RESIZE:
730             return rowResizeCursor();
731         case CURSOR_TEXT:
732             return iBeamCursor();
733         case CURSOR_WAIT:
734             return waitCursor();
735         case CURSOR_HELP:
736             return helpCursor();
737         case CURSOR_VERTICAL_TEXT:
738             return verticalTextCursor();
739         case CURSOR_CELL:
740             return cellCursor();
741         case CURSOR_CONTEXT_MENU:
742             return contextMenuCursor();
743         case CURSOR_PROGRESS:
744             return progressCursor();
745         case CURSOR_NO_DROP:
746             return noDropCursor();
747         case CURSOR_ALIAS:
748             return aliasCursor();
749         case CURSOR_COPY:
750             return copyCursor();
751         case CURSOR_NONE:
752             return noneCursor();
753         case CURSOR_NOT_ALLOWED:
754             return notAllowedCursor();
755         case CURSOR_DEFAULT:
756             return pointerCursor();
757     }
758     return pointerCursor();
759 }
760
761 bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
762 {
763     if (!m_frame->document())
764         return false;
765
766     RefPtr<FrameView> protector(m_frame->view());
767
768     m_mousePressed = true;
769     m_currentMousePosition = mouseEvent.pos();
770     m_mouseDownTimestamp = mouseEvent.timestamp();
771     m_mouseDownMayStartDrag = false;
772     m_mouseDownMayStartSelect = false;
773     m_mouseDownMayStartAutoscroll = false;
774     m_mouseDownPos = m_frame->view()->windowToContents(mouseEvent.pos());
775     m_mouseDownWasInSubframe = false;
776     
777     MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, true), mouseEvent);
778
779     if (!mev.targetNode()) {
780         invalidateClick();
781         return false;
782     }
783
784     m_mousePressNode = mev.targetNode();
785
786     Frame* subframe = subframeForTargetNode(mev.targetNode());
787     if (subframe && passMousePressEventToSubframe(mev, subframe)) {
788         invalidateClick();
789         return true;
790     }
791
792     m_clickCount = mouseEvent.clickCount();
793     m_clickNode = mev.targetNode();
794     
795     RenderLayer* layer = m_clickNode->renderer() ? m_clickNode->renderer()->enclosingLayer() : 0;
796     IntPoint p = m_frame->view()->windowToContents(mouseEvent.pos());
797     if (layer && layer->isPointInResizeControl(p)) {
798         layer->setInResizeMode(true);
799         m_resizeLayer = layer;
800         m_offsetFromResizeCorner = layer->offsetFromResizeCorner(p);
801         invalidateClick();
802         return true;
803     }
804
805     bool swallowEvent = dispatchMouseEvent(mousedownEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
806
807     if (swallowEvent) {
808         // scrollbars should get events anyway, even disabled controls might be scrollable
809         if (mev.scrollbar())
810             passMousePressEventToScrollbar(mev, mev.scrollbar());
811     } else {
812         // Refetch the event target node if it currently is the shadow node inside an <input> element.
813         // If a mouse event handler changes the input element type to one that has a widget associated,
814         // we'd like to EventHandler::handleMousePressEvent to pass the event to the widget and thus the
815         // event target node can't still be the shadow node.
816         if (mev.targetNode()->isShadowNode() && mev.targetNode()->shadowParentNode()->hasTagName(inputTag))
817             mev = prepareMouseEvent(HitTestRequest(true, true), mouseEvent);
818
819         PlatformScrollbar* scrollbar = m_frame->view()->scrollbarUnderMouse(mouseEvent);
820         if (!scrollbar)
821             scrollbar = mev.scrollbar();
822         if (scrollbar && passMousePressEventToScrollbar(mev, scrollbar))
823             swallowEvent = true;
824         else
825             swallowEvent = handleMousePressEvent(mev);
826     }
827
828     return swallowEvent;
829 }
830
831 // This method only exists for platforms that don't know how to deliver 
832 bool EventHandler::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent)
833 {
834     if (!m_frame->document())
835         return false;
836
837     RefPtr<FrameView> protector(m_frame->view());
838
839     // We get this instead of a second mouse-up 
840     m_mousePressed = false;
841     m_currentMousePosition = mouseEvent.pos();
842
843     MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, true), mouseEvent);
844     Frame* subframe = subframeForTargetNode(mev.targetNode());
845     if (subframe && passMousePressEventToSubframe(mev, subframe))
846         return true;
847
848     m_clickCount = mouseEvent.clickCount();
849     bool swallowMouseUpEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode(), true, m_clickCount, mouseEvent, false);
850
851     bool swallowClickEvent = false;
852     if (mev.targetNode() == m_clickNode)
853         swallowClickEvent = dispatchMouseEvent(clickEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
854
855     bool swallowMouseReleaseEvent = false;
856     if (!swallowMouseUpEvent)
857         swallowMouseReleaseEvent = handleMouseReleaseEvent(mev);
858
859     invalidateClick();
860
861     return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
862 }
863
864 bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent)
865 {
866     // in Radar 3703768 we saw frequent crashes apparently due to the
867     // part being null here, which seems impossible, so check for nil
868     // but also assert so that we can try to figure this out in debug
869     // builds, if it happens.
870     ASSERT(m_frame);
871     if (!m_frame || !m_frame->document())
872         return false;
873
874     RefPtr<FrameView> protector(m_frame->view());
875     m_currentMousePosition = mouseEvent.pos();
876    
877     if (m_hoverTimer.isActive())
878         m_hoverTimer.stop();
879
880     if (m_frameSetBeingResized)
881         return dispatchMouseEvent(mousemoveEvent, m_frameSetBeingResized.get(), false, 0, mouseEvent, false);
882
883     // Treat mouse move events while the mouse is pressed as "read-only" in prepareMouseEvent
884     // if we are allowed to select.
885     // This means that :hover and :active freeze in the state they were in when the mouse
886     // was pressed, rather than updating for nodes the mouse moves over as you hold the mouse down.
887     HitTestRequest request(m_mousePressed && m_mouseDownMayStartSelect, m_mousePressed, true);
888     MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
889
890     if (m_lastMouseMoveEventSubframe && m_lastMouseMoveEventSubframe->tree()->isDescendantOf(m_frame))
891         passMouseMoveEventToSubframe(mev, m_lastMouseMoveEventSubframe.get());
892
893     bool swallowEvent = dispatchMouseEvent(mousemoveEvent, mev.targetNode(), false, 0, mouseEvent, true);
894
895     PlatformScrollbar* scrollbar = 0;
896     if (m_frame->view())
897         scrollbar = m_frame->view()->scrollbarUnderMouse(mouseEvent);
898
899     if (!scrollbar)
900         scrollbar = mev.scrollbar();
901
902     if (m_lastScrollbarUnderMouse != scrollbar) {
903         // Send mouse exited to the old scrollbar.
904         if (m_lastScrollbarUnderMouse)
905             m_lastScrollbarUnderMouse->handleMouseOutEvent(mouseEvent);
906         m_lastScrollbarUnderMouse = scrollbar;
907     }
908
909     if (m_resizeLayer && m_resizeLayer->inResizeMode())
910         m_resizeLayer->resize(mouseEvent, m_offsetFromResizeCorner);
911
912     if (!swallowEvent)
913         swallowEvent = handleMouseMoveEvent(mev);
914     
915     RefPtr<Frame> newSubframe = subframeForTargetNode(mev.targetNode());
916     if (newSubframe) {
917         if (m_lastMouseMoveEventSubframe != newSubframe)
918             swallowEvent |= passMouseMoveEventToSubframe(mev, newSubframe.get());
919     } else {
920         if (scrollbar && !m_mousePressed)
921             scrollbar->handleMouseMoveEvent(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
922         if ((!m_resizeLayer || !m_resizeLayer->inResizeMode()) && m_frame->view())
923             m_frame->view()->setCursor(selectCursor(mev, m_frame, m_mousePressed, scrollbar));
924     }
925
926     m_lastMouseMoveEventSubframe = newSubframe;
927
928     return swallowEvent;
929 }
930
931 void EventHandler::invalidateClick()
932 {
933     m_clickCount = 0;
934     m_clickNode = 0;
935 }
936
937 bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
938 {
939     if (!m_frame->document())
940         return false;
941
942     RefPtr<FrameView> protector(m_frame->view());
943
944     m_mousePressed = false;
945     m_currentMousePosition = mouseEvent.pos();
946
947     if (m_frameSetBeingResized)
948         return dispatchMouseEvent(mouseupEvent, m_frameSetBeingResized.get(), true, m_clickCount, mouseEvent, false);
949
950     MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, false, false, true), mouseEvent);
951     Frame* subframe = subframeForTargetNode(mev.targetNode());
952     if (subframe && passMouseReleaseEventToSubframe(mev, subframe))
953         return true;
954
955     bool swallowMouseUpEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode(), true, m_clickCount, mouseEvent, false);
956
957     bool swallowClickEvent = false;
958     if (m_clickCount > 0 && mev.targetNode() == m_clickNode)
959         swallowClickEvent = dispatchMouseEvent(clickEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
960
961     if (m_resizeLayer) {
962         m_resizeLayer->setInResizeMode(false);
963         m_resizeLayer = 0;
964     }
965
966     bool swallowMouseReleaseEvent = false;
967     if (!swallowMouseUpEvent)
968         swallowMouseReleaseEvent = handleMouseReleaseEvent(mev);
969
970     invalidateClick();
971
972     return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
973 }
974
975 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard)
976 {
977     IntPoint contentsPos = m_frame->view()->windowToContents(event.pos());
978     
979     RefPtr<MouseEvent> me = new MouseEvent(eventType,
980         true, true, m_frame->document()->defaultView(),
981         0, event.globalX(), event.globalY(), contentsPos.x(), contentsPos.y(),
982         event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
983         0, 0, clipboard);
984
985     ExceptionCode ec = 0;
986     EventTargetNodeCast(dragTarget)->dispatchEvent(me.get(), ec, true);
987     return me->defaultPrevented();
988 }
989
990 bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
991 {
992     bool accept = false;
993
994     MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(true, false), event);
995
996     // Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
997     Node* newTarget = mev.targetNode();
998     if (newTarget && newTarget->isTextNode())
999         newTarget = newTarget->parentNode();
1000     if (newTarget)
1001         newTarget = newTarget->shadowAncestorNode();
1002
1003     if (m_dragTarget != newTarget) {
1004         // FIXME: this ordering was explicitly chosen to match WinIE. However,
1005         // it is sometimes incorrect when dragging within subframes, as seen with
1006         // LayoutTests/fast/events/drag-in-frames.html.
1007         if (newTarget)
1008             if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag))
1009                 accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->eventHandler()->updateDragAndDrop(event, clipboard);
1010             else
1011                 accept = dispatchDragEvent(dragenterEvent, newTarget, event, clipboard);
1012         
1013         if (m_dragTarget) {
1014             Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag)) 
1015                             ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0;
1016             if (frame)
1017                 accept = frame->eventHandler()->updateDragAndDrop(event, clipboard);
1018             else
1019                 dispatchDragEvent(dragleaveEvent, m_dragTarget.get(), event, clipboard);
1020         }
1021     } else {
1022         if (newTarget)
1023             if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag))
1024                 accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->eventHandler()->updateDragAndDrop(event, clipboard);
1025             else
1026                 accept = dispatchDragEvent(dragoverEvent, newTarget, event, clipboard);
1027     }
1028     m_dragTarget = newTarget;
1029
1030     return accept;
1031 }
1032
1033 void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
1034 {
1035     if (m_dragTarget) {
1036         Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag)) 
1037                         ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0;
1038         if (frame)
1039             frame->eventHandler()->cancelDragAndDrop(event, clipboard);
1040         else
1041             dispatchDragEvent(dragleaveEvent, m_dragTarget.get(), event, clipboard);
1042     }
1043     m_dragTarget = 0;
1044 }
1045
1046 bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
1047 {
1048     bool accept = false;
1049     if (m_dragTarget) {
1050         Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag)) 
1051                         ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0;
1052         if (frame)
1053             accept = frame->eventHandler()->performDragAndDrop(event, clipboard);
1054         else
1055             accept = dispatchDragEvent(dropEvent, m_dragTarget.get(), event, clipboard);
1056     }
1057     m_dragTarget = 0;
1058     return accept;
1059 }
1060
1061 Node* EventHandler::nodeUnderMouse() const
1062 {
1063     return m_nodeUnderMouse.get();
1064 }
1065
1066 void EventHandler::setCapturingMouseEventsNode(PassRefPtr<Node> n)
1067 {
1068     m_capturingMouseEventsNode = n;
1069 }
1070
1071 MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestRequest& request, const PlatformMouseEvent& mev)
1072 {
1073     ASSERT(m_frame);
1074     ASSERT(m_frame->document());
1075     
1076     IntPoint documentPoint = m_frame->view()->windowToContents(mev.pos());
1077     return m_frame->document()->prepareMouseEvent(request, documentPoint, mev);
1078 }
1079
1080 bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool cancelable,
1081     int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder)
1082 {
1083     // if the target node is a text node, dispatch on the parent node - rdar://4196646
1084     if (targetNode && targetNode->isTextNode())
1085         targetNode = targetNode->parentNode();
1086     if (targetNode)
1087         targetNode = targetNode->shadowAncestorNode();
1088
1089     if (m_capturingMouseEventsNode)
1090         targetNode = m_capturingMouseEventsNode.get();
1091         
1092     m_nodeUnderMouse = targetNode;
1093
1094     // mouseout/mouseover
1095     if (setUnder) {
1096         if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame->document()) {
1097             m_lastNodeUnderMouse = 0;
1098             m_lastScrollbarUnderMouse = 0;
1099         }
1100
1101         if (m_lastNodeUnderMouse != targetNode) {
1102             // send mouseout event to the old node
1103             if (m_lastNodeUnderMouse)
1104                 EventTargetNodeCast(m_lastNodeUnderMouse.get())->dispatchMouseEvent(mouseEvent, mouseoutEvent, 0, targetNode);
1105             // send mouseover event to the new node
1106             if (targetNode)
1107                 EventTargetNodeCast(targetNode)->dispatchMouseEvent(mouseEvent, mouseoverEvent, 0, m_lastNodeUnderMouse.get());
1108         }
1109         m_lastNodeUnderMouse = targetNode;
1110     }
1111
1112     bool swallowEvent = false;
1113
1114     if (targetNode)
1115         swallowEvent = EventTargetNodeCast(targetNode)->dispatchMouseEvent(mouseEvent, eventType, clickCount);
1116     
1117     if (!swallowEvent && eventType == mousedownEvent) {
1118         // Blur current focus node when a link/button is clicked; this
1119         // is expected by some sites that rely on onChange handlers running
1120         // from form fields before the button click is processed.
1121         Node* node = targetNode;
1122         RenderObject* renderer = node ? node->renderer() : 0;
1123                 
1124         // Walk up the render tree to search for a node to focus.
1125         // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
1126         while (renderer) {
1127             node = renderer->element();
1128             if (node && node->isFocusable())
1129                 break;
1130             renderer = renderer->parent();
1131         }
1132         // If focus shift is blocked, we eat the event.  Note we should never clear swallowEvent
1133         // if the page already set it (e.g., by canceling default behavior).
1134         if (node && node->isMouseFocusable()) {
1135             if (!m_frame->document()->setFocusedNode(node))
1136                 swallowEvent = true;
1137         } else if (!node || !node->focused()) {
1138             if (!m_frame->document()->setFocusedNode(0))
1139                 swallowEvent = true;
1140         }
1141     }
1142
1143     return swallowEvent;
1144 }
1145
1146 bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
1147 {
1148     Document* doc = m_frame->document();
1149     if (!doc)
1150         return false;
1151
1152     RenderObject* docRenderer = doc->renderer();
1153     if (!docRenderer)
1154         return false;
1155
1156     IntPoint vPoint = m_frame->view()->windowToContents(e.pos());
1157
1158     HitTestRequest request(true, false);
1159     HitTestResult result(vPoint);
1160     doc->renderer()->layer()->hitTest(request, result);
1161     Node* node = result.innerNode();    
1162     Frame* subframe = subframeForTargetNode(node);
1163     if (subframe && passWheelEventToSubframe(e, subframe)) {
1164         e.accept();
1165         return true;
1166     }
1167
1168     if (node) {
1169         node = node->shadowAncestorNode();
1170         EventTargetNodeCast(node)->dispatchWheelEvent(e);
1171         if (e.isAccepted())
1172             return true;
1173             
1174         if (node->renderer()) {
1175 #if PLATFORM(MAC)
1176             if (!e.deltaX() && !e.deltaY() && node->renderer()->isScrollable())
1177                 // smooth scroll events on mac may have (0,0) deltas
1178                 // they need to be eaten until we start supporting them
1179                 e.accept();
1180 #endif
1181         
1182             // Just break up into two scrolls if we need to.  Diagonal movement on 
1183             // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
1184             if (e.deltaX() && node->renderer()->scroll(e.deltaX() < 0 ? ScrollRight : ScrollLeft, ScrollByWheel,
1185                                                        e.deltaX() < 0 ? -e.deltaX() : e.deltaX()))
1186                 e.accept();
1187             if (e.deltaY() && node->renderer()->scroll(e.deltaY() < 0 ? ScrollDown : ScrollUp, ScrollByWheel,
1188                                                        e.deltaY() < 0 ? -e.deltaY() : e.deltaY()))
1189                 e.accept();
1190         }
1191     }
1192
1193     if (!e.isAccepted())
1194         m_frame->view()->wheelEvent(e);
1195     
1196     return e.isAccepted();
1197 }
1198
1199 bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event)
1200 {
1201     Document* doc = m_frame->document();
1202     FrameView* v = m_frame->view();
1203     if (!doc || !v)
1204         return false;
1205     
1206     bool swallowEvent;
1207     IntPoint viewportPos = v->windowToContents(event.pos());
1208     MouseEventWithHitTestResults mev = doc->prepareMouseEvent(HitTestRequest(false, true), viewportPos, event);
1209
1210     if (!m_frame->selectionController()->contains(viewportPos) &&
1211             (m_frame->editor()->selectWordBeforeMenuEvent() || m_frame->editor()->clientIsEditable()
1212             || (mev.targetNode() && mev.targetNode()->isContentEditable()))) {
1213         m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection
1214         selectClosestWordFromMouseEvent(mev);
1215     }
1216
1217     swallowEvent = dispatchMouseEvent(contextmenuEvent, mev.targetNode(), true, 0, event, true);
1218     
1219     return swallowEvent;
1220 }
1221
1222 void EventHandler::scheduleHoverStateUpdate()
1223 {
1224     if (!m_hoverTimer.isActive())
1225         m_hoverTimer.startOneShot(0);
1226 }
1227
1228 bool EventHandler::canMouseDownStartSelect(Node* node)
1229 {
1230     if (!node || !node->renderer())
1231         return true;
1232     
1233     // Check to see if -webkit-user-select has been set to none
1234     if (!node->renderer()->canSelect())
1235         return false;
1236     
1237     // Some controls and images can't start a select on a mouse down.
1238     for (RenderObject* curr = node->renderer(); curr; curr = curr->parent())
1239         if (curr->style()->userSelect() == SELECT_IGNORE)
1240             return false;
1241     
1242     return true;
1243 }
1244
1245 void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet)
1246 {
1247     m_frameSetBeingResized = frameSet;
1248 }
1249
1250 void EventHandler::hoverTimerFired(Timer<EventHandler>*)
1251 {
1252     m_hoverTimer.stop();
1253     prepareMouseEvent(HitTestRequest(false, false, true), PlatformMouseEvent(PlatformMouseEvent::currentEvent));
1254 }
1255
1256 static EventTargetNode* eventTargetNodeForDocument(Document* doc)
1257 {
1258     if (!doc)
1259         return 0;
1260     Node* node = doc->focusedNode();
1261     if (!node) {
1262         if (doc->isHTMLDocument())
1263             node = doc->body();
1264         else
1265             node = doc->documentElement();
1266         if (!node)
1267             return 0;
1268     }
1269     return EventTargetNodeCast(node);
1270 }
1271
1272 bool EventHandler::keyEvent(const PlatformKeyboardEvent& keyEvent)
1273 {
1274     // Check for cases where we are too early for events -- possible unmatched key up
1275     // from pressing return in the location bar.
1276     EventTargetNode* node = eventTargetNodeForDocument(m_frame->document());
1277     if (!node)
1278         return false;
1279     
1280     if (!keyEvent.isKeyUp())
1281         m_frame->loader()->resetMultipleFormSubmissionProtection();
1282
1283     return !node->dispatchKeyEvent(keyEvent);
1284 }
1285
1286 void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event)
1287 {
1288     if (event->type() == keydownEvent) {     
1289         // Get the target node again, in case the focus has changed
1290         if (EventTargetNode* node = eventTargetNodeForDocument(m_frame->document())) {
1291             // Create a keypress event from the keydown event
1292             RefPtr<KeyboardEvent> keypress;
1293             const PlatformKeyboardEvent* keyEvent = event->keyEvent();
1294             if (keyEvent) {
1295                 PlatformKeyboardEvent key = *keyEvent;
1296                 // Set "is repeat" to true, which will cause this PlatformKeyboardEvent to be interpreted as a keypress event.
1297                 // We should do this a better way.
1298                 key.setIsAutoRepeat(true);
1299                 keypress = new KeyboardEvent(key, event->view());
1300             } else {
1301                 keypress = new KeyboardEvent(keypressEvent, event->bubbles(), event->cancelable(), 
1302                                             event->view(), event->keyIdentifier(), event->keyLocation(),
1303                                             event->ctrlKey(), event->altKey(), event->shiftKey(), event->metaKey(), event->altGraphKey());
1304             }
1305             keypress->setUnderlyingEvent(event);   
1306             keypress->setTarget(node);
1307             
1308             // Call handleInputMethodKeypress so that input methods have a chance to handle the event.
1309             // If that happens, then we don't need to send the keypress event.  If an input method doesn't handle the event, 
1310             // then we'll save the data we need to perform the correct action (like inserting text) 
1311             // when we call handleKeypress.
1312             m_frame->editor()->handleInputMethodKeypress(keypress.get());
1313             
1314             if (!keypress->defaultHandled()) {
1315                 // Dispatch the new keypress event
1316                 ExceptionCode ec;
1317                 node->dispatchEvent(keypress, ec, true);
1318             }
1319             if (keypress->defaultHandled() || keypress->defaultPrevented())
1320                 event->setDefaultHandled();
1321         }
1322     } else if (event->type() == keypressEvent) {
1323         m_frame->editor()->handleKeypress(event);
1324         if (event->defaultHandled())
1325             return;
1326         if (event->keyIdentifier() == "U+000009")
1327             defaultTabEventHandler(event, false);
1328     }
1329 }
1330
1331 bool EventHandler::dragHysteresisExceeded(const FloatPoint& floatDragViewportLocation) const
1332 {
1333     IntPoint dragViewportLocation((int)floatDragViewportLocation.x(), (int)floatDragViewportLocation.y());
1334     return dragHysteresisExceeded(dragViewportLocation);
1335 }
1336     
1337 bool EventHandler::dragHysteresisExceeded(const IntPoint& dragViewportLocation) const
1338 {
1339     IntPoint dragLocation = m_frame->view()->windowToContents(dragViewportLocation);
1340     IntSize delta = dragLocation - m_mouseDownPos;
1341     
1342     int threshold = GeneralDragHysteresis;
1343     if (dragState().m_dragSrcIsImage)
1344         threshold = ImageDragHysteresis;
1345     else if (dragState().m_dragSrcIsLink)
1346         threshold = LinkDragHysteresis;
1347     else if (dragState().m_dragSrcInSelection)
1348         threshold = TextDragHysteresis;
1349     
1350     return abs(delta.width()) >= threshold || abs(delta.height()) >= threshold;
1351 }
1352     
1353 void EventHandler::freeClipboard()
1354 {
1355     if (dragState().m_dragClipboard)
1356         dragState().m_dragClipboard->setAccessPolicy(ClipboardNumb);
1357 }
1358
1359 bool EventHandler::shouldDragAutoNode(Node* node, const IntPoint& point) const
1360 {
1361     ASSERT(node);
1362     if (node->hasChildNodes() || !m_frame->view())
1363         return false;
1364     return m_frame->page() && m_frame->page()->dragController()->mayStartDragAtEventLocation(m_frame, point);
1365 }
1366     
1367 void EventHandler::dragSourceMovedTo(const PlatformMouseEvent& event)
1368 {
1369     if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML)
1370         // for now we don't care if event handler cancels default behavior, since there is none
1371         dispatchDragSrcEvent(dragEvent, event);
1372 }
1373     
1374 void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, DragOperation operation)
1375 {
1376     if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) {
1377         dragState().m_dragClipboard->setDestinationOperation(operation);
1378         // for now we don't care if event handler cancels default behavior, since there is none
1379         dispatchDragSrcEvent(dragendEvent, event);
1380     }
1381     freeClipboard();
1382     dragState().m_dragSrc = 0;
1383 }
1384     
1385 // returns if we should continue "default processing", i.e., whether eventhandler canceled
1386 bool EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent& event)
1387 {
1388     return !dispatchDragEvent(eventType, dragState().m_dragSrc.get(), event, dragState().m_dragClipboard.get());
1389 }
1390     
1391 bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event)
1392 {
1393     if (event.event().button() != LeftButton || event.event().eventType() != MouseEventMoved) {
1394         // If we allowed the other side of the bridge to handle a drag
1395         // last time, then m_mousePressed might still be set. So we
1396         // clear it now to make sure the next move after a drag
1397         // doesn't look like a drag.
1398         m_mousePressed = false;
1399         return false;
1400     }
1401     
1402     if (eventLoopHandleMouseDragged(event))
1403         return true;
1404     
1405     // Careful that the drag starting logic stays in sync with eventMayStartDrag()
1406     
1407     if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
1408         allowDHTMLDrag(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA);
1409         if (!dragState().m_dragSrcMayBeDHTML && !dragState().m_dragSrcMayBeUA)
1410             m_mouseDownMayStartDrag = false;     // no element is draggable
1411     }
1412
1413     if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
1414         // try to find an element that wants to be dragged
1415         HitTestRequest request(true, false);
1416         HitTestResult result(m_mouseDownPos);
1417         m_frame->renderer()->layer()->hitTest(request, result);
1418         Node* node = result.innerNode();
1419         if (node && node->renderer())
1420             dragState().m_dragSrc = node->renderer()->draggableNode(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA,
1421                                                                     m_mouseDownPos.x(), m_mouseDownPos.y(), dragState().m_dragSrcIsDHTML);
1422         else
1423             dragState().m_dragSrc = 0;
1424         
1425         if (!dragState().m_dragSrc)
1426             m_mouseDownMayStartDrag = false;     // no element is draggable
1427         else {
1428             // remember some facts about this source, while we have a HitTestResult handy
1429             node = result.URLElement();
1430             dragState().m_dragSrcIsLink = node && node->isLink();
1431             
1432             node = result.innerNonSharedNode();
1433             dragState().m_dragSrcIsImage = node && node->renderer() && node->renderer()->isImage();
1434             
1435             dragState().m_dragSrcInSelection = m_frame->selectionController()->contains(m_mouseDownPos);
1436         }                
1437     }
1438     
1439     // For drags starting in the selection, the user must wait between the mousedown and mousedrag,
1440     // or else we bail on the dragging stuff and allow selection to occur
1441     if (m_mouseDownMayStartDrag && dragState().m_dragSrcInSelection && event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay) {
1442         m_mouseDownMayStartDrag = false;
1443         dragState().m_dragSrc = 0;
1444         // ...but if this was the first click in the window, we don't even want to start selection
1445         if (eventActivatedView(event.event()))
1446             m_mouseDownMayStartSelect = false;
1447     }
1448     
1449     if (!m_mouseDownMayStartDrag)
1450         return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll;
1451     
1452     // We are starting a text/image/url drag, so the cursor should be an arrow
1453     m_frame->view()->setCursor(pointerCursor());
1454     
1455     if (!dragHysteresisExceeded(event.event().pos())) 
1456         return true;
1457     
1458     // Once we're past the hysteresis point, we don't want to treat this gesture as a click
1459     invalidateClick();
1460     
1461     DragOperation srcOp = DragOperationNone;        
1462     if (dragState().m_dragSrcMayBeDHTML) {
1463         freeClipboard();    // would only happen if we missed a dragEnd.  Do it anyway, just
1464                             // to make sure it gets numbified
1465         
1466         dragState().m_dragClipboard = createDraggingClipboard();
1467         
1468         // Check to see if the is a DOM based drag, if it is get the DOM specified drag 
1469         // image and offset
1470         if (dragState().m_dragSrcIsDHTML) {
1471             int srcX, srcY;
1472             dragState().m_dragSrc->renderer()->absolutePosition(srcX, srcY);
1473             IntSize delta = m_mouseDownPos - IntPoint(srcX, srcY);
1474             dragState().m_dragClipboard->setDragImageElement(dragState().m_dragSrc.get(), IntPoint() + delta);
1475         } 
1476         
1477         m_mouseDownMayStartDrag = dispatchDragSrcEvent(dragstartEvent, m_mouseDown)
1478             && !m_frame->selectionController()->isInPasswordField();
1479         
1480         // Invalidate clipboard here against anymore pasteboard writing for security.  The drag
1481         // image can still be changed as we drag, but not the pasteboard data.
1482         dragState().m_dragClipboard->setAccessPolicy(ClipboardImageWritable);
1483         
1484         if (m_mouseDownMayStartDrag) {
1485             // gather values from DHTML element, if it set any
1486             dragState().m_dragClipboard->sourceOperation(srcOp);
1487             
1488             // Yuck, dragSourceMovedTo() can be called as a result of kicking off the drag with
1489             // dragImage!  Because of that dumb reentrancy, we may think we've not started the
1490             // drag when that happens.  So we have to assume it's started before we kick it off.
1491             dragState().m_dragClipboard->setDragHasStarted();
1492         }
1493     }
1494     
1495     if (m_mouseDownMayStartDrag) {
1496         DragController* dragController = m_frame->page() ? m_frame->page()->dragController() : 0;
1497         bool startedDrag = dragController && dragController->startDrag(m_frame, dragState().m_dragClipboard.get(), srcOp, event.event(), m_mouseDownPos, dragState().m_dragSrcIsDHTML);
1498         if (!startedDrag && dragState().m_dragSrcMayBeDHTML) {
1499             // Drag was canned at the last minute - we owe m_dragSrc a DRAGEND event
1500             PlatformMouseEvent event(PlatformMouseEvent::currentEvent);
1501             dispatchDragSrcEvent(dragendEvent, event);
1502             m_mouseDownMayStartDrag = false;
1503         }
1504     } 
1505     
1506     if (!m_mouseDownMayStartDrag) {
1507         // something failed to start the drag, cleanup
1508         freeClipboard();
1509         dragState().m_dragSrc = 0;
1510     }
1511     
1512     // No more default handling (like selection), whether we're past the hysteresis bounds or not
1513     return true;
1514 }
1515   
1516 bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEvent,
1517                                         bool isLineBreak, bool isBackTab)
1518 {
1519     if (!m_frame)
1520         return false;
1521     EventTarget* target;
1522     if (underlyingEvent)
1523         target = underlyingEvent->target();
1524     else
1525         target = eventTargetNodeForDocument(m_frame->document());
1526     if (!target)
1527         return false;
1528     RefPtr<TextEvent> event = new TextEvent(m_frame->domWindow(), text);
1529     event->setUnderlyingEvent(underlyingEvent);
1530     event->setIsLineBreak(isLineBreak);
1531     event->setIsBackTab(isBackTab);
1532     ExceptionCode ec;
1533     return target->dispatchEvent(event.release(), ec, true);
1534 }
1535     
1536     
1537 #if !PLATFORM(MAC) && !PLATFORM(QT)
1538 bool EventHandler::invertSenseOfTabsToLinks(KeyboardEvent*) const
1539 {
1540     return false;
1541 }
1542 #endif
1543
1544 bool EventHandler::tabsToLinks(KeyboardEvent* event) const
1545 {
1546     Page* page = m_frame->page();
1547     if (!page)
1548         return false;
1549
1550     if (page->chrome()->client()->tabsToLinks())
1551         return !invertSenseOfTabsToLinks(event);
1552
1553     return invertSenseOfTabsToLinks(event);
1554 }
1555
1556 void EventHandler::defaultTextInputEventHandler(TextEvent* event)
1557 {
1558     String data = event->data();
1559     if (data == "\t") {
1560         defaultTabEventHandler(event, event->isBackTab());
1561         if (event->defaultHandled())
1562             return;
1563     }
1564     if (data == "\n") {
1565         if (event->isLineBreak()) {
1566             if (m_frame->editor()->insertLineBreak())
1567                 event->setDefaultHandled();
1568         } else {
1569             if (m_frame->editor()->insertParagraphSeparator())
1570                 event->setDefaultHandled();
1571         }
1572     } else {
1573         if (m_frame->editor()->insertTextWithoutSendingTextEvent(data, false, event))
1574             event->setDefaultHandled();
1575     }
1576 }
1577
1578 void EventHandler::defaultTabEventHandler(Event* event, bool isBackTab)
1579 {
1580     Page* page = m_frame->page();
1581     // Tabs can be used in design mode editing. You can still move out with back tab.
1582     if (!page || !page->tabKeyCyclesThroughElements() || (m_frame->document()->inDesignMode() && !isBackTab))
1583         return;
1584     FocusController* focus = page->focusController();
1585     KeyboardEvent* keyboardEvent = findKeyboardEvent(event);
1586     bool handled;
1587     if (isBackTab)
1588         handled = focus->advanceFocus(FocusDirectionBackward, keyboardEvent);
1589     else
1590         handled = focus->advanceFocus(keyboardEvent); // get direction from keyboard event
1591     if (handled)
1592         event->setDefaultHandled();
1593 }
1594
1595 }