diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
commit | 2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch) | |
tree | 988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/WebCore/page/EventHandler.cpp | |
parent | dd91e772430dc294e3bf478c119ef8d43c0a3358 (diff) | |
download | qtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz |
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/WebCore/page/EventHandler.cpp')
-rw-r--r-- | Source/WebCore/page/EventHandler.cpp | 175 |
1 files changed, 126 insertions, 49 deletions
diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp index 1738db896..290e58f3a 100644 --- a/Source/WebCore/page/EventHandler.cpp +++ b/Source/WebCore/page/EventHandler.cpp @@ -73,6 +73,7 @@ #include "Scrollbar.h" #include "Settings.h" #include "SpatialNavigation.h" +#include "StaticHashSetNodeList.h" #include "StyleCachedImage.h" #include "TextEvent.h" #include "TextIterator.h" @@ -89,6 +90,10 @@ #include "PlatformGestureEvent.h" #endif +#if ENABLE(TOUCH_ADJUSTMENT) +#include "TouchAdjustment.h" +#endif + #if ENABLE(SVG) #include "SVGDocument.h" #include "SVGElementInstance.h" @@ -694,7 +699,7 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e if (m_selectionInitiationState != ExtendedSelection) { HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); HitTestResult result(m_mouseDownPos); - m_frame->document()->renderView()->layer()->hitTest(request, result); + m_frame->document()->renderView()->hitTest(request, result); updateSelectionForMouseDrag(result); } @@ -725,7 +730,7 @@ bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const updateDragSourceActionsAllowed(); HitTestRequest request(HitTestRequest::ReadOnly); HitTestResult result(view->windowToContents(event.position())); - m_frame->contentRenderer()->layer()->hitTest(request, result); + m_frame->contentRenderer()->hitTest(request, result); DragState state; return result.innerNode() && page->dragController()->draggableNode(m_frame, result.innerNode(), roundedIntPoint(result.point()), state); } @@ -738,15 +743,12 @@ void EventHandler::updateSelectionForMouseDrag() RenderView* renderer = m_frame->contentRenderer(); if (!renderer) return; - RenderLayer* layer = renderer->layer(); - if (!layer) - return; HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::Move); HitTestResult result(view->windowToContents(m_currentMousePosition)); - layer->hitTest(request, result); + renderer->hitTest(request, result); updateSelectionForMouseDrag(result); } @@ -1035,12 +1037,14 @@ DragSourceAction EventHandler::updateDragSourceActionsAllowed() const HitTestResult EventHandler::hitTestResultAtPoint(const LayoutPoint& point, bool allowShadowContent, bool ignoreClipping, HitTestScrollbars testScrollbars, HitTestRequest::HitTestRequestType hitType, const LayoutSize& padding) { - HitTestResult result(point, padding.height(), padding.width(), padding.height(), padding.width()); + enum ShadowContentFilterPolicy shadowContentFilterPolicy = allowShadowContent ? AllowShadowContent : DoNotAllowShadowContent; + HitTestResult result(point, padding.height(), padding.width(), padding.height(), padding.width(), shadowContentFilterPolicy); + if (!m_frame->contentRenderer()) return result; if (ignoreClipping) hitType |= HitTestRequest::IgnoreClipping; - m_frame->contentRenderer()->layer()->hitTest(HitTestRequest(hitType), result); + m_frame->contentRenderer()->hitTest(HitTestRequest(hitType), result); while (true) { Node* n = result.innerNode(); @@ -1056,8 +1060,8 @@ HitTestResult EventHandler::hitTestResultAtPoint(const LayoutPoint& point, bool FrameView* view = static_cast<FrameView*>(widget); LayoutPoint widgetPoint(result.localPoint().x() + view->scrollX() - renderWidget->borderLeft() - renderWidget->paddingLeft(), result.localPoint().y() + view->scrollY() - renderWidget->borderTop() - renderWidget->paddingTop()); - HitTestResult widgetHitTestResult(widgetPoint, padding.height(), padding.width(), padding.height(), padding.width()); - frame->contentRenderer()->layer()->hitTest(HitTestRequest(hitType), widgetHitTestResult); + HitTestResult widgetHitTestResult(widgetPoint, padding.height(), padding.width(), padding.height(), padding.width(), shadowContentFilterPolicy); + frame->contentRenderer()->hitTest(HitTestRequest(hitType), widgetHitTestResult); result = widgetHitTestResult; if (testScrollbars == ShouldHitTestScrollbars) { @@ -1290,7 +1294,11 @@ OptionalCursor EventHandler::selectCursor(const MouseEventWithHitTestResults& ev // During selection, use an I-beam no matter what we're over. // If a drag may be starting or we're capturing mouse events for a particular node, don't treat this as a selection. - if (m_mousePressed && m_mouseDownMayStartSelect && !m_mouseDownMayStartDrag && m_frame->selection()->isCaretOrRange() && !m_capturingMouseEventsNode) + if (m_mousePressed && m_mouseDownMayStartSelect +#if ENABLE(DRAG_SUPPORT) + && !m_mouseDownMayStartDrag +#endif + && m_frame->selection()->isCaretOrRange() && !m_capturingMouseEventsNode) return iBeam; if (renderer) { @@ -1738,6 +1746,13 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi HitTestRequest::HitTestRequestType hitType = HitTestRequest::Move; if (m_mousePressed) hitType |= HitTestRequest::Active; + else if (onlyUpdateScrollbars) { + // Mouse events should be treated as "read-only" if we're updating only scrollbars. This + // means that :hover and :active freeze in the state they were in, rather than updating + // for nodes the mouse moves while the window is not key (which will be the case if + // onlyUpdateScrollbars is true). + hitType |= HitTestRequest::ReadOnly; + } #if ENABLE(TOUCH_EVENTS) // Treat any mouse move events as readonly if the user is currently touching the screen. @@ -2289,7 +2304,7 @@ bool EventHandler::handleWheelEvent(const PlatformWheelEvent& e) HitTestRequest request(HitTestRequest::ReadOnly); HitTestResult result(vPoint); - doc->renderView()->layer()->hitTest(request, result); + doc->renderView()->hitTest(request, result); #if PLATFORM(MAC) m_useLatchedWheelEventNode = e.momentumPhase() == PlatformWheelEventPhaseBegan || e.momentumPhase() == PlatformWheelEventPhaseChanged; @@ -2317,7 +2332,7 @@ bool EventHandler::handleWheelEvent(const PlatformWheelEvent& e) // Instead, the handlers should know convert vertical scrolls // appropriately. PlatformWheelEvent event = e; - if (m_baseEventType != PlatformEvent::NoType && shouldTurnVerticalTicksIntoHorizontal(result)) + if (m_baseEventType == PlatformEvent::NoType && shouldTurnVerticalTicksIntoHorizontal(result)) event = event.copyTurningVerticalTicksIntoHorizontalTicks(); if (node) { @@ -2365,6 +2380,25 @@ void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEv } #if ENABLE(GESTURE_EVENTS) +bool EventHandler::handleGestureTapDown() +{ + FrameView* view = m_frame->view(); + if (!view) + return false; + if (ScrollAnimator* scrollAnimator = view->existingScrollAnimator()) + scrollAnimator->cancelAnimations(); + const FrameView::ScrollableAreaSet* areas = view->scrollableAreas(); + if (!areas) + return false; + for (FrameView::ScrollableAreaSet::const_iterator it = areas->begin(); it != areas->end(); ++it) { + ScrollableArea* sa = *it; + ScrollAnimator* animator = sa->scrollAnimator(); + if (animator) + animator->cancelAnimations(); + } + return false; +} + bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent) { // FIXME: A more general scroll system (https://bugs.webkit.org/show_bug.cgi?id=80596) will @@ -2372,19 +2406,22 @@ bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent) TemporaryChange<PlatformEvent::Type> baseEventType(m_baseEventType, gestureEvent.type()); switch (gestureEvent.type()) { - case PlatformEvent::GestureTapDown: - // FIXME: Stop animation here. - break; - case PlatformEvent::GestureTap: - return handleGestureTap(gestureEvent); - case PlatformEvent::GestureScrollUpdate: - return handleGestureScrollUpdate(gestureEvent); - case PlatformEvent::GestureDoubleTap: - break; case PlatformEvent::GestureScrollBegin: return handleGestureScrollCore(gestureEvent, ScrollByPixelWheelEvent, false); case PlatformEvent::GestureScrollEnd: return handleGestureScrollCore(gestureEvent, ScrollByPixelVelocityWheelEvent, true); + case PlatformEvent::GestureScrollUpdate: + return handleGestureScrollUpdate(gestureEvent); + case PlatformEvent::GestureTap: + return handleGestureTap(gestureEvent); + case PlatformEvent::GestureTapDown: + return handleGestureTapDown(); + case PlatformEvent::GestureDoubleTap: + case PlatformEvent::GestureLongPress: + case PlatformEvent::GesturePinchBegin: + case PlatformEvent::GesturePinchEnd: + case PlatformEvent::GesturePinchUpdate: + break; default: ASSERT_NOT_REACHED(); } @@ -2392,13 +2429,26 @@ bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent) return false; } -bool EventHandler::handleGestureTap(const PlatformGestureEvent& gestureEvent) +bool EventHandler::handleGestureTap(const PlatformGestureEvent& gestureEvent, Node* preTargetedNode) { - // FIXME: Refactor this code to not hit test multiple times. + IntPoint adjustedPoint = gestureEvent.position(); +#if ENABLE(TOUCH_ADJUSTMENT) + if (!gestureEvent.area().isEmpty() && !preTargetedNode) { + Node* targetNode = 0; + // For now we use the adjusted position to ensure the later redundant hit-tests hits the right node. + bestClickableNodeForTouchPoint(gestureEvent.position(), IntSize(gestureEvent.area().width() / 2, gestureEvent.area().height() / 2), adjustedPoint, targetNode); + if (!targetNode) + return false; + } +#endif + // FIXME: Refactor to avoid hit testing multiple times (this is only an interim step). + if (preTargetedNode) + adjustedPoint = preTargetedNode->getPixelSnappedRect().center(); + bool defaultPrevented = false; - PlatformMouseEvent fakeMouseMove(gestureEvent.position(), gestureEvent.globalPosition(), NoButton, PlatformEvent::MouseMoved, /* clickCount */ 1, gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp()); - PlatformMouseEvent fakeMouseDown(gestureEvent.position(), gestureEvent.globalPosition(), LeftButton, PlatformEvent::MousePressed, /* clickCount */ 1, gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp()); - PlatformMouseEvent fakeMouseUp(gestureEvent.position(), gestureEvent.globalPosition(), LeftButton, PlatformEvent::MouseReleased, /* clickCount */ 1, gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp()); + PlatformMouseEvent fakeMouseMove(adjustedPoint, gestureEvent.globalPosition(), NoButton, PlatformEvent::MouseMoved, /* clickCount */ 1, gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp()); + PlatformMouseEvent fakeMouseDown(adjustedPoint, gestureEvent.globalPosition(), LeftButton, PlatformEvent::MousePressed, /* clickCount */ 1, gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp()); + PlatformMouseEvent fakeMouseUp(adjustedPoint, gestureEvent.globalPosition(), LeftButton, PlatformEvent::MouseReleased, /* clickCount */ 1, gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp()); mouseMoved(fakeMouseMove); defaultPrevented |= handleMousePressEvent(fakeMouseDown); defaultPrevented |= handleMouseReleaseEvent(fakeMouseUp); @@ -2424,6 +2474,28 @@ bool EventHandler::handleGestureScrollCore(const PlatformGestureEvent& gestureEv } #endif +#if ENABLE(TOUCH_ADJUSTMENT) +bool EventHandler::bestClickableNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode) +{ + HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active; + HitTestResult result = hitTestResultAtPoint(touchCenter, /*allowShadowContent*/ false, /*ignoreClipping*/ false, DontHitTestScrollbars, hitType, touchRadius); + + IntRect touchRect = result.rectForPoint(touchCenter); + RefPtr<StaticHashSetNodeList> nodeList = StaticHashSetNodeList::adopt(result.rectBasedTestResult()); + return findBestClickableCandidate(targetNode, targetPoint, touchCenter, touchRect, *nodeList.get()); +} + +bool EventHandler::bestZoomableAreaForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntRect& targetArea, Node*& targetNode) +{ + HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active; + HitTestResult result = hitTestResultAtPoint(touchCenter, /*allowShadowContent*/ false, /*ignoreClipping*/ false, DontHitTestScrollbars, hitType, touchRadius); + + IntRect touchRect = result.rectForPoint(touchCenter); + RefPtr<StaticHashSetNodeList> nodeList = StaticHashSetNodeList::adopt(result.rectBasedTestResult()); + return findBestZoomableArea(targetNode, targetArea, touchCenter, touchRect, *nodeList.get()); +} +#endif + #if ENABLE(CONTEXT_MENUS) bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event) { @@ -2487,7 +2559,7 @@ bool EventHandler::sendContextMenuEventForKey() RenderBoxModelObject* box = focusedNode->renderBoxModelObject(); if (!box) return false; - IntRect clippedRect = box->absoluteClippedOverflowRect(); + IntRect clippedRect = box->pixelSnappedAbsoluteClippedOverflowRect(); location = IntPoint(clippedRect.x(), clippedRect.maxY() - 1); } else { location = IntPoint( @@ -2610,28 +2682,12 @@ void EventHandler::hoverTimerFired(Timer<EventHandler>*) if (FrameView* view = m_frame->view()) { HitTestRequest request(HitTestRequest::Move); HitTestResult result(view->windowToContents(m_currentMousePosition)); - renderer->layer()->hitTest(request, result); + renderer->hitTest(request, result); m_frame->document()->updateStyleIfNeeded(); } } } -static Node* eventTargetNodeForDocument(Document* doc) -{ - if (!doc) - return 0; - Node* node = doc->focusedNode(); - if (!node && doc->isPluginDocument()) { - PluginDocument* pluginDocument = static_cast<PluginDocument*>(doc); - node = pluginDocument->pluginNode(); - } - if (!node && doc->isHTMLDocument()) - node = doc->body(); - if (!node) - node = doc->documentElement(); - return node; -} - bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& evt) { // FIXME: Ignoring the state of Shift key is what neither IE nor Firefox do. @@ -2663,6 +2719,13 @@ bool EventHandler::isKeyEventAllowedInFullScreen(const PlatformKeyboardEvent& ke if (document->webkitFullScreenKeyboardInputAllowed()) return true; + if (keyEvent.type() == PlatformKeyboardEvent::Char) { + if (keyEvent.text().length() != 1) + return false; + UChar character = keyEvent.text()[0]; + return character == ' '; + } + int keyCode = keyEvent.windowsVirtualKeyCode(); return (keyCode >= VK_BACK && keyCode <= VK_CAPITAL) || (keyCode >= VK_SPACE && keyCode <= VK_DELETE) @@ -2980,7 +3043,7 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event) // try to find an element that wants to be dragged HitTestRequest request(HitTestRequest::ReadOnly); HitTestResult result(m_mouseDownPos); - m_frame->contentRenderer()->layer()->hitTest(request, result); + m_frame->contentRenderer()->hitTest(request, result); Node* node = result.innerNode(); if (node && m_frame->page()) dragState().m_dragSrc = m_frame->page()->dragController()->draggableNode(m_frame, node, m_mouseDownPos, dragState()); @@ -3089,7 +3152,14 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event) Page* page = m_frame->page(); DragController* dragController = page ? page->dragController() : 0; bool startedDrag = dragController && dragController->startDrag(m_frame, dragState(), srcOp, event.event(), m_mouseDownPos); - if (!startedDrag && dragState().shouldDispatchEvents()) { + // In WebKit2 we could reenter this code and start another drag. + // On OS X this causes problems with the ownership of the pasteboard + // and the promised types. + if (startedDrag) { + m_mouseDownMayStartDrag = false; + return true; + } + if (dragState().shouldDispatchEvents()) { // Drag was canned at the last minute - we owe m_dragSrc a DRAGEND event dispatchDragSrcEvent(eventNames().dragendEvent, event.event()); m_mouseDownMayStartDrag = false; @@ -3443,8 +3513,15 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) if (!touchTarget.get()) continue; + Document* doc = touchTarget->toNode()->document(); + if (!doc) + continue; + if (!doc->hasListenerType(Document::TOUCH_LISTENER)) + continue; + Frame* targetFrame = doc->frame(); + if (!targetFrame) + continue; - Frame* targetFrame = touchTarget->toNode()->document()->frame(); if (m_frame != targetFrame) { // pagePoint should always be relative to the target elements containing frame. pagePoint = documentPointForWindowPoint(targetFrame, point.pos()); @@ -3463,7 +3540,7 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) // Ensure this target's touch list exists, even if it ends up empty, so it can always be passed to TouchEvent::Create below. TargetTouchesMap::iterator targetTouchesIterator = touchesByTarget.find(touchTarget.get()); if (targetTouchesIterator == touchesByTarget.end()) - targetTouchesIterator = touchesByTarget.set(touchTarget.get(), TouchList::create()).first; + targetTouchesIterator = touchesByTarget.set(touchTarget.get(), TouchList::create()).iterator; // touches and targetTouches should only contain information about touches still on the screen, so if this point is // released or cancelled it will only appear in the changedTouches list. |