| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv
ed. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv
ed. |
| 3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
| 4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) | 4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 8 * are met: | 8 * are met: |
| 9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 #include "core/events/WheelEvent.h" | 51 #include "core/events/WheelEvent.h" |
| 52 #include "core/fetch/ImageResource.h" | 52 #include "core/fetch/ImageResource.h" |
| 53 #include "core/frame/Deprecation.h" | 53 #include "core/frame/Deprecation.h" |
| 54 #include "core/frame/EventHandlerRegistry.h" | 54 #include "core/frame/EventHandlerRegistry.h" |
| 55 #include "core/frame/FrameHost.h" | 55 #include "core/frame/FrameHost.h" |
| 56 #include "core/frame/FrameView.h" | 56 #include "core/frame/FrameView.h" |
| 57 #include "core/frame/LocalFrame.h" | 57 #include "core/frame/LocalFrame.h" |
| 58 #include "core/frame/Settings.h" | 58 #include "core/frame/Settings.h" |
| 59 #include "core/frame/UseCounter.h" | 59 #include "core/frame/UseCounter.h" |
| 60 #include "core/frame/VisualViewport.h" | 60 #include "core/frame/VisualViewport.h" |
| 61 #include "core/html/HTMLCanvasElement.h" | |
| 62 #include "core/html/HTMLDialogElement.h" | 61 #include "core/html/HTMLDialogElement.h" |
| 63 #include "core/html/HTMLFrameElementBase.h" | 62 #include "core/html/HTMLFrameElementBase.h" |
| 64 #include "core/html/HTMLFrameSetElement.h" | 63 #include "core/html/HTMLFrameSetElement.h" |
| 65 #include "core/html/HTMLInputElement.h" | 64 #include "core/html/HTMLInputElement.h" |
| 66 #include "core/input/InputDeviceCapabilities.h" | 65 #include "core/input/InputDeviceCapabilities.h" |
| 67 #include "core/input/TouchActionUtil.h" | 66 #include "core/input/TouchActionUtil.h" |
| 68 #include "core/layout/HitTestRequest.h" | 67 #include "core/layout/HitTestRequest.h" |
| 69 #include "core/layout/HitTestResult.h" | 68 #include "core/layout/HitTestResult.h" |
| 70 #include "core/layout/LayoutPart.h" | 69 #include "core/layout/LayoutPart.h" |
| 71 #include "core/layout/LayoutTextControlSingleLine.h" | 70 #include "core/layout/LayoutTextControlSingleLine.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 100 #include "platform/scroll/Scrollbar.h" | 99 #include "platform/scroll/Scrollbar.h" |
| 101 #include "wtf/Assertions.h" | 100 #include "wtf/Assertions.h" |
| 102 #include "wtf/CurrentTime.h" | 101 #include "wtf/CurrentTime.h" |
| 103 #include "wtf/StdLibExtras.h" | 102 #include "wtf/StdLibExtras.h" |
| 104 #include "wtf/TemporaryChange.h" | 103 #include "wtf/TemporaryChange.h" |
| 105 | 104 |
| 106 namespace blink { | 105 namespace blink { |
| 107 | 106 |
| 108 namespace { | 107 namespace { |
| 109 | 108 |
| 110 bool hasTouchHandlers(const EventHandlerRegistry& registry) | |
| 111 { | |
| 112 return registry.hasEventHandlers(EventHandlerRegistry::TouchEventBlocking) | |
| 113 || registry.hasEventHandlers(EventHandlerRegistry::TouchEventPassive); | |
| 114 } | |
| 115 | |
| 116 const AtomicString& touchEventNameForTouchPointState(PlatformTouchPoint::TouchSt
ate state) | |
| 117 { | |
| 118 switch (state) { | |
| 119 case PlatformTouchPoint::TouchReleased: | |
| 120 return EventTypeNames::touchend; | |
| 121 case PlatformTouchPoint::TouchCancelled: | |
| 122 return EventTypeNames::touchcancel; | |
| 123 case PlatformTouchPoint::TouchPressed: | |
| 124 return EventTypeNames::touchstart; | |
| 125 case PlatformTouchPoint::TouchMoved: | |
| 126 return EventTypeNames::touchmove; | |
| 127 case PlatformTouchPoint::TouchStationary: | |
| 128 // Fall through to default | |
| 129 default: | |
| 130 ASSERT_NOT_REACHED(); | |
| 131 return emptyAtom; | |
| 132 } | |
| 133 } | |
| 134 | |
| 135 // Convert |event->deltaMode()| to scroll granularity and output as |granularity
|. | 109 // Convert |event->deltaMode()| to scroll granularity and output as |granularity
|. |
| 136 bool wheelGranularityToScrollGranularity(const WheelEvent* event, ScrollGranular
ity* granularity) | 110 bool wheelGranularityToScrollGranularity(const WheelEvent* event, ScrollGranular
ity* granularity) |
| 137 { | 111 { |
| 138 DCHECK(granularity); | 112 DCHECK(granularity); |
| 139 switch (event->deltaMode()) { | 113 switch (event->deltaMode()) { |
| 140 case WheelEvent::DOM_DELTA_PAGE: | 114 case WheelEvent::DOM_DELTA_PAGE: |
| 141 *granularity = ScrollByPage; | 115 *granularity = ScrollByPage; |
| 142 return true; | 116 return true; |
| 143 case WheelEvent::DOM_DELTA_LINE: | 117 case WheelEvent::DOM_DELTA_LINE: |
| 144 *granularity = ScrollByLine; | 118 *granularity = ScrollByLine; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 , m_mouseDownMayStartAutoscroll(false) | 236 , m_mouseDownMayStartAutoscroll(false) |
| 263 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFire
d) | 237 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFire
d) |
| 264 , m_svgPan(false) | 238 , m_svgPan(false) |
| 265 , m_resizeScrollableArea(nullptr) | 239 , m_resizeScrollableArea(nullptr) |
| 266 , m_eventHandlerWillResetCapturingMouseEventsNode(0) | 240 , m_eventHandlerWillResetCapturingMouseEventsNode(0) |
| 267 , m_clickCount(0) | 241 , m_clickCount(0) |
| 268 , m_shouldOnlyFireDragOverEvent(false) | 242 , m_shouldOnlyFireDragOverEvent(false) |
| 269 , m_accumulatedRootOverscroll(FloatSize()) | 243 , m_accumulatedRootOverscroll(FloatSize()) |
| 270 , m_mousePositionIsUnknown(true) | 244 , m_mousePositionIsUnknown(true) |
| 271 , m_mouseDownTimestamp(0) | 245 , m_mouseDownTimestamp(0) |
| 272 , m_touchPressed(false) | 246 , m_pointerEventManager(frame) |
| 273 , m_scrollGestureHandlingNode(nullptr) | 247 , m_scrollGestureHandlingNode(nullptr) |
| 274 , m_lastGestureScrollOverWidget(false) | 248 , m_lastGestureScrollOverWidget(false) |
| 275 , m_longTapShouldInvokeContextMenu(false) | 249 , m_longTapShouldInvokeContextMenu(false) |
| 276 , m_activeIntervalTimer(this, &EventHandler::activeIntervalTimerFired) | 250 , m_activeIntervalTimer(this, &EventHandler::activeIntervalTimerFired) |
| 277 , m_lastShowPressTimestamp(0) | 251 , m_lastShowPressTimestamp(0) |
| 278 , m_deltaConsumedForScrollSequence(false) | 252 , m_deltaConsumedForScrollSequence(false) |
| 279 { | 253 { |
| 280 } | 254 } |
| 281 | 255 |
| 282 EventHandler::~EventHandler() | 256 EventHandler::~EventHandler() |
| 283 { | 257 { |
| 284 ASSERT(!m_fakeMouseMoveEventTimer.isActive()); | 258 ASSERT(!m_fakeMouseMoveEventTimer.isActive()); |
| 285 } | 259 } |
| 286 | 260 |
| 287 DEFINE_TRACE(EventHandler) | 261 DEFINE_TRACE(EventHandler) |
| 288 { | 262 { |
| 289 visitor->trace(m_frame); | 263 visitor->trace(m_frame); |
| 290 visitor->trace(m_mousePressNode); | 264 visitor->trace(m_mousePressNode); |
| 291 visitor->trace(m_resizeScrollableArea); | 265 visitor->trace(m_resizeScrollableArea); |
| 292 visitor->trace(m_capturingMouseEventsNode); | 266 visitor->trace(m_capturingMouseEventsNode); |
| 293 visitor->trace(m_nodeUnderMouse); | 267 visitor->trace(m_nodeUnderMouse); |
| 294 visitor->trace(m_lastMouseMoveEventSubframe); | 268 visitor->trace(m_lastMouseMoveEventSubframe); |
| 295 visitor->trace(m_lastScrollbarUnderMouse); | 269 visitor->trace(m_lastScrollbarUnderMouse); |
| 296 visitor->trace(m_clickNode); | 270 visitor->trace(m_clickNode); |
| 297 visitor->trace(m_dragTarget); | 271 visitor->trace(m_dragTarget); |
| 298 visitor->trace(m_frameSetBeingResized); | 272 visitor->trace(m_frameSetBeingResized); |
| 299 visitor->trace(m_scrollbarHandlingScrollGesture); | 273 visitor->trace(m_scrollbarHandlingScrollGesture); |
| 300 visitor->trace(m_targetForTouchID); | |
| 301 visitor->trace(m_regionForTouchID); | |
| 302 visitor->trace(m_touchSequenceDocument); | |
| 303 visitor->trace(m_scrollGestureHandlingNode); | 274 visitor->trace(m_scrollGestureHandlingNode); |
| 304 visitor->trace(m_previousGestureScrolledNode); | 275 visitor->trace(m_previousGestureScrolledNode); |
| 305 visitor->trace(m_lastDeferredTapElement); | 276 visitor->trace(m_lastDeferredTapElement); |
| 306 visitor->trace(m_selectionController); | 277 visitor->trace(m_selectionController); |
| 307 visitor->trace(m_pointerEventManager); | 278 visitor->trace(m_pointerEventManager); |
| 308 } | 279 } |
| 309 | 280 |
| 310 DragState& EventHandler::dragState() | 281 DragState& EventHandler::dragState() |
| 311 { | 282 { |
| 312 DEFINE_STATIC_LOCAL(DragState, state, (new DragState)); | 283 DEFINE_STATIC_LOCAL(DragState, state, (new DragState)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 329 m_dragTarget = nullptr; | 300 m_dragTarget = nullptr; |
| 330 m_shouldOnlyFireDragOverEvent = false; | 301 m_shouldOnlyFireDragOverEvent = false; |
| 331 m_mousePositionIsUnknown = true; | 302 m_mousePositionIsUnknown = true; |
| 332 m_lastKnownMousePosition = IntPoint(); | 303 m_lastKnownMousePosition = IntPoint(); |
| 333 m_lastKnownMouseGlobalPosition = IntPoint(); | 304 m_lastKnownMouseGlobalPosition = IntPoint(); |
| 334 m_lastMouseDownUserGestureToken.clear(); | 305 m_lastMouseDownUserGestureToken.clear(); |
| 335 m_mousePressNode = nullptr; | 306 m_mousePressNode = nullptr; |
| 336 m_mousePressed = false; | 307 m_mousePressed = false; |
| 337 m_capturesDragging = false; | 308 m_capturesDragging = false; |
| 338 m_capturingMouseEventsNode = nullptr; | 309 m_capturingMouseEventsNode = nullptr; |
| 339 m_targetForTouchID.clear(); | |
| 340 m_touchSequenceDocument.clear(); | |
| 341 m_touchSequenceUserGestureToken.clear(); | |
| 342 clearGestureScrollState(); | 310 clearGestureScrollState(); |
| 343 m_lastGestureScrollOverWidget = false; | 311 m_lastGestureScrollOverWidget = false; |
| 344 m_scrollbarHandlingScrollGesture = nullptr; | 312 m_scrollbarHandlingScrollGesture = nullptr; |
| 345 m_touchPressed = false; | |
| 346 m_pointerEventManager.clear(); | 313 m_pointerEventManager.clear(); |
| 347 m_mouseDownMayStartDrag = false; | 314 m_mouseDownMayStartDrag = false; |
| 348 m_lastShowPressTimestamp = 0; | 315 m_lastShowPressTimestamp = 0; |
| 349 m_lastDeferredTapElement = nullptr; | 316 m_lastDeferredTapElement = nullptr; |
| 350 m_eventHandlerWillResetCapturingMouseEventsNode = false; | 317 m_eventHandlerWillResetCapturingMouseEventsNode = false; |
| 351 m_mouseDownMayStartAutoscroll = false; | 318 m_mouseDownMayStartAutoscroll = false; |
| 352 m_svgPan = false; | 319 m_svgPan = false; |
| 353 m_mouseDownPos = IntPoint(); | 320 m_mouseDownPos = IntPoint(); |
| 354 m_mouseDownTimestamp = 0; | 321 m_mouseDownTimestamp = 0; |
| 355 m_longTapShouldInvokeContextMenu = false; | 322 m_longTapShouldInvokeContextMenu = false; |
| (...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1215 hitType |= HitTestRequest::Active; | 1182 hitType |= HitTestRequest::Active; |
| 1216 } else if (onlyUpdateScrollbars) { | 1183 } else if (onlyUpdateScrollbars) { |
| 1217 // Mouse events should be treated as "read-only" if we're updating only
scrollbars. This | 1184 // Mouse events should be treated as "read-only" if we're updating only
scrollbars. This |
| 1218 // means that :hover and :active freeze in the state they were in, rathe
r than updating | 1185 // means that :hover and :active freeze in the state they were in, rathe
r than updating |
| 1219 // for nodes the mouse moves while the window is not key (which will be
the case if | 1186 // for nodes the mouse moves while the window is not key (which will be
the case if |
| 1220 // onlyUpdateScrollbars is true). | 1187 // onlyUpdateScrollbars is true). |
| 1221 hitType |= HitTestRequest::ReadOnly; | 1188 hitType |= HitTestRequest::ReadOnly; |
| 1222 } | 1189 } |
| 1223 | 1190 |
| 1224 // Treat any mouse move events as readonly if the user is currently touching
the screen. | 1191 // Treat any mouse move events as readonly if the user is currently touching
the screen. |
| 1225 if (m_touchPressed) | 1192 if (m_pointerEventManager.getTouchEventManager().isAnyTouchActive()) |
| 1226 hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly; | 1193 hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly; |
| 1227 HitTestRequest request(hitType); | 1194 HitTestRequest request(hitType); |
| 1228 MouseEventWithHitTestResults mev = MouseEventWithHitTestResults(mouseEvent,
HitTestResult(request, LayoutPoint())); | 1195 MouseEventWithHitTestResults mev = MouseEventWithHitTestResults(mouseEvent,
HitTestResult(request, LayoutPoint())); |
| 1229 | 1196 |
| 1230 // We don't want to do a hit-test in forceLeave scenarios because there migh
t actually be some other frame above this one at the specified co-ordinate. | 1197 // We don't want to do a hit-test in forceLeave scenarios because there migh
t actually be some other frame above this one at the specified co-ordinate. |
| 1231 // So we must force the hit-test to fail, while still clearing hover/active
state. | 1198 // So we must force the hit-test to fail, while still clearing hover/active
state. |
| 1232 if (forceLeave) | 1199 if (forceLeave) |
| 1233 m_frame->document()->updateHoverActiveState(request, 0); | 1200 m_frame->document()->updateHoverActiveState(request, 0); |
| 1234 else | 1201 else |
| 1235 mev = prepareMouseEvent(request, mouseEvent); | 1202 mev = prepareMouseEvent(request, mouseEvent); |
| (...skipping 2329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3565 return result; | 3532 return result; |
| 3566 if (frame->view()) { | 3533 if (frame->view()) { |
| 3567 IntRect rect = frame->view()->visibleContentRect(IncludeScrollbars); | 3534 IntRect rect = frame->view()->visibleContentRect(IncludeScrollbars); |
| 3568 if (!rect.contains(roundedIntPoint(point))) | 3535 if (!rect.contains(roundedIntPoint(point))) |
| 3569 return result; | 3536 return result; |
| 3570 } | 3537 } |
| 3571 frame->contentLayoutItem().hitTest(result); | 3538 frame->contentLayoutItem().hitTest(result); |
| 3572 return result; | 3539 return result; |
| 3573 } | 3540 } |
| 3574 | 3541 |
| 3575 void EventHandler::dispatchPointerEvents(const PlatformTouchEvent& event, | |
| 3576 HeapVector<TouchInfo>& touchInfos) | |
| 3577 { | |
| 3578 if (!RuntimeEnabledFeatures::pointerEventEnabled()) | |
| 3579 return; | |
| 3580 | |
| 3581 // Iterate through the touch points, sending PointerEvents to the targets as
required. | |
| 3582 for (unsigned i = 0; i < touchInfos.size(); ++i) { | |
| 3583 TouchInfo& touchInfo = touchInfos[i]; | |
| 3584 const PlatformTouchPoint& touchPoint = touchInfo.point; | |
| 3585 | |
| 3586 | |
| 3587 if (touchPoint.state() == PlatformTouchPoint::TouchStationary | |
| 3588 || !touchInfo.knownTarget) | |
| 3589 continue; | |
| 3590 | |
| 3591 WebInputEventResult result = | |
| 3592 m_pointerEventManager.sendTouchPointerEvent( | |
| 3593 touchInfo.touchTarget, touchPoint, event.getModifiers(), | |
| 3594 touchInfo.adjustedRadius.width(), touchInfo.adjustedRadius.height(), | |
| 3595 touchInfo.adjustedPagePoint.x(), touchInfo.adjustedPagePoint.y()); | |
| 3596 touchInfo.consumed = result != WebInputEventResult::NotHandled; | |
| 3597 } | |
| 3598 } | |
| 3599 | |
| 3600 namespace { | |
| 3601 | |
| 3602 // Defining this class type local to dispatchTouchEvents() and annotating | |
| 3603 // it with STACK_ALLOCATED(), runs into MSVC(VS 2013)'s C4822 warning | |
| 3604 // that the local class doesn't provide a local definition for 'operator new'. | |
| 3605 // Which it intentionally doesn't and shouldn't. | |
| 3606 // | |
| 3607 // Work around such toolchain bugginess by lifting out the type, thereby | |
| 3608 // taking it out of C4822's reach. | |
| 3609 class ChangedTouches final { | |
| 3610 STACK_ALLOCATED(); | |
| 3611 public: | |
| 3612 // The touches corresponding to the particular change state this struct | |
| 3613 // instance represents. | |
| 3614 Member<TouchList> m_touches; | |
| 3615 | |
| 3616 using EventTargetSet = HeapHashSet<Member<EventTarget>>; | |
| 3617 // Set of targets involved in m_touches. | |
| 3618 EventTargetSet m_targets; | |
| 3619 }; | |
| 3620 | |
| 3621 } // namespace | |
| 3622 | |
| 3623 WebInputEventResult EventHandler::dispatchTouchEvents(const PlatformTouchEvent&
event, | |
| 3624 HeapVector<TouchInfo>& touchInfos, bool freshTouchEvents, bool allTouchRelea
sed) | |
| 3625 { | |
| 3626 // Build up the lists to use for the 'touches', 'targetTouches' and | |
| 3627 // 'changedTouches' attributes in the JS event. See | |
| 3628 // http://www.w3.org/TR/touch-events/#touchevent-interface for how these | |
| 3629 // lists fit together. | |
| 3630 | |
| 3631 // Holds the complete set of touches on the screen. | |
| 3632 TouchList* touches = TouchList::create(); | |
| 3633 | |
| 3634 // A different view on the 'touches' list above, filtered and grouped by | |
| 3635 // event target. Used for the 'targetTouches' list in the JS event. | |
| 3636 using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>; | |
| 3637 TargetTouchesHeapMap touchesByTarget; | |
| 3638 | |
| 3639 // Array of touches per state, used to assemble the 'changedTouches' list. | |
| 3640 ChangedTouches changedTouches[PlatformTouchPoint::TouchStateEnd]; | |
| 3641 | |
| 3642 for (unsigned i = 0; i < touchInfos.size(); ++i) { | |
| 3643 const TouchInfo& touchInfo = touchInfos[i]; | |
| 3644 const PlatformTouchPoint& point = touchInfo.point; | |
| 3645 PlatformTouchPoint::TouchState pointState = point.state(); | |
| 3646 | |
| 3647 if (touchInfo.consumed) | |
| 3648 continue; | |
| 3649 | |
| 3650 Touch* touch = Touch::create( | |
| 3651 touchInfo.targetFrame.get(), | |
| 3652 touchInfo.touchTarget.get(), | |
| 3653 point.id(), | |
| 3654 point.screenPos(), | |
| 3655 touchInfo.adjustedPagePoint, | |
| 3656 touchInfo.adjustedRadius, | |
| 3657 point.rotationAngle(), | |
| 3658 point.force(), | |
| 3659 touchInfo.region); | |
| 3660 | |
| 3661 // Ensure this target's touch list exists, even if it ends up empty, so | |
| 3662 // it can always be passed to TouchEvent::Create below. | |
| 3663 TargetTouchesHeapMap::iterator targetTouchesIterator = touchesByTarget.f
ind(touchInfo.touchTarget.get()); | |
| 3664 if (targetTouchesIterator == touchesByTarget.end()) { | |
| 3665 touchesByTarget.set(touchInfo.touchTarget.get(), TouchList::create()
); | |
| 3666 targetTouchesIterator = touchesByTarget.find(touchInfo.touchTarget.g
et()); | |
| 3667 } | |
| 3668 | |
| 3669 // touches and targetTouches should only contain information about | |
| 3670 // touches still on the screen, so if this point is released or | |
| 3671 // cancelled it will only appear in the changedTouches list. | |
| 3672 if (pointState != PlatformTouchPoint::TouchReleased && pointState != Pla
tformTouchPoint::TouchCancelled) { | |
| 3673 touches->append(touch); | |
| 3674 targetTouchesIterator->value->append(touch); | |
| 3675 } | |
| 3676 | |
| 3677 // Now build up the correct list for changedTouches. | |
| 3678 // Note that any touches that are in the TouchStationary state (e.g. if | |
| 3679 // the user had several points touched but did not move them all) should | |
| 3680 // never be in the changedTouches list so we do not handle them | |
| 3681 // explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609 | |
| 3682 // for further discussion about the TouchStationary state. | |
| 3683 if (pointState != PlatformTouchPoint::TouchStationary && touchInfo.known
Target) { | |
| 3684 ASSERT(pointState < PlatformTouchPoint::TouchStateEnd); | |
| 3685 if (!changedTouches[pointState].m_touches) | |
| 3686 changedTouches[pointState].m_touches = TouchList::create(); | |
| 3687 changedTouches[pointState].m_touches->append(touch); | |
| 3688 changedTouches[pointState].m_targets.add(touchInfo.touchTarget); | |
| 3689 } | |
| 3690 } | |
| 3691 if (allTouchReleased) { | |
| 3692 m_touchSequenceDocument.clear(); | |
| 3693 m_touchSequenceUserGestureToken.clear(); | |
| 3694 } | |
| 3695 | |
| 3696 WebInputEventResult eventResult = WebInputEventResult::NotHandled; | |
| 3697 | |
| 3698 // Now iterate through the changedTouches list and m_targets within it, send
ing | |
| 3699 // TouchEvents to the targets as required. | |
| 3700 for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; ++state
) { | |
| 3701 if (!changedTouches[state].m_touches) | |
| 3702 continue; | |
| 3703 | |
| 3704 const AtomicString& eventName(touchEventNameForTouchPointState(static_ca
st<PlatformTouchPoint::TouchState>(state))); | |
| 3705 for (const auto& eventTarget : changedTouches[state].m_targets) { | |
| 3706 EventTarget* touchEventTarget = eventTarget; | |
| 3707 TouchEvent* touchEvent = TouchEvent::create( | |
| 3708 touches, touchesByTarget.get(touchEventTarget), changedTouches[s
tate].m_touches.get(), | |
| 3709 eventName, touchEventTarget->toNode()->document().domWindow(), | |
| 3710 event.getModifiers(), event.cancelable(), event.causesScrollingI
fUncanceled(), event.timestamp()); | |
| 3711 | |
| 3712 eventResult = mergeEventResult(eventResult, toWebInputEventResult(to
uchEventTarget->dispatchEvent(touchEvent))); | |
| 3713 } | |
| 3714 } | |
| 3715 | |
| 3716 return eventResult; | |
| 3717 } | |
| 3718 | |
| 3719 WebInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEvent& eve
nt) | 3542 WebInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEvent& eve
nt) |
| 3720 { | 3543 { |
| 3721 TRACE_EVENT0("blink", "EventHandler::handleTouchEvent"); | 3544 TRACE_EVENT0("blink", "EventHandler::handleTouchEvent"); |
| 3722 | 3545 |
| 3723 if (event.type() == PlatformEvent::TouchScrollStarted) { | 3546 return m_pointerEventManager.handleTouchEvents(event); |
| 3724 m_pointerEventManager.blockTouchPointers(); | |
| 3725 return WebInputEventResult::HandledSystem; | |
| 3726 } | |
| 3727 | |
| 3728 const Vector<PlatformTouchPoint>& points = event.touchPoints(); | |
| 3729 | |
| 3730 bool newTouchSequence = true; | |
| 3731 bool allTouchReleased = true; | |
| 3732 for (unsigned i = 0; i < points.size(); ++i) { | |
| 3733 const PlatformTouchPoint& point = points[i]; | |
| 3734 | |
| 3735 if (point.state() != PlatformTouchPoint::TouchPressed) | |
| 3736 newTouchSequence = false; | |
| 3737 if (point.state() != PlatformTouchPoint::TouchReleased && point.state()
!= PlatformTouchPoint::TouchCancelled) | |
| 3738 allTouchReleased = false; | |
| 3739 } | |
| 3740 if (newTouchSequence) { | |
| 3741 // Ideally we'd ASSERT !m_touchSequenceDocument here since we should | |
| 3742 // have cleared the active document when we saw the last release. But we | |
| 3743 // have some tests that violate this, ClusterFuzz could trigger it, and | |
| 3744 // there may be cases where the browser doesn't reliably release all | |
| 3745 // touches. http://crbug.com/345372 tracks this. | |
| 3746 m_touchSequenceDocument.clear(); | |
| 3747 m_touchSequenceUserGestureToken.clear(); | |
| 3748 } | |
| 3749 | |
| 3750 ASSERT(m_frame->view()); | |
| 3751 if (m_touchSequenceDocument && (!m_touchSequenceDocument->frame() || !m_touc
hSequenceDocument->frame()->view())) { | |
| 3752 // If the active touch document has no frame or view, it's probably bein
g destroyed | |
| 3753 // so we can't dispatch events. | |
| 3754 return WebInputEventResult::NotHandled; | |
| 3755 } | |
| 3756 | |
| 3757 // First do hit tests for any new touch points. | |
| 3758 for (unsigned i = 0; i < points.size(); ++i) { | |
| 3759 const PlatformTouchPoint& point = points[i]; | |
| 3760 | |
| 3761 // Touch events implicitly capture to the touched node, and don't change | |
| 3762 // active/hover states themselves (Gesture events do). So we only need | |
| 3763 // to hit-test on touchstart, and it can be read-only. | |
| 3764 if (point.state() == PlatformTouchPoint::TouchPressed) { | |
| 3765 HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEv
ent | HitTestRequest::ReadOnly | HitTestRequest::Active; | |
| 3766 LayoutPoint pagePoint = roundedLayoutPoint(m_frame->view()->rootFram
eToContents(point.pos())); | |
| 3767 HitTestResult result; | |
| 3768 if (!m_touchSequenceDocument) { | |
| 3769 result = hitTestResultAtPoint(pagePoint, hitType); | |
| 3770 } else if (m_touchSequenceDocument->frame()) { | |
| 3771 LayoutPoint framePoint = roundedLayoutPoint(m_touchSequenceDocum
ent->frame()->view()->rootFrameToContents(point.pos())); | |
| 3772 result = hitTestResultInFrame(m_touchSequenceDocument->frame(),
framePoint, hitType); | |
| 3773 } else { | |
| 3774 continue; | |
| 3775 } | |
| 3776 | |
| 3777 Node* node = result.innerNode(); | |
| 3778 if (!node) | |
| 3779 continue; | |
| 3780 | |
| 3781 if (isHTMLCanvasElement(node)) { | |
| 3782 std::pair<Element*, String> regionInfo = toHTMLCanvasElement(nod
e)->getControlAndIdIfHitRegionExists(result.pointInInnerNodeFrame()); | |
| 3783 if (regionInfo.first) | |
| 3784 node = regionInfo.first; | |
| 3785 m_regionForTouchID.set(point.id(), regionInfo.second); | |
| 3786 } | |
| 3787 | |
| 3788 // Touch events should not go to text nodes | |
| 3789 if (node->isTextNode()) | |
| 3790 node = FlatTreeTraversal::parent(*node); | |
| 3791 | |
| 3792 if (!m_touchSequenceDocument) { | |
| 3793 // Keep track of which document should receive all touch events | |
| 3794 // in the active sequence. This must be a single document to | |
| 3795 // ensure we don't leak Nodes between documents. | |
| 3796 m_touchSequenceDocument = &(result.innerNode()->document()); | |
| 3797 ASSERT(m_touchSequenceDocument->frame()->view()); | |
| 3798 } | |
| 3799 | |
| 3800 // Ideally we'd ASSERT(!m_targetForTouchID.contains(point.id()) | |
| 3801 // since we shouldn't get a touchstart for a touch that's already | |
| 3802 // down. However EventSender allows this to be violated and there's | |
| 3803 // some tests that take advantage of it. There may also be edge | |
| 3804 // cases in the browser where this happens. | |
| 3805 // See http://crbug.com/345372. | |
| 3806 m_targetForTouchID.set(point.id(), node); | |
| 3807 | |
| 3808 TouchAction effectiveTouchAction = TouchActionUtil::computeEffective
TouchAction(*node); | |
| 3809 if (effectiveTouchAction != TouchActionAuto) | |
| 3810 m_frame->page()->chromeClient().setTouchAction(effectiveTouchAct
ion); | |
| 3811 } | |
| 3812 } | |
| 3813 | |
| 3814 m_touchPressed = !allTouchReleased; | |
| 3815 | |
| 3816 // If there's no document receiving touch events, or no handlers on the | |
| 3817 // document set to receive the events, then we can skip all the rest of | |
| 3818 // this work. | |
| 3819 if (!m_touchSequenceDocument || !m_touchSequenceDocument->frameHost() || !ha
sTouchHandlers(m_touchSequenceDocument->frameHost()->eventHandlerRegistry()) ||
!m_touchSequenceDocument->frame()) { | |
| 3820 if (allTouchReleased) { | |
| 3821 m_touchSequenceDocument.clear(); | |
| 3822 m_touchSequenceUserGestureToken.clear(); | |
| 3823 } | |
| 3824 return WebInputEventResult::NotHandled; | |
| 3825 } | |
| 3826 | |
| 3827 // Whether a touch should be considered a "user gesture" or not is a tricky
question. | |
| 3828 // https://docs.google.com/document/d/1oF1T3O7_E4t1PYHV6gyCwHxOi3ystm0eSL5xZ
u7nvOg/edit# | |
| 3829 // TODO(rbyers): Disable user gesture in some cases but retain logging for n
ow (crbug.com/582140). | |
| 3830 OwnPtr<UserGestureIndicator> gestureIndicator; | |
| 3831 if (event.touchPoints().size() == 1 | |
| 3832 && event.touchPoints()[0].state() == PlatformTouchPoint::TouchReleased | |
| 3833 && !event.causesScrollingIfUncanceled()) { | |
| 3834 // This is a touchend corresponding to a tap, definitely a user gesture.
So don't supply | |
| 3835 // a UserGestureUtilizedCallback. | |
| 3836 gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProcessin
gUserGesture)); | |
| 3837 } else { | |
| 3838 // This is some other touch event that perhaps shouldn't be considered a
user gesture. So | |
| 3839 // use a UserGestureUtilizedCallback to get metrics / deprecation warnin
gs. | |
| 3840 if (m_touchSequenceUserGestureToken) | |
| 3841 gestureIndicator = adoptPtr(new UserGestureIndicator(m_touchSequence
UserGestureToken.release(), &m_touchSequenceDocument->frame()->eventHandler())); | |
| 3842 else | |
| 3843 gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProce
ssingUserGesture, &m_touchSequenceDocument->frame()->eventHandler())); | |
| 3844 m_touchSequenceUserGestureToken = UserGestureIndicator::currentToken(); | |
| 3845 } | |
| 3846 | |
| 3847 // Compute and store the common info used by both PointerEvent and TouchEven
t. | |
| 3848 HeapVector<TouchInfo> touchInfos(points.size()); | |
| 3849 | |
| 3850 for (unsigned i = 0; i < points.size(); ++i) { | |
| 3851 const PlatformTouchPoint& point = points[i]; | |
| 3852 PlatformTouchPoint::TouchState pointState = point.state(); | |
| 3853 EventTarget* touchTarget = nullptr; | |
| 3854 String regionID; | |
| 3855 | |
| 3856 if (pointState == PlatformTouchPoint::TouchReleased || pointState == Pla
tformTouchPoint::TouchCancelled) { | |
| 3857 // The target should be the original target for this touch, so get | |
| 3858 // it from the hashmap. As it's a release or cancel we also remove | |
| 3859 // it from the map. | |
| 3860 touchTarget = m_targetForTouchID.take(point.id()); | |
| 3861 regionID = m_regionForTouchID.take(point.id()); | |
| 3862 } else { | |
| 3863 // No hittest is performed on move or stationary, since the target | |
| 3864 // is not allowed to change anyway. | |
| 3865 touchTarget = m_targetForTouchID.get(point.id()); | |
| 3866 regionID = m_regionForTouchID.get(point.id()); | |
| 3867 } | |
| 3868 | |
| 3869 LocalFrame* targetFrame = nullptr; | |
| 3870 bool knownTarget = false; | |
| 3871 if (touchTarget) { | |
| 3872 Document& doc = touchTarget->toNode()->document(); | |
| 3873 // If the target node has moved to a new document while it was being
touched, | |
| 3874 // we can't send events to the new document because that could leak
nodes | |
| 3875 // from one document to another. See http://crbug.com/394339. | |
| 3876 if (&doc == m_touchSequenceDocument.get()) { | |
| 3877 targetFrame = doc.frame(); | |
| 3878 knownTarget = true; | |
| 3879 } | |
| 3880 } | |
| 3881 if (!knownTarget) { | |
| 3882 // If we don't have a target registered for the point it means we've | |
| 3883 // missed our opportunity to do a hit test for it (due to some | |
| 3884 // optimization that prevented blink from ever seeing the | |
| 3885 // touchstart), or that the touch started outside the active touch | |
| 3886 // sequence document. We should still include the touch in the | |
| 3887 // Touches list reported to the application (eg. so it can | |
| 3888 // differentiate between a one and two finger gesture), but we won't | |
| 3889 // actually dispatch any events for it. Set the target to the | |
| 3890 // Document so that there's some valid node here. Perhaps this | |
| 3891 // should really be LocalDOMWindow, but in all other cases the targe
t of | |
| 3892 // a Touch is a Node so using the window could be a breaking change. | |
| 3893 // Since we know there was no handler invoked, the specific target | |
| 3894 // should be completely irrelevant to the application. | |
| 3895 touchTarget = m_touchSequenceDocument; | |
| 3896 targetFrame = m_touchSequenceDocument->frame(); | |
| 3897 } | |
| 3898 ASSERT(targetFrame); | |
| 3899 | |
| 3900 // pagePoint should always be in the target element's document coordinat
es. | |
| 3901 FloatPoint pagePoint = targetFrame->view()->rootFrameToContents(point.po
s()); | |
| 3902 float scaleFactor = 1.0f / targetFrame->pageZoomFactor(); | |
| 3903 | |
| 3904 TouchInfo& touchInfo = touchInfos[i]; | |
| 3905 touchInfo.point = point; | |
| 3906 touchInfo.touchTarget = touchTarget; | |
| 3907 touchInfo.targetFrame = targetFrame; | |
| 3908 touchInfo.adjustedPagePoint = pagePoint.scaledBy(scaleFactor); | |
| 3909 touchInfo.adjustedRadius = point.radius().scaledBy(scaleFactor); | |
| 3910 touchInfo.knownTarget = knownTarget; | |
| 3911 touchInfo.consumed = false; | |
| 3912 touchInfo.region = regionID; | |
| 3913 } | |
| 3914 | |
| 3915 if (newTouchSequence) | |
| 3916 m_pointerEventManager.unblockTouchPointers(); | |
| 3917 dispatchPointerEvents(event, touchInfos); | |
| 3918 // Note that the disposition of any pointer events affects only the generati
on of touch | |
| 3919 // events. If all pointer events were handled (and hence no touch events wer
e fired), that | |
| 3920 // is still equivalent to the touch events going unhandled because pointer e
vent handler | |
| 3921 // don't block scroll gesture generation. | |
| 3922 | |
| 3923 // TODO(crbug.com/507408): If PE handlers always call preventDefault, we won
't see TEs until after | |
| 3924 // scrolling starts because the scrolling would suppress upcoming PEs. This
sudden "break" in TE | |
| 3925 // suppression can make the visible TEs inconsistent (e.g. touchmove without
a touchstart). | |
| 3926 | |
| 3927 return dispatchTouchEvents(event, touchInfos, newTouchSequence, allTouchRele
ased); | |
| 3928 } | 3547 } |
| 3929 | 3548 |
| 3930 void EventHandler::userGestureUtilized() | 3549 void EventHandler::userGestureUtilized() |
| 3931 { | 3550 { |
| 3932 // This is invoked for UserGestureIndicators created in handleTouchEvent whi
ch perhaps represent | 3551 // This is invoked for UserGestureIndicators created in handleTouchEvent whi
ch perhaps represent |
| 3933 // touch actions which shouldn't be considered a user-gesture. | 3552 // touch actions which shouldn't be considered a user-gesture. |
| 3934 UseCounter::count(m_frame, UseCounter::TouchDragUserGestureUsed); | 3553 UseCounter::count(m_frame, UseCounter::TouchDragUserGestureUsed); |
| 3935 Deprecation::countDeprecationCrossOriginIframe(m_frame, UseCounter::TouchDra
gUserGestureUsedCrossOrigin); | 3554 Deprecation::countDeprecationCrossOriginIframe(m_frame, UseCounter::TouchDra
gUserGestureUsedCrossOrigin); |
| 3936 } | 3555 } |
| 3937 | 3556 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3985 PlatformEvent::Modifiers EventHandler::accessKeyModifiers() | 3604 PlatformEvent::Modifiers EventHandler::accessKeyModifiers() |
| 3986 { | 3605 { |
| 3987 #if OS(MACOSX) | 3606 #if OS(MACOSX) |
| 3988 return static_cast<PlatformEvent::Modifiers>(PlatformEvent::CtrlKey | Platfo
rmEvent::AltKey); | 3607 return static_cast<PlatformEvent::Modifiers>(PlatformEvent::CtrlKey | Platfo
rmEvent::AltKey); |
| 3989 #else | 3608 #else |
| 3990 return PlatformEvent::AltKey; | 3609 return PlatformEvent::AltKey; |
| 3991 #endif | 3610 #endif |
| 3992 } | 3611 } |
| 3993 | 3612 |
| 3994 } // namespace blink | 3613 } // namespace blink |
| OLD | NEW |