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

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: Rebased Created 4 years, 7 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"
72 #include "core/layout/LayoutView.h" 71 #include "core/layout/LayoutView.h"
73 #include "core/layout/api/LayoutViewItem.h" 72 #include "core/layout/api/LayoutViewItem.h"
74 #include "core/loader/DocumentLoader.h" 73 #include "core/loader/DocumentLoader.h"
75 #include "core/loader/FrameLoader.h" 74 #include "core/loader/FrameLoader.h"
76 #include "core/loader/FrameLoaderClient.h" 75 #include "core/loader/FrameLoaderClient.h"
77 #include "core/page/AutoscrollController.h" 76 #include "core/page/AutoscrollController.h"
78 #include "core/page/ChromeClient.h" 77 #include "core/page/ChromeClient.h"
79 #include "core/page/DragController.h" 78 #include "core/page/DragController.h"
80 #include "core/page/DragState.h" 79 #include "core/page/DragState.h"
81 #include "core/page/FocusController.h" 80 #include "core/page/FocusController.h"
82 #include "core/page/FrameTree.h" 81 #include "core/page/FrameTree.h"
83 #include "core/page/Page.h" 82 #include "core/page/Page.h"
84 #include "core/page/SpatialNavigation.h" 83 #include "core/page/SpatialNavigation.h"
85 #include "core/page/TouchAdjustment.h" 84 #include "core/page/TouchAdjustment.h"
86 #include "core/page/scrolling/ScrollState.h" 85 #include "core/page/scrolling/ScrollState.h"
87 #include "core/paint/PaintLayer.h" 86 #include "core/paint/PaintLayer.h"
88 #include "core/style/ComputedStyle.h" 87 #include "core/style/ComputedStyle.h"
89 #include "core/svg/SVGDocumentExtensions.h" 88 #include "core/svg/SVGDocumentExtensions.h"
90 #include "platform/Histogram.h"
91 #include "platform/PlatformGestureEvent.h" 89 #include "platform/PlatformGestureEvent.h"
92 #include "platform/PlatformKeyboardEvent.h" 90 #include "platform/PlatformKeyboardEvent.h"
93 #include "platform/PlatformTouchEvent.h" 91 #include "platform/PlatformTouchEvent.h"
94 #include "platform/PlatformWheelEvent.h" 92 #include "platform/PlatformWheelEvent.h"
95 #include "platform/RuntimeEnabledFeatures.h" 93 #include "platform/RuntimeEnabledFeatures.h"
96 #include "platform/TraceEvent.h" 94 #include "platform/TraceEvent.h"
97 #include "platform/WindowsKeyboardCodes.h" 95 #include "platform/WindowsKeyboardCodes.h"
98 #include "platform/geometry/FloatPoint.h" 96 #include "platform/geometry/FloatPoint.h"
99 #include "platform/graphics/Image.h" 97 #include "platform/graphics/Image.h"
100 #include "platform/heap/Handle.h" 98 #include "platform/heap/Handle.h"
101 #include "platform/scroll/ScrollAnimatorBase.h" 99 #include "platform/scroll/ScrollAnimatorBase.h"
102 #include "platform/scroll/Scrollbar.h" 100 #include "platform/scroll/Scrollbar.h"
103 #include "wtf/Assertions.h" 101 #include "wtf/Assertions.h"
104 #include "wtf/CurrentTime.h" 102 #include "wtf/CurrentTime.h"
105 #include "wtf/StdLibExtras.h" 103 #include "wtf/StdLibExtras.h"
106 #include "wtf/TemporaryChange.h" 104 #include "wtf/TemporaryChange.h"
107 105
108 namespace blink { 106 namespace blink {
109 107
110 namespace { 108 namespace {
111 109
112 bool hasTouchHandlers(const EventHandlerRegistry& registry)
113 {
114 return registry.hasEventHandlers(EventHandlerRegistry::TouchStartOrMoveEvent Blocking)
115 || registry.hasEventHandlers(EventHandlerRegistry::TouchStartOrMoveEvent Passive)
116 || registry.hasEventHandlers(EventHandlerRegistry::TouchEndOrCancelEvent Blocking)
117 || registry.hasEventHandlers(EventHandlerRegistry::TouchEndOrCancelEvent Passive);
118 }
119
120 const AtomicString& touchEventNameForTouchPointState(PlatformTouchPoint::TouchSt ate state)
121 {
122 switch (state) {
123 case PlatformTouchPoint::TouchReleased:
124 return EventTypeNames::touchend;
125 case PlatformTouchPoint::TouchCancelled:
126 return EventTypeNames::touchcancel;
127 case PlatformTouchPoint::TouchPressed:
128 return EventTypeNames::touchstart;
129 case PlatformTouchPoint::TouchMoved:
130 return EventTypeNames::touchmove;
131 case PlatformTouchPoint::TouchStationary:
132 // Fall through to default
133 default:
134 ASSERT_NOT_REACHED();
135 return emptyAtom;
136 }
137 }
138
139 // Convert |event->deltaMode()| to scroll granularity and output as |granularity |. 110 // Convert |event->deltaMode()| to scroll granularity and output as |granularity |.
140 bool wheelGranularityToScrollGranularity(const WheelEvent* event, ScrollGranular ity* granularity) 111 bool wheelGranularityToScrollGranularity(const WheelEvent* event, ScrollGranular ity* granularity)
141 { 112 {
142 DCHECK(granularity); 113 DCHECK(granularity);
143 switch (event->deltaMode()) { 114 switch (event->deltaMode()) {
144 case WheelEvent::DOM_DELTA_PAGE: 115 case WheelEvent::DOM_DELTA_PAGE:
145 *granularity = ScrollByPage; 116 *granularity = ScrollByPage;
146 return true; 117 return true;
147 case WheelEvent::DOM_DELTA_LINE: 118 case WheelEvent::DOM_DELTA_LINE:
148 *granularity = ScrollByLine; 119 *granularity = ScrollByLine;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 } 173 }
203 // TODO(tdresser): this should sometimes be excluded, as part of crbug.com/4 10974. 174 // TODO(tdresser): this should sometimes be excluded, as part of crbug.com/4 10974.
204 // We need to ensure that the scrollingElement is always part of 175 // We need to ensure that the scrollingElement is always part of
205 // the scroll chain. In quirks mode, when the scrollingElement is 176 // the scroll chain. In quirks mode, when the scrollingElement is
206 // the body, some elements may use the documentElement as their 177 // the body, some elements may use the documentElement as their
207 // containingBlock, so we ensure the scrollingElement is added 178 // containingBlock, so we ensure the scrollingElement is added
208 // here. 179 // here.
209 scrollChain.push_front(DOMNodeIds::idForNode(frame.document()->scrollingElem ent())); 180 scrollChain.push_front(DOMNodeIds::idForNode(frame.document()->scrollingElem ent()));
210 } 181 }
211 182
212 // These offsets change indicies into the ListenerHistogram
213 // enumeration. The addition of a series of offsets then
214 // produces the resulting ListenerHistogram value.
215 const size_t kTouchTargetHistogramRootScrollerOffset = 4;
216 const size_t kTouchTargetHistogramScrollableDocumentOffset = 2;
217 const size_t kTouchTargetHistogramHandledOffset = 1;
218
219 enum TouchTargetAndDispatchResultType {
220 NonRootScrollerNonScrollableNotHandled, // Non-root-scroller, non-scrollable document, not handled.
221 NonRootScrollerNonScrollableHandled, // Non-root-scroller, non-scrollable do cument, handled application.
222 NonRootScrollerScrollableDocumentNotHandled, // Non-root-scroller, scrollabl e document, not handled.
223 NonRootScrollerScrollableDocumentHandled, // Non-root-scroller, scrollable d ocument, handled application.
224 RootScrollerNonScrollableNotHandled, // Root-scroller, non-scrollable docume nt, not handled.
225 RootScrollerNonScrollableHandled, // Root-scroller, non-scrollable document, handled.
226 RootScrollerScrollableDocumentNotHandled, // Root-scroller, scrollable docum ent, not handled.
227 RootScrollerScrollableDocumentHandled, // Root-scroller, scrollable document , handled.
228 TouchTargetAndDispatchResultTypeMax,
229 };
230
231 TouchTargetAndDispatchResultType toTouchTargetHistogramValue(EventTarget* eventT arget, DispatchEventResult dispatchResult)
232 {
233 int result = 0;
234 Document* document = nullptr;
235
236 if (const LocalDOMWindow* domWindow = eventTarget->toLocalDOMWindow()) {
237 // Treat the window as a root scroller as well.
238 document = domWindow->document();
239 result += kTouchTargetHistogramRootScrollerOffset;
240 } else if (Node* node = eventTarget->toNode()) {
241 // Report if the target node is the document or body.
242 if (node->isDocumentNode() || static_cast<Node*>(node->document().docume ntElement()) == node || static_cast<Node*>(node->document().body()) == node) {
243 result += kTouchTargetHistogramRootScrollerOffset;
244 }
245 document = &node->document();
246 }
247
248 if (document) {
249 FrameView* view = document->view();
250 if (view && view->isScrollable())
251 result += kTouchTargetHistogramScrollableDocumentOffset;
252 }
253
254 if (dispatchResult != DispatchEventResult::NotCanceled)
255 result += kTouchTargetHistogramHandledOffset;
256 return static_cast<TouchTargetAndDispatchResultType>(result);
257 }
258
259 } // namespace 183 } // namespace
260 184
261 using namespace HTMLNames; 185 using namespace HTMLNames;
262 186
263 // The link drag hysteresis is much larger than the others because there 187 // The link drag hysteresis is much larger than the others because there
264 // needs to be enough space to cancel the link press without starting a link dra g, 188 // needs to be enough space to cancel the link press without starting a link dra g,
265 // and because dragging links is rare. 189 // and because dragging links is rare.
266 static const int LinkDragHysteresis = 40; 190 static const int LinkDragHysteresis = 40;
267 static const int ImageDragHysteresis = 5; 191 static const int ImageDragHysteresis = 5;
268 static const int TextDragHysteresis = 3; 192 static const int TextDragHysteresis = 3;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 , m_mouseDownMayStartAutoscroll(false) 249 , m_mouseDownMayStartAutoscroll(false)
326 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFire d) 250 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFire d)
327 , m_svgPan(false) 251 , m_svgPan(false)
328 , m_resizeScrollableArea(nullptr) 252 , m_resizeScrollableArea(nullptr)
329 , m_eventHandlerWillResetCapturingMouseEventsNode(0) 253 , m_eventHandlerWillResetCapturingMouseEventsNode(0)
330 , m_clickCount(0) 254 , m_clickCount(0)
331 , m_shouldOnlyFireDragOverEvent(false) 255 , m_shouldOnlyFireDragOverEvent(false)
332 , m_accumulatedRootOverscroll(FloatSize()) 256 , m_accumulatedRootOverscroll(FloatSize())
333 , m_mousePositionIsUnknown(true) 257 , m_mousePositionIsUnknown(true)
334 , m_mouseDownTimestamp(0) 258 , m_mouseDownTimestamp(0)
335 , m_touchPressed(false) 259 , m_pointerEventManager(frame)
336 , m_scrollGestureHandlingNode(nullptr) 260 , m_scrollGestureHandlingNode(nullptr)
337 , m_lastGestureScrollOverWidget(false) 261 , m_lastGestureScrollOverWidget(false)
338 , m_longTapShouldInvokeContextMenu(false) 262 , m_longTapShouldInvokeContextMenu(false)
339 , m_activeIntervalTimer(this, &EventHandler::activeIntervalTimerFired) 263 , m_activeIntervalTimer(this, &EventHandler::activeIntervalTimerFired)
340 , m_lastShowPressTimestamp(0) 264 , m_lastShowPressTimestamp(0)
341 , m_deltaConsumedForScrollSequence(false) 265 , m_deltaConsumedForScrollSequence(false)
342 , m_waitingForFirstTouchMove(false)
343 { 266 {
344 } 267 }
345 268
346 EventHandler::~EventHandler() 269 EventHandler::~EventHandler()
347 { 270 {
348 ASSERT(!m_fakeMouseMoveEventTimer.isActive()); 271 ASSERT(!m_fakeMouseMoveEventTimer.isActive());
349 } 272 }
350 273
351 DEFINE_TRACE(EventHandler) 274 DEFINE_TRACE(EventHandler)
352 { 275 {
353 visitor->trace(m_frame); 276 visitor->trace(m_frame);
354 visitor->trace(m_mousePressNode); 277 visitor->trace(m_mousePressNode);
355 visitor->trace(m_resizeScrollableArea); 278 visitor->trace(m_resizeScrollableArea);
356 visitor->trace(m_capturingMouseEventsNode); 279 visitor->trace(m_capturingMouseEventsNode);
357 visitor->trace(m_nodeUnderMouse); 280 visitor->trace(m_nodeUnderMouse);
358 visitor->trace(m_lastMouseMoveEventSubframe); 281 visitor->trace(m_lastMouseMoveEventSubframe);
359 visitor->trace(m_lastScrollbarUnderMouse); 282 visitor->trace(m_lastScrollbarUnderMouse);
360 visitor->trace(m_clickNode); 283 visitor->trace(m_clickNode);
361 visitor->trace(m_dragTarget); 284 visitor->trace(m_dragTarget);
362 visitor->trace(m_frameSetBeingResized); 285 visitor->trace(m_frameSetBeingResized);
363 visitor->trace(m_scrollbarHandlingScrollGesture); 286 visitor->trace(m_scrollbarHandlingScrollGesture);
364 visitor->trace(m_targetForTouchID);
365 visitor->trace(m_touchSequenceDocument);
366 visitor->trace(m_scrollGestureHandlingNode); 287 visitor->trace(m_scrollGestureHandlingNode);
367 visitor->trace(m_previousGestureScrolledNode); 288 visitor->trace(m_previousGestureScrolledNode);
368 visitor->trace(m_lastDeferredTapElement); 289 visitor->trace(m_lastDeferredTapElement);
369 visitor->trace(m_selectionController); 290 visitor->trace(m_selectionController);
370 visitor->trace(m_pointerEventManager); 291 visitor->trace(m_pointerEventManager);
371 } 292 }
372 293
373 DragState& EventHandler::dragState() 294 DragState& EventHandler::dragState()
374 { 295 {
375 DEFINE_STATIC_LOCAL(DragState, state, (new DragState)); 296 DEFINE_STATIC_LOCAL(DragState, state, (new DragState));
(...skipping 16 matching lines...) Expand all
392 m_dragTarget = nullptr; 313 m_dragTarget = nullptr;
393 m_shouldOnlyFireDragOverEvent = false; 314 m_shouldOnlyFireDragOverEvent = false;
394 m_mousePositionIsUnknown = true; 315 m_mousePositionIsUnknown = true;
395 m_lastKnownMousePosition = IntPoint(); 316 m_lastKnownMousePosition = IntPoint();
396 m_lastKnownMouseGlobalPosition = IntPoint(); 317 m_lastKnownMouseGlobalPosition = IntPoint();
397 m_lastMouseDownUserGestureToken.clear(); 318 m_lastMouseDownUserGestureToken.clear();
398 m_mousePressNode = nullptr; 319 m_mousePressNode = nullptr;
399 m_mousePressed = false; 320 m_mousePressed = false;
400 m_capturesDragging = false; 321 m_capturesDragging = false;
401 m_capturingMouseEventsNode = nullptr; 322 m_capturingMouseEventsNode = nullptr;
402 m_targetForTouchID.clear();
403 m_touchSequenceDocument.clear();
404 m_touchSequenceUserGestureToken.clear();
405 clearGestureScrollState(); 323 clearGestureScrollState();
406 m_lastGestureScrollOverWidget = false; 324 m_lastGestureScrollOverWidget = false;
407 m_scrollbarHandlingScrollGesture = nullptr; 325 m_scrollbarHandlingScrollGesture = nullptr;
408 m_touchPressed = false;
409 m_pointerEventManager.clear(); 326 m_pointerEventManager.clear();
410 m_mouseDownMayStartDrag = false; 327 m_mouseDownMayStartDrag = false;
411 m_lastShowPressTimestamp = 0; 328 m_lastShowPressTimestamp = 0;
412 m_lastDeferredTapElement = nullptr; 329 m_lastDeferredTapElement = nullptr;
413 m_eventHandlerWillResetCapturingMouseEventsNode = false; 330 m_eventHandlerWillResetCapturingMouseEventsNode = false;
414 m_mouseDownMayStartAutoscroll = false; 331 m_mouseDownMayStartAutoscroll = false;
415 m_svgPan = false; 332 m_svgPan = false;
416 m_mouseDownPos = IntPoint(); 333 m_mouseDownPos = IntPoint();
417 m_mouseDownTimestamp = 0; 334 m_mouseDownTimestamp = 0;
418 m_longTapShouldInvokeContextMenu = false; 335 m_longTapShouldInvokeContextMenu = false;
(...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after
1352 hitType |= HitTestRequest::Active; 1269 hitType |= HitTestRequest::Active;
1353 } else if (onlyUpdateScrollbars) { 1270 } else if (onlyUpdateScrollbars) {
1354 // Mouse events should be treated as "read-only" if we're updating only scrollbars. This 1271 // Mouse events should be treated as "read-only" if we're updating only scrollbars. This
1355 // means that :hover and :active freeze in the state they were in, rathe r than updating 1272 // means that :hover and :active freeze in the state they were in, rathe r than updating
1356 // for nodes the mouse moves while the window is not key (which will be the case if 1273 // for nodes the mouse moves while the window is not key (which will be the case if
1357 // onlyUpdateScrollbars is true). 1274 // onlyUpdateScrollbars is true).
1358 hitType |= HitTestRequest::ReadOnly; 1275 hitType |= HitTestRequest::ReadOnly;
1359 } 1276 }
1360 1277
1361 // Treat any mouse move events as readonly if the user is currently touching the screen. 1278 // Treat any mouse move events as readonly if the user is currently touching the screen.
1362 if (m_touchPressed) 1279 if (m_pointerEventManager.isAnyTouchActive())
1363 hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly; 1280 hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly;
1364 HitTestRequest request(hitType); 1281 HitTestRequest request(hitType);
1365 MouseEventWithHitTestResults mev = MouseEventWithHitTestResults(mouseEvent, HitTestResult(request, LayoutPoint())); 1282 MouseEventWithHitTestResults mev = MouseEventWithHitTestResults(mouseEvent, HitTestResult(request, LayoutPoint()));
1366 1283
1367 // 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. 1284 // 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.
1368 // So we must force the hit-test to fail, while still clearing hover/active state. 1285 // So we must force the hit-test to fail, while still clearing hover/active state.
1369 if (forceLeave) 1286 if (forceLeave)
1370 m_frame->document()->updateHoverActiveState(request, 0); 1287 m_frame->document()->updateHoverActiveState(request, 0);
1371 else 1288 else
1372 mev = prepareMouseEvent(request, mouseEvent); 1289 mev = prepareMouseEvent(request, mouseEvent);
(...skipping 2359 matching lines...) Expand 10 before | Expand all | Expand 10 after
3732 return result; 3649 return result;
3733 if (frame->view()) { 3650 if (frame->view()) {
3734 IntRect rect = frame->view()->visibleContentRect(IncludeScrollbars); 3651 IntRect rect = frame->view()->visibleContentRect(IncludeScrollbars);
3735 if (!rect.contains(roundedIntPoint(point))) 3652 if (!rect.contains(roundedIntPoint(point)))
3736 return result; 3653 return result;
3737 } 3654 }
3738 frame->contentLayoutItem().hitTest(result); 3655 frame->contentLayoutItem().hitTest(result);
3739 return result; 3656 return result;
3740 } 3657 }
3741 3658
3742 void EventHandler::dispatchPointerEvents(const PlatformTouchEvent& event,
3743 HeapVector<TouchInfo>& touchInfos)
3744 {
3745 if (!RuntimeEnabledFeatures::pointerEventEnabled())
3746 return;
3747
3748 // Iterate through the touch points, sending PointerEvents to the targets as required.
3749 for (unsigned i = 0; i < touchInfos.size(); ++i) {
3750 TouchInfo& touchInfo = touchInfos[i];
3751 const PlatformTouchPoint& touchPoint = touchInfo.point;
3752
3753
3754 if (touchPoint.state() == PlatformTouchPoint::TouchStationary
3755 || !touchInfo.knownTarget)
3756 continue;
3757
3758 WebInputEventResult result =
3759 m_pointerEventManager.sendTouchPointerEvent(
3760 touchInfo.touchTarget, touchPoint, event.getModifiers(),
3761 touchInfo.adjustedRadius.width(), touchInfo.adjustedRadius.height(),
3762 touchInfo.adjustedPagePoint.x(), touchInfo.adjustedPagePoint.y());
3763 touchInfo.consumed = result != WebInputEventResult::NotHandled;
3764 }
3765 }
3766
3767 namespace {
3768
3769 // Defining this class type local to dispatchTouchEvents() and annotating
3770 // it with STACK_ALLOCATED(), runs into MSVC(VS 2013)'s C4822 warning
3771 // that the local class doesn't provide a local definition for 'operator new'.
3772 // Which it intentionally doesn't and shouldn't.
3773 //
3774 // Work around such toolchain bugginess by lifting out the type, thereby
3775 // taking it out of C4822's reach.
3776 class ChangedTouches final {
3777 STACK_ALLOCATED();
3778 public:
3779 // The touches corresponding to the particular change state this struct
3780 // instance represents.
3781 Member<TouchList> m_touches;
3782
3783 using EventTargetSet = HeapHashSet<Member<EventTarget>>;
3784 // Set of targets involved in m_touches.
3785 EventTargetSet m_targets;
3786 };
3787
3788 } // namespace
3789
3790 WebInputEventResult EventHandler::dispatchTouchEvents(const PlatformTouchEvent& event,
3791 HeapVector<TouchInfo>& touchInfos, bool allTouchReleased)
3792 {
3793 bool touchStartOrFirstTouchMove = false;
3794 if (event.type() == PlatformEvent::TouchStart) {
3795 m_waitingForFirstTouchMove = true;
3796 touchStartOrFirstTouchMove = true;
3797 } else if (event.type() == PlatformEvent::TouchMove) {
3798 touchStartOrFirstTouchMove = m_waitingForFirstTouchMove;
3799 m_waitingForFirstTouchMove = false;
3800 }
3801
3802 // Build up the lists to use for the 'touches', 'targetTouches' and
3803 // 'changedTouches' attributes in the JS event. See
3804 // http://www.w3.org/TR/touch-events/#touchevent-interface for how these
3805 // lists fit together.
3806
3807 // Holds the complete set of touches on the screen.
3808 TouchList* touches = TouchList::create();
3809
3810 // A different view on the 'touches' list above, filtered and grouped by
3811 // event target. Used for the 'targetTouches' list in the JS event.
3812 using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>;
3813 TargetTouchesHeapMap touchesByTarget;
3814
3815 // Array of touches per state, used to assemble the 'changedTouches' list.
3816 ChangedTouches changedTouches[PlatformTouchPoint::TouchStateEnd];
3817
3818 for (unsigned i = 0; i < touchInfos.size(); ++i) {
3819 const TouchInfo& touchInfo = touchInfos[i];
3820 const PlatformTouchPoint& point = touchInfo.point;
3821 PlatformTouchPoint::TouchState pointState = point.state();
3822
3823 if (touchInfo.consumed)
3824 continue;
3825
3826 Touch* touch = Touch::create(
3827 touchInfo.targetFrame.get(),
3828 touchInfo.touchTarget.get(),
3829 point.id(),
3830 point.screenPos(),
3831 touchInfo.adjustedPagePoint,
3832 touchInfo.adjustedRadius,
3833 point.rotationAngle(),
3834 point.force(),
3835 touchInfo.region);
3836
3837 // Ensure this target's touch list exists, even if it ends up empty, so
3838 // it can always be passed to TouchEvent::Create below.
3839 TargetTouchesHeapMap::iterator targetTouchesIterator = touchesByTarget.f ind(touchInfo.touchTarget.get());
3840 if (targetTouchesIterator == touchesByTarget.end()) {
3841 touchesByTarget.set(touchInfo.touchTarget.get(), TouchList::create() );
3842 targetTouchesIterator = touchesByTarget.find(touchInfo.touchTarget.g et());
3843 }
3844
3845 // touches and targetTouches should only contain information about
3846 // touches still on the screen, so if this point is released or
3847 // cancelled it will only appear in the changedTouches list.
3848 if (pointState != PlatformTouchPoint::TouchReleased && pointState != Pla tformTouchPoint::TouchCancelled) {
3849 touches->append(touch);
3850 targetTouchesIterator->value->append(touch);
3851 }
3852
3853 // Now build up the correct list for changedTouches.
3854 // Note that any touches that are in the TouchStationary state (e.g. if
3855 // the user had several points touched but did not move them all) should
3856 // never be in the changedTouches list so we do not handle them
3857 // explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609
3858 // for further discussion about the TouchStationary state.
3859 if (pointState != PlatformTouchPoint::TouchStationary && touchInfo.known Target) {
3860 ASSERT(pointState < PlatformTouchPoint::TouchStateEnd);
3861 if (!changedTouches[pointState].m_touches)
3862 changedTouches[pointState].m_touches = TouchList::create();
3863 changedTouches[pointState].m_touches->append(touch);
3864 changedTouches[pointState].m_targets.add(touchInfo.touchTarget);
3865 }
3866 }
3867 if (allTouchReleased) {
3868 m_touchSequenceDocument.clear();
3869 m_touchSequenceUserGestureToken.clear();
3870 }
3871
3872 WebInputEventResult eventResult = WebInputEventResult::NotHandled;
3873
3874 // Now iterate through the changedTouches list and m_targets within it, send ing
3875 // TouchEvents to the targets as required.
3876 for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; ++state ) {
3877 if (!changedTouches[state].m_touches)
3878 continue;
3879
3880 const AtomicString& eventName(touchEventNameForTouchPointState(static_ca st<PlatformTouchPoint::TouchState>(state)));
3881 for (const auto& eventTarget : changedTouches[state].m_targets) {
3882 EventTarget* touchEventTarget = eventTarget;
3883 TouchEvent* touchEvent = TouchEvent::create(
3884 touches, touchesByTarget.get(touchEventTarget), changedTouches[s tate].m_touches.get(),
3885 eventName, touchEventTarget->toNode()->document().domWindow(),
3886 event.getModifiers(), event.cancelable(), event.causesScrollingI fUncanceled(), event.timestamp());
3887
3888 DispatchEventResult domDispatchResult = touchEventTarget->dispatchEv ent(touchEvent);
3889
3890 // Only report for top level documents with a single touch on
3891 // touch-start or the first touch-move.
3892 if (touchStartOrFirstTouchMove && touchInfos.size() == 1 && event.ca ncelable() && !m_frame->document()->ownerElement()) {
3893 DEFINE_STATIC_LOCAL(EnumerationHistogram, rootDocumentListenerHi stogram, ("Event.Touch.TargetAndDispatchResult", TouchTargetAndDispatchResultTyp eMax));
3894 rootDocumentListenerHistogram.count(toTouchTargetHistogramValue( eventTarget, domDispatchResult));
3895 }
3896 eventResult = mergeEventResult(eventResult, toWebInputEventResult(do mDispatchResult));
3897 }
3898 }
3899
3900 return eventResult;
3901 }
3902
3903 WebInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEvent& eve nt) 3659 WebInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEvent& eve nt)
3904 { 3660 {
3905 TRACE_EVENT0("blink", "EventHandler::handleTouchEvent"); 3661 TRACE_EVENT0("blink", "EventHandler::handleTouchEvent");
3906 3662
3907 if (event.type() == PlatformEvent::TouchScrollStarted) { 3663 return m_pointerEventManager.handleTouchEvents(event);
3908 m_pointerEventManager.blockTouchPointers();
3909 return WebInputEventResult::HandledSystem;
3910 }
3911
3912 const Vector<PlatformTouchPoint>& points = event.touchPoints();
3913
3914 bool newTouchSequence = true;
3915 bool allTouchReleased = true;
3916 for (unsigned i = 0; i < points.size(); ++i) {
3917 const PlatformTouchPoint& point = points[i];
3918
3919 if (point.state() != PlatformTouchPoint::TouchPressed)
3920 newTouchSequence = false;
3921 if (point.state() != PlatformTouchPoint::TouchReleased && point.state() != PlatformTouchPoint::TouchCancelled)
3922 allTouchReleased = false;
3923 }
3924
3925 if (newTouchSequence) {
3926 // Ideally we'd ASSERT !m_touchSequenceDocument here since we should
3927 // have cleared the active document when we saw the last release. But we
3928 // have some tests that violate this, ClusterFuzz could trigger it, and
3929 // there may be cases where the browser doesn't reliably release all
3930 // touches. http://crbug.com/345372 tracks this.
3931 m_touchSequenceDocument.clear();
3932 m_touchSequenceUserGestureToken.clear();
3933 m_pointerEventManager.unblockTouchPointers();
3934 }
3935
3936 ASSERT(m_frame->view());
3937 if (m_touchSequenceDocument && (!m_touchSequenceDocument->frame() || !m_touc hSequenceDocument->frame()->view())) {
3938 // If the active touch document has no frame or view, it's probably bein g destroyed
3939 // so we can't dispatch events.
3940 return WebInputEventResult::NotHandled;
3941 }
3942
3943 // First do hit tests for any new touch points.
3944 for (unsigned i = 0; i < points.size(); ++i) {
3945 const PlatformTouchPoint& point = points[i];
3946
3947 // Touch events implicitly capture to the touched node, and don't change
3948 // active/hover states themselves (Gesture events do). So we only need
3949 // to hit-test on touchstart, and it can be read-only.
3950 if (point.state() == PlatformTouchPoint::TouchPressed) {
3951 HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEv ent | HitTestRequest::ReadOnly | HitTestRequest::Active;
3952 LayoutPoint pagePoint = roundedLayoutPoint(m_frame->view()->rootFram eToContents(point.pos()));
3953 HitTestResult result;
3954 if (!m_touchSequenceDocument) {
3955 result = hitTestResultAtPoint(pagePoint, hitType);
3956 } else if (m_touchSequenceDocument->frame()) {
3957 LayoutPoint framePoint = roundedLayoutPoint(m_touchSequenceDocum ent->frame()->view()->rootFrameToContents(point.pos()));
3958 result = hitTestResultInFrame(m_touchSequenceDocument->frame(), framePoint, hitType);
3959 } else {
3960 continue;
3961 }
3962
3963 Node* node = result.innerNode();
3964 if (!node)
3965 continue;
3966
3967 if (isHTMLCanvasElement(node)) {
3968 std::pair<Element*, String> regionInfo = toHTMLCanvasElement(nod e)->getControlAndIdIfHitRegionExists(result.pointInInnerNodeFrame());
3969 if (regionInfo.first)
3970 node = regionInfo.first;
3971 m_regionForTouchID.set(point.id(), regionInfo.second);
3972 }
3973
3974 // Touch events should not go to text nodes
3975 if (node->isTextNode())
3976 node = FlatTreeTraversal::parent(*node);
3977
3978 if (!m_touchSequenceDocument) {
3979 // Keep track of which document should receive all touch events
3980 // in the active sequence. This must be a single document to
3981 // ensure we don't leak Nodes between documents.
3982 m_touchSequenceDocument = &(result.innerNode()->document());
3983 ASSERT(m_touchSequenceDocument->frame()->view());
3984 }
3985
3986 // Ideally we'd ASSERT(!m_targetForTouchID.contains(point.id())
3987 // since we shouldn't get a touchstart for a touch that's already
3988 // down. However EventSender allows this to be violated and there's
3989 // some tests that take advantage of it. There may also be edge
3990 // cases in the browser where this happens.
3991 // See http://crbug.com/345372.
3992 m_targetForTouchID.set(point.id(), node);
3993
3994 TouchAction effectiveTouchAction = TouchActionUtil::computeEffective TouchAction(*node);
3995 if (effectiveTouchAction != TouchActionAuto)
3996 m_frame->page()->chromeClient().setTouchAction(effectiveTouchAct ion);
3997 }
3998 }
3999
4000 m_touchPressed = !allTouchReleased;
4001
4002 // If there's no document receiving touch events, or no handlers on the
4003 // document set to receive the events, then we can skip all the rest of
4004 // this work.
4005 if (!m_touchSequenceDocument || !m_touchSequenceDocument->frameHost() || !ha sTouchHandlers(m_touchSequenceDocument->frameHost()->eventHandlerRegistry()) || !m_touchSequenceDocument->frame()) {
4006 if (allTouchReleased) {
4007 m_touchSequenceDocument.clear();
4008 m_touchSequenceUserGestureToken.clear();
4009 }
4010 return WebInputEventResult::NotHandled;
4011 }
4012
4013 // Whether a touch should be considered a "user gesture" or not is a tricky question.
4014 // https://docs.google.com/document/d/1oF1T3O7_E4t1PYHV6gyCwHxOi3ystm0eSL5xZ u7nvOg/edit#
4015 // TODO(rbyers): Disable user gesture in some cases but retain logging for n ow (crbug.com/582140).
4016 OwnPtr<UserGestureIndicator> gestureIndicator;
4017 if (event.touchPoints().size() == 1
4018 && event.touchPoints()[0].state() == PlatformTouchPoint::TouchReleased
4019 && !event.causesScrollingIfUncanceled()) {
4020 // This is a touchend corresponding to a tap, definitely a user gesture. So don't supply
4021 // a UserGestureUtilizedCallback.
4022 gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProcessin gUserGesture));
4023 } else {
4024 // This is some other touch event that perhaps shouldn't be considered a user gesture. So
4025 // use a UserGestureUtilizedCallback to get metrics / deprecation warnin gs.
4026 if (m_touchSequenceUserGestureToken)
4027 gestureIndicator = adoptPtr(new UserGestureIndicator(m_touchSequence UserGestureToken.release(), &m_touchSequenceDocument->frame()->eventHandler()));
4028 else
4029 gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProce ssingUserGesture, &m_touchSequenceDocument->frame()->eventHandler()));
4030 m_touchSequenceUserGestureToken = UserGestureIndicator::currentToken();
4031 }
4032
4033 // Compute and store the common info used by both PointerEvent and TouchEven t.
4034 HeapVector<TouchInfo> touchInfos(points.size());
4035
4036 for (unsigned i = 0; i < points.size(); ++i) {
4037 const PlatformTouchPoint& point = points[i];
4038 PlatformTouchPoint::TouchState pointState = point.state();
4039 EventTarget* touchTarget = nullptr;
4040 String regionID;
4041
4042 if (pointState == PlatformTouchPoint::TouchReleased || pointState == Pla tformTouchPoint::TouchCancelled) {
4043 // The target should be the original target for this touch, so get
4044 // it from the hashmap. As it's a release or cancel we also remove
4045 // it from the map.
4046 touchTarget = m_targetForTouchID.take(point.id());
4047 regionID = m_regionForTouchID.take(point.id());
4048 } else {
4049 // No hittest is performed on move or stationary, since the target
4050 // is not allowed to change anyway.
4051 touchTarget = m_targetForTouchID.get(point.id());
4052 regionID = m_regionForTouchID.get(point.id());
4053 }
4054
4055 LocalFrame* targetFrame = nullptr;
4056 bool knownTarget = false;
4057 if (touchTarget) {
4058 Document& doc = touchTarget->toNode()->document();
4059 // If the target node has moved to a new document while it was being touched,
4060 // we can't send events to the new document because that could leak nodes
4061 // from one document to another. See http://crbug.com/394339.
4062 if (&doc == m_touchSequenceDocument.get()) {
4063 targetFrame = doc.frame();
4064 knownTarget = true;
4065 }
4066 }
4067 if (!knownTarget) {
4068 // If we don't have a target registered for the point it means we've
4069 // missed our opportunity to do a hit test for it (due to some
4070 // optimization that prevented blink from ever seeing the
4071 // touchstart), or that the touch started outside the active touch
4072 // sequence document. We should still include the touch in the
4073 // Touches list reported to the application (eg. so it can
4074 // differentiate between a one and two finger gesture), but we won't
4075 // actually dispatch any events for it. Set the target to the
4076 // Document so that there's some valid node here. Perhaps this
4077 // should really be LocalDOMWindow, but in all other cases the targe t of
4078 // a Touch is a Node so using the window could be a breaking change.
4079 // Since we know there was no handler invoked, the specific target
4080 // should be completely irrelevant to the application.
4081 touchTarget = m_touchSequenceDocument;
4082 targetFrame = m_touchSequenceDocument->frame();
4083 }
4084 ASSERT(targetFrame);
4085
4086 // pagePoint should always be in the target element's document coordinat es.
4087 FloatPoint pagePoint = targetFrame->view()->rootFrameToContents(point.po s());
4088 float scaleFactor = 1.0f / targetFrame->pageZoomFactor();
4089
4090 TouchInfo& touchInfo = touchInfos[i];
4091 touchInfo.point = point;
4092 touchInfo.touchTarget = touchTarget;
4093 touchInfo.targetFrame = targetFrame;
4094 touchInfo.adjustedPagePoint = pagePoint.scaledBy(scaleFactor);
4095 touchInfo.adjustedRadius = point.radius().scaledBy(scaleFactor);
4096 touchInfo.knownTarget = knownTarget;
4097 touchInfo.consumed = false;
4098 touchInfo.region = regionID;
4099 }
4100
4101 dispatchPointerEvents(event, touchInfos);
4102 // Note that the disposition of any pointer events affects only the generati on of touch
4103 // events. If all pointer events were handled (and hence no touch events wer e fired), that
4104 // is still equivalent to the touch events going unhandled because pointer e vent handler
4105 // don't block scroll gesture generation.
4106
4107 // TODO(crbug.com/507408): If PE handlers always call preventDefault, we won 't see TEs until after
4108 // scrolling starts because the scrolling would suppress upcoming PEs. This sudden "break" in TE
4109 // suppression can make the visible TEs inconsistent (e.g. touchmove without a touchstart).
4110
4111 return dispatchTouchEvents(event, touchInfos, allTouchReleased);
4112 } 3664 }
4113 3665
4114 void EventHandler::userGestureUtilized() 3666 void EventHandler::userGestureUtilized()
4115 { 3667 {
4116 // This is invoked for UserGestureIndicators created in handleTouchEvent whi ch perhaps represent 3668 // This is invoked for UserGestureIndicators created in handleTouchEvent whi ch perhaps represent
4117 // touch actions which shouldn't be considered a user-gesture. 3669 // touch actions which shouldn't be considered a user-gesture.
4118 UseCounter::count(m_frame, UseCounter::TouchDragUserGestureUsed); 3670 UseCounter::count(m_frame, UseCounter::TouchDragUserGestureUsed);
4119 Deprecation::countDeprecationCrossOriginIframe(m_frame, UseCounter::TouchDra gUserGestureUsedCrossOrigin); 3671 Deprecation::countDeprecationCrossOriginIframe(m_frame, UseCounter::TouchDra gUserGestureUsedCrossOrigin);
4120 } 3672 }
4121 3673
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
4169 PlatformEvent::Modifiers EventHandler::accessKeyModifiers() 3721 PlatformEvent::Modifiers EventHandler::accessKeyModifiers()
4170 { 3722 {
4171 #if OS(MACOSX) 3723 #if OS(MACOSX)
4172 return static_cast<PlatformEvent::Modifiers>(PlatformEvent::CtrlKey | Platfo rmEvent::AltKey); 3724 return static_cast<PlatformEvent::Modifiers>(PlatformEvent::CtrlKey | Platfo rmEvent::AltKey);
4173 #else 3725 #else
4174 return PlatformEvent::AltKey; 3726 return PlatformEvent::AltKey;
4175 #endif 3727 #endif
4176 } 3728 }
4177 3729
4178 } // namespace blink 3730 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698