2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
28 #include "EventHandler.h"
30 #include "AXObjectCache.h"
31 #include "CachedImage.h"
32 #include "ChromeClient.h"
35 #include "DragController.h"
37 #include "EventNames.h"
38 #include "FloatPoint.h"
39 #include "FloatRect.h"
40 #include "FocusController.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"
52 #include "InspectorController.h"
53 #include "KeyboardEvent.h"
54 #include "MouseEvent.h"
55 #include "MouseEventWithHitTestResults.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"
65 #include "TextEvent.h"
68 #include "SVGDocument.h"
69 #include "SVGElementInstance.h"
71 #include "SVGUseElement.h"
76 using namespace EventNames;
77 using namespace HTMLNames;
79 // The link drag hysteresis is much larger than the others because there
80 // needs to be enough space to cancel the link press without starting a link drag,
81 // and because dragging links is rare.
82 const int LinkDragHysteresis = 40;
83 const int ImageDragHysteresis = 5;
84 const int TextDragHysteresis = 3;
85 const int GeneralDragHysteresis = 3;
87 // Match key code of composition keydown event on windows.
88 // IE sends VK_PROCESSKEY which has value 229;
89 const int CompositionEventKeyCode = 229;
92 using namespace SVGNames;
95 // When the autoscroll or the panScroll is triggered when do the scroll every 0.05s to make it smooth
96 const double autoscrollInterval = 0.05;
98 static Frame* subframeForTargetNode(Node*);
99 static Frame* subframeForHitTestResult(const MouseEventWithHitTestResults&);
101 static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDirection, ScrollDirection negativeDirection, PlatformWheelEvent& e, Node* node)
105 if (e.granularity() == ScrollByPageWheelEvent) {
106 if (node->renderer()->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPage, 1))
110 float pixelsToScroll = delta > 0 ? delta : -delta;
111 if (e.granularity() == ScrollByLineWheelEvent)
112 pixelsToScroll *= cMouseWheelPixelsPerLineStep;
113 if (node->renderer()->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, pixelsToScroll))
117 EventHandler::EventHandler(Frame* frame)
119 , m_mousePressed(false)
120 , m_mouseDownMayStartSelect(false)
121 , m_mouseDownMayStartDrag(false)
122 , m_mouseDownWasSingleClickInSelection(false)
123 , m_beganSelectingText(false)
124 , m_panScrollInProgress(false)
125 , m_hoverTimer(this, &EventHandler::hoverTimerFired)
126 , m_autoscrollTimer(this, &EventHandler::autoscrollTimerFired)
127 , m_autoscrollRenderer(0)
128 , m_autoscrollInProgress(false)
129 , m_mouseDownMayStartAutoscroll(false)
130 , m_mouseDownWasInSubframe(false)
135 , m_capturingMouseEventsNode(0)
137 , m_mouseDownTimestamp(0)
138 , m_pendingFrameUnloadEventCount(0)
139 , m_pendingFrameBeforeUnloadEventCount(0)
141 , m_mouseDownView(nil)
142 , m_sendingEventToSubview(false)
143 , m_activationEventNumber(0)
148 EventHandler::~EventHandler()
152 EventHandler::EventHandlerDragState& EventHandler::dragState()
154 static EventHandlerDragState state;
158 void EventHandler::clear()
162 m_nodeUnderMouse = 0;
163 m_lastNodeUnderMouse = 0;
165 m_instanceUnderMouse = 0;
166 m_lastInstanceUnderMouse = 0;
168 m_lastMouseMoveEventSubframe = 0;
169 m_lastScrollbarUnderMouse = 0;
172 m_frameSetBeingResized = 0;
174 m_currentMousePosition = IntPoint();
175 m_mousePressNode = 0;
176 m_mousePressed = false;
177 m_capturingMouseEventsNode = 0;
180 void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result)
182 Node* innerNode = result.targetNode();
183 Selection newSelection;
185 if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
186 VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
187 if (pos.isNotNull()) {
188 newSelection = Selection(pos);
189 newSelection.expandUsingGranularity(WordGranularity);
192 if (newSelection.isRange()) {
193 m_frame->setSelectionGranularity(WordGranularity);
194 m_beganSelectingText = true;
197 if (m_frame->shouldChangeSelection(newSelection))
198 m_frame->selection()->setSelection(newSelection);
202 void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults& result)
204 if (!result.hitTestResult().isLiveLink())
205 return selectClosestWordFromMouseEvent(result);
207 Node* innerNode = result.targetNode();
209 if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
210 Selection newSelection;
211 Element* URLElement = result.hitTestResult().URLElement();
212 VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
213 if (pos.isNotNull() && pos.deepEquivalent().node()->isDescendantOf(URLElement))
214 newSelection = Selection::selectionFromContentsOfNode(URLElement);
216 if (newSelection.isRange()) {
217 m_frame->setSelectionGranularity(WordGranularity);
218 m_beganSelectingText = true;
221 if (m_frame->shouldChangeSelection(newSelection))
222 m_frame->selection()->setSelection(newSelection);
226 bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event)
228 if (event.event().button() != LeftButton)
231 if (m_frame->selection()->isRange())
232 // A double-click when range is already selected
233 // should not change the selection. So, do not call
234 // selectClosestWordFromMouseEvent, but do set
235 // m_beganSelectingText to prevent handleMouseReleaseEvent
236 // from setting caret selection.
237 m_beganSelectingText = true;
239 selectClosestWordFromMouseEvent(event);
244 bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event)
246 if (event.event().button() != LeftButton)
249 Node* innerNode = event.targetNode();
250 if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
253 Selection newSelection;
254 VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint()));
255 if (pos.isNotNull()) {
256 newSelection = Selection(pos);
257 newSelection.expandUsingGranularity(ParagraphGranularity);
259 if (newSelection.isRange()) {
260 m_frame->setSelectionGranularity(ParagraphGranularity);
261 m_beganSelectingText = true;
264 if (m_frame->shouldChangeSelection(newSelection))
265 m_frame->selection()->setSelection(newSelection);
270 bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
272 if (event.event().button() != LeftButton)
275 Node* innerNode = event.targetNode();
276 if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
279 // Extend the selection if the Shift key is down, unless the click is in a link.
280 bool extendSelection = event.event().shiftKey() && !event.isOverLink();
282 // Don't restart the selection when the mouse is pressed on an
283 // existing selection so we can allow for text dragging.
284 IntPoint vPoint = m_frame->view()->windowToContents(event.event().pos());
285 if (!extendSelection && m_frame->selection()->contains(vPoint)) {
286 m_mouseDownWasSingleClickInSelection = true;
290 VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(event.localPoint()));
291 if (visiblePos.isNull())
292 visiblePos = VisiblePosition(innerNode, 0, DOWNSTREAM);
293 Position pos = visiblePos.deepEquivalent();
295 Selection newSelection = m_frame->selection()->selection();
296 if (extendSelection && newSelection.isCaretOrRange()) {
297 m_frame->selection()->setLastChangeWasHorizontalExtension(false);
299 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection
300 // was created right-to-left
301 Position start = newSelection.start();
302 Position end = newSelection.end();
303 short before = Range::compareBoundaryPoints(pos.node(), pos.offset(), start.node(), start.offset());
305 newSelection = Selection(pos, end);
307 newSelection = Selection(start, pos);
309 if (m_frame->selectionGranularity() != CharacterGranularity)
310 newSelection.expandUsingGranularity(m_frame->selectionGranularity());
311 m_beganSelectingText = true;
313 newSelection = Selection(visiblePos);
314 m_frame->setSelectionGranularity(CharacterGranularity);
317 if (m_frame->shouldChangeSelection(newSelection))
318 m_frame->selection()->setSelection(newSelection);
323 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event)
326 dragState().m_dragSrc = 0;
328 bool singleClick = event.event().clickCount() <= 1;
330 // If we got the event back, that must mean it wasn't prevented,
331 // so it's allowed to start a drag or selection.
332 m_mouseDownMayStartSelect = canMouseDownStartSelect(event.targetNode());
334 // Careful that the drag starting logic stays in sync with eventMayStartDrag()
335 m_mouseDownMayStartDrag = singleClick;
337 m_mouseDownWasSingleClickInSelection = false;
339 if (event.isOverWidget() && passWidgetMouseDownEventToWidget(event))
343 if (m_frame->document()->isSVGDocument() &&
344 static_cast<SVGDocument*>(m_frame->document())->zoomAndPanEnabled()) {
345 if (event.event().shiftKey() && singleClick) {
347 static_cast<SVGDocument*>(m_frame->document())->startPan(event.event().pos());
353 // We don't do this at the start of mouse down handling,
354 // because we don't want to do it until we know we didn't hit a widget.
358 Node* innerNode = event.targetNode();
360 m_mousePressNode = innerNode;
361 m_dragStartPos = event.event().pos();
363 bool swallowEvent = false;
364 if (event.event().button() == LeftButton || event.event().button() == MiddleButton) {
365 m_frame->selection()->setCaretBlinkingSuspended(true);
366 m_mousePressed = true;
367 m_beganSelectingText = false;
369 if (event.event().clickCount() == 2)
370 swallowEvent = handleMousePressEventDoubleClick(event);
371 else if (event.event().clickCount() >= 3)
372 swallowEvent = handleMousePressEventTripleClick(event);
374 swallowEvent = handleMousePressEventSingleClick(event);
377 m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect ||
378 (m_mousePressNode && m_mousePressNode->renderer() && m_mousePressNode->renderer()->canBeProgramaticallyScrolled(true));
383 bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event)
385 if (handleDrag(event))
391 Node* targetNode = event.targetNode();
392 if (event.event().button() != LeftButton || !targetNode || !targetNode->renderer())
395 #if PLATFORM(MAC) // FIXME: Why does this assertion fire on other platforms?
396 ASSERT(m_mouseDownMayStartSelect || m_mouseDownMayStartAutoscroll);
399 m_mouseDownMayStartDrag = false;
401 if (m_mouseDownMayStartAutoscroll && !m_panScrollInProgress) {
402 // If the selection is contained in a layer that can scroll, that layer should handle the autoscroll
403 // Otherwise, let the bridge handle it so the view can scroll itself.
404 RenderObject* renderer = targetNode->renderer();
405 while (renderer && !renderer->canBeProgramaticallyScrolled(false)) {
406 if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement())
407 renderer = renderer->document()->ownerElement()->renderer();
409 renderer = renderer->parent();
413 m_autoscrollInProgress = true;
414 handleAutoscroll(renderer);
417 m_mouseDownMayStartAutoscroll = false;
420 updateSelectionForMouseDrag(targetNode, event.localPoint());
424 bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const
426 // This is a pre-flight check of whether the event might lead to a drag being started. Be careful
427 // that its logic needs to stay in sync with handleMouseMoveEvent() and the way we setMouseDownMayStartDrag
428 // in handleMousePressEvent
430 if (!m_frame->contentRenderer() || !m_frame->contentRenderer()->hasLayer()
431 || event.button() != LeftButton || event.clickCount() != 1)
436 allowDHTMLDrag(DHTMLFlag, UAFlag);
437 if (!DHTMLFlag && !UAFlag)
440 HitTestRequest request(true, false);
441 HitTestResult result(m_frame->view()->windowToContents(event.pos()));
442 m_frame->contentRenderer()->layer()->hitTest(request, result);
444 return result.innerNode() && result.innerNode()->renderer()->draggableNode(DHTMLFlag, UAFlag, result.point().x(), result.point().y(), srcIsDHTML);
447 void EventHandler::updateSelectionForMouseDrag()
449 FrameView* view = m_frame->view();
452 RenderObject* renderer = m_frame->contentRenderer();
455 RenderLayer* layer = renderer->layer();
459 HitTestResult result(view->windowToContents(m_currentMousePosition));
460 layer->hitTest(HitTestRequest(true, true, true), result);
461 updateSelectionForMouseDrag(result.innerNode(), result.localPoint());
464 void EventHandler::updateSelectionForMouseDrag(Node* targetNode, const IntPoint& localPoint)
466 if (!m_mouseDownMayStartSelect)
472 RenderObject* targetRenderer = targetNode->renderer();
476 if (!canMouseDragExtendSelect(targetNode))
479 VisiblePosition targetPosition(targetRenderer->positionForPoint(localPoint));
481 // Don't modify the selection if we're not on a node.
482 if (targetPosition.isNull())
485 // Restart the selection if this is the first mouse move. This work is usually
486 // done in handleMousePressEvent, but not if the mouse press was on an existing selection.
487 Selection newSelection = m_frame->selection()->selection();
490 // Special case to limit selection to the containing block for SVG text.
491 // FIXME: Isn't there a better non-SVG-specific way to do this?
492 if (Node* selectionBaseNode = newSelection.base().node())
493 if (RenderObject* selectionBaseRenderer = selectionBaseNode->renderer())
494 if (selectionBaseRenderer->isSVGText())
495 if (targetNode->renderer()->containingBlock() != selectionBaseRenderer->containingBlock())
499 if (!m_beganSelectingText) {
500 m_beganSelectingText = true;
501 newSelection = Selection(targetPosition);
504 newSelection.setExtent(targetPosition);
505 if (m_frame->selectionGranularity() != CharacterGranularity)
506 newSelection.expandUsingGranularity(m_frame->selectionGranularity());
508 if (m_frame->shouldChangeSelection(newSelection)) {
509 m_frame->selection()->setLastChangeWasHorizontalExtension(false);
510 m_frame->selection()->setSelection(newSelection);
514 bool EventHandler::handleMouseUp(const MouseEventWithHitTestResults& event)
516 if (eventLoopHandleMouseUp(event))
519 // If this was the first click in the window, we don't even want to clear the selection.
520 // This case occurs when the user clicks on a draggable element, since we have to process
521 // the mouse down and drag events to see if we might start a drag. For other first clicks
522 // in a window, we just don't acceptFirstMouse, and the whole down-drag-up sequence gets
523 // ignored upstream of this layer.
524 return eventActivatedView(event.event());
527 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
529 if (m_autoscrollInProgress)
530 stopAutoscrollTimer();
532 if (handleMouseUp(event))
535 // Used to prevent mouseMoveEvent from initiating a drag before
536 // the mouse is pressed again.
537 m_frame->selection()->setCaretBlinkingSuspended(false);
538 m_mousePressed = false;
539 m_mouseDownMayStartDrag = false;
540 m_mouseDownMayStartSelect = false;
541 m_mouseDownMayStartAutoscroll = false;
542 m_mouseDownWasInSubframe = false;
544 bool handled = false;
546 // Clear the selection if the mouse didn't move after the last mouse press.
547 // We do this so when clicking on the selection, the selection goes away.
548 // However, if we are editing, place the caret.
549 if (m_mouseDownWasSingleClickInSelection && !m_beganSelectingText
550 && m_dragStartPos == event.event().pos()
551 && m_frame->selection()->isRange()) {
552 Selection newSelection;
553 Node *node = event.targetNode();
554 if (node && node->isContentEditable() && node->renderer()) {
555 VisiblePosition pos = node->renderer()->positionForPoint(event.localPoint());
556 newSelection = Selection(pos);
558 if (m_frame->shouldChangeSelection(newSelection))
559 m_frame->selection()->setSelection(newSelection);
564 m_frame->notifyRendererOfSelectionChange(true);
566 m_frame->selection()->selectFrameElementInParentIfFullySelected();
571 void EventHandler::handleAutoscroll(RenderObject* renderer)
573 // We don't want to trigger the autoscroll or the panScroll if it's already active
574 if (m_autoscrollTimer.isActive())
577 setAutoscrollRenderer(renderer);
579 #if ENABLE(PAN_SCROLLING)
580 if (m_panScrollInProgress) {
581 m_panScrollStartPos = currentMousePosition();
582 m_frame->view()->addPanScrollIcon(m_panScrollStartPos);
583 // If we're not in the top frame we notify it that we are using the panScroll
584 if (m_frame != m_frame->page()->mainFrame())
585 m_frame->page()->mainFrame()->eventHandler()->setPanScrollInProgress(true);
589 startAutoscrollTimer();
592 void EventHandler::autoscrollTimerFired(Timer<EventHandler>*)
594 RenderObject* r = autoscrollRenderer();
596 stopAutoscrollTimer();
600 if (m_autoscrollInProgress) {
601 if (!m_mousePressed) {
602 stopAutoscrollTimer();
607 // we verify that the main frame hasn't received the order to stop the panScroll
608 if (!m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress()) {
609 stopAutoscrollTimer();
612 #if ENABLE(PAN_SCROLLING)
613 setPanScrollCursor();
614 r->panScroll(m_panScrollStartPos);
619 void EventHandler::setPanScrollCursor()
621 // At the original click location we draw a 4 arrowed icon. Over this icon there won't be any scroll
622 // So we don't want to change the cursor over this area
623 const int noScrollRadius = 9;
624 bool east = m_panScrollStartPos.x() < (m_currentMousePosition.x() - noScrollRadius);
625 bool west = m_panScrollStartPos.x() > (m_currentMousePosition.x() + noScrollRadius);
626 bool north = m_panScrollStartPos.y() > (m_currentMousePosition.y() + noScrollRadius);
627 bool south = m_panScrollStartPos.y() < (m_currentMousePosition.y() - noScrollRadius);
631 m_frame->view()->setCursor(northEastPanningCursor());
633 m_frame->view()->setCursor(northWestPanningCursor());
635 m_frame->view()->setCursor(northPanningCursor());
638 m_frame->view()->setCursor(southEastPanningCursor());
640 m_frame->view()->setCursor(southWestPanningCursor());
642 m_frame->view()->setCursor(southPanningCursor());
644 m_frame->view()->setCursor(eastPanningCursor());
646 m_frame->view()->setCursor(westPanningCursor());
648 m_frame->view()->setCursor(middlePanningCursor());
651 RenderObject* EventHandler::autoscrollRenderer() const
653 return m_autoscrollRenderer;
656 void EventHandler::updateAutoscrollRenderer()
658 if (!m_autoscrollRenderer)
661 HitTestResult hitTest = hitTestResultAtPoint(m_panScrollStartPos, true);
663 if (Node* nodeAtPoint = hitTest.innerNode())
664 m_autoscrollRenderer = nodeAtPoint->renderer();
666 while (m_autoscrollRenderer && !m_autoscrollRenderer->canBeProgramaticallyScrolled(false))
667 m_autoscrollRenderer = m_autoscrollRenderer->parent();
670 void EventHandler::setAutoscrollRenderer(RenderObject* renderer)
672 m_autoscrollRenderer = renderer;
675 void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const
677 if (!m_frame || !m_frame->document()) {
682 unsigned mask = m_frame->page()->dragController()->delegateDragSourceAction(m_frame->view()->contentsToWindow(m_mouseDownPos));
683 flagDHTML = (mask & DragSourceActionDHTML) != DragSourceActionNone;
684 flagUA = ((mask & DragSourceActionImage) || (mask & DragSourceActionLink) || (mask & DragSourceActionSelection));
687 HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent)
689 HitTestResult result(point);
690 if (!m_frame->contentRenderer())
692 m_frame->contentRenderer()->layer()->hitTest(HitTestRequest(true, true), result);
695 Node* n = result.innerNode();
696 if (!result.isOverWidget() || !n || !n->renderer() || !n->renderer()->isWidget())
698 Widget* widget = static_cast<RenderWidget*>(n->renderer())->widget();
699 if (!widget || !widget->isFrameView())
701 Frame* frame = static_cast<HTMLFrameElementBase*>(n)->contentFrame();
702 if (!frame || !frame->contentRenderer())
704 FrameView* view = static_cast<FrameView*>(widget);
705 IntPoint widgetPoint(result.localPoint().x() + view->scrollX() - n->renderer()->borderLeft() - n->renderer()->paddingLeft(),
706 result.localPoint().y() + view->scrollY() - n->renderer()->borderTop() - n->renderer()->paddingTop());
707 HitTestResult widgetHitTestResult(widgetPoint);
708 frame->contentRenderer()->layer()->hitTest(HitTestRequest(true, true), widgetHitTestResult);
709 result = widgetHitTestResult;
712 // If our HitTestResult is not visible, then we started hit testing too far down the frame chain.
713 // Another hit test at the main frame level should get us the correct visible result.
714 Frame* resultFrame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : 0;
715 Frame* mainFrame = m_frame->page()->mainFrame();
716 if (m_frame != mainFrame && resultFrame && resultFrame != mainFrame && !resultFrame->editor()->insideVisibleArea(result.point())) {
717 IntPoint windowPoint = resultFrame->view()->contentsToWindow(result.point());
718 IntPoint mainFramePoint = mainFrame->view()->windowToContents(windowPoint);
719 result = mainFrame->eventHandler()->hitTestResultAtPoint(mainFramePoint, allowShadowContent);
722 if (!allowShadowContent)
723 result.setToNonShadowAncestor();
729 void EventHandler::startAutoscrollTimer()
731 m_autoscrollTimer.startRepeating(autoscrollInterval);
734 void EventHandler::stopAutoscrollTimer(bool rendererIsBeingDestroyed)
736 if (m_autoscrollInProgress) {
737 if (m_mouseDownWasInSubframe) {
738 if (Frame* subframe = subframeForTargetNode(m_mousePressNode.get()))
739 subframe->eventHandler()->stopAutoscrollTimer(rendererIsBeingDestroyed);
744 if (autoscrollRenderer()) {
745 if (!rendererIsBeingDestroyed && (m_autoscrollInProgress || m_panScrollInProgress))
746 autoscrollRenderer()->stopAutoscroll();
747 #if ENABLE(PAN_SCROLLING)
748 if (m_panScrollInProgress) {
749 m_frame->view()->removePanScrollIcon();
750 m_frame->view()->setCursor(pointerCursor());
754 setAutoscrollRenderer(0);
757 m_autoscrollTimer.stop();
759 m_panScrollInProgress = false;
760 // If we're not in the top frame we notify it that we are not using the panScroll anymore
761 if (m_frame->page() && m_frame != m_frame->page()->mainFrame())
762 m_frame->page()->mainFrame()->eventHandler()->setPanScrollInProgress(false);
763 m_autoscrollInProgress = false;
766 Node* EventHandler::mousePressNode() const
768 return m_mousePressNode.get();
771 void EventHandler::setMousePressNode(PassRefPtr<Node> node)
773 m_mousePressNode = node;
776 bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity)
778 if (!m_frame->document())
781 Node* node = m_frame->document()->focusedNode();
783 node = m_mousePressNode.get();
786 RenderObject *r = node->renderer();
787 if (r && !r->isListBox())
788 return r->scroll(direction, granularity);
794 IntPoint EventHandler::currentMousePosition() const
796 return m_currentMousePosition;
799 Frame* subframeForHitTestResult(const MouseEventWithHitTestResults& hitTestResult)
801 if (!hitTestResult.isOverWidget())
803 return subframeForTargetNode(hitTestResult.targetNode());
806 Frame* subframeForTargetNode(Node* node)
811 RenderObject* renderer = node->renderer();
812 if (!renderer || !renderer->isWidget())
815 Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
816 if (!widget || !widget->isFrameView())
819 return static_cast<FrameView*>(widget)->frame();
822 static bool isSubmitImage(Node* node)
824 return node && node->hasTagName(inputTag)
825 && static_cast<HTMLInputElement*>(node)->inputType() == HTMLInputElement::IMAGE;
828 // Returns true if the node's editable block is not current focused for editing
829 static bool nodeIsNotBeingEdited(Node* node, Frame* frame)
831 return frame->selection()->rootEditableElement() != node->rootEditableElement();
834 Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Scrollbar* scrollbar)
836 // During selection, use an I-beam no matter what we're over.
837 // If you're capturing mouse events for a particular node, don't treat this as a selection.
838 if (m_mousePressed && m_mouseDownMayStartSelect && m_frame->selection()->isCaretOrRange() && !m_capturingMouseEventsNode)
839 return iBeamCursor();
841 Node* node = event.targetNode();
842 RenderObject* renderer = node ? node->renderer() : 0;
843 RenderStyle* style = renderer ? renderer->style() : 0;
845 if (renderer && renderer->isFrameSet()) {
846 RenderFrameSet* fs = static_cast<RenderFrameSet*>(renderer);
847 if (fs->canResizeRow(event.localPoint()))
848 return rowResizeCursor();
849 if (fs->canResizeColumn(event.localPoint()))
850 return columnResizeCursor();
853 if (style && style->cursors()) {
854 const CursorList* cursors = style->cursors();
855 for (unsigned i = 0; i < cursors->size(); ++i) {
856 CachedImage* cimage = (*cursors)[i].cursorImage.get();
857 IntPoint hotSpot = (*cursors)[i].hotSpot;
860 // Limit the size of cursors so that they cannot be used to cover UI elements in chrome.
861 IntSize size = cimage->image()->size();
862 if (size.width() > 128 || size.height() > 128)
864 // Do not let the hotspot be outside the bounds of the image.
865 if (hotSpot.x() < 0 || hotSpot.y() < 0 || hotSpot.x() > size.width() || hotSpot.y() > size.height())
867 if (cimage->image()->isNull())
869 if (!cimage->errorOccurred())
870 return Cursor(cimage->image(), hotSpot);
874 switch (style ? style->cursor() : CURSOR_AUTO) {
876 bool editable = (node && node->isContentEditable());
877 bool editableLinkEnabled = false;
879 // If the link is editable, then we need to check the settings to see whether or not the link should be followed
881 ASSERT(m_frame->settings());
882 switch(m_frame->settings()->editableLinkBehavior()) {
884 case EditableLinkDefaultBehavior:
885 case EditableLinkAlwaysLive:
886 editableLinkEnabled = true;
889 case EditableLinkNeverLive:
890 editableLinkEnabled = false;
893 case EditableLinkLiveWhenNotFocused:
894 editableLinkEnabled = nodeIsNotBeingEdited(node, m_frame) || event.event().shiftKey();
897 case EditableLinkOnlyLiveWithShiftKey:
898 editableLinkEnabled = event.event().shiftKey();
903 if ((event.isOverLink() || isSubmitImage(node)) && (!editable || editableLinkEnabled))
905 RenderLayer* layer = renderer ? renderer->enclosingLayer() : 0;
906 bool inResizer = false;
907 if (m_frame->view() && layer && layer->isPointInResizeControl(m_frame->view()->windowToContents(event.event().pos())))
909 if ((editable || (renderer && renderer->isText() && node->canStartSelection())) && !inResizer && !scrollbar)
910 return iBeamCursor();
911 return pointerCursor();
914 return crossCursor();
919 case CURSOR_ALL_SCROLL:
921 case CURSOR_E_RESIZE:
922 return eastResizeCursor();
923 case CURSOR_W_RESIZE:
924 return westResizeCursor();
925 case CURSOR_N_RESIZE:
926 return northResizeCursor();
927 case CURSOR_S_RESIZE:
928 return southResizeCursor();
929 case CURSOR_NE_RESIZE:
930 return northEastResizeCursor();
931 case CURSOR_SW_RESIZE:
932 return southWestResizeCursor();
933 case CURSOR_NW_RESIZE:
934 return northWestResizeCursor();
935 case CURSOR_SE_RESIZE:
936 return southEastResizeCursor();
937 case CURSOR_NS_RESIZE:
938 return northSouthResizeCursor();
939 case CURSOR_EW_RESIZE:
940 return eastWestResizeCursor();
941 case CURSOR_NESW_RESIZE:
942 return northEastSouthWestResizeCursor();
943 case CURSOR_NWSE_RESIZE:
944 return northWestSouthEastResizeCursor();
945 case CURSOR_COL_RESIZE:
946 return columnResizeCursor();
947 case CURSOR_ROW_RESIZE:
948 return rowResizeCursor();
950 return iBeamCursor();
955 case CURSOR_VERTICAL_TEXT:
956 return verticalTextCursor();
959 case CURSOR_CONTEXT_MENU:
960 return contextMenuCursor();
961 case CURSOR_PROGRESS:
962 return progressCursor();
964 return noDropCursor();
966 return aliasCursor();
971 case CURSOR_NOT_ALLOWED:
972 return notAllowedCursor();
974 return pointerCursor();
975 case CURSOR_WEBKIT_ZOOM_IN:
976 return zoomInCursor();
977 case CURSOR_WEBKIT_ZOOM_OUT:
978 return zoomOutCursor();
980 return pointerCursor();
983 bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
985 if (!m_frame->document())
988 RefPtr<FrameView> protector(m_frame->view());
990 m_mousePressed = true;
991 m_currentMousePosition = mouseEvent.pos();
992 m_mouseDownTimestamp = mouseEvent.timestamp();
993 m_mouseDownMayStartDrag = false;
994 m_mouseDownMayStartSelect = false;
995 m_mouseDownMayStartAutoscroll = false;
996 m_mouseDownPos = m_frame->view()->windowToContents(mouseEvent.pos());
997 m_mouseDownWasInSubframe = false;
999 MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, true), mouseEvent);
1001 if (!mev.targetNode()) {
1006 m_mousePressNode = mev.targetNode();
1008 InspectorController* inspector = m_frame->page()->inspectorController();
1009 if (inspector && inspector->enabled() && inspector->searchingForNodeInPage()) {
1010 inspector->handleMousePressOnNode(m_mousePressNode.get());
1015 Frame* subframe = subframeForHitTestResult(mev);
1016 if (subframe && passMousePressEventToSubframe(mev, subframe)) {
1017 // Start capturing future events for this frame. We only do this if we didn't clear
1018 // the m_mousePressed flag, which may happen if an AppKit widget entered a modal event loop.
1020 m_capturingMouseEventsNode = mev.targetNode();
1025 #if ENABLE(PAN_SCROLLING)
1026 if (m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress) {
1027 stopAutoscrollTimer();
1032 if (mouseEvent.button() == MiddleButton && !mev.isOverLink()) {
1033 RenderObject* renderer = mev.targetNode()->renderer();
1035 while (renderer && !renderer->canBeProgramaticallyScrolled(false)) {
1036 if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement())
1037 renderer = renderer->document()->ownerElement()->renderer();
1039 renderer = renderer->parent();
1043 m_panScrollInProgress = true;
1044 handleAutoscroll(renderer);
1051 m_clickCount = mouseEvent.clickCount();
1052 m_clickNode = mev.targetNode();
1054 RenderLayer* layer = m_clickNode->renderer() ? m_clickNode->renderer()->enclosingLayer() : 0;
1055 IntPoint p = m_frame->view()->windowToContents(mouseEvent.pos());
1056 if (layer && layer->isPointInResizeControl(p)) {
1057 layer->setInResizeMode(true);
1058 m_resizeLayer = layer;
1059 m_offsetFromResizeCorner = layer->offsetFromResizeCorner(p);
1064 bool swallowEvent = dispatchMouseEvent(mousedownEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
1066 // If the hit testing originally determined the event was in a scrollbar, refetch the MouseEventWithHitTestResults
1067 // in case the scrollbar widget was destroyed when the mouse event was handled.
1068 if (mev.scrollbar()) {
1069 const bool wasLastScrollBar = mev.scrollbar() == m_lastScrollbarUnderMouse.get();
1070 mev = prepareMouseEvent(HitTestRequest(true, true), mouseEvent);
1072 if (wasLastScrollBar && mev.scrollbar() != m_lastScrollbarUnderMouse.get())
1073 m_lastScrollbarUnderMouse = 0;
1077 // scrollbars should get events anyway, even disabled controls might be scrollable
1078 if (mev.scrollbar())
1079 passMousePressEventToScrollbar(mev, mev.scrollbar());
1081 // Refetch the event target node if it currently is the shadow node inside an <input> element.
1082 // If a mouse event handler changes the input element type to one that has a widget associated,
1083 // we'd like to EventHandler::handleMousePressEvent to pass the event to the widget and thus the
1084 // event target node can't still be the shadow node.
1085 if (mev.targetNode()->isShadowNode() && mev.targetNode()->shadowParentNode()->hasTagName(inputTag))
1086 mev = prepareMouseEvent(HitTestRequest(true, true), mouseEvent);
1088 Scrollbar* scrollbar = m_frame->view()->scrollbarUnderMouse(mouseEvent);
1090 scrollbar = mev.scrollbar();
1091 if (scrollbar && passMousePressEventToScrollbar(mev, scrollbar))
1092 swallowEvent = true;
1094 swallowEvent = handleMousePressEvent(mev);
1097 return swallowEvent;
1100 // This method only exists for platforms that don't know how to deliver
1101 bool EventHandler::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent)
1103 if (!m_frame->document())
1106 RefPtr<FrameView> protector(m_frame->view());
1108 // We get this instead of a second mouse-up
1109 m_mousePressed = false;
1110 m_currentMousePosition = mouseEvent.pos();
1112 MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, true), mouseEvent);
1113 Frame* subframe = subframeForHitTestResult(mev);
1114 if (subframe && passMousePressEventToSubframe(mev, subframe)) {
1115 m_capturingMouseEventsNode = 0;
1119 m_clickCount = mouseEvent.clickCount();
1120 bool swallowMouseUpEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode(), true, m_clickCount, mouseEvent, false);
1122 bool swallowClickEvent = false;
1123 // Don't ever dispatch click events for right clicks
1124 if (mouseEvent.button() != RightButton && mev.targetNode() == m_clickNode)
1125 swallowClickEvent = dispatchMouseEvent(clickEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
1127 if (m_lastScrollbarUnderMouse)
1128 swallowMouseUpEvent = m_lastScrollbarUnderMouse->mouseUp();
1130 bool swallowMouseReleaseEvent = false;
1131 if (!swallowMouseUpEvent)
1132 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev);
1136 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
1139 bool EventHandler::mouseMoved(const PlatformMouseEvent& event)
1141 HitTestResult hoveredNode = HitTestResult(IntPoint());
1142 bool result = handleMouseMoveEvent(event, &hoveredNode);
1144 Page* page = m_frame->page();
1148 hoveredNode.setToNonShadowAncestor();
1149 page->chrome()->mouseDidMoveOverElement(hoveredNode, event.modifierFlags());
1150 page->chrome()->setToolTip(hoveredNode);
1154 bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, HitTestResult* hoveredNode)
1156 // in Radar 3703768 we saw frequent crashes apparently due to the
1157 // part being null here, which seems impossible, so check for nil
1158 // but also assert so that we can try to figure this out in debug
1159 // builds, if it happens.
1161 if (!m_frame || !m_frame->document())
1164 RefPtr<FrameView> protector(m_frame->view());
1165 m_currentMousePosition = mouseEvent.pos();
1167 if (m_hoverTimer.isActive())
1168 m_hoverTimer.stop();
1172 static_cast<SVGDocument*>(m_frame->document())->updatePan(m_currentMousePosition);
1177 if (m_frameSetBeingResized)
1178 return dispatchMouseEvent(mousemoveEvent, m_frameSetBeingResized.get(), false, 0, mouseEvent, false);
1180 // Send events right to a scrollbar if the mouse is pressed.
1181 if (m_lastScrollbarUnderMouse && m_mousePressed)
1182 return m_lastScrollbarUnderMouse->mouseMoved(m_lastScrollbarUnderMouse->transformEvent(mouseEvent));
1184 // Treat mouse move events while the mouse is pressed as "read-only" in prepareMouseEvent
1185 // if we are allowed to select.
1186 // This means that :hover and :active freeze in the state they were in when the mouse
1187 // was pressed, rather than updating for nodes the mouse moves over as you hold the mouse down.
1188 HitTestRequest request(m_mousePressed && m_mouseDownMayStartSelect, m_mousePressed, true);
1189 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
1191 *hoveredNode = mev.hitTestResult();
1193 Scrollbar* scrollbar = 0;
1195 if (m_resizeLayer && m_resizeLayer->inResizeMode())
1196 m_resizeLayer->resize(mouseEvent, m_offsetFromResizeCorner);
1198 if (m_frame->view())
1199 scrollbar = m_frame->view()->scrollbarUnderMouse(mouseEvent);
1202 scrollbar = mev.scrollbar();
1204 if (m_lastScrollbarUnderMouse != scrollbar) {
1205 // Send mouse exited to the old scrollbar.
1206 if (m_lastScrollbarUnderMouse)
1207 m_lastScrollbarUnderMouse->mouseExited();
1208 m_lastScrollbarUnderMouse = m_mousePressed ? 0 : scrollbar;
1212 bool swallowEvent = false;
1213 RefPtr<Frame> newSubframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev);
1215 // 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.
1216 if (m_lastMouseMoveEventSubframe && m_lastMouseMoveEventSubframe->tree()->isDescendantOf(m_frame) && m_lastMouseMoveEventSubframe != newSubframe)
1217 passMouseMoveEventToSubframe(mev, m_lastMouseMoveEventSubframe.get());
1220 // Update over/out state before passing the event to the subframe.
1221 updateMouseEventTargetNode(mev.targetNode(), mouseEvent, true);
1223 // Event dispatch in updateMouseEventTargetNode may have caused the subframe of the target
1224 // node to be detached from its FrameView, in which case the event should not be passed.
1225 if (newSubframe->view())
1226 swallowEvent |= passMouseMoveEventToSubframe(mev, newSubframe.get(), hoveredNode);
1228 if (scrollbar && !m_mousePressed)
1229 scrollbar->mouseMoved(scrollbar->transformEvent(mouseEvent)); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
1230 if ((!m_resizeLayer || !m_resizeLayer->inResizeMode()) && !m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress() && m_frame->view())
1231 m_frame->view()->setCursor(selectCursor(mev, scrollbar));
1234 m_lastMouseMoveEventSubframe = newSubframe;
1239 swallowEvent = dispatchMouseEvent(mousemoveEvent, mev.targetNode(), false, 0, mouseEvent, true);
1241 swallowEvent = handleMouseDraggedEvent(mev);
1243 return swallowEvent;
1246 void EventHandler::invalidateClick()
1252 bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
1254 if (!m_frame->document())
1257 RefPtr<FrameView> protector(m_frame->view());
1259 m_mousePressed = false;
1260 m_currentMousePosition = mouseEvent.pos();
1265 static_cast<SVGDocument*>(m_frame->document())->updatePan(m_currentMousePosition);
1270 if (m_frameSetBeingResized)
1271 return dispatchMouseEvent(mouseupEvent, m_frameSetBeingResized.get(), true, m_clickCount, mouseEvent, false);
1273 if (m_lastScrollbarUnderMouse) {
1275 return m_lastScrollbarUnderMouse->mouseUp();
1278 MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, false, false, true), mouseEvent);
1279 Frame* subframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev);
1280 if (subframe && passMouseReleaseEventToSubframe(mev, subframe)) {
1281 m_capturingMouseEventsNode = 0;
1285 bool swallowMouseUpEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode(), true, m_clickCount, mouseEvent, false);
1287 // Don't ever dispatch click events for right clicks
1288 bool swallowClickEvent = false;
1289 if (m_clickCount > 0 && mouseEvent.button() != RightButton && mev.targetNode() == m_clickNode)
1290 swallowClickEvent = dispatchMouseEvent(clickEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
1292 if (m_resizeLayer) {
1293 m_resizeLayer->setInResizeMode(false);
1297 bool swallowMouseReleaseEvent = false;
1298 if (!swallowMouseUpEvent)
1299 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev);
1303 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
1306 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard)
1308 IntPoint contentsPos = m_frame->view()->windowToContents(event.pos());
1310 RefPtr<MouseEvent> me = MouseEvent::create(eventType,
1311 true, true, m_frame->document()->defaultView(),
1312 0, event.globalX(), event.globalY(), contentsPos.x(), contentsPos.y(),
1313 event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
1316 ExceptionCode ec = 0;
1317 EventTargetNodeCast(dragTarget)->dispatchEvent(me.get(), ec, true);
1318 return me->defaultPrevented();
1321 bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
1323 bool accept = false;
1325 if (!m_frame->document())
1328 if (!m_frame->view())
1331 MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(true, false), event);
1333 // Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
1334 Node* newTarget = mev.targetNode();
1335 if (newTarget && newTarget->isTextNode())
1336 newTarget = newTarget->parentNode();
1338 newTarget = newTarget->shadowAncestorNode();
1340 if (m_dragTarget != newTarget) {
1341 // FIXME: this ordering was explicitly chosen to match WinIE. However,
1342 // it is sometimes incorrect when dragging within subframes, as seen with
1343 // LayoutTests/fast/events/drag-in-frames.html.
1345 if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag))
1346 accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->eventHandler()->updateDragAndDrop(event, clipboard);
1348 accept = dispatchDragEvent(dragenterEvent, newTarget, event, clipboard);
1351 Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag))
1352 ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0;
1354 accept = frame->eventHandler()->updateDragAndDrop(event, clipboard);
1356 dispatchDragEvent(dragleaveEvent, m_dragTarget.get(), event, clipboard);
1360 if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag))
1361 accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->eventHandler()->updateDragAndDrop(event, clipboard);
1363 accept = dispatchDragEvent(dragoverEvent, newTarget, event, clipboard);
1365 m_dragTarget = newTarget;
1370 void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
1373 Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag))
1374 ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0;
1376 frame->eventHandler()->cancelDragAndDrop(event, clipboard);
1378 dispatchDragEvent(dragleaveEvent, m_dragTarget.get(), event, clipboard);
1383 bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
1385 bool accept = false;
1387 Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag))
1388 ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0;
1390 accept = frame->eventHandler()->performDragAndDrop(event, clipboard);
1392 accept = dispatchDragEvent(dropEvent, m_dragTarget.get(), event, clipboard);
1398 void EventHandler::clearDragState()
1401 m_capturingMouseEventsNode = 0;
1403 m_sendingEventToSubview = false;
1407 void EventHandler::setCapturingMouseEventsNode(PassRefPtr<Node> n)
1409 m_capturingMouseEventsNode = n;
1412 MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestRequest& request, const PlatformMouseEvent& mev)
1415 ASSERT(m_frame->document());
1417 IntPoint documentPoint = m_frame->view()->windowToContents(mev.pos());
1418 return m_frame->document()->prepareMouseEvent(request, documentPoint, mev);
1422 static inline SVGElementInstance* instanceAssociatedWithShadowTreeElement(Node* referenceNode)
1424 if (!referenceNode || !referenceNode->isSVGElement())
1427 Node* shadowTreeElement = referenceNode->shadowTreeRootNode();
1428 if (!shadowTreeElement)
1431 Node* shadowTreeParentElement = shadowTreeElement->shadowParentNode();
1432 if (!shadowTreeParentElement)
1435 ASSERT(shadowTreeParentElement->hasTagName(useTag));
1436 return static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode);
1440 void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMouseEvent& mouseEvent, bool fireMouseOverOut)
1442 Node* result = targetNode;
1444 // If we're capturing, we always go right to that node.
1445 if (m_capturingMouseEventsNode)
1446 result = m_capturingMouseEventsNode.get();
1448 // If the target node is a text node, dispatch on the parent node - rdar://4196646
1449 if (result && result->isTextNode())
1450 result = result->parentNode();
1452 result = result->shadowAncestorNode();
1454 m_nodeUnderMouse = result;
1456 m_instanceUnderMouse = instanceAssociatedWithShadowTreeElement(result);
1458 // <use> shadow tree elements may have been recloned, update node under mouse in any case
1459 if (m_lastInstanceUnderMouse) {
1460 SVGElement* lastCorrespondingElement = m_lastInstanceUnderMouse->correspondingElement();
1461 SVGElement* lastCorrespondingUseElement = m_lastInstanceUnderMouse->correspondingUseElement();
1463 if (lastCorrespondingElement && lastCorrespondingUseElement) {
1464 HashSet<SVGElementInstance*> instances = lastCorrespondingElement->instancesForElement();
1466 // Locate the recloned shadow tree element for our corresponding instance
1467 HashSet<SVGElementInstance*>::iterator end = instances.end();
1468 for (HashSet<SVGElementInstance*>::iterator it = instances.begin(); it != end; ++it) {
1469 SVGElementInstance* instance = (*it);
1470 ASSERT(instance->correspondingElement() == lastCorrespondingElement);
1472 if (instance == m_lastInstanceUnderMouse)
1475 if (instance->correspondingUseElement() != lastCorrespondingUseElement)
1478 SVGElement* shadowTreeElement = instance->shadowTreeElement();
1479 if (!shadowTreeElement->inDocument() || m_lastNodeUnderMouse == shadowTreeElement)
1482 m_lastNodeUnderMouse = shadowTreeElement;
1483 m_lastInstanceUnderMouse = instance;
1490 // Fire mouseout/mouseover if the mouse has shifted to a different node.
1491 if (fireMouseOverOut) {
1492 if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame->document()) {
1493 m_lastNodeUnderMouse = 0;
1494 m_lastScrollbarUnderMouse = 0;
1496 m_lastInstanceUnderMouse = 0;
1500 if (m_lastNodeUnderMouse != m_nodeUnderMouse) {
1501 // send mouseout event to the old node
1502 if (m_lastNodeUnderMouse)
1503 EventTargetNodeCast(m_lastNodeUnderMouse.get())->dispatchMouseEvent(mouseEvent, mouseoutEvent, 0, m_nodeUnderMouse.get());
1504 // send mouseover event to the new node
1505 if (m_nodeUnderMouse)
1506 EventTargetNodeCast(m_nodeUnderMouse.get())->dispatchMouseEvent(mouseEvent, mouseoverEvent, 0, m_lastNodeUnderMouse.get());
1508 m_lastNodeUnderMouse = m_nodeUnderMouse;
1510 m_lastInstanceUnderMouse = instanceAssociatedWithShadowTreeElement(m_nodeUnderMouse.get());
1515 bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool cancelable, int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder)
1517 updateMouseEventTargetNode(targetNode, mouseEvent, setUnder);
1519 bool swallowEvent = false;
1521 if (m_nodeUnderMouse)
1522 swallowEvent = EventTargetNodeCast(m_nodeUnderMouse.get())->dispatchMouseEvent(mouseEvent, eventType, clickCount);
1524 if (!swallowEvent && eventType == mousedownEvent) {
1525 // Blur current focus node when a link/button is clicked; this
1526 // is expected by some sites that rely on onChange handlers running
1527 // from form fields before the button click is processed.
1528 Node* node = m_nodeUnderMouse.get();
1529 RenderObject* renderer = node ? node->renderer() : 0;
1531 // Walk up the render tree to search for a node to focus.
1532 // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
1534 node = renderer->element();
1535 if (node && node->isFocusable()) {
1536 // To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus a
1537 // node on mouse down if it's selected and inside a focused node. It will be
1538 // focused if the user does a mouseup over it, however, because the mouseup
1539 // will set a selection inside it, which will call setFocuseNodeIfNeeded.
1540 ExceptionCode ec = 0;
1541 Node* n = node->isShadowNode() ? node->shadowParentNode() : node;
1542 if (m_frame->selection()->isRange() &&
1543 m_frame->selection()->toRange()->compareNode(n, ec) == Range::NODE_INSIDE &&
1544 n->isDescendantOf(m_frame->document()->focusedNode()))
1550 renderer = renderer->parent();
1552 // If focus shift is blocked, we eat the event. Note we should never clear swallowEvent
1553 // if the page already set it (e.g., by canceling default behavior).
1554 if (node && node->isMouseFocusable()) {
1555 if (!m_frame->page()->focusController()->setFocusedNode(node, m_frame))
1556 swallowEvent = true;
1557 } else if (!node || !node->focused()) {
1558 if (!m_frame->page()->focusController()->setFocusedNode(0, m_frame))
1559 swallowEvent = true;
1563 return swallowEvent;
1566 bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
1568 Document* doc = m_frame->document();
1572 RenderObject* docRenderer = doc->renderer();
1576 IntPoint vPoint = m_frame->view()->windowToContents(e.pos());
1578 HitTestRequest request(true, false);
1579 HitTestResult result(vPoint);
1580 doc->renderer()->layer()->hitTest(request, result);
1581 Node* node = result.innerNode();
1584 // Figure out which view to send the event to.
1585 RenderObject* target = node->renderer();
1587 if (result.isOverWidget() && target && target->isWidget()) {
1588 Widget* widget = static_cast<RenderWidget*>(target)->widget();
1590 if (widget && passWheelEventToWidget(e, widget)) {
1596 node = node->shadowAncestorNode();
1597 EventTargetNodeCast(node)->dispatchWheelEvent(e);
1601 if (node->renderer()) {
1602 // Just break up into two scrolls if we need to. Diagonal movement on
1603 // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
1604 scrollAndAcceptEvent(e.deltaX(), ScrollLeft, ScrollRight, e, node);
1605 scrollAndAcceptEvent(e.deltaY(), ScrollUp, ScrollDown, e, node);
1609 if (!e.isAccepted())
1610 m_frame->view()->wheelEvent(e);
1612 return e.isAccepted();
1615 bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event)
1617 Document* doc = m_frame->document();
1618 FrameView* v = m_frame->view();
1623 IntPoint viewportPos = v->windowToContents(event.pos());
1624 MouseEventWithHitTestResults mev = doc->prepareMouseEvent(HitTestRequest(false, true), viewportPos, event);
1626 // Context menu events shouldn't select text in GTK+ applications.
1628 if (!m_frame->selection()->contains(viewportPos) &&
1629 // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse.
1630 // If the selection is non-editable, we do word selection to make it easier to use the contextual menu items
1631 // available for text selections. But only if we're above text.
1632 (m_frame->selection()->isContentEditable() || mev.targetNode() && mev.targetNode()->isTextNode())) {
1633 m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection
1634 selectClosestWordOrLinkFromMouseEvent(mev);
1638 swallowEvent = dispatchMouseEvent(contextmenuEvent, mev.targetNode(), true, 0, event, true);
1640 return swallowEvent;
1643 void EventHandler::scheduleHoverStateUpdate()
1645 if (!m_hoverTimer.isActive())
1646 m_hoverTimer.startOneShot(0);
1649 // Whether or not a mouse down can begin the creation of a selection. Fires the selectStart event.
1650 bool EventHandler::canMouseDownStartSelect(Node* node)
1652 if (!node || !node->renderer())
1655 // Some controls and images can't start a select on a mouse down.
1656 if (!node->canStartSelection())
1659 for (RenderObject* curr = node->renderer(); curr; curr = curr->parent())
1660 if (Node* node = curr->element())
1661 return EventTargetNodeCast(node)->dispatchEventForType(selectstartEvent, true, true);
1666 bool EventHandler::canMouseDragExtendSelect(Node* node)
1668 if (!node || !node->renderer())
1671 for (RenderObject* curr = node->renderer(); curr; curr = curr->parent())
1672 if (Node* node = curr->element())
1673 return EventTargetNodeCast(node)->dispatchEventForType(selectstartEvent, true, true);
1678 void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet)
1680 m_frameSetBeingResized = frameSet;
1683 void EventHandler::resizeLayerDestroyed()
1685 ASSERT(m_resizeLayer);
1689 void EventHandler::hoverTimerFired(Timer<EventHandler>*)
1691 m_hoverTimer.stop();
1694 ASSERT(m_frame->document());
1696 if (RenderObject* renderer = m_frame->contentRenderer()) {
1697 HitTestResult result(m_frame->view()->windowToContents(m_currentMousePosition));
1698 renderer->layer()->hitTest(HitTestRequest(false, false, true), result);
1699 m_frame->document()->updateRendering();
1703 static EventTargetNode* eventTargetNodeForDocument(Document* doc)
1707 Node* node = doc->focusedNode();
1709 if (doc->isHTMLDocument())
1712 node = doc->documentElement();
1716 return EventTargetNodeCast(node);
1719 bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& evt)
1721 if ((evt.modifiers() & s_accessKeyModifiers) != s_accessKeyModifiers)
1723 String key = evt.unmodifiedText();
1724 Element* elem = m_frame->document()->getElementByAccessKey(key.lower());
1727 elem->accessKeyAction(false);
1732 bool EventHandler::needsKeyboardEventDisambiguationQuirks() const
1738 bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent)
1740 #if ENABLE(PAN_SCROLLING)
1741 if (m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress) {
1742 String escKeyId = "U+001B";
1743 // If a key is pressed while the autoscroll/panScroll is in progress then we want to stop
1744 if (initialKeyEvent.keyIdentifier() == escKeyId && initialKeyEvent.type() == PlatformKeyboardEvent::KeyUp)
1745 stopAutoscrollTimer();
1747 // If we were in autoscroll/panscroll mode, we swallow the key event
1752 // Check for cases where we are too early for events -- possible unmatched key up
1753 // from pressing return in the location bar.
1754 RefPtr<EventTargetNode> node = eventTargetNodeForDocument(m_frame->document());
1758 // FIXME: what is this doing here, in keyboard event handler?
1759 m_frame->loader()->resetMultipleFormSubmissionProtection();
1761 // In IE, access keys are special, they are handled after default keydown processing, but cannot be canceled - this is hard to match.
1762 // On Mac OS X, we process them before dispatching keydown, as the default keydown handler implements Emacs key bindings, which may conflict
1763 // with access keys. Then we dispatch keydown, but suppress its default handling.
1764 // On Windows, WebKit explicitly calls handleAccessKey() instead of dispatching a keypress event for WM_SYSCHAR messages.
1765 // Other platforms currently match either Mac or Windows behavior, depending on whether they send combined KeyDown events.
1766 bool matchedAnAccessKey = false;
1767 if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyDown)
1768 matchedAnAccessKey = handleAccessKey(initialKeyEvent);
1770 // FIXME: it would be fair to let an input method handle KeyUp events before DOM dispatch.
1771 if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyUp || initialKeyEvent.type() == PlatformKeyboardEvent::Char)
1772 return !node->dispatchKeyEvent(initialKeyEvent);
1774 bool backwardCompatibilityMode = needsKeyboardEventDisambiguationQuirks();
1777 PlatformKeyboardEvent keyDownEvent = initialKeyEvent;
1778 if (keyDownEvent.type() != PlatformKeyboardEvent::RawKeyDown)
1779 keyDownEvent.disambiguateKeyDownEvent(PlatformKeyboardEvent::RawKeyDown, backwardCompatibilityMode);
1780 RefPtr<KeyboardEvent> keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->defaultView());
1781 if (matchedAnAccessKey)
1782 keydown->setDefaultPrevented(true);
1783 keydown->setTarget(node);
1785 if (initialKeyEvent.type() == PlatformKeyboardEvent::RawKeyDown) {
1786 node->dispatchEvent(keydown, ec, true);
1787 return keydown->defaultHandled() || keydown->defaultPrevented();
1790 // Run input method in advance of DOM event handling. This may result in the IM
1791 // modifying the page prior the keydown event, but this behaviour is necessary
1792 // in order to match IE:
1793 // 1. preventing default handling of keydown and keypress events has no effect on IM input;
1794 // 2. if an input method handles the event, its keyCode is set to 229 in keydown event.
1795 m_frame->editor()->handleInputMethodKeydown(keydown.get());
1797 bool handledByInputMethod = keydown->defaultHandled();
1799 if (handledByInputMethod) {
1800 keyDownEvent.setWindowsVirtualKeyCode(CompositionEventKeyCode);
1801 keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->defaultView());
1802 keydown->setTarget(node);
1803 keydown->setDefaultHandled();
1806 node->dispatchEvent(keydown, ec, true);
1807 bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented();
1808 if (handledByInputMethod || (keydownResult && !backwardCompatibilityMode))
1809 return keydownResult;
1811 // Focus may have changed during keydown handling, so refetch node.
1812 // But if we are dispatching a fake backward compatibility keypress, then we pretend that the keypress happened on the original node.
1813 if (!keydownResult) {
1814 node = eventTargetNodeForDocument(m_frame->document());
1819 PlatformKeyboardEvent keyPressEvent = initialKeyEvent;
1820 keyPressEvent.disambiguateKeyDownEvent(PlatformKeyboardEvent::Char, backwardCompatibilityMode);
1821 if (keyPressEvent.text().isEmpty())
1822 return keydownResult;
1823 RefPtr<KeyboardEvent> keypress = KeyboardEvent::create(keyPressEvent, m_frame->document()->defaultView());
1824 keypress->setTarget(node);
1826 keypress->setDefaultPrevented(true);
1828 keypress->keypressCommands() = keydown->keypressCommands();
1830 node->dispatchEvent(keypress, ec, true);
1832 return keydownResult || keypress->defaultPrevented() || keypress->defaultHandled();
1835 void EventHandler::handleKeyboardSelectionMovement(KeyboardEvent* event)
1840 String key = event->keyIdentifier();
1841 bool isShifted = event->getModifierState("Shift");
1842 bool isOptioned = event->getModifierState("Alt");
1845 m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::BACKWARD, LineGranularity, true);
1846 event->setDefaultHandled();
1848 else if (key == "Down") {
1849 m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::FORWARD, LineGranularity, true);
1850 event->setDefaultHandled();
1852 else if (key == "Left") {
1853 m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::LEFT, (isOptioned) ? WordGranularity : CharacterGranularity, true);
1854 event->setDefaultHandled();
1856 else if (key == "Right") {
1857 m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::RIGHT, (isOptioned) ? WordGranularity : CharacterGranularity, true);
1858 event->setDefaultHandled();
1862 void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event)
1864 if (event->type() == keydownEvent) {
1865 m_frame->editor()->handleKeyboardEvent(event);
1866 if (event->defaultHandled())
1868 if (event->keyIdentifier() == "U+0009")
1869 defaultTabEventHandler(event);
1871 // provides KB navigation and selection for enhanced accessibility users
1872 if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled())
1873 handleKeyboardSelectionMovement(event);
1875 if (event->type() == keypressEvent) {
1876 m_frame->editor()->handleKeyboardEvent(event);
1877 if (event->defaultHandled())
1882 bool EventHandler::dragHysteresisExceeded(const FloatPoint& floatDragViewportLocation) const
1884 IntPoint dragViewportLocation((int)floatDragViewportLocation.x(), (int)floatDragViewportLocation.y());
1885 return dragHysteresisExceeded(dragViewportLocation);
1888 bool EventHandler::dragHysteresisExceeded(const IntPoint& dragViewportLocation) const
1890 IntPoint dragLocation = m_frame->view()->windowToContents(dragViewportLocation);
1891 IntSize delta = dragLocation - m_mouseDownPos;
1893 int threshold = GeneralDragHysteresis;
1894 if (dragState().m_dragSrcIsImage)
1895 threshold = ImageDragHysteresis;
1896 else if (dragState().m_dragSrcIsLink)
1897 threshold = LinkDragHysteresis;
1898 else if (dragState().m_dragSrcInSelection)
1899 threshold = TextDragHysteresis;
1901 return abs(delta.width()) >= threshold || abs(delta.height()) >= threshold;
1904 void EventHandler::freeClipboard()
1906 if (dragState().m_dragClipboard)
1907 dragState().m_dragClipboard->setAccessPolicy(ClipboardNumb);
1910 bool EventHandler::shouldDragAutoNode(Node* node, const IntPoint& point) const
1913 if (node->hasChildNodes() || !m_frame->view())
1915 return m_frame->page() && m_frame->page()->dragController()->mayStartDragAtEventLocation(m_frame, point);
1918 void EventHandler::dragSourceMovedTo(const PlatformMouseEvent& event)
1920 if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML)
1921 // for now we don't care if event handler cancels default behavior, since there is none
1922 dispatchDragSrcEvent(dragEvent, event);
1925 void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, DragOperation operation)
1927 if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) {
1928 dragState().m_dragClipboard->setDestinationOperation(operation);
1929 // for now we don't care if event handler cancels default behavior, since there is none
1930 dispatchDragSrcEvent(dragendEvent, event);
1933 dragState().m_dragSrc = 0;
1936 // returns if we should continue "default processing", i.e., whether eventhandler canceled
1937 bool EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent& event)
1939 return !dispatchDragEvent(eventType, dragState().m_dragSrc.get(), event, dragState().m_dragClipboard.get());
1942 bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event)
1944 if (event.event().button() != LeftButton || event.event().eventType() != MouseEventMoved) {
1945 // If we allowed the other side of the bridge to handle a drag
1946 // last time, then m_mousePressed might still be set. So we
1947 // clear it now to make sure the next move after a drag
1948 // doesn't look like a drag.
1949 m_mousePressed = false;
1953 if (eventLoopHandleMouseDragged(event))
1956 // Careful that the drag starting logic stays in sync with eventMayStartDrag()
1958 if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
1959 allowDHTMLDrag(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA);
1960 if (!dragState().m_dragSrcMayBeDHTML && !dragState().m_dragSrcMayBeUA)
1961 m_mouseDownMayStartDrag = false; // no element is draggable
1964 if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
1965 // try to find an element that wants to be dragged
1966 HitTestRequest request(true, false);
1967 HitTestResult result(m_mouseDownPos);
1968 m_frame->contentRenderer()->layer()->hitTest(request, result);
1969 Node* node = result.innerNode();
1970 if (node && node->renderer())
1971 dragState().m_dragSrc = node->renderer()->draggableNode(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA,
1972 m_mouseDownPos.x(), m_mouseDownPos.y(), dragState().m_dragSrcIsDHTML);
1974 dragState().m_dragSrc = 0;
1976 if (!dragState().m_dragSrc)
1977 m_mouseDownMayStartDrag = false; // no element is draggable
1979 // remember some facts about this source, while we have a HitTestResult handy
1980 node = result.URLElement();
1981 dragState().m_dragSrcIsLink = node && node->isLink();
1983 node = result.innerNonSharedNode();
1984 dragState().m_dragSrcIsImage = node && node->renderer() && node->renderer()->isImage();
1986 dragState().m_dragSrcInSelection = m_frame->selection()->contains(m_mouseDownPos);
1990 // For drags starting in the selection, the user must wait between the mousedown and mousedrag,
1991 // or else we bail on the dragging stuff and allow selection to occur
1992 if (m_mouseDownMayStartDrag && !dragState().m_dragSrcIsImage && dragState().m_dragSrcInSelection && event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay) {
1993 m_mouseDownMayStartDrag = false;
1994 dragState().m_dragSrc = 0;
1995 // ...but if this was the first click in the window, we don't even want to start selection
1996 if (eventActivatedView(event.event()))
1997 m_mouseDownMayStartSelect = false;
2000 if (!m_mouseDownMayStartDrag)
2001 return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll;
2003 // We are starting a text/image/url drag, so the cursor should be an arrow
2004 m_frame->view()->setCursor(pointerCursor());
2006 if (!dragHysteresisExceeded(event.event().pos()))
2009 // Once we're past the hysteresis point, we don't want to treat this gesture as a click
2012 DragOperation srcOp = DragOperationNone;
2014 freeClipboard(); // would only happen if we missed a dragEnd. Do it anyway, just
2015 // to make sure it gets numbified
2016 dragState().m_dragClipboard = createDraggingClipboard();
2018 if (dragState().m_dragSrcMayBeDHTML) {
2019 // Check to see if the is a DOM based drag, if it is get the DOM specified drag
2021 if (dragState().m_dragSrcIsDHTML) {
2023 if (RenderObject* renderer = dragState().m_dragSrc->renderer()) {
2024 renderer->absolutePosition(srcX, srcY);
2025 IntSize delta = m_mouseDownPos - IntPoint(srcX, srcY);
2026 dragState().m_dragClipboard->setDragImageElement(dragState().m_dragSrc.get(), IntPoint() + delta);
2028 // The renderer has disappeared, this can happen if the onStartDrag handler has hidden
2029 // the element in some way. In this case we just kill the drag.
2030 m_mouseDownMayStartDrag = false;
2035 m_mouseDownMayStartDrag = dispatchDragSrcEvent(dragstartEvent, m_mouseDown)
2036 && !m_frame->selection()->isInPasswordField();
2038 // Invalidate clipboard here against anymore pasteboard writing for security. The drag
2039 // image can still be changed as we drag, but not the pasteboard data.
2040 dragState().m_dragClipboard->setAccessPolicy(ClipboardImageWritable);
2042 if (m_mouseDownMayStartDrag) {
2043 // gather values from DHTML element, if it set any
2044 dragState().m_dragClipboard->sourceOperation(srcOp);
2046 // Yuck, dragSourceMovedTo() can be called as a result of kicking off the drag with
2047 // dragImage! Because of that dumb reentrancy, we may think we've not started the
2048 // drag when that happens. So we have to assume it's started before we kick it off.
2049 dragState().m_dragClipboard->setDragHasStarted();
2053 if (m_mouseDownMayStartDrag) {
2054 DragController* dragController = m_frame->page() ? m_frame->page()->dragController() : 0;
2055 bool startedDrag = dragController && dragController->startDrag(m_frame, dragState().m_dragClipboard.get(), srcOp, event.event(), m_mouseDownPos, dragState().m_dragSrcIsDHTML);
2056 if (!startedDrag && dragState().m_dragSrcMayBeDHTML) {
2057 // Drag was canned at the last minute - we owe m_dragSrc a DRAGEND event
2058 dispatchDragSrcEvent(dragendEvent, event.event());
2059 m_mouseDownMayStartDrag = false;
2064 if (!m_mouseDownMayStartDrag) {
2065 // something failed to start the drag, cleanup
2067 dragState().m_dragSrc = 0;
2070 // No more default handling (like selection), whether we're past the hysteresis bounds or not
2074 bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEvent,
2075 bool isLineBreak, bool isBackTab)
2080 // Platforms should differentiate real commands like selectAll from text input in disguise (like insertNewline),
2081 // and avoid dispatching text input events from keydown default handlers.
2082 if (underlyingEvent && underlyingEvent->isKeyboardEvent())
2083 ASSERT(static_cast<KeyboardEvent*>(underlyingEvent)->type() == keypressEvent);
2085 EventTarget* target;
2086 if (underlyingEvent)
2087 target = underlyingEvent->target();
2089 target = eventTargetNodeForDocument(m_frame->document());
2092 RefPtr<TextEvent> event = TextEvent::create(m_frame->domWindow(), text);
2093 event->setUnderlyingEvent(underlyingEvent);
2094 event->setIsLineBreak(isLineBreak);
2095 event->setIsBackTab(isBackTab);
2097 return target->dispatchEvent(event.release(), ec, true);
2101 #if !PLATFORM(MAC) && !PLATFORM(QT)
2102 bool EventHandler::invertSenseOfTabsToLinks(KeyboardEvent*) const
2108 bool EventHandler::tabsToLinks(KeyboardEvent* event) const
2110 Page* page = m_frame->page();
2114 if (page->chrome()->client()->tabsToLinks())
2115 return !invertSenseOfTabsToLinks(event);
2117 return invertSenseOfTabsToLinks(event);
2120 void EventHandler::defaultTextInputEventHandler(TextEvent* event)
2122 String data = event->data();
2124 if (event->isLineBreak()) {
2125 if (m_frame->editor()->insertLineBreak())
2126 event->setDefaultHandled();
2128 if (m_frame->editor()->insertParagraphSeparator())
2129 event->setDefaultHandled();
2132 if (m_frame->editor()->insertTextWithoutSendingTextEvent(data, false, event))
2133 event->setDefaultHandled();
2137 void EventHandler::defaultTabEventHandler(KeyboardEvent* event)
2139 // We should only advance focus on tabs if no special modifier keys are held down.
2140 if (event->ctrlKey() || event->metaKey() || event->altGraphKey())
2143 Page* page = m_frame->page();
2146 if (!page->tabKeyCyclesThroughElements())
2149 FocusDirection focusDirection = event->shiftKey() ? FocusDirectionBackward : FocusDirectionForward;
2151 // Tabs can be used in design mode editing.
2152 if (m_frame->document()->inDesignMode())
2155 if (page->focusController()->advanceFocus(focusDirection, event))
2156 event->setDefaultHandled();
2159 void EventHandler::capsLockStateMayHaveChanged()
2161 if (Document* d = m_frame->document())
2162 if (Node* node = d->focusedNode())
2163 if (RenderObject* r = node->renderer())
2164 r->capsLockStateMayHaveChanged();
2167 unsigned EventHandler::pendingFrameUnloadEventCount()
2169 return m_pendingFrameUnloadEventCount;
2172 void EventHandler::addPendingFrameUnloadEventCount()
2174 m_pendingFrameUnloadEventCount += 1;
2175 m_frame->page()->changePendingUnloadEventCount(1);
2179 void EventHandler::removePendingFrameUnloadEventCount()
2181 ASSERT( (-1 + (int)m_pendingFrameUnloadEventCount) >= 0 );
2182 m_pendingFrameUnloadEventCount -= 1;
2183 m_frame->page()->changePendingUnloadEventCount(-1);
2187 void EventHandler::clearPendingFrameUnloadEventCount()
2189 m_frame->page()->changePendingUnloadEventCount(-((int)m_pendingFrameUnloadEventCount));
2190 m_pendingFrameUnloadEventCount = 0;
2194 unsigned EventHandler::pendingFrameBeforeUnloadEventCount()
2196 return m_pendingFrameBeforeUnloadEventCount;
2199 void EventHandler::addPendingFrameBeforeUnloadEventCount()
2201 m_pendingFrameBeforeUnloadEventCount += 1;
2202 m_frame->page()->changePendingBeforeUnloadEventCount(1);
2206 void EventHandler::removePendingFrameBeforeUnloadEventCount()
2208 ASSERT( (-1 + (int)m_pendingFrameBeforeUnloadEventCount) >= 0 );
2209 m_pendingFrameBeforeUnloadEventCount -= 1;
2210 m_frame->page()->changePendingBeforeUnloadEventCount(-1);
2214 void EventHandler::clearPendingFrameBeforeUnloadEventCount()
2216 m_frame->page()->changePendingBeforeUnloadEventCount(-((int)m_pendingFrameBeforeUnloadEventCount));
2217 m_pendingFrameBeforeUnloadEventCount = 0;
2221 bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults& mev, Scrollbar* scrollbar)
2223 if (!scrollbar || !scrollbar->enabled())
2225 return scrollbar->mouseDown(mev.event());