OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/input/TouchEventManager.h" | 5 #include "core/input/TouchEventManager.h" |
6 | 6 |
7 #include "core/dom/Document.h" | 7 #include "core/dom/Document.h" |
8 #include "core/events/TouchEvent.h" | 8 #include "core/events/TouchEvent.h" |
9 #include "core/frame/Deprecation.h" | 9 #include "core/frame/Deprecation.h" |
10 #include "core/frame/EventHandlerRegistry.h" | 10 #include "core/frame/EventHandlerRegistry.h" |
11 #include "core/frame/FrameHost.h" | 11 #include "core/frame/FrameHost.h" |
12 #include "core/frame/FrameView.h" | 12 #include "core/frame/FrameView.h" |
13 #include "core/html/HTMLCanvasElement.h" | 13 #include "core/html/HTMLCanvasElement.h" |
14 #include "core/input/EventHandlingUtil.h" | 14 #include "core/input/EventHandlingUtil.h" |
15 #include "core/input/TouchActionUtil.h" | 15 #include "core/input/TouchActionUtil.h" |
16 #include "core/layout/HitTestCanvasResult.h" | 16 #include "core/layout/HitTestCanvasResult.h" |
17 #include "core/page/ChromeClient.h" | 17 #include "core/page/ChromeClient.h" |
18 #include "core/page/Page.h" | 18 #include "core/page/Page.h" |
19 #include "platform/Histogram.h" | 19 #include "platform/Histogram.h" |
20 #include "platform/PlatformTouchEvent.h" | 20 #include "public/platform/WebTouchEvent.h" |
21 #include "wtf/CurrentTime.h" | 21 #include "wtf/CurrentTime.h" |
22 #include "wtf/PtrUtil.h" | 22 #include "wtf/PtrUtil.h" |
23 #include <memory> | 23 #include <memory> |
24 | 24 |
25 namespace blink { | 25 namespace blink { |
26 | 26 |
27 namespace { | 27 namespace { |
28 | 28 |
29 bool hasTouchHandlers(const EventHandlerRegistry& registry) { | 29 bool hasTouchHandlers(const EventHandlerRegistry& registry) { |
30 return registry.hasEventHandlers( | 30 return registry.hasEventHandlers( |
31 EventHandlerRegistry::TouchStartOrMoveEventBlocking) || | 31 EventHandlerRegistry::TouchStartOrMoveEventBlocking) || |
32 registry.hasEventHandlers( | 32 registry.hasEventHandlers( |
33 EventHandlerRegistry::TouchStartOrMoveEventPassive) || | 33 EventHandlerRegistry::TouchStartOrMoveEventPassive) || |
34 registry.hasEventHandlers( | 34 registry.hasEventHandlers( |
35 EventHandlerRegistry::TouchEndOrCancelEventBlocking) || | 35 EventHandlerRegistry::TouchEndOrCancelEventBlocking) || |
36 registry.hasEventHandlers( | 36 registry.hasEventHandlers( |
37 EventHandlerRegistry::TouchEndOrCancelEventPassive); | 37 EventHandlerRegistry::TouchEndOrCancelEventPassive); |
38 } | 38 } |
39 | 39 |
40 const AtomicString& touchEventNameForTouchPointState( | 40 const AtomicString& touchEventNameForTouchPointState( |
41 PlatformTouchPoint::TouchState state) { | 41 WebTouchPoint::State state) { |
42 switch (state) { | 42 switch (state) { |
43 case PlatformTouchPoint::TouchReleased: | 43 case WebTouchPoint::StateReleased: |
44 return EventTypeNames::touchend; | 44 return EventTypeNames::touchend; |
45 case PlatformTouchPoint::TouchCancelled: | 45 case WebTouchPoint::StateCancelled: |
46 return EventTypeNames::touchcancel; | 46 return EventTypeNames::touchcancel; |
47 case PlatformTouchPoint::TouchPressed: | 47 case WebTouchPoint::StatePressed: |
48 return EventTypeNames::touchstart; | 48 return EventTypeNames::touchstart; |
49 case PlatformTouchPoint::TouchMoved: | 49 case WebTouchPoint::StateMoved: |
50 return EventTypeNames::touchmove; | 50 return EventTypeNames::touchmove; |
51 case PlatformTouchPoint::TouchStationary: | 51 case WebTouchPoint::StateStationary: |
52 // Fall through to default | 52 // Fall through to default |
53 default: | 53 default: |
54 ASSERT_NOT_REACHED(); | 54 ASSERT_NOT_REACHED(); |
55 return emptyAtom; | 55 return emptyAtom; |
56 } | 56 } |
57 } | 57 } |
58 | 58 |
59 enum TouchEventDispatchResultType { | 59 enum TouchEventDispatchResultType { |
60 UnhandledTouches, // Unhandled touch events. | 60 UnhandledTouches, // Unhandled touch events. |
61 HandledTouches, // Handled touch events. | 61 HandledTouches, // Handled touch events. |
(...skipping 26 matching lines...) Expand all Loading... |
88 | 88 |
89 TouchEventManager::TouchEventManager(LocalFrame& frame) : m_frame(frame) { | 89 TouchEventManager::TouchEventManager(LocalFrame& frame) : m_frame(frame) { |
90 clear(); | 90 clear(); |
91 } | 91 } |
92 | 92 |
93 void TouchEventManager::clear() { | 93 void TouchEventManager::clear() { |
94 m_touchSequenceDocument.clear(); | 94 m_touchSequenceDocument.clear(); |
95 m_targetForTouchID.clear(); | 95 m_targetForTouchID.clear(); |
96 m_regionForTouchID.clear(); | 96 m_regionForTouchID.clear(); |
97 m_touchPressed = false; | 97 m_touchPressed = false; |
98 m_currentEvent = PlatformEvent::NoType; | |
99 m_currentTouchAction = TouchActionAuto; | 98 m_currentTouchAction = TouchActionAuto; |
100 } | 99 } |
101 | 100 |
102 DEFINE_TRACE(TouchEventManager) { | 101 DEFINE_TRACE(TouchEventManager) { |
103 visitor->trace(m_frame); | 102 visitor->trace(m_frame); |
104 visitor->trace(m_touchSequenceDocument); | 103 visitor->trace(m_touchSequenceDocument); |
105 visitor->trace(m_targetForTouchID); | 104 visitor->trace(m_targetForTouchID); |
106 } | 105 } |
107 | 106 |
108 WebInputEventResult TouchEventManager::dispatchTouchEvents( | 107 WebInputEventResult TouchEventManager::dispatchTouchEvents( |
109 const PlatformTouchEvent& event, | 108 const WebTouchEvent& event, |
110 const HeapVector<TouchInfo>& touchInfos, | 109 const HeapVector<TouchInfo>& touchInfos, |
111 bool allTouchesReleased) { | 110 bool allTouchesReleased) { |
112 // Build up the lists to use for the |touches|, |targetTouches| and | 111 // Build up the lists to use for the |touches|, |targetTouches| and |
113 // |changedTouches| attributes in the JS event. See | 112 // |changedTouches| attributes in the JS event. See |
114 // http://www.w3.org/TR/touch-events/#touchevent-interface for how these | 113 // http://www.w3.org/TR/touch-events/#touchevent-interface for how these |
115 // lists fit together. | 114 // lists fit together. |
116 | 115 |
117 // Holds the complete set of touches on the screen. | 116 // Holds the complete set of touches on the screen. |
118 TouchList* touches = TouchList::create(); | 117 TouchList* touches = TouchList::create(); |
119 | 118 |
120 // A different view on the 'touches' list above, filtered and grouped by | 119 // A different view on the 'touches' list above, filtered and grouped by |
121 // event target. Used for the |targetTouches| list in the JS event. | 120 // event target. Used for the |targetTouches| list in the JS event. |
122 using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>; | 121 using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>; |
123 TargetTouchesHeapMap touchesByTarget; | 122 TargetTouchesHeapMap touchesByTarget; |
124 | 123 |
125 // Array of touches per state, used to assemble the |changedTouches| list. | 124 // Array of touches per state, used to assemble the |changedTouches| list. |
126 ChangedTouches changedTouches[PlatformTouchPoint::TouchStateEnd]; | 125 ChangedTouches changedTouches[WebTouchPoint::StateMax + 1]; |
127 | 126 |
128 for (auto touchInfo : touchInfos) { | 127 for (auto touchInfo : touchInfos) { |
129 const PlatformTouchPoint& point = touchInfo.point; | 128 const WebTouchPoint& point = touchInfo.point; |
130 PlatformTouchPoint::TouchState pointState = point.state(); | 129 WebTouchPoint::State pointState = point.state; |
131 | 130 |
132 Touch* touch = Touch::create( | 131 Touch* touch = Touch::create( |
133 touchInfo.targetFrame.get(), touchInfo.touchNode.get(), point.id(), | 132 touchInfo.targetFrame.get(), touchInfo.touchNode.get(), point.id, |
134 point.screenPos(), touchInfo.contentPoint, touchInfo.adjustedRadius, | 133 point.screenPosition, touchInfo.contentPoint, touchInfo.adjustedRadius, |
135 point.rotationAngle(), point.force(), touchInfo.region); | 134 point.rotationAngle, point.force, touchInfo.region); |
136 | 135 |
137 // Ensure this target's touch list exists, even if it ends up empty, so | 136 // Ensure this target's touch list exists, even if it ends up empty, so |
138 // it can always be passed to TouchEvent::Create below. | 137 // it can always be passed to TouchEvent::Create below. |
139 TargetTouchesHeapMap::iterator targetTouchesIterator = | 138 TargetTouchesHeapMap::iterator targetTouchesIterator = |
140 touchesByTarget.find(touchInfo.touchNode.get()); | 139 touchesByTarget.find(touchInfo.touchNode.get()); |
141 if (targetTouchesIterator == touchesByTarget.end()) { | 140 if (targetTouchesIterator == touchesByTarget.end()) { |
142 touchesByTarget.set(touchInfo.touchNode.get(), TouchList::create()); | 141 touchesByTarget.set(touchInfo.touchNode.get(), TouchList::create()); |
143 targetTouchesIterator = touchesByTarget.find(touchInfo.touchNode.get()); | 142 targetTouchesIterator = touchesByTarget.find(touchInfo.touchNode.get()); |
144 } | 143 } |
145 | 144 |
146 // |touches| and |targetTouches| should only contain information about | 145 // |touches| and |targetTouches| should only contain information about |
147 // touches still on the screen, so if this point is released or | 146 // touches still on the screen, so if this point is released or |
148 // cancelled it will only appear in the |changedTouches| list. | 147 // cancelled it will only appear in the |changedTouches| list. |
149 if (pointState != PlatformTouchPoint::TouchReleased && | 148 if (pointState != WebTouchPoint::StateReleased && |
150 pointState != PlatformTouchPoint::TouchCancelled) { | 149 pointState != WebTouchPoint::StateCancelled) { |
151 touches->append(touch); | 150 touches->append(touch); |
152 targetTouchesIterator->value->append(touch); | 151 targetTouchesIterator->value->append(touch); |
153 } | 152 } |
154 | 153 |
155 // Now build up the correct list for |changedTouches|. | 154 // Now build up the correct list for |changedTouches|. |
156 // Note that any touches that are in the TouchStationary state (e.g. if | 155 // Note that any touches that are in the TouchStationary state (e.g. if |
157 // the user had several points touched but did not move them all) should | 156 // the user had several points touched but did not move them all) should |
158 // never be in the |changedTouches| list so we do not handle them | 157 // never be in the |changedTouches| list so we do not handle them |
159 // explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609 | 158 // explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609 |
160 // for further discussion about the TouchStationary state. | 159 // for further discussion about the TouchStationary state. |
161 if (pointState != PlatformTouchPoint::TouchStationary && | 160 if (pointState != WebTouchPoint::StateStationary && touchInfo.knownTarget) { |
162 touchInfo.knownTarget) { | 161 DCHECK_LE(pointState, WebTouchPoint::StateMax); |
163 ASSERT(pointState < PlatformTouchPoint::TouchStateEnd); | |
164 if (!changedTouches[pointState].m_touches) | 162 if (!changedTouches[pointState].m_touches) |
165 changedTouches[pointState].m_touches = TouchList::create(); | 163 changedTouches[pointState].m_touches = TouchList::create(); |
166 changedTouches[pointState].m_touches->append(touch); | 164 changedTouches[pointState].m_touches->append(touch); |
167 changedTouches[pointState].m_targets.insert(touchInfo.touchNode); | 165 changedTouches[pointState].m_targets.insert(touchInfo.touchNode); |
168 changedTouches[pointState].m_pointerType = | 166 changedTouches[pointState].m_pointerType = point.pointerType; |
169 point.pointerProperties().pointerType; | |
170 } | 167 } |
171 } | 168 } |
172 | 169 |
173 if (allTouchesReleased) { | 170 if (allTouchesReleased) { |
174 m_touchSequenceDocument.clear(); | 171 m_touchSequenceDocument.clear(); |
175 m_currentTouchAction = TouchActionAuto; | 172 m_currentTouchAction = TouchActionAuto; |
176 } | 173 } |
177 | 174 |
178 WebInputEventResult eventResult = WebInputEventResult::NotHandled; | 175 WebInputEventResult eventResult = WebInputEventResult::NotHandled; |
179 | 176 |
180 // Now iterate through the |changedTouches| list and |m_targets| within it, | 177 // Now iterate through the |changedTouches| list and |m_targets| within it, |
181 // sending TouchEvents to the targets as required. | 178 // sending TouchEvents to the targets as required. |
182 for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; | 179 for (unsigned state = 0; state <= WebTouchPoint::StateMax; ++state) { |
183 ++state) { | |
184 if (!changedTouches[state].m_touches) | 180 if (!changedTouches[state].m_touches) |
185 continue; | 181 continue; |
186 | 182 |
187 const AtomicString& eventName(touchEventNameForTouchPointState( | 183 const AtomicString& eventName(touchEventNameForTouchPointState( |
188 static_cast<PlatformTouchPoint::TouchState>(state))); | 184 static_cast<WebTouchPoint::State>(state))); |
189 for (const auto& eventTarget : changedTouches[state].m_targets) { | 185 for (const auto& eventTarget : changedTouches[state].m_targets) { |
190 EventTarget* touchEventTarget = eventTarget; | 186 EventTarget* touchEventTarget = eventTarget; |
191 TouchEvent* touchEvent = TouchEvent::create( | 187 TouchEvent* touchEvent = TouchEvent::create( |
192 touches, touchesByTarget.get(touchEventTarget), | 188 event, touches, touchesByTarget.get(touchEventTarget), |
193 changedTouches[state].m_touches.get(), eventName, | 189 changedTouches[state].m_touches.get(), eventName, |
194 touchEventTarget->toNode()->document().domWindow(), | 190 touchEventTarget->toNode()->document().domWindow(), |
195 event.getModifiers(), event.cancelable(), | 191 m_currentTouchAction); |
196 event.causesScrollingIfUncanceled(), | |
197 event.touchStartOrFirstTouchMove(), event.timestamp(), | |
198 m_currentTouchAction, changedTouches[state].m_pointerType); | |
199 | 192 |
200 DispatchEventResult domDispatchResult = | 193 DispatchEventResult domDispatchResult = |
201 touchEventTarget->dispatchEvent(touchEvent); | 194 touchEventTarget->dispatchEvent(touchEvent); |
202 | 195 |
203 // Only report for top level documents with a single touch on | 196 // Only report for top level documents with a single touch on |
204 // touch-start or the first touch-move. | 197 // touch-start or the first touch-move. |
205 if (event.touchStartOrFirstTouchMove() && touchInfos.size() == 1 && | 198 if (event.touchStartOrFirstTouchMove && touchInfos.size() == 1 && |
206 m_frame->isMainFrame()) { | 199 m_frame->isMainFrame()) { |
207 // Record the disposition and latency of touch starts and first touch | 200 // Record the disposition and latency of touch starts and first touch |
208 // moves before and after the page is fully loaded respectively. | 201 // moves before and after the page is fully loaded respectively. |
209 int64_t latencyInMicros = | 202 int64_t latencyInMicros = |
210 (TimeTicks::Now() - event.timestamp()).InMicroseconds(); | 203 (TimeTicks::Now() - |
211 if (event.cancelable()) { | 204 TimeTicks::FromSeconds(event.timeStampSeconds())) |
| 205 .InMicroseconds(); |
| 206 if (event.isCancelable()) { |
212 if (m_frame->document()->isLoadCompleted()) { | 207 if (m_frame->document()->isLoadCompleted()) { |
213 DEFINE_STATIC_LOCAL(EnumerationHistogram, | 208 DEFINE_STATIC_LOCAL(EnumerationHistogram, |
214 touchDispositionsAfterPageLoadHistogram, | 209 touchDispositionsAfterPageLoadHistogram, |
215 ("Event.Touch.TouchDispositionsAfterPageLoad", | 210 ("Event.Touch.TouchDispositionsAfterPageLoad", |
216 TouchEventDispatchResultTypeMax)); | 211 TouchEventDispatchResultTypeMax)); |
217 touchDispositionsAfterPageLoadHistogram.count( | 212 touchDispositionsAfterPageLoadHistogram.count( |
218 (domDispatchResult != DispatchEventResult::NotCanceled) | 213 (domDispatchResult != DispatchEventResult::NotCanceled) |
219 ? HandledTouches | 214 ? HandledTouches |
220 : UnhandledTouches); | 215 : UnhandledTouches); |
221 | 216 |
(...skipping 21 matching lines...) Expand all Loading... |
243 touchDispositionsOutsideFlingHistogram, | 238 touchDispositionsOutsideFlingHistogram, |
244 ("Event.Touch.TouchDispositionsOutsideFling2", | 239 ("Event.Touch.TouchDispositionsOutsideFling2", |
245 TouchEventDispatchResultTypeMax)); | 240 TouchEventDispatchResultTypeMax)); |
246 touchDispositionsOutsideFlingHistogram.count( | 241 touchDispositionsOutsideFlingHistogram.count( |
247 (domDispatchResult != DispatchEventResult::NotCanceled) | 242 (domDispatchResult != DispatchEventResult::NotCanceled) |
248 ? HandledTouches | 243 ? HandledTouches |
249 : UnhandledTouches); | 244 : UnhandledTouches); |
250 } | 245 } |
251 | 246 |
252 // Report the touch disposition when there is an active fling animation. | 247 // Report the touch disposition when there is an active fling animation. |
253 if (event.dispatchType() == | 248 if (event.dispatchType == |
254 PlatformEvent::ListenersForcedNonBlockingDueToFling) { | 249 WebInputEvent::ListenersForcedNonBlockingDueToFling) { |
255 DEFINE_STATIC_LOCAL(EnumerationHistogram, | 250 DEFINE_STATIC_LOCAL(EnumerationHistogram, |
256 touchDispositionsDuringFlingHistogram, | 251 touchDispositionsDuringFlingHistogram, |
257 ("Event.Touch.TouchDispositionsDuringFling2", | 252 ("Event.Touch.TouchDispositionsDuringFling2", |
258 TouchEventDispatchResultTypeMax)); | 253 TouchEventDispatchResultTypeMax)); |
259 touchDispositionsDuringFlingHistogram.count( | 254 touchDispositionsDuringFlingHistogram.count( |
260 touchEvent->preventDefaultCalledOnUncancelableEvent() | 255 touchEvent->preventDefaultCalledOnUncancelableEvent() |
261 ? HandledTouches | 256 ? HandledTouches |
262 : UnhandledTouches); | 257 : UnhandledTouches); |
263 } | 258 } |
264 } | 259 } |
265 eventResult = EventHandlingUtil::mergeEventResult( | 260 eventResult = EventHandlingUtil::mergeEventResult( |
266 eventResult, | 261 eventResult, |
267 EventHandlingUtil::toWebInputEventResult(domDispatchResult)); | 262 EventHandlingUtil::toWebInputEventResult(domDispatchResult)); |
268 } | 263 } |
269 } | 264 } |
270 | 265 |
271 return eventResult; | 266 return eventResult; |
272 } | 267 } |
273 | 268 |
274 void TouchEventManager::updateTargetAndRegionMapsForTouchStarts( | 269 void TouchEventManager::updateTargetAndRegionMapsForTouchStarts( |
275 HeapVector<TouchInfo>& touchInfos) { | 270 HeapVector<TouchInfo>& touchInfos) { |
276 for (auto& touchInfo : touchInfos) { | 271 for (auto& touchInfo : touchInfos) { |
277 // Touch events implicitly capture to the touched node, and don't change | 272 // Touch events implicitly capture to the touched node, and don't change |
278 // active/hover states themselves (Gesture events do). So we only need | 273 // active/hover states themselves (Gesture events do). So we only need |
279 // to hit-test on touchstart and when the target could be different than | 274 // to hit-test on touchstart and when the target could be different than |
280 // the corresponding pointer event target. | 275 // the corresponding pointer event target. |
281 if (touchInfo.point.state() == PlatformTouchPoint::TouchPressed) { | 276 if (touchInfo.point.state == WebTouchPoint::StatePressed) { |
282 HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent | | 277 HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent | |
283 HitTestRequest::ReadOnly | | 278 HitTestRequest::ReadOnly | |
284 HitTestRequest::Active; | 279 HitTestRequest::Active; |
285 HitTestResult result; | 280 HitTestResult result; |
286 // For the touchPressed points hit-testing is done in | 281 // For the touchPressed points hit-testing is done in |
287 // PointerEventManager. If it was the second touch there is a | 282 // PointerEventManager. If it was the second touch there is a |
288 // capturing documents for the touch and |m_touchSequenceDocument| | 283 // capturing documents for the touch and |m_touchSequenceDocument| |
289 // is not null. So if PointerEventManager should hit-test again | 284 // is not null. So if PointerEventManager should hit-test again |
290 // against |m_touchSequenceDocument| if the target set by | 285 // against |m_touchSequenceDocument| if the target set by |
291 // PointerEventManager was either null or not in | 286 // PointerEventManager was either null or not in |
292 // |m_touchSequenceDocument|. | 287 // |m_touchSequenceDocument|. |
293 if (m_touchSequenceDocument && | 288 if (m_touchSequenceDocument && |
294 (!touchInfo.touchNode || | 289 (!touchInfo.touchNode || |
295 &touchInfo.touchNode->document() != m_touchSequenceDocument)) { | 290 &touchInfo.touchNode->document() != m_touchSequenceDocument)) { |
296 if (m_touchSequenceDocument->frame()) { | 291 if (m_touchSequenceDocument->frame()) { |
297 LayoutPoint framePoint = LayoutPoint( | 292 LayoutPoint framePoint = LayoutPoint( |
298 m_touchSequenceDocument->frame()->view()->rootFrameToContents( | 293 m_touchSequenceDocument->frame()->view()->rootFrameToContents( |
299 touchInfo.point.pos())); | 294 touchInfo.point.position)); |
300 result = EventHandlingUtil::hitTestResultInFrame( | 295 result = EventHandlingUtil::hitTestResultInFrame( |
301 m_touchSequenceDocument->frame(), framePoint, hitType); | 296 m_touchSequenceDocument->frame(), framePoint, hitType); |
302 Node* node = result.innerNode(); | 297 Node* node = result.innerNode(); |
303 if (!node) | 298 if (!node) |
304 continue; | 299 continue; |
305 if (isHTMLCanvasElement(node)) { | 300 if (isHTMLCanvasElement(node)) { |
306 HitTestCanvasResult* hitTestCanvasResult = | 301 HitTestCanvasResult* hitTestCanvasResult = |
307 toHTMLCanvasElement(node)->getControlAndIdIfHitRegionExists( | 302 toHTMLCanvasElement(node)->getControlAndIdIfHitRegionExists( |
308 result.pointInInnerNodeFrame()); | 303 result.pointInInnerNodeFrame()); |
309 if (hitTestCanvasResult->getControl()) | 304 if (hitTestCanvasResult->getControl()) |
(...skipping 17 matching lines...) Expand all Loading... |
327 m_touchSequenceDocument = &(touchInfo.touchNode->document()); | 322 m_touchSequenceDocument = &(touchInfo.touchNode->document()); |
328 ASSERT(m_touchSequenceDocument->frame()->view()); | 323 ASSERT(m_touchSequenceDocument->frame()->view()); |
329 } | 324 } |
330 | 325 |
331 // Ideally we'd ASSERT(!m_targetForTouchID.contains(point.id()) | 326 // Ideally we'd ASSERT(!m_targetForTouchID.contains(point.id()) |
332 // since we shouldn't get a touchstart for a touch that's already | 327 // since we shouldn't get a touchstart for a touch that's already |
333 // down. However EventSender allows this to be violated and there's | 328 // down. However EventSender allows this to be violated and there's |
334 // some tests that take advantage of it. There may also be edge | 329 // some tests that take advantage of it. There may also be edge |
335 // cases in the browser where this happens. | 330 // cases in the browser where this happens. |
336 // See http://crbug.com/345372. | 331 // See http://crbug.com/345372. |
337 m_targetForTouchID.set(touchInfo.point.id(), touchInfo.touchNode); | 332 m_targetForTouchID.set(touchInfo.point.id, touchInfo.touchNode); |
338 | 333 |
339 m_regionForTouchID.set(touchInfo.point.id(), touchInfo.region); | 334 m_regionForTouchID.set(touchInfo.point.id, touchInfo.region); |
340 | 335 |
341 TouchAction effectiveTouchAction = | 336 TouchAction effectiveTouchAction = |
342 TouchActionUtil::computeEffectiveTouchAction(*touchInfo.touchNode); | 337 TouchActionUtil::computeEffectiveTouchAction(*touchInfo.touchNode); |
343 if (effectiveTouchAction != TouchActionAuto) { | 338 if (effectiveTouchAction != TouchActionAuto) { |
344 m_frame->page()->chromeClient().setTouchAction(m_frame, | 339 m_frame->page()->chromeClient().setTouchAction(m_frame, |
345 effectiveTouchAction); | 340 effectiveTouchAction); |
346 | 341 |
347 // Combine the current touch action sequence with the touch action | 342 // Combine the current touch action sequence with the touch action |
348 // for the current finger press. | 343 // for the current finger press. |
349 m_currentTouchAction &= effectiveTouchAction; | 344 m_currentTouchAction &= effectiveTouchAction; |
350 } | 345 } |
351 } | 346 } |
352 } | 347 } |
353 } | 348 } |
354 | 349 |
355 void TouchEventManager::setAllPropertiesOfTouchInfos( | 350 void TouchEventManager::setAllPropertiesOfTouchInfos( |
356 HeapVector<TouchInfo>& touchInfos) { | 351 HeapVector<TouchInfo>& touchInfos) { |
357 for (auto& touchInfo : touchInfos) { | 352 for (auto& touchInfo : touchInfos) { |
358 PlatformTouchPoint::TouchState pointState = touchInfo.point.state(); | 353 WebTouchPoint::State pointState = touchInfo.point.state; |
359 Node* touchNode = nullptr; | 354 Node* touchNode = nullptr; |
360 String regionID; | 355 String regionID; |
361 | 356 |
362 if (pointState == PlatformTouchPoint::TouchReleased || | 357 if (pointState == WebTouchPoint::StateReleased || |
363 pointState == PlatformTouchPoint::TouchCancelled) { | 358 pointState == WebTouchPoint::StateCancelled) { |
364 // The target should be the original target for this touch, so get | 359 // The target should be the original target for this touch, so get |
365 // it from the hashmap. As it's a release or cancel we also remove | 360 // it from the hashmap. As it's a release or cancel we also remove |
366 // it from the map. | 361 // it from the map. |
367 touchNode = m_targetForTouchID.take(touchInfo.point.id()); | 362 touchNode = m_targetForTouchID.take(touchInfo.point.id); |
368 regionID = m_regionForTouchID.take(touchInfo.point.id()); | 363 regionID = m_regionForTouchID.take(touchInfo.point.id); |
369 } else { | 364 } else { |
370 // No hittest is performed on move or stationary, since the target | 365 // No hittest is performed on move or stationary, since the target |
371 // is not allowed to change anyway. | 366 // is not allowed to change anyway. |
372 touchNode = m_targetForTouchID.get(touchInfo.point.id()); | 367 touchNode = m_targetForTouchID.get(touchInfo.point.id); |
373 regionID = m_regionForTouchID.get(touchInfo.point.id()); | 368 regionID = m_regionForTouchID.get(touchInfo.point.id); |
374 } | 369 } |
375 | 370 |
376 LocalFrame* targetFrame = nullptr; | 371 LocalFrame* targetFrame = nullptr; |
377 bool knownTarget = false; | 372 bool knownTarget = false; |
378 if (touchNode) { | 373 if (touchNode) { |
379 Document& doc = touchNode->document(); | 374 Document& doc = touchNode->document(); |
380 // If the target node has moved to a new document while it was being | 375 // If the target node has moved to a new document while it was being |
381 // touched, we can't send events to the new document because that could | 376 // touched, we can't send events to the new document because that could |
382 // leak nodes from one document to another. See http://crbug.com/394339. | 377 // leak nodes from one document to another. See http://crbug.com/394339. |
383 if (&doc == m_touchSequenceDocument.get()) { | 378 if (&doc == m_touchSequenceDocument.get()) { |
(...skipping 15 matching lines...) Expand all Loading... |
399 // a Touch is a Node so using the window could be a breaking change. | 394 // a Touch is a Node so using the window could be a breaking change. |
400 // Since we know there was no handler invoked, the specific target | 395 // Since we know there was no handler invoked, the specific target |
401 // should be completely irrelevant to the application. | 396 // should be completely irrelevant to the application. |
402 touchNode = m_touchSequenceDocument; | 397 touchNode = m_touchSequenceDocument; |
403 targetFrame = m_touchSequenceDocument->frame(); | 398 targetFrame = m_touchSequenceDocument->frame(); |
404 } | 399 } |
405 ASSERT(targetFrame); | 400 ASSERT(targetFrame); |
406 | 401 |
407 // pagePoint should always be in the target element's document coordinates. | 402 // pagePoint should always be in the target element's document coordinates. |
408 FloatPoint pagePoint = | 403 FloatPoint pagePoint = |
409 targetFrame->view()->rootFrameToContents(touchInfo.point.pos()); | 404 targetFrame->view()->rootFrameToContents(touchInfo.point.position); |
410 float scaleFactor = 1.0f / targetFrame->pageZoomFactor(); | 405 float scaleFactor = 1.0f / targetFrame->pageZoomFactor(); |
411 | 406 |
412 touchInfo.touchNode = touchNode; | 407 touchInfo.touchNode = touchNode; |
413 touchInfo.targetFrame = targetFrame; | 408 touchInfo.targetFrame = targetFrame; |
414 touchInfo.contentPoint = pagePoint.scaledBy(scaleFactor); | 409 touchInfo.contentPoint = pagePoint.scaledBy(scaleFactor); |
415 touchInfo.adjustedRadius = touchInfo.point.radius().scaledBy(scaleFactor); | 410 touchInfo.adjustedRadius = |
| 411 FloatSize(touchInfo.point.radiusX, touchInfo.point.radiusY) |
| 412 .scaledBy(scaleFactor); |
416 touchInfo.knownTarget = knownTarget; | 413 touchInfo.knownTarget = knownTarget; |
417 touchInfo.region = regionID; | 414 touchInfo.region = regionID; |
418 } | 415 } |
419 } | 416 } |
420 | 417 |
421 bool TouchEventManager::reHitTestTouchPointsIfNeeded( | 418 bool TouchEventManager::reHitTestTouchPointsIfNeeded( |
422 const PlatformTouchEvent& event, | 419 const WebTouchEvent& event, |
423 HeapVector<TouchInfo>& touchInfos) { | 420 HeapVector<TouchInfo>& touchInfos) { |
424 bool newTouchSequence = true; | 421 bool newTouchSequence = true; |
425 bool allTouchesReleased = true; | 422 bool allTouchesReleased = true; |
426 | 423 |
427 for (const auto& point : event.touchPoints()) { | 424 for (unsigned i = 0; i < event.touchesLength; ++i) { |
428 if (point.state() != PlatformTouchPoint::TouchPressed) | 425 WebTouchPoint::State state = event.touches[i].state; |
| 426 if (state != WebTouchPoint::StatePressed) |
429 newTouchSequence = false; | 427 newTouchSequence = false; |
430 if (point.state() != PlatformTouchPoint::TouchReleased && | 428 if (state != WebTouchPoint::StateReleased && |
431 point.state() != PlatformTouchPoint::TouchCancelled) | 429 state != WebTouchPoint::StateCancelled) |
432 allTouchesReleased = false; | 430 allTouchesReleased = false; |
433 } | 431 } |
434 if (newTouchSequence) { | 432 if (newTouchSequence) { |
435 // Ideally we'd ASSERT(!m_touchSequenceDocument) here since we should | 433 // Ideally we'd ASSERT(!m_touchSequenceDocument) here since we should |
436 // have cleared the active document when we saw the last release. But we | 434 // have cleared the active document when we saw the last release. But we |
437 // have some tests that violate this, ClusterFuzz could trigger it, and | 435 // have some tests that violate this, ClusterFuzz could trigger it, and |
438 // there may be cases where the browser doesn't reliably release all | 436 // there may be cases where the browser doesn't reliably release all |
439 // touches. http://crbug.com/345372 tracks this. | 437 // touches. http://crbug.com/345372 tracks this. |
440 m_touchSequenceDocument.clear(); | 438 m_touchSequenceDocument.clear(); |
441 } | 439 } |
(...skipping 21 matching lines...) Expand all Loading... |
463 m_touchSequenceDocument.clear(); | 461 m_touchSequenceDocument.clear(); |
464 } | 462 } |
465 return false; | 463 return false; |
466 } | 464 } |
467 | 465 |
468 setAllPropertiesOfTouchInfos(touchInfos); | 466 setAllPropertiesOfTouchInfos(touchInfos); |
469 | 467 |
470 return true; | 468 return true; |
471 } | 469 } |
472 | 470 |
473 // TODO(rbyers): Replace with AutoReset as base/WTF unification permits. | |
474 class CurrentEventHolder { | |
475 // Always stack allocated to ensure lifetime doesn't exceed that of target | |
476 DISALLOW_NEW(); | |
477 | |
478 public: | |
479 CurrentEventHolder(PlatformEvent::EventType& target, | |
480 PlatformEvent::EventType value) | |
481 : m_target(target) { | |
482 m_target = value; | |
483 } | |
484 ~CurrentEventHolder() { m_target = PlatformEvent::NoType; } | |
485 | |
486 private: | |
487 PlatformEvent::EventType& m_target; | |
488 }; | |
489 | |
490 WebInputEventResult TouchEventManager::handleTouchEvent( | 471 WebInputEventResult TouchEventManager::handleTouchEvent( |
491 const PlatformTouchEvent& event, | 472 const WebTouchEvent& event, |
492 HeapVector<TouchInfo>& touchInfos) { | 473 HeapVector<TouchInfo>& touchInfos) { |
493 | |
494 // Track the current event for the scope of this function. | |
495 CurrentEventHolder holder(m_currentEvent, event.type()); | |
496 | |
497 if (!reHitTestTouchPointsIfNeeded(event, touchInfos)) | 474 if (!reHitTestTouchPointsIfNeeded(event, touchInfos)) |
498 return WebInputEventResult::NotHandled; | 475 return WebInputEventResult::NotHandled; |
499 | 476 |
500 bool allTouchesReleased = true; | 477 bool allTouchesReleased = true; |
501 for (const auto& point : event.touchPoints()) { | 478 for (unsigned i = 0; i < event.touchesLength; ++i) { |
502 if (point.state() != PlatformTouchPoint::TouchReleased && | 479 WebTouchPoint::State state = event.touches[i].state; |
503 point.state() != PlatformTouchPoint::TouchCancelled) | 480 if (state != WebTouchPoint::StateReleased && |
| 481 state != WebTouchPoint::StateCancelled) |
504 allTouchesReleased = false; | 482 allTouchesReleased = false; |
505 } | 483 } |
506 | 484 |
507 return dispatchTouchEvents(event, touchInfos, allTouchesReleased); | 485 return dispatchTouchEvents(event, touchInfos, allTouchesReleased); |
508 } | 486 } |
509 | 487 |
510 bool TouchEventManager::isAnyTouchActive() const { | 488 bool TouchEventManager::isAnyTouchActive() const { |
511 return m_touchPressed; | 489 return m_touchPressed; |
512 } | 490 } |
513 | 491 |
514 } // namespace blink | 492 } // namespace blink |
OLD | NEW |