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

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

Issue 2914673002: Refactor TouchEventManager::TouchInfo class (Closed)
Patch Set: Rebase Created 3 years, 6 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
« no previous file with comments | « third_party/WebKit/Source/core/input/TouchEventManager.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <memory> 7 #include <memory>
8 #include "core/dom/Document.h" 8 #include "core/dom/Document.h"
9 #include "core/events/TouchEvent.h" 9 #include "core/events/TouchEvent.h"
10 #include "core/frame/Deprecation.h" 10 #include "core/frame/Deprecation.h"
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 suppressing_touchmoves_within_slop_ = false; 110 suppressing_touchmoves_within_slop_ = false;
111 current_touch_action_ = TouchAction::kTouchActionAuto; 111 current_touch_action_ = TouchAction::kTouchActionAuto;
112 } 112 }
113 113
114 DEFINE_TRACE(TouchEventManager) { 114 DEFINE_TRACE(TouchEventManager) {
115 visitor->Trace(frame_); 115 visitor->Trace(frame_);
116 visitor->Trace(touch_sequence_document_); 116 visitor->Trace(touch_sequence_document_);
117 visitor->Trace(target_for_touch_id_); 117 visitor->Trace(target_for_touch_id_);
118 } 118 }
119 119
120 Touch* TouchEventManager::CreateDomTouch(const WebTouchPoint& point,
121 bool* known_target) {
122 Node* touch_node = nullptr;
123 String region_id;
124 *known_target = false;
125 FloatPoint content_point;
126 FloatSize adjusted_radius;
127
128 if (point.state == WebTouchPoint::kStateReleased ||
129 point.state == WebTouchPoint::kStateCancelled) {
130 // The target should be the original target for this touch, so get
131 // it from the hashmap. As it's a release or cancel we also remove
132 // it from the map.
133 touch_node = target_for_touch_id_.Take(point.id);
134 region_id = region_for_touch_id_.Take(point.id);
135 } else {
136 // No hittest is performed on move or stationary, since the target
137 // is not allowed to change anyway.
138 touch_node = target_for_touch_id_.at(point.id);
139 region_id = region_for_touch_id_.at(point.id);
140 }
141
142 LocalFrame* target_frame = nullptr;
143 if (touch_node) {
144 Document& doc = touch_node->GetDocument();
145 // If the target node has moved to a new document while it was being
146 // touched, we can't send events to the new document because that could
147 // leak nodes from one document to another. See http://crbug.com/394339.
148 if (&doc == touch_sequence_document_.Get()) {
149 target_frame = doc.GetFrame();
150 *known_target = true;
151 }
152 }
153 if (!(*known_target)) {
154 // If we don't have a target registered for the point it means we've
155 // missed our opportunity to do a hit test for it (due to some
156 // optimization that prevented blink from ever seeing the
157 // touchstart), or that the touch started outside the active touch
158 // sequence document. We should still include the touch in the
159 // Touches list reported to the application (eg. so it can
160 // differentiate between a one and two finger gesture), but we won't
161 // actually dispatch any events for it. Set the target to the
162 // Document so that there's some valid node here. Perhaps this
163 // should really be LocalDOMWindow, but in all other cases the target of
164 // a Touch is a Node so using the window could be a breaking change.
165 // Since we know there was no handler invoked, the specific target
166 // should be completely irrelevant to the application.
167 touch_node = touch_sequence_document_;
168 target_frame = touch_sequence_document_->GetFrame();
169 }
170 DCHECK(target_frame);
171
172 // pagePoint should always be in the target element's document coordinates.
173 FloatPoint page_point =
174 target_frame->View()->RootFrameToContents(point.PositionInWidget());
175 float scale_factor = 1.0f / target_frame->PageZoomFactor();
176
177 content_point = page_point.ScaledBy(scale_factor);
178 adjusted_radius =
179 FloatSize(point.radius_x, point.radius_y).ScaledBy(scale_factor);
180
181 return Touch::Create(target_frame, touch_node, point.id,
182 point.PositionInScreen(), content_point, adjusted_radius,
183 point.rotation_angle, point.force, region_id);
184 }
185
120 WebInputEventResult TouchEventManager::DispatchTouchEvents( 186 WebInputEventResult TouchEventManager::DispatchTouchEvents(
121 const WebTouchEvent& event, 187 const WebTouchEvent& event,
122 const Vector<WebTouchEvent>& coalesced_events, 188 const Vector<WebTouchEvent>& coalesced_events,
123 const HeapVector<TouchInfo>& touch_infos,
124 bool all_touches_released) { 189 bool all_touches_released) {
125 // Build up the lists to use for the |touches|, |targetTouches| and 190 // Build up the lists to use for the |touches|, |targetTouches| and
126 // |changedTouches| attributes in the JS event. See 191 // |changedTouches| attributes in the JS event. See
127 // http://www.w3.org/TR/touch-events/#touchevent-interface for how these 192 // http://www.w3.org/TR/touch-events/#touchevent-interface for how these
128 // lists fit together. 193 // lists fit together.
129 194
130 if (event.GetType() == WebInputEvent::kTouchEnd || 195 if (event.GetType() == WebInputEvent::kTouchEnd ||
131 event.GetType() == WebInputEvent::kTouchCancel || 196 event.GetType() == WebInputEvent::kTouchCancel ||
132 event.touches_length > 1) { 197 event.touches_length > 1) {
133 suppressing_touchmoves_within_slop_ = false; 198 suppressing_touchmoves_within_slop_ = false;
(...skipping 10 matching lines...) Expand all
144 TouchList* touches = TouchList::Create(); 209 TouchList* touches = TouchList::Create();
145 210
146 // A different view on the 'touches' list above, filtered and grouped by 211 // A different view on the 'touches' list above, filtered and grouped by
147 // event target. Used for the |targetTouches| list in the JS event. 212 // event target. Used for the |targetTouches| list in the JS event.
148 using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>; 213 using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>;
149 TargetTouchesHeapMap touches_by_target; 214 TargetTouchesHeapMap touches_by_target;
150 215
151 // Array of touches per state, used to assemble the |changedTouches| list. 216 // Array of touches per state, used to assemble the |changedTouches| list.
152 ChangedTouches changed_touches[WebTouchPoint::kStateMax + 1]; 217 ChangedTouches changed_touches[WebTouchPoint::kStateMax + 1];
153 218
154 for (auto touch_info : touch_infos) { 219 for (unsigned touch_point_idx = 0; touch_point_idx < event.touches_length;
155 const WebTouchPoint& point = touch_info.point; 220 touch_point_idx++) {
221 const WebTouchPoint& point = event.TouchPointInRootFrame(touch_point_idx);
156 WebTouchPoint::State point_state = point.state; 222 WebTouchPoint::State point_state = point.state;
223 bool known_target;
157 224
158 Touch* touch = Touch::Create( 225 Touch* touch = CreateDomTouch(point, &known_target);
159 touch_info.target_frame.Get(), touch_info.touch_node.Get(), point.id, 226 EventTarget* touch_target = touch->target();
160 point.PositionInScreen(), touch_info.content_point,
161 touch_info.adjusted_radius, point.rotation_angle, point.force,
162 touch_info.region);
163 227
164 // Ensure this target's touch list exists, even if it ends up empty, so 228 // Ensure this target's touch list exists, even if it ends up empty, so
165 // it can always be passed to TouchEvent::Create below. 229 // it can always be passed to TouchEvent::Create below.
166 TargetTouchesHeapMap::iterator target_touches_iterator = 230 TargetTouchesHeapMap::iterator target_touches_iterator =
167 touches_by_target.find(touch_info.touch_node.Get()); 231 touches_by_target.find(touch_target);
168 if (target_touches_iterator == touches_by_target.end()) { 232 if (target_touches_iterator == touches_by_target.end()) {
169 touches_by_target.Set(touch_info.touch_node.Get(), TouchList::Create()); 233 touches_by_target.Set(touch_target, TouchList::Create());
170 target_touches_iterator = 234 target_touches_iterator = touches_by_target.find(touch_target);
171 touches_by_target.find(touch_info.touch_node.Get());
172 } 235 }
173 236
174 // |touches| and |targetTouches| should only contain information about 237 // |touches| and |targetTouches| should only contain information about
175 // touches still on the screen, so if this point is released or 238 // touches still on the screen, so if this point is released or
176 // cancelled it will only appear in the |changedTouches| list. 239 // cancelled it will only appear in the |changedTouches| list.
177 if (point_state != WebTouchPoint::kStateReleased && 240 if (point_state != WebTouchPoint::kStateReleased &&
178 point_state != WebTouchPoint::kStateCancelled) { 241 point_state != WebTouchPoint::kStateCancelled) {
179 touches->Append(touch); 242 touches->Append(touch);
180 target_touches_iterator->value->Append(touch); 243 target_touches_iterator->value->Append(touch);
181 } 244 }
182 245
183 // Now build up the correct list for |changedTouches|. 246 // Now build up the correct list for |changedTouches|.
184 // Note that any touches that are in the TouchStationary state (e.g. if 247 // Note that any touches that are in the TouchStationary state (e.g. if
185 // the user had several points touched but did not move them all) should 248 // the user had several points touched but did not move them all) should
186 // never be in the |changedTouches| list so we do not handle them 249 // never be in the |changedTouches| list so we do not handle them
187 // explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609 250 // explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609
188 // for further discussion about the TouchStationary state. 251 // for further discussion about the TouchStationary state.
189 if (point_state != WebTouchPoint::kStateStationary && 252 if (point_state != WebTouchPoint::kStateStationary && known_target) {
190 touch_info.known_target) {
191 DCHECK_LE(point_state, WebTouchPoint::kStateMax); 253 DCHECK_LE(point_state, WebTouchPoint::kStateMax);
192 if (!changed_touches[point_state].touches_) 254 if (!changed_touches[point_state].touches_)
193 changed_touches[point_state].touches_ = TouchList::Create(); 255 changed_touches[point_state].touches_ = TouchList::Create();
194 changed_touches[point_state].touches_->Append(touch); 256 changed_touches[point_state].touches_->Append(touch);
195 changed_touches[point_state].targets_.insert(touch_info.touch_node); 257 changed_touches[point_state].targets_.insert(touch_target);
196 changed_touches[point_state].pointer_type_ = point.pointer_type; 258 changed_touches[point_state].pointer_type_ = point.pointer_type;
197 } 259 }
198 } 260 }
199 261
200 if (all_touches_released) { 262 if (all_touches_released) {
201 touch_sequence_document_.Clear(); 263 touch_sequence_document_.Clear();
202 current_touch_action_ = TouchAction::kTouchActionAuto; 264 current_touch_action_ = TouchAction::kTouchActionAuto;
203 } 265 }
204 266
205 WebInputEventResult event_result = WebInputEventResult::kNotHandled; 267 WebInputEventResult event_result = WebInputEventResult::kNotHandled;
(...skipping 19 matching lines...) Expand all
225 coalesced_event, touches, touches_by_target.at(touch_event_target), 287 coalesced_event, touches, touches_by_target.at(touch_event_target),
226 changed_touches[state].touches_.Get(), event_name, 288 changed_touches[state].touches_.Get(), event_name,
227 touch_event_target->ToNode()->GetDocument().domWindow(), 289 touch_event_target->ToNode()->GetDocument().domWindow(),
228 current_touch_action_); 290 current_touch_action_);
229 291
230 DispatchEventResult dom_dispatch_result = 292 DispatchEventResult dom_dispatch_result =
231 touch_event_target->DispatchEvent(touch_event); 293 touch_event_target->DispatchEvent(touch_event);
232 294
233 // Only report for top level documents with a single touch on 295 // Only report for top level documents with a single touch on
234 // touch-start or the first touch-move. 296 // touch-start or the first touch-move.
235 if (event.touch_start_or_first_touch_move && touch_infos.size() == 1 && 297 if (event.touch_start_or_first_touch_move && event.touches_length == 1 &&
236 frame_->IsMainFrame()) { 298 frame_->IsMainFrame()) {
237 // Record the disposition and latency of touch starts and first touch 299 // Record the disposition and latency of touch starts and first touch
238 // moves before and after the page is fully loaded respectively. 300 // moves before and after the page is fully loaded respectively.
239 int64_t latency_in_micros = 301 int64_t latency_in_micros =
240 (TimeTicks::Now() - 302 (TimeTicks::Now() -
241 TimeTicks::FromSeconds(event.TimeStampSeconds())) 303 TimeTicks::FromSeconds(event.TimeStampSeconds()))
242 .InMicroseconds(); 304 .InMicroseconds();
243 if (event.IsCancelable()) { 305 if (event.IsCancelable()) {
244 if (frame_->GetDocument()->IsLoadCompleted()) { 306 if (frame_->GetDocument()->IsLoadCompleted()) {
245 DEFINE_STATIC_LOCAL(EnumerationHistogram, 307 DEFINE_STATIC_LOCAL(EnumerationHistogram,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 364
303 // Do not suppress any touchmoves if the touchstart is consumed. 365 // Do not suppress any touchmoves if the touchstart is consumed.
304 if (IsTouchSequenceStart(event) && 366 if (IsTouchSequenceStart(event) &&
305 event_result == WebInputEventResult::kNotHandled) { 367 event_result == WebInputEventResult::kNotHandled) {
306 suppressing_touchmoves_within_slop_ = true; 368 suppressing_touchmoves_within_slop_ = true;
307 } 369 }
308 370
309 return event_result; 371 return event_result;
310 } 372 }
311 373
312 void TouchEventManager::UpdateTargetAndRegionMapsForTouchStarts( 374 void TouchEventManager::UpdateTargetAndRegionMapsForTouchStart(
313 HeapVector<TouchInfo>& touch_infos) { 375 const WebTouchPoint& touch_point,
314 for (auto& touch_info : touch_infos) { 376 const EventHandlingUtil::PointerEventTarget& pointer_event_target) {
315 // Touch events implicitly capture to the touched node, and don't change 377 // Touch events implicitly capture to the touched node, and don't change
316 // active/hover states themselves (Gesture events do). So we only need 378 // active/hover states themselves (Gesture events do). So we only need
317 // to hit-test on touchstart and when the target could be different than 379 // to hit-test on touchstart and when the target could be different than
318 // the corresponding pointer event target. 380 // the corresponding pointer event target.
319 if (touch_info.point.state == WebTouchPoint::kStatePressed) { 381 DCHECK(touch_point.state == WebTouchPoint::kStatePressed);
320 HitTestRequest::HitTestRequestType hit_type = 382 Node* touch_node = pointer_event_target.target_node;
321 HitTestRequest::kTouchEvent | HitTestRequest::kReadOnly | 383 String region = pointer_event_target.region;
322 HitTestRequest::kActive; 384
323 HitTestResult result; 385 HitTestRequest::HitTestRequestType hit_type = HitTestRequest::kTouchEvent |
324 // For the touchPressed points hit-testing is done in 386 HitTestRequest::kReadOnly |
325 // PointerEventManager. If it was the second touch there is a 387 HitTestRequest::kActive;
326 // capturing documents for the touch and |m_touchSequenceDocument| 388 HitTestResult result;
327 // is not null. So if PointerEventManager should hit-test again 389 // For the touchPressed points hit-testing is done in
328 // against |m_touchSequenceDocument| if the target set by 390 // PointerEventManager. If it was the second touch there is a
329 // PointerEventManager was either null or not in 391 // capturing documents for the touch and |m_touchSequenceDocument|
330 // |m_touchSequenceDocument|. 392 // is not null. So if PointerEventManager should hit-test again
331 if (touch_sequence_document_ && 393 // against |m_touchSequenceDocument| if the target set by
332 (!touch_info.touch_node || 394 // PointerEventManager was either null or not in
333 &touch_info.touch_node->GetDocument() != touch_sequence_document_)) { 395 // |m_touchSequenceDocument|.
334 if (touch_sequence_document_->GetFrame()) { 396 if (touch_sequence_document_ &&
335 LayoutPoint frame_point = LayoutPoint( 397 (!touch_node || &touch_node->GetDocument() != touch_sequence_document_)) {
336 touch_sequence_document_->GetFrame()->View()->RootFrameToContents( 398 if (touch_sequence_document_->GetFrame()) {
337 touch_info.point.PositionInWidget())); 399 LayoutPoint frame_point = LayoutPoint(
338 result = EventHandlingUtil::HitTestResultInFrame( 400 touch_sequence_document_->GetFrame()->View()->RootFrameToContents(
339 touch_sequence_document_->GetFrame(), frame_point, hit_type); 401 touch_point.PositionInWidget()));
340 Node* node = result.InnerNode(); 402 result = EventHandlingUtil::HitTestResultInFrame(
341 if (!node) 403 touch_sequence_document_->GetFrame(), frame_point, hit_type);
342 continue; 404 Node* node = result.InnerNode();
343 if (isHTMLCanvasElement(node)) { 405 if (!node)
344 HitTestCanvasResult* hit_test_canvas_result = 406 return;
345 toHTMLCanvasElement(node)->GetControlAndIdIfHitRegionExists( 407 if (isHTMLCanvasElement(node)) {
346 result.PointInInnerNodeFrame()); 408 HitTestCanvasResult* hit_test_canvas_result =
347 if (hit_test_canvas_result->GetControl()) 409 toHTMLCanvasElement(node)->GetControlAndIdIfHitRegionExists(
348 node = hit_test_canvas_result->GetControl(); 410 result.PointInInnerNodeFrame());
349 touch_info.region = hit_test_canvas_result->GetId(); 411 if (hit_test_canvas_result->GetControl())
350 } 412 node = hit_test_canvas_result->GetControl();
351 // Touch events should not go to text nodes. 413 region = hit_test_canvas_result->GetId();
352 if (node->IsTextNode())
353 node = FlatTreeTraversal::Parent(*node);
354 touch_info.touch_node = node;
355 } else {
356 continue;
357 }
358 } 414 }
359 if (!touch_info.touch_node) 415 // Touch events should not go to text nodes.
360 continue; 416 if (node->IsTextNode())
361 if (!touch_sequence_document_) { 417 node = FlatTreeTraversal::Parent(*node);
362 // Keep track of which document should receive all touch events 418 touch_node = node;
363 // in the active sequence. This must be a single document to 419 } else {
364 // ensure we don't leak Nodes between documents. 420 return;
365 touch_sequence_document_ = &(touch_info.touch_node->GetDocument()); 421 }
366 DCHECK(touch_sequence_document_->GetFrame()->View()); 422 }
367 } 423 if (!touch_node)
424 return;
425 if (!touch_sequence_document_) {
426 // Keep track of which document should receive all touch events
427 // in the active sequence. This must be a single document to
428 // ensure we don't leak Nodes between documents.
429 touch_sequence_document_ = &(touch_node->GetDocument());
430 DCHECK(touch_sequence_document_->GetFrame()->View());
431 }
368 432
369 // Ideally we'd DCHECK(!m_targetForTouchID.contains(point.id()) 433 // Ideally we'd DCHECK(!m_targetForTouchID.contains(point.id())
370 // since we shouldn't get a touchstart for a touch that's already 434 // since we shouldn't get a touchstart for a touch that's already
371 // down. However EventSender allows this to be violated and there's 435 // down. However EventSender allows this to be violated and there's
372 // some tests that take advantage of it. There may also be edge 436 // some tests that take advantage of it. There may also be edge
373 // cases in the browser where this happens. 437 // cases in the browser where this happens.
374 // See http://crbug.com/345372. 438 // See http://crbug.com/345372.
375 target_for_touch_id_.Set(touch_info.point.id, touch_info.touch_node); 439 target_for_touch_id_.Set(touch_point.id, touch_node);
376 440
377 region_for_touch_id_.Set(touch_info.point.id, touch_info.region); 441 region_for_touch_id_.Set(touch_point.id, region);
378 442
379 TouchAction effective_touch_action = 443 TouchAction effective_touch_action =
380 TouchActionUtil::ComputeEffectiveTouchAction(*touch_info.touch_node); 444 TouchActionUtil::ComputeEffectiveTouchAction(*touch_node);
381 if (effective_touch_action != TouchAction::kTouchActionAuto) { 445 if (effective_touch_action != TouchAction::kTouchActionAuto) {
382 frame_->GetPage()->GetChromeClient().SetTouchAction( 446 frame_->GetPage()->GetChromeClient().SetTouchAction(frame_,
383 frame_, effective_touch_action); 447 effective_touch_action);
384 448
385 // Combine the current touch action sequence with the touch action 449 // Combine the current touch action sequence with the touch action
386 // for the current finger press. 450 // for the current finger press.
387 current_touch_action_ &= effective_touch_action; 451 current_touch_action_ &= effective_touch_action;
388 }
389 }
390 } 452 }
391 } 453 }
392 454
393 void TouchEventManager::SetAllPropertiesOfTouchInfos( 455 bool TouchEventManager::HitTestTouchPointsIfNeeded(
394 HeapVector<TouchInfo>& touch_infos) {
395 for (auto& touch_info : touch_infos) {
396 WebTouchPoint::State point_state = touch_info.point.state;
397 Node* touch_node = nullptr;
398 String region_id;
399
400 if (point_state == WebTouchPoint::kStateReleased ||
401 point_state == WebTouchPoint::kStateCancelled) {
402 // The target should be the original target for this touch, so get
403 // it from the hashmap. As it's a release or cancel we also remove
404 // it from the map.
405 touch_node = target_for_touch_id_.Take(touch_info.point.id);
406 region_id = region_for_touch_id_.Take(touch_info.point.id);
407 } else {
408 // No hittest is performed on move or stationary, since the target
409 // is not allowed to change anyway.
410 touch_node = target_for_touch_id_.at(touch_info.point.id);
411 region_id = region_for_touch_id_.at(touch_info.point.id);
412 }
413
414 LocalFrame* target_frame = nullptr;
415 bool known_target = false;
416 if (touch_node) {
417 Document& doc = touch_node->GetDocument();
418 // If the target node has moved to a new document while it was being
419 // touched, we can't send events to the new document because that could
420 // leak nodes from one document to another. See http://crbug.com/394339.
421 if (&doc == touch_sequence_document_.Get()) {
422 target_frame = doc.GetFrame();
423 known_target = true;
424 }
425 }
426 if (!known_target) {
427 // If we don't have a target registered for the point it means we've
428 // missed our opportunity to do a hit test for it (due to some
429 // optimization that prevented blink from ever seeing the
430 // touchstart), or that the touch started outside the active touch
431 // sequence document. We should still include the touch in the
432 // Touches list reported to the application (eg. so it can
433 // differentiate between a one and two finger gesture), but we won't
434 // actually dispatch any events for it. Set the target to the
435 // Document so that there's some valid node here. Perhaps this
436 // should really be LocalDOMWindow, but in all other cases the target of
437 // a Touch is a Node so using the window could be a breaking change.
438 // Since we know there was no handler invoked, the specific target
439 // should be completely irrelevant to the application.
440 touch_node = touch_sequence_document_;
441 target_frame = touch_sequence_document_->GetFrame();
442 }
443 DCHECK(target_frame);
444
445 // pagePoint should always be in the target element's document coordinates.
446 FloatPoint page_point = target_frame->View()->RootFrameToContents(
447 touch_info.point.PositionInWidget());
448 float scale_factor = 1.0f / target_frame->PageZoomFactor();
449
450 touch_info.touch_node = touch_node;
451 touch_info.target_frame = target_frame;
452 touch_info.content_point = page_point.ScaledBy(scale_factor);
453 touch_info.adjusted_radius =
454 FloatSize(touch_info.point.radius_x, touch_info.point.radius_y)
455 .ScaledBy(scale_factor);
456 touch_info.known_target = known_target;
457 touch_info.region = region_id;
458 }
459 }
460
461 bool TouchEventManager::ReHitTestTouchPointsIfNeeded(
462 const WebTouchEvent& event, 456 const WebTouchEvent& event,
463 HeapVector<TouchInfo>& touch_infos) { 457 const HeapVector<EventHandlingUtil::PointerEventTarget>&
458 pointer_event_targets) {
464 bool new_touch_sequence = true; 459 bool new_touch_sequence = true;
465 bool all_touches_released = true; 460 bool all_touches_released = true;
466 461
467 for (unsigned i = 0; i < event.touches_length; ++i) { 462 for (unsigned i = 0; i < event.touches_length; ++i) {
468 WebTouchPoint::State state = event.touches[i].state; 463 WebTouchPoint::State state = event.touches[i].state;
469 if (state != WebTouchPoint::kStatePressed) 464 if (state != WebTouchPoint::kStatePressed)
470 new_touch_sequence = false; 465 new_touch_sequence = false;
471 if (state != WebTouchPoint::kStateReleased && 466 if (state != WebTouchPoint::kStateReleased &&
472 state != WebTouchPoint::kStateCancelled) 467 state != WebTouchPoint::kStateCancelled)
473 all_touches_released = false; 468 all_touches_released = false;
474 } 469 }
475 if (new_touch_sequence) { 470 if (new_touch_sequence) {
476 // Ideally we'd DCHECK(!m_touchSequenceDocument) here since we should 471 // Ideally we'd DCHECK(!m_touchSequenceDocument) here since we should
477 // have cleared the active document when we saw the last release. But we 472 // have cleared the active document when we saw the last release. But we
478 // have some tests that violate this, ClusterFuzz could trigger it, and 473 // have some tests that violate this, ClusterFuzz could trigger it, and
479 // there may be cases where the browser doesn't reliably release all 474 // there may be cases where the browser doesn't reliably release all
480 // touches. http://crbug.com/345372 tracks this. 475 // touches. http://crbug.com/345372 tracks this.
481 touch_sequence_document_.Clear(); 476 touch_sequence_document_.Clear();
482 } 477 }
483 478
484 DCHECK(frame_->View()); 479 DCHECK(frame_->View());
485 if (touch_sequence_document_ && 480 if (touch_sequence_document_ &&
486 (!touch_sequence_document_->GetFrame() || 481 (!touch_sequence_document_->GetFrame() ||
487 !touch_sequence_document_->GetFrame()->View())) { 482 !touch_sequence_document_->GetFrame()->View())) {
488 // If the active touch document has no frame or view, it's probably being 483 // If the active touch document has no frame or view, it's probably being
489 // destroyed so we can't dispatch events. 484 // destroyed so we can't dispatch events.
490 return false; 485 return false;
491 } 486 }
492 487
493 UpdateTargetAndRegionMapsForTouchStarts(touch_infos); 488 for (unsigned i = 0; i < event.touches_length; ++i) {
489 // In touch event model only touch starts can set the target and after that
490 // the touch event always goes to that target.
491 if (event.touches[i].state == WebTouchPoint::kStatePressed) {
492 UpdateTargetAndRegionMapsForTouchStart(event.TouchPointInRootFrame(i),
493 pointer_event_targets[i]);
494 }
495 }
494 496
495 touch_pressed_ = !all_touches_released; 497 touch_pressed_ = !all_touches_released;
496 498
497 // If there's no document receiving touch events, or no handlers on the 499 // If there's no document receiving touch events, or no handlers on the
498 // document set to receive the events, then we can skip all the rest of 500 // document set to receive the events, then we can skip all the rest of
499 // this work. 501 // this work.
500 if (!touch_sequence_document_ || !touch_sequence_document_->GetPage() || 502 if (!touch_sequence_document_ || !touch_sequence_document_->GetPage() ||
501 !HasTouchHandlers( 503 !HasTouchHandlers(
502 touch_sequence_document_->GetPage()->GetEventHandlerRegistry()) || 504 touch_sequence_document_->GetPage()->GetEventHandlerRegistry()) ||
503 !touch_sequence_document_->GetFrame()) { 505 !touch_sequence_document_->GetFrame()) {
504 if (all_touches_released) { 506 if (all_touches_released) {
505 touch_sequence_document_.Clear(); 507 touch_sequence_document_.Clear();
506 } 508 }
507 return false; 509 return false;
508 } 510 }
509 511
510 SetAllPropertiesOfTouchInfos(touch_infos);
511
512 return true; 512 return true;
513 } 513 }
514 514
515 WebInputEventResult TouchEventManager::HandleTouchEvent( 515 WebInputEventResult TouchEventManager::HandleTouchEvent(
516 const WebTouchEvent& event, 516 const WebTouchEvent& event,
517 const Vector<WebTouchEvent>& coalesced_events, 517 const Vector<WebTouchEvent>& coalesced_events,
518 HeapVector<TouchInfo>& touch_infos) { 518 const HeapVector<EventHandlingUtil::PointerEventTarget>&
519 if (!ReHitTestTouchPointsIfNeeded(event, touch_infos)) 519 pointer_event_targets) {
520 DCHECK(event.touches_length == pointer_event_targets.size());
521
522 if (!HitTestTouchPointsIfNeeded(event, pointer_event_targets))
520 return WebInputEventResult::kNotHandled; 523 return WebInputEventResult::kNotHandled;
521 524
522 bool all_touches_released = true; 525 bool all_touches_released = true;
523 for (unsigned i = 0; i < event.touches_length; ++i) { 526 for (unsigned i = 0; i < event.touches_length; ++i) {
524 WebTouchPoint::State state = event.touches[i].state; 527 WebTouchPoint::State state = event.touches[i].state;
525 if (state != WebTouchPoint::kStateReleased && 528 if (state != WebTouchPoint::kStateReleased &&
526 state != WebTouchPoint::kStateCancelled) 529 state != WebTouchPoint::kStateCancelled)
527 all_touches_released = false; 530 all_touches_released = false;
528 } 531 }
529 532
530 return DispatchTouchEvents(event, coalesced_events, touch_infos, 533 return DispatchTouchEvents(event, coalesced_events, all_touches_released);
531 all_touches_released);
532 } 534 }
533 535
534 bool TouchEventManager::IsAnyTouchActive() const { 536 bool TouchEventManager::IsAnyTouchActive() const {
535 return touch_pressed_; 537 return touch_pressed_;
536 } 538 }
537 539
538 } // namespace blink 540 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/input/TouchEventManager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698