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

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

Issue 1971473002: Move touch hit testing to PointerEventManager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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 // 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/EventHandlerRegistry.h" 9 #include "core/frame/EventHandlerRegistry.h"
10 #include "core/frame/FrameHost.h" 10 #include "core/frame/FrameHost.h"
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 TargetTouchesHeapMap touchesByTarget; 162 TargetTouchesHeapMap touchesByTarget;
163 163
164 // Array of touches per state, used to assemble the |changedTouches| list. 164 // Array of touches per state, used to assemble the |changedTouches| list.
165 ChangedTouches changedTouches[PlatformTouchPoint::TouchStateEnd]; 165 ChangedTouches changedTouches[PlatformTouchPoint::TouchStateEnd];
166 166
167 for (unsigned i = 0; i < touchInfos.size(); ++i) { 167 for (unsigned i = 0; i < touchInfos.size(); ++i) {
168 const TouchInfo& touchInfo = touchInfos[i]; 168 const TouchInfo& touchInfo = touchInfos[i];
169 const PlatformTouchPoint& point = touchInfo.point; 169 const PlatformTouchPoint& point = touchInfo.point;
170 PlatformTouchPoint::TouchState pointState = point.state(); 170 PlatformTouchPoint::TouchState pointState = point.state();
171 171
172 if (touchInfo.consumed)
173 continue;
174
175 Touch* touch = Touch::create( 172 Touch* touch = Touch::create(
176 touchInfo.targetFrame.get(), 173 touchInfo.targetFrame.get(),
177 touchInfo.touchNode.get(), 174 touchInfo.touchNode.get(),
178 point.id(), 175 point.id(),
179 point.screenPos(), 176 point.screenPos(),
180 touchInfo.adjustedPagePoint, 177 touchInfo.adjustedPagePoint,
181 touchInfo.adjustedRadius, 178 touchInfo.adjustedRadius,
182 point.rotationAngle(), 179 point.rotationAngle(),
183 point.force(), 180 point.force(),
184 touchInfo.region); 181 touchInfo.region);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 void TouchEventManager::updateTargetAndRegionMapsForTouchStarts( 259 void TouchEventManager::updateTargetAndRegionMapsForTouchStarts(
263 HeapVector<TouchInfo>& touchInfos) 260 HeapVector<TouchInfo>& touchInfos)
264 { 261 {
265 for (auto& touchInfo : touchInfos) { 262 for (auto& touchInfo : touchInfos) {
266 // Touch events implicitly capture to the touched node, and don't change 263 // Touch events implicitly capture to the touched node, and don't change
267 // active/hover states themselves (Gesture events do). So we only need 264 // active/hover states themselves (Gesture events do). So we only need
268 // to hit-test on touchstart and when the target could be different than 265 // to hit-test on touchstart and when the target could be different than
269 // the corresponding pointer event target. 266 // the corresponding pointer event target.
270 if (touchInfo.point.state() == PlatformTouchPoint::TouchPressed) { 267 if (touchInfo.point.state() == PlatformTouchPoint::TouchPressed) {
271 HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEv ent | HitTestRequest::ReadOnly | HitTestRequest::Active; 268 HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEv ent | HitTestRequest::ReadOnly | HitTestRequest::Active;
272 LayoutPoint pagePoint = roundedLayoutPoint(m_frame->view()->rootFram eToContents(touchInfo.point.pos()));
273 HitTestResult result; 269 HitTestResult result;
274 if (!m_touchSequenceDocument) { 270 if (m_touchSequenceDocument && (!touchInfo.touchNode
dtapuska 2016/05/13 16:51:36 Can we add a comment what the intent of this code
Navid Zolghadr 2016/05/16 20:01:50 Done.
275 result = m_frame->eventHandler().hitTestResultAtPoint(pagePoint, hitType); 271 || &touchInfo.touchNode->document() != m_touchSequenceDocument)) {
mustaq 2016/05/11 14:30:55 Looks like we are not covering this case anymore.
Navid Zolghadr 2016/05/11 16:43:42 We are not. This scenario (which is generally the
276 } else if (m_touchSequenceDocument->frame()) { 272 if (m_touchSequenceDocument->frame()) {
277 LayoutPoint framePoint = roundedLayoutPoint(m_touchSequenceDocum ent->frame()->view()->rootFrameToContents(touchInfo.point.pos())); 273 LayoutPoint framePoint = roundedLayoutPoint(m_touchSequenceD ocument->frame()->view()->rootFrameToContents(touchInfo.point.pos()));
278 result = EventHandler::hitTestResultInFrame(m_touchSequenceDocum ent->frame(), framePoint, hitType); 274 result = EventHandler::hitTestResultInFrame(m_touchSequenceD ocument->frame(), framePoint, hitType);
279 } else { 275 Node* node = result.innerNode();
276 if (!node)
277 continue;
278 if (isHTMLCanvasElement(node)) {
279 std::pair<Element*, String> regionInfo = toHTMLCanvasEle ment(node)->getControlAndIdIfHitRegionExists(result.pointInInnerNodeFrame());
280 if (regionInfo.first)
281 node = regionInfo.first;
282 touchInfo.region = regionInfo.second;
283 }
284 // Touch events should not go to text nodes.
285 if (node->isTextNode())
286 node = FlatTreeTraversal::parent(*node);
287 touchInfo.touchNode = node;
288 } else {
289 continue;
290 }
291 }
292 if (!touchInfo.touchNode)
280 continue; 293 continue;
281 }
282
283 Node* node = result.innerNode();
284 if (!node)
285 continue;
286 if (isHTMLCanvasElement(node)) {
287 std::pair<Element*, String> regionInfo = toHTMLCanvasElement(nod e)->getControlAndIdIfHitRegionExists(result.pointInInnerNodeFrame());
288 if (regionInfo.first)
289 node = regionInfo.first;
290 touchInfo.region = regionInfo.second;
291 }
292 // Touch events should not go to text nodes.
293 if (node->isTextNode())
294 node = FlatTreeTraversal::parent(*node);
295 touchInfo.touchNode = node;
296
297 if (!m_touchSequenceDocument) { 294 if (!m_touchSequenceDocument) {
298 // Keep track of which document should receive all touch events 295 // Keep track of which document should receive all touch events
299 // in the active sequence. This must be a single document to 296 // in the active sequence. This must be a single document to
300 // ensure we don't leak Nodes between documents. 297 // ensure we don't leak Nodes between documents.
301 m_touchSequenceDocument = &(touchInfo.touchNode->document()); 298 m_touchSequenceDocument = &(touchInfo.touchNode->document());
302 ASSERT(m_touchSequenceDocument->frame()->view()); 299 ASSERT(m_touchSequenceDocument->frame()->view());
303 } 300 }
304 301
305 // Ideally we'd ASSERT(!m_targetForTouchID.contains(point.id()) 302 // Ideally we'd ASSERT(!m_targetForTouchID.contains(point.id())
306 // since we shouldn't get a touchstart for a touch that's already 303 // since we shouldn't get a touchstart for a touch that's already
307 // down. However EventSender allows this to be violated and there's 304 // down. However EventSender allows this to be violated and there's
308 // some tests that take advantage of it. There may also be edge 305 // some tests that take advantage of it. There may also be edge
309 // cases in the browser where this happens. 306 // cases in the browser where this happens.
310 // See http://crbug.com/345372. 307 // See http://crbug.com/345372.
311 m_targetForTouchID.set(touchInfo.point.id(), touchInfo.touchNode); 308 m_targetForTouchID.set(touchInfo.point.id(), touchInfo.touchNode);
312 309
313 m_regionForTouchID.set(touchInfo.point.id(), touchInfo.region); 310 m_regionForTouchID.set(touchInfo.point.id(), touchInfo.region);
314
315 TouchAction effectiveTouchAction =
316 TouchActionUtil::computeEffectiveTouchAction(
317 *touchInfo.touchNode);
318 if (effectiveTouchAction != TouchActionAuto)
319 m_frame->page()->chromeClient().setTouchAction(effectiveTouchAct ion);
320 } 311 }
321 } 312 }
322 } 313 }
323 314
324 void TouchEventManager::setAllPropertiesOfTouchInfos( 315 void TouchEventManager::setAllPropertiesOfTouchInfos(
325 HeapVector<TouchInfo>& touchInfos) 316 HeapVector<TouchInfo>& touchInfos)
326 { 317 {
327 for (auto& touchInfo : touchInfos) { 318 for (auto& touchInfo : touchInfos) {
328 PlatformTouchPoint::TouchState pointState = touchInfo.point.state(); 319 PlatformTouchPoint::TouchState pointState = touchInfo.point.state();
329 Node* touchNode = nullptr; 320 Node* touchNode = nullptr;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 // pagePoint should always be in the target element's document coordinat es. 368 // pagePoint should always be in the target element's document coordinat es.
378 FloatPoint pagePoint = targetFrame->view()->rootFrameToContents( 369 FloatPoint pagePoint = targetFrame->view()->rootFrameToContents(
379 touchInfo.point.pos()); 370 touchInfo.point.pos());
380 float scaleFactor = 1.0f / targetFrame->pageZoomFactor(); 371 float scaleFactor = 1.0f / targetFrame->pageZoomFactor();
381 372
382 touchInfo.touchNode = touchNode; 373 touchInfo.touchNode = touchNode;
383 touchInfo.targetFrame = targetFrame; 374 touchInfo.targetFrame = targetFrame;
384 touchInfo.adjustedPagePoint = pagePoint.scaledBy(scaleFactor); 375 touchInfo.adjustedPagePoint = pagePoint.scaledBy(scaleFactor);
385 touchInfo.adjustedRadius = touchInfo.point.radius().scaledBy(scaleFactor ); 376 touchInfo.adjustedRadius = touchInfo.point.radius().scaledBy(scaleFactor );
386 touchInfo.knownTarget = knownTarget; 377 touchInfo.knownTarget = knownTarget;
387 touchInfo.consumed = false;
388 touchInfo.region = regionID; 378 touchInfo.region = regionID;
389 } 379 }
390 } 380 }
391 381
392 bool TouchEventManager::generateTouchInfosAfterHittest( 382 bool TouchEventManager::reHitTestTouchPointsIfNeeded(
393 const PlatformTouchEvent& event, 383 const PlatformTouchEvent& event,
394 HeapVector<TouchInfo>& touchInfos) 384 HeapVector<TouchInfo>& touchInfos)
395 { 385 {
396 bool newTouchSequence = true; 386 bool newTouchSequence = true;
397 bool allTouchesReleased = true; 387 bool allTouchesReleased = true;
398 388
399 for (const auto& point : event.touchPoints()) { 389 for (const auto& point : event.touchPoints()) {
400 if (point.state() != PlatformTouchPoint::TouchPressed) 390 if (point.state() != PlatformTouchPoint::TouchPressed)
401 newTouchSequence = false; 391 newTouchSequence = false;
402 if (point.state() != PlatformTouchPoint::TouchReleased && point.state() != PlatformTouchPoint::TouchCancelled) 392 if (point.state() != PlatformTouchPoint::TouchReleased && point.state() != PlatformTouchPoint::TouchCancelled)
403 allTouchesReleased = false; 393 allTouchesReleased = false;
404 } 394 }
405 if (newTouchSequence) { 395 if (newTouchSequence) {
406 // Ideally we'd ASSERT(!m_touchSequenceDocument) here since we should 396 // Ideally we'd ASSERT(!m_touchSequenceDocument) here since we should
407 // have cleared the active document when we saw the last release. But we 397 // have cleared the active document when we saw the last release. But we
408 // have some tests that violate this, ClusterFuzz could trigger it, and 398 // have some tests that violate this, ClusterFuzz could trigger it, and
409 // there may be cases where the browser doesn't reliably release all 399 // there may be cases where the browser doesn't reliably release all
410 // touches. http://crbug.com/345372 tracks this. 400 // touches. http://crbug.com/345372 tracks this.
411 m_touchSequenceDocument.clear(); 401 m_touchSequenceDocument.clear();
412 m_touchSequenceUserGestureToken.clear(); 402 m_touchSequenceUserGestureToken.clear();
413 } 403 }
414 404
415 ASSERT(m_frame->view()); 405 ASSERT(m_frame->view());
416 if (m_touchSequenceDocument && (!m_touchSequenceDocument->frame() || !m_touc hSequenceDocument->frame()->view())) { 406 if (m_touchSequenceDocument && (!m_touchSequenceDocument->frame() || !m_touc hSequenceDocument->frame()->view())) {
417 // If the active touch document has no frame or view, it's probably bein g destroyed 407 // If the active touch document has no frame or view, it's probably bein g destroyed
418 // so we can't dispatch events. 408 // so we can't dispatch events.
419 return false; 409 return false;
420 } 410 }
421 411
422 for (const auto& point : event.touchPoints()) {
423 TouchEventManager::TouchInfo touchInfo;
424 touchInfo.point = point;
425 touchInfos.append(touchInfo);
426 }
427
428 updateTargetAndRegionMapsForTouchStarts(touchInfos); 412 updateTargetAndRegionMapsForTouchStarts(touchInfos);
429 413
430 m_touchPressed = !allTouchesReleased; 414 m_touchPressed = !allTouchesReleased;
431 415
432 // If there's no document receiving touch events, or no handlers on the 416 // If there's no document receiving touch events, or no handlers on the
433 // document set to receive the events, then we can skip all the rest of 417 // document set to receive the events, then we can skip all the rest of
434 // this work. 418 // this work.
435 if (!m_touchSequenceDocument || !m_touchSequenceDocument->frameHost() || !ha sTouchHandlers(m_touchSequenceDocument->frameHost()->eventHandlerRegistry()) || !m_touchSequenceDocument->frame()) { 419 if (!m_touchSequenceDocument || !m_touchSequenceDocument->frameHost() || !ha sTouchHandlers(m_touchSequenceDocument->frameHost()->eventHandlerRegistry()) || !m_touchSequenceDocument->frame()) {
436 if (allTouchesReleased) { 420 if (allTouchesReleased) {
437 m_touchSequenceDocument.clear(); 421 m_touchSequenceDocument.clear();
438 m_touchSequenceUserGestureToken.clear(); 422 m_touchSequenceUserGestureToken.clear();
439 } 423 }
440 return false; 424 return false;
441 } 425 }
442 426
443 setAllPropertiesOfTouchInfos(touchInfos); 427 setAllPropertiesOfTouchInfos(touchInfos);
444 428
445 return true; 429 return true;
446 } 430 }
447 431
448 WebInputEventResult TouchEventManager::handleTouchEvent( 432 WebInputEventResult TouchEventManager::handleTouchEvent(
449 const PlatformTouchEvent& event, 433 const PlatformTouchEvent& event,
450 const HeapVector<TouchInfo>& touchInfos) 434 HeapVector<TouchInfo>& touchInfos)
451 { 435 {
436 if (!reHitTestTouchPointsIfNeeded(event, touchInfos))
437 return WebInputEventResult::NotHandled;
438
452 // Note that the disposition of any pointer events affects only the generati on of touch 439 // Note that the disposition of any pointer events affects only the generati on of touch
453 // events. If all pointer events were handled (and hence no touch events wer e fired), that 440 // events. If all pointer events were handled (and hence no touch events wer e fired), that
454 // is still equivalent to the touch events going unhandled because pointer e vent handler 441 // is still equivalent to the touch events going unhandled because pointer e vent handler
455 // don't block scroll gesture generation. 442 // don't block scroll gesture generation.
456 443
457 // TODO(crbug.com/507408): If PE handlers always call preventDefault, we won 't see TEs until after 444 // TODO(crbug.com/507408): If PE handlers always call preventDefault, we won 't see TEs until after
458 // scrolling starts because the scrolling would suppress upcoming PEs. This sudden "break" in TE 445 // scrolling starts because the scrolling would suppress upcoming PEs. This sudden "break" in TE
459 // suppression can make the visible TEs inconsistent (e.g. touchmove without a touchstart). 446 // suppression can make the visible TEs inconsistent (e.g. touchmove without a touchstart).
460 447
461 bool allTouchesReleased = true; 448 bool allTouchesReleased = true;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 } 491 }
505 492
506 DEFINE_TRACE(TouchEventManager) 493 DEFINE_TRACE(TouchEventManager)
507 { 494 {
508 visitor->trace(m_frame); 495 visitor->trace(m_frame);
509 visitor->trace(m_touchSequenceDocument); 496 visitor->trace(m_touchSequenceDocument);
510 visitor->trace(m_targetForTouchID); 497 visitor->trace(m_targetForTouchID);
511 } 498 }
512 499
513 } // namespace blink 500 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698