Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(390)

Side by Side Diff: third_party/WebKit/Source/core/input/EventHandler.cpp

Issue 1892653003: Extract touch handling logic from EventHandler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698