summaryrefslogtreecommitdiff
path: root/Source/WebCore/page/EventHandler.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-05-07 11:21:11 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-05-07 11:21:11 +0200
commit2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch)
tree988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/WebCore/page/EventHandler.cpp
parentdd91e772430dc294e3bf478c119ef8d43c0a3358 (diff)
downloadqtwebkit-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.cpp175
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.