diff options
Diffstat (limited to 'WebCore/page/EventHandler.cpp')
-rw-r--r-- | WebCore/page/EventHandler.cpp | 147 |
1 files changed, 105 insertions, 42 deletions
diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp index 937f08f..6b4031e 100644 --- a/WebCore/page/EventHandler.cpp +++ b/WebCore/page/EventHandler.cpp @@ -87,6 +87,7 @@ namespace WebCore { using namespace HTMLNames; +#if ENABLE(DRAG_SUPPORT) // The link drag hysteresis is much larger than the others because there // needs to be enough space to cancel the link press without starting a link drag, // and because dragging links is rare. @@ -94,6 +95,7 @@ const int LinkDragHysteresis = 40; const int ImageDragHysteresis = 5; const int TextDragHysteresis = 3; const int GeneralDragHysteresis = 3; +#endif // ENABLE(DRAG_SUPPORT) // Match key code of composition keydown event on windows. // IE sends VK_PROCESSKEY which has value 229; @@ -106,10 +108,9 @@ using namespace SVGNames; // When the autoscroll or the panScroll is triggered when do the scroll every 0.05s to make it smooth const double autoscrollInterval = 0.05; -static Frame* subframeForTargetNode(Node*); static Frame* subframeForHitTestResult(const MouseEventWithHitTestResults&); -static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDirection, ScrollDirection negativeDirection, PlatformWheelEvent& e, Node* node) +static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDirection, ScrollDirection negativeDirection, PlatformWheelEvent& e, Node* node, Node** stopNode) { if (!delta) return; @@ -118,12 +119,13 @@ static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDir RenderBox* enclosingBox = node->renderer()->enclosingBox(); if (e.granularity() == ScrollByPageWheelEvent) { - if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPage, 1)) + if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPage, 1, stopNode)) e.accept(); return; - } + } + float pixelsToScroll = delta > 0 ? delta : -delta; - if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, pixelsToScroll)) + if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, pixelsToScroll, stopNode)) e.accept(); } @@ -146,7 +148,9 @@ EventHandler::EventHandler(Frame* frame) , m_mousePressed(false) , m_capturesDragging(false) , m_mouseDownMayStartSelect(false) +#if ENABLE(DRAG_SUPPORT) , m_mouseDownMayStartDrag(false) +#endif , m_mouseDownWasSingleClickInSelection(false) , m_beganSelectingText(false) , m_panScrollInProgress(false) @@ -179,11 +183,13 @@ EventHandler::~EventHandler() { } +#if ENABLE(DRAG_SUPPORT) EventHandler::EventHandlerDragState& EventHandler::dragState() { DEFINE_STATIC_LOCAL(EventHandlerDragState, state, ()); return state; } +#endif // ENABLE(DRAG_SUPPORT) void EventHandler::clear() { @@ -203,13 +209,16 @@ void EventHandler::clear() m_touch = 0; #endif m_frameSetBeingResized = 0; +#if ENABLE(DRAG_SUPPORT) m_dragTarget = 0; +#endif m_currentMousePosition = IntPoint(); m_mousePressNode = 0; m_mousePressed = false; m_capturesDragging = false; m_capturingMouseEventsNode = 0; m_latchedWheelEventNode = 0; + m_previousWheelScrolledNode = 0; } void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result) @@ -357,8 +366,10 @@ bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event) { +#if ENABLE(DRAG_SUPPORT) // Reset drag state. dragState().m_dragSrc = 0; +#endif if (ScrollView* scrollView = m_frame->view()) { if (scrollView->isPointInScrollbarCorner(event.event().pos())) @@ -371,8 +382,10 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve // so it's allowed to start a drag or selection. m_mouseDownMayStartSelect = canMouseDownStartSelect(event.targetNode()); +#if ENABLE(DRAG_SUPPORT) // Careful that the drag starting logic stays in sync with eventMayStartDrag() m_mouseDownMayStartDrag = singleClick; +#endif m_mouseDownWasSingleClickInSelection = false; @@ -400,7 +413,9 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve Node* innerNode = event.targetNode(); m_mousePressNode = innerNode; +#if ENABLE(DRAG_SUPPORT) m_dragStartPos = event.event().pos(); +#endif bool swallowEvent = false; m_frame->selection()->setCaretBlinkingSuspended(true); @@ -420,6 +435,7 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve return swallowEvent; } +#if ENABLE(DRAG_SUPPORT) bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event) { if (handleDrag(event)) @@ -442,7 +458,7 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e // If the selection is contained in a layer that can scroll, that layer should handle the autoscroll // Otherwise, let the bridge handle it so the view can scroll itself. RenderObject* renderer = targetNode->renderer(); - while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeProgramaticallyScrolled(false))) { + while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeScrolledAndHasScrollableArea())) { if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement()) renderer = renderer->document()->ownerElement()->renderer(); else @@ -559,6 +575,7 @@ void EventHandler::updateSelectionForMouseDrag(Node* targetNode, const IntPoint& m_frame->selection()->setSelection(newSelection); } } +#endif // ENABLE(DRAG_SUPPORT) bool EventHandler::handleMouseUp(const MouseEventWithHitTestResults& event) { @@ -586,7 +603,9 @@ bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e m_frame->selection()->setCaretBlinkingSuspended(false); m_mousePressed = false; m_capturesDragging = false; +#if ENABLE(DRAG_SUPPORT) m_mouseDownMayStartDrag = false; +#endif m_mouseDownMayStartSelect = false; m_mouseDownMayStartAutoscroll = false; m_mouseDownWasInSubframe = false; @@ -598,7 +617,9 @@ bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e // on the selection, the selection goes away. However, if we are // editing, place the caret. if (m_mouseDownWasSingleClickInSelection && !m_beganSelectingText +#if ENABLE(DRAG_SUPPORT) && m_dragStartPos == event.event().pos() +#endif && m_frame->selection()->isRange() && event.event().button() != RightButton) { VisibleSelection newSelection; @@ -732,7 +753,7 @@ void EventHandler::updateAutoscrollRenderer() if (Node* nodeAtPoint = hitTest.innerNode()) m_autoscrollRenderer = nodeAtPoint->renderer(); - while (m_autoscrollRenderer && (!m_autoscrollRenderer->isBox() || !toRenderBox(m_autoscrollRenderer)->canBeProgramaticallyScrolled(false))) + while (m_autoscrollRenderer && (!m_autoscrollRenderer->isBox() || !toRenderBox(m_autoscrollRenderer)->canBeScrolledAndHasScrollableArea())) m_autoscrollRenderer = m_autoscrollRenderer->parent(); } @@ -741,6 +762,7 @@ void EventHandler::setAutoscrollRenderer(RenderObject* renderer) m_autoscrollRenderer = renderer; } +#if ENABLE(DRAG_SUPPORT) void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const { flagDHTML = false; @@ -761,6 +783,7 @@ void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const flagDHTML = (mask & DragSourceActionDHTML) != DragSourceActionNone; flagUA = ((mask & DragSourceActionImage) || (mask & DragSourceActionLink) || (mask & DragSourceActionSelection)); } +#endif // ENABLE(DRAG_SUPPORT) HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent, bool ignoreClipping, HitTestScrollbars testScrollbars) { @@ -883,8 +906,10 @@ bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity g if (node) { RenderObject* r = node->renderer(); - if (r && !r->isListBox()) - return r->enclosingBox()->scroll(direction, granularity); + if (r && !r->isListBox() && r->enclosingBox()->scroll(direction, granularity)) { + setFrameWasScrolledByUser(); + return true; + } } return false; @@ -914,10 +939,10 @@ Frame* subframeForHitTestResult(const MouseEventWithHitTestResults& hitTestResul { if (!hitTestResult.isOverWidget()) return 0; - return subframeForTargetNode(hitTestResult.targetNode()); + return EventHandler::subframeForTargetNode(hitTestResult.targetNode()); } -Frame* subframeForTargetNode(Node* node) +Frame* EventHandler::subframeForTargetNode(Node* node) { if (!node) return 0; @@ -1117,7 +1142,9 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) m_capturesDragging = true; m_currentMousePosition = mouseEvent.pos(); m_mouseDownTimestamp = mouseEvent.timestamp(); +#if ENABLE(DRAG_SUPPORT) m_mouseDownMayStartDrag = false; +#endif m_mouseDownMayStartSelect = false; m_mouseDownMayStartAutoscroll = false; if (FrameView* view = m_frame->view()) @@ -1141,6 +1168,7 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) m_mousePressNode = mev.targetNode(); +#if ENABLE(INSPECTOR) if (Page* page = m_frame->page()) { InspectorController* inspector = page->inspectorController(); if (inspector && inspector->enabled() && inspector->searchingForNodeInPage()) { @@ -1149,6 +1177,7 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) return true; } } +#endif Frame* subframe = subframeForHitTestResult(mev); if (subframe && passMousePressEventToSubframe(mev, subframe)) { @@ -1172,7 +1201,7 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) if (mouseEvent.button() == MiddleButton && !mev.isOverLink()) { RenderObject* renderer = mev.targetNode()->renderer(); - while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeProgramaticallyScrolled(false))) { + while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeScrolledAndHasScrollableArea())) { if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement()) renderer = renderer->document()->ownerElement()->renderer(); else @@ -1393,8 +1422,10 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi return true; swallowEvent = dispatchMouseEvent(eventNames().mousemoveEvent, mev.targetNode(), false, 0, mouseEvent, true); +#if ENABLE(DRAG_SUPPORT) if (!swallowEvent) swallowEvent = handleMouseDraggedEvent(mev); +#endif // ENABLE(DRAG_SUPPORT) return swallowEvent; } @@ -1464,6 +1495,7 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; } +#if ENABLE(DRAG_SUPPORT) bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard) { FrameView* view = m_frame->view(); @@ -1508,15 +1540,15 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* // it is sometimes incorrect when dragging within subframes, as seen with // LayoutTests/fast/events/drag-in-frames.html. if (newTarget) { - if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag)) - accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->eventHandler()->updateDragAndDrop(event, clipboard); + Frame* frame = (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag)) ? static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame() : 0; + if (frame) + accept = frame->eventHandler()->updateDragAndDrop(event, clipboard); else accept = dispatchDragEvent(eventNames().dragenterEvent, newTarget, event, clipboard); } if (m_dragTarget) { - Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag)) - ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0; + Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag)) ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0; if (frame) accept = frame->eventHandler()->updateDragAndDrop(event, clipboard); else @@ -1524,8 +1556,9 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* } } else { if (newTarget) { - if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag)) - accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->eventHandler()->updateDragAndDrop(event, clipboard); + Frame* frame = (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag)) ? static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame() : 0; + if (frame) + accept = frame->eventHandler()->updateDragAndDrop(event, clipboard); else accept = dispatchDragEvent(eventNames().dragoverEvent, newTarget, event, clipboard); } @@ -1571,6 +1604,7 @@ void EventHandler::clearDragState() m_sendingEventToSubview = false; #endif } +#endif // ENABLE(DRAG_SUPPORT) void EventHandler::setCapturingMouseEventsNode(PassRefPtr<Node> n) { @@ -1692,12 +1726,15 @@ bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe swallowEvent = m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventType, clickCount); if (!swallowEvent && eventType == eventNames().mousedownEvent) { + // The layout needs to be up to date to determine if an element is focusable. + m_frame->document()->updateLayoutIgnorePendingStylesheets(); + // Blur current focus node when a link/button is clicked; this // is expected by some sites that rely on onChange handlers running // from form fields before the button click is processed. Node* node = m_nodeUnderMouse.get(); RenderObject* renderer = node ? node->renderer() : 0; - + // Walk up the render tree to search for a node to focus. // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields. while (renderer) { @@ -1736,6 +1773,13 @@ bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe return swallowEvent; } +#if !PLATFORM(GTK) +bool EventHandler::shouldTurnVerticalTicksIntoHorizontal(const HitTestResult&) const +{ + return false; +} +#endif + bool EventHandler::handleWheelEvent(PlatformWheelEvent& e) { Document* doc = m_frame->document(); @@ -1749,35 +1793,39 @@ bool EventHandler::handleWheelEvent(PlatformWheelEvent& e) FrameView* view = m_frame->view(); if (!view) return false; + setFrameWasScrolledByUser(); IntPoint vPoint = view->windowToContents(e.pos()); Node* node; bool isOverWidget; bool didSetLatchedNode = false; - + + HitTestRequest request(HitTestRequest::ReadOnly); + HitTestResult result(vPoint); + doc->renderView()->layer()->hitTest(request, result); + if (m_useLatchedWheelEventNode) { if (!m_latchedWheelEventNode) { - HitTestRequest request(HitTestRequest::ReadOnly); - HitTestResult result(vPoint); - doc->renderView()->layer()->hitTest(request, result); m_latchedWheelEventNode = result.innerNode(); m_widgetIsLatched = result.isOverWidget(); didSetLatchedNode = true; } - + node = m_latchedWheelEventNode.get(); isOverWidget = m_widgetIsLatched; } else { if (m_latchedWheelEventNode) m_latchedWheelEventNode = 0; - - HitTestRequest request(HitTestRequest::ReadOnly); - HitTestResult result(vPoint); - doc->renderView()->layer()->hitTest(request, result); + if (m_previousWheelScrolledNode) + m_previousWheelScrolledNode = 0; + node = result.innerNode(); isOverWidget = result.isOverWidget(); } - + + if (shouldTurnVerticalTicksIntoHorizontal(result)) + e.turnVerticalTicksIntoHorizontal(); + if (node) { // Figure out which view to send the event to. RenderObject* target = node->renderer(); @@ -1794,17 +1842,20 @@ bool EventHandler::handleWheelEvent(PlatformWheelEvent& e) node->dispatchWheelEvent(e); if (e.isAccepted()) return true; - + // If we don't have a renderer, send the wheel event to the first node we find with a renderer. // This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll. while (node && !node->renderer()) node = node->parent(); - + if (node && node->renderer()) { // Just break up into two scrolls if we need to. Diagonal movement on // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set). - scrollAndAcceptEvent(e.deltaX(), ScrollLeft, ScrollRight, e, node); - scrollAndAcceptEvent(e.deltaY(), ScrollUp, ScrollDown, e, node); + Node* stopNode = m_previousWheelScrolledNode.get(); + scrollAndAcceptEvent(e.deltaX(), ScrollLeft, ScrollRight, e, node, &stopNode); + scrollAndAcceptEvent(e.deltaY(), ScrollUp, ScrollDown, e, node, &stopNode); + if (!m_useLatchedWheelEventNode) + m_previousWheelScrolledNode = stopNode; } } @@ -1819,6 +1870,7 @@ bool EventHandler::handleWheelEvent(PlatformWheelEvent& e) return e.isAccepted(); } +#if ENABLE(CONTEXT_MENUS) bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event) { Document* doc = m_frame->document(); @@ -1849,6 +1901,7 @@ bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event) return swallowEvent; } +#endif // ENABLE(CONTEXT_MENUS) void EventHandler::scheduleHoverStateUpdate() { @@ -1868,12 +1921,13 @@ bool EventHandler::canMouseDownStartSelect(Node* node) for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) { if (Node* node = curr->node()) - return node->dispatchEvent(eventNames().selectstartEvent, true, true); + return node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true)); } return true; } +#if ENABLE(DRAG_SUPPORT) bool EventHandler::canMouseDragExtendSelect(Node* node) { if (!node || !node->renderer()) @@ -1881,11 +1935,12 @@ bool EventHandler::canMouseDragExtendSelect(Node* node) for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) { if (Node* node = curr->node()) - return node->dispatchEvent(eventNames().selectstartEvent, true, true); + return node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true)); } return true; } +#endif // ENABLE(DRAG_SUPPORT) void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet) { @@ -2109,6 +2164,7 @@ void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event) } } +#if ENABLE(DRAG_SUPPORT) bool EventHandler::dragHysteresisExceeded(const FloatPoint& floatDragViewportLocation) const { IntPoint dragViewportLocation((int)floatDragViewportLocation.x(), (int)floatDragViewportLocation.y()); @@ -2142,7 +2198,7 @@ void EventHandler::freeClipboard() bool EventHandler::shouldDragAutoNode(Node* node, const IntPoint& point) const { - if (!node || node->hasChildNodes() || !m_frame->view()) + if (!node || !m_frame->view()) return false; Page* page = m_frame->page(); return page && page->dragController()->mayStartDragAtEventLocation(m_frame, point); @@ -2308,6 +2364,7 @@ cleanupDrag: // No more default handling (like selection), whether we're past the hysteresis bounds or not return true; } +#endif // ENABLE(DRAG_SUPPORT) bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEvent, bool isLineBreak, bool isBackTab) { @@ -2339,7 +2396,7 @@ bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEve } -#if !PLATFORM(MAC) && !PLATFORM(QT) +#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(HAIKU) bool EventHandler::invertSenseOfTabsToLinks(KeyboardEvent*) const { return false; @@ -2440,22 +2497,28 @@ void EventHandler::capsLockStateMayHaveChanged() void EventHandler::sendResizeEvent() { - m_frame->document()->dispatchWindowEvent(eventNames().resizeEvent, false, false); + m_frame->document()->dispatchWindowEvent(Event::create(eventNames().resizeEvent, false, false)); } void EventHandler::sendScrollEvent() { + setFrameWasScrolledByUser(); + if (m_frame->view()) + m_frame->document()->dispatchEvent(Event::create(eventNames().scrollEvent, true, false)); +} + +void EventHandler::setFrameWasScrolledByUser() +{ FrameView* v = m_frame->view(); - if (!v) - return; - v->setWasScrolledByUser(true); - m_frame->document()->dispatchEvent(eventNames().scrollEvent, true, false); + if (v) + v->setWasScrolledByUser(true); } bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults& mev, Scrollbar* scrollbar) { if (!scrollbar || !scrollbar->enabled()) return false; + setFrameWasScrolledByUser(); return scrollbar->mouseDown(mev.event()); } |