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

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

Issue 2860663006: Remove WebTouchEvent from TouchEventManager APIs (Closed)
Patch Set: Handle the cases for inconsitent inputs 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
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 19 matching lines...) Expand all
30 return registry.HasEventHandlers( 30 return registry.HasEventHandlers(
31 EventHandlerRegistry::kTouchStartOrMoveEventBlocking) || 31 EventHandlerRegistry::kTouchStartOrMoveEventBlocking) ||
32 registry.HasEventHandlers( 32 registry.HasEventHandlers(
33 EventHandlerRegistry::kTouchStartOrMoveEventPassive) || 33 EventHandlerRegistry::kTouchStartOrMoveEventPassive) ||
34 registry.HasEventHandlers( 34 registry.HasEventHandlers(
35 EventHandlerRegistry::kTouchEndOrCancelEventBlocking) || 35 EventHandlerRegistry::kTouchEndOrCancelEventBlocking) ||
36 registry.HasEventHandlers( 36 registry.HasEventHandlers(
37 EventHandlerRegistry::kTouchEndOrCancelEventPassive); 37 EventHandlerRegistry::kTouchEndOrCancelEventPassive);
38 } 38 }
39 39
40 const AtomicString& TouchEventNameForTouchPointState( 40 const AtomicString& TouchEventNameForPointerEventType(
41 WebTouchPoint::State state) { 41 WebInputEvent::Type type) {
42 switch (state) { 42 switch (type) {
43 case WebTouchPoint::kStateReleased: 43 case WebInputEvent::kPointerUp:
44 return EventTypeNames::touchend; 44 return EventTypeNames::touchend;
45 case WebTouchPoint::kStateCancelled: 45 case WebInputEvent::kPointerCancel:
46 return EventTypeNames::touchcancel; 46 return EventTypeNames::touchcancel;
47 case WebTouchPoint::kStatePressed: 47 case WebInputEvent::kPointerDown:
48 return EventTypeNames::touchstart; 48 return EventTypeNames::touchstart;
49 case WebTouchPoint::kStateMoved: 49 case WebInputEvent::kPointerMove:
50 return EventTypeNames::touchmove; 50 return EventTypeNames::touchmove;
51 case WebTouchPoint::kStateStationary:
52 // Fall through to default
53 default: 51 default:
54 NOTREACHED(); 52 NOTREACHED();
55 return g_empty_atom; 53 return g_empty_atom;
56 } 54 }
57 } 55 }
58 56
59 enum TouchEventDispatchResultType { 57 enum TouchEventDispatchResultType {
60 kUnhandledTouches, // Unhandled touch events. 58 kUnhandledTouches, // Unhandled touch events.
61 kHandledTouches, // Handled touch events. 59 kHandledTouches, // Handled touch events.
62 kTouchEventDispatchResultTypeMax, 60 kTouchEventDispatchResultTypeMax,
63 }; 61 };
64 62
65 bool IsTouchSequenceStart(const WebTouchEvent& event) { 63 WebTouchPoint::State TouchPointStateFromPointerEventType(
66 if (!event.touches_length) 64 WebInputEvent::Type type,
67 return false; 65 bool stale) {
68 if (event.GetType() != WebInputEvent::kTouchStart) 66 if (stale)
69 return false; 67 return WebTouchPoint::kStateStationary;
70 for (size_t i = 0; i < event.touches_length; ++i) { 68 switch (type) {
71 if (event.touches[i].state != blink::WebTouchPoint::kStatePressed) 69 case WebInputEvent::Type::kPointerUp:
72 return false; 70 return WebTouchPoint::kStateReleased;
71 case WebInputEvent::Type::kPointerCancel:
72 return WebTouchPoint::kStateCancelled;
73 case WebInputEvent::Type::kPointerDown:
74 return WebTouchPoint::kStatePressed;
75 case WebInputEvent::Type::kPointerMove:
76 return WebTouchPoint::kStateMoved;
77 default:
78 NOTREACHED();
79 return WebTouchPoint::kStateUndefined;
73 } 80 }
74 return true;
75 } 81 }
76 82
77 // Defining this class type local to dispatchTouchEvents() and annotating 83 WebTouchPoint CreateWebTouchPointFromWebPointerEvent(
84 const WebPointerEvent& web_pointer_event,
85 bool stale) {
86 WebTouchPoint web_touch_point(web_pointer_event);
87 web_touch_point.state =
88 TouchPointStateFromPointerEventType(web_pointer_event.GetType(), stale);
89 // TODO(crbug.com/731725): This mapping needs a division by 2.
90 web_touch_point.radius_x = web_pointer_event.width;
dtapuska 2017/06/20 16:17:21 I'm not sure we can break this today can we? What
Navid Zolghadr 2017/06/20 16:33:00 It is already broken. I just kept the logic as bef
dtapuska 2017/06/20 16:44:03 No as explained offline to me. WebPointerEvent is
91 web_touch_point.radius_y = web_pointer_event.height;
92 web_touch_point.rotation_angle = web_pointer_event.rotation_angle;
93 return web_touch_point;
94 }
95
96 void SetWebTouchEventAttributesFromWebPointerEvent(
97 WebTouchEvent* web_touch_event,
98 const WebPointerEvent& web_pointer_event) {
99 web_touch_event->dispatch_type = web_pointer_event.dispatch_type;
100 web_touch_event->touch_start_or_first_touch_move =
101 web_pointer_event.touch_start_or_first_touch_move;
102 web_touch_event->moved_beyond_slop_region =
103 web_pointer_event.moved_beyond_slop_region;
104 web_touch_event->SetFrameScale(web_pointer_event.FrameScale());
105 web_touch_event->SetFrameTranslate(web_pointer_event.FrameTranslate());
106 web_touch_event->SetTimeStampSeconds(web_pointer_event.TimeStampSeconds());
107 web_touch_event->SetModifiers(web_pointer_event.GetModifiers());
108 }
109
110 // Defining this class type local to
111 // DispatchTouchEventFromAccumulatdTouchPoints() and annotating
78 // it with STACK_ALLOCATED(), runs into MSVC(VS 2013)'s C4822 warning 112 // it with STACK_ALLOCATED(), runs into MSVC(VS 2013)'s C4822 warning
79 // that the local class doesn't provide a local definition for 'operator new'. 113 // that the local class doesn't provide a local definition for 'operator new'.
80 // Which it intentionally doesn't and shouldn't. 114 // Which it intentionally doesn't and shouldn't.
81 // 115 //
82 // Work around such toolchain bugginess by lifting out the type, thereby 116 // Work around such toolchain bugginess by lifting out the type, thereby
83 // taking it out of C4822's reach. 117 // taking it out of C4822's reach.
84 class ChangedTouches final { 118 class ChangedTouches final {
85 STACK_ALLOCATED(); 119 STACK_ALLOCATED();
86 120
87 public: 121 public:
88 // The touches corresponding to the particular change state this struct 122 // The touches corresponding to the particular change state this struct
89 // instance represents. 123 // instance represents.
90 Member<TouchList> touches_; 124 Member<TouchList> touches_;
91 125
92 using EventTargetSet = HeapHashSet<Member<EventTarget>>; 126 using EventTargetSet = HeapHashSet<Member<EventTarget>>;
93 // Set of targets involved in m_touches. 127 // Set of targets involved in m_touches.
94 EventTargetSet targets_; 128 EventTargetSet targets_;
129 };
95 130
96 WebPointerProperties::PointerType pointer_type_; 131 void ReportMetricsForTouch(const WebPointerEvent& event,
97 }; 132 DispatchEventResult dom_dispatch_result,
133 bool prevent_default_called_on_uncancelable_event,
134 bool is_frame_loaded) {
135 int64_t latency_in_micros =
136 (TimeTicks::Now() - TimeTicks::FromSeconds(event.TimeStampSeconds()))
137 .InMicroseconds();
138 if (event.IsCancelable()) {
139 if (is_frame_loaded) {
140 DEFINE_STATIC_LOCAL(EnumerationHistogram,
141 touch_dispositions_after_page_load_histogram,
142 ("Event.Touch.TouchDispositionsAfterPageLoad",
143 kTouchEventDispatchResultTypeMax));
144 touch_dispositions_after_page_load_histogram.Count(
145 (dom_dispatch_result != DispatchEventResult::kNotCanceled)
146 ? kHandledTouches
147 : kUnhandledTouches);
148
149 DEFINE_STATIC_LOCAL(
150 CustomCountHistogram, event_latency_after_page_load_histogram,
151 ("Event.Touch.TouchLatencyAfterPageLoad", 1, 100000000, 50));
152 event_latency_after_page_load_histogram.Count(latency_in_micros);
153 } else {
154 DEFINE_STATIC_LOCAL(EnumerationHistogram,
155 touch_dispositions_before_page_load_histogram,
156 ("Event.Touch.TouchDispositionsBeforePageLoad",
157 kTouchEventDispatchResultTypeMax));
158 touch_dispositions_before_page_load_histogram.Count(
159 (dom_dispatch_result != DispatchEventResult::kNotCanceled)
160 ? kHandledTouches
161 : kUnhandledTouches);
162
163 DEFINE_STATIC_LOCAL(
164 CustomCountHistogram, event_latency_before_page_load_histogram,
165 ("Event.Touch.TouchLatencyBeforePageLoad", 1, 100000000, 50));
166 event_latency_before_page_load_histogram.Count(latency_in_micros);
167 }
168 // Report the touch disposition there is no active fling animation.
169 DEFINE_STATIC_LOCAL(EnumerationHistogram,
170 touch_dispositions_outside_fling_histogram,
171 ("Event.Touch.TouchDispositionsOutsideFling2",
172 kTouchEventDispatchResultTypeMax));
173 touch_dispositions_outside_fling_histogram.Count(
174 (dom_dispatch_result != DispatchEventResult::kNotCanceled)
175 ? kHandledTouches
176 : kUnhandledTouches);
177 }
178
179 // Report the touch disposition when there is an active fling
180 // animation.
181 if (event.dispatch_type ==
182 WebInputEvent::kListenersForcedNonBlockingDueToFling) {
183 DEFINE_STATIC_LOCAL(EnumerationHistogram,
184 touch_dispositions_during_fling_histogram,
185 ("Event.Touch.TouchDispositionsDuringFling2",
186 kTouchEventDispatchResultTypeMax));
187 touch_dispositions_during_fling_histogram.Count(
188 prevent_default_called_on_uncancelable_event ? kHandledTouches
189 : kUnhandledTouches);
190 }
191 }
98 192
99 } // namespace 193 } // namespace
100 194
101 TouchEventManager::TouchEventManager(LocalFrame& frame) : frame_(frame) { 195 TouchEventManager::TouchEventManager(LocalFrame& frame) : frame_(frame) {
102 Clear(); 196 Clear();
103 } 197 }
104 198
105 void TouchEventManager::Clear() { 199 void TouchEventManager::Clear() {
106 touch_sequence_document_.Clear(); 200 touch_sequence_document_.Clear();
107 target_for_touch_id_.clear(); 201 touch_attribute_map_.clear();
108 region_for_touch_id_.clear(); 202 last_coalesced_touch_event_ = WebTouchEvent();
109 touch_pressed_ = false;
110 suppressing_touchmoves_within_slop_ = false; 203 suppressing_touchmoves_within_slop_ = false;
111 current_touch_action_ = TouchAction::kTouchActionAuto; 204 current_touch_action_ = TouchAction::kTouchActionAuto;
112 } 205 }
113 206
114 DEFINE_TRACE(TouchEventManager) { 207 DEFINE_TRACE(TouchEventManager) {
115 visitor->Trace(frame_); 208 visitor->Trace(frame_);
116 visitor->Trace(touch_sequence_document_); 209 visitor->Trace(touch_sequence_document_);
117 visitor->Trace(target_for_touch_id_); 210 visitor->Trace(touch_attribute_map_);
118 } 211 }
119 212
120 Touch* TouchEventManager::CreateDomTouch(const WebTouchPoint& point, 213 Touch* TouchEventManager::CreateDomTouch(
121 bool* known_target) { 214 const TouchEventManager::TouchPointAttributes* point_attr,
122 Node* touch_node = nullptr; 215 bool* known_target) {
123 String region_id; 216 Node* touch_node = point_attr->target_;
217 String region_id = point_attr->region_;
124 *known_target = false; 218 *known_target = false;
125 FloatPoint content_point; 219 FloatPoint content_point;
126 FloatSize adjusted_radius; 220 FloatSize adjusted_radius;
127 221
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; 222 LocalFrame* target_frame = nullptr;
143 if (touch_node) { 223 if (touch_node) {
144 Document& doc = touch_node->GetDocument(); 224 Document& doc = touch_node->GetDocument();
145 // If the target node has moved to a new document while it was being 225 // 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 226 // 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. 227 // leak nodes from one document to another. See http://crbug.com/394339.
148 if (&doc == touch_sequence_document_.Get()) { 228 if (&doc == touch_sequence_document_.Get()) {
149 target_frame = doc.GetFrame(); 229 target_frame = doc.GetFrame();
150 *known_target = true; 230 *known_target = true;
151 } 231 }
(...skipping 10 matching lines...) Expand all
162 // Document so that there's some valid node here. Perhaps this 242 // Document so that there's some valid node here. Perhaps this
163 // should really be LocalDOMWindow, but in all other cases the target of 243 // 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. 244 // 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 245 // Since we know there was no handler invoked, the specific target
166 // should be completely irrelevant to the application. 246 // should be completely irrelevant to the application.
167 touch_node = touch_sequence_document_; 247 touch_node = touch_sequence_document_;
168 target_frame = touch_sequence_document_->GetFrame(); 248 target_frame = touch_sequence_document_->GetFrame();
169 } 249 }
170 DCHECK(target_frame); 250 DCHECK(target_frame);
171 251
252 WebPointerEvent transformed_event =
253 point_attr->event_.WebPointerEventInRootFrame();
172 // pagePoint should always be in the target element's document coordinates. 254 // pagePoint should always be in the target element's document coordinates.
173 FloatPoint page_point = 255 FloatPoint page_point = target_frame->View()->RootFrameToContents(
174 target_frame->View()->RootFrameToContents(point.PositionInWidget()); 256 transformed_event.PositionInWidget());
175 float scale_factor = 1.0f / target_frame->PageZoomFactor(); 257 float scale_factor = 1.0f / target_frame->PageZoomFactor();
176 258
177 content_point = page_point.ScaledBy(scale_factor); 259 content_point = page_point.ScaledBy(scale_factor);
178 adjusted_radius = 260 adjusted_radius = FloatSize(transformed_event.width, transformed_event.height)
179 FloatSize(point.radius_x, point.radius_y).ScaledBy(scale_factor); 261 .ScaledBy(scale_factor);
180 262
181 return Touch::Create(target_frame, touch_node, point.id, 263 return Touch::Create(target_frame, touch_node, point_attr->event_.id,
182 point.PositionInScreen(), content_point, adjusted_radius, 264 transformed_event.PositionInScreen(), content_point,
183 point.rotation_angle, point.force, region_id); 265 adjusted_radius, transformed_event.rotation_angle,
266 transformed_event.force, region_id);
184 } 267 }
185 268
186 WebInputEventResult TouchEventManager::DispatchTouchEvents( 269 WebCoalescedInputEvent TouchEventManager::GenerateWebCoalescedInputEvent() {
187 const WebTouchEvent& event, 270 DCHECK(!touch_attribute_map_.IsEmpty());
188 const Vector<WebTouchEvent>& coalesced_events, 271
189 bool all_touches_released) { 272 WebTouchEvent event;
273
274 const auto& first_touch_pointer_event =
275 touch_attribute_map_.begin()->value->event_;
276
277 SetWebTouchEventAttributesFromWebPointerEvent(&event,
278 first_touch_pointer_event);
279 SetWebTouchEventAttributesFromWebPointerEvent(&last_coalesced_touch_event_,
280 first_touch_pointer_event);
281 WebInputEvent::Type touch_event_type = WebInputEvent::kTouchMove;
282 Vector<WebPointerEvent> all_coalesced_events;
283 Vector<int> available_ids;
284 for (const auto& id : touch_attribute_map_.Keys())
285 available_ids.push_back(id);
286 std::sort(available_ids.begin(), available_ids.end());
287 for (const int& touch_point_id : available_ids) {
288 const auto& touch_point_attribute = touch_attribute_map_.at(touch_point_id);
289 const WebPointerEvent& touch_pointer_event = touch_point_attribute->event_;
290 event.touches[event.touches_length++] =
291 CreateWebTouchPointFromWebPointerEvent(touch_pointer_event,
292 touch_point_attribute->stale_);
293
294 // Only change the touch event type from move. So if we have two pointers
295 // in up and down state we just set the touch event type to the first one
296 // we see.
297 // TODO(crbug.com/732842): Note that event sender API allows sending any
298 // mix of input and as long as we don't crash or anything we should be good
299 // for now.
300 if (touch_event_type == WebInputEvent::kTouchMove) {
301 if (touch_pointer_event.GetType() == WebInputEvent::kPointerDown)
302 touch_event_type = WebInputEvent::kTouchStart;
303 else if (touch_pointer_event.GetType() == WebInputEvent::kPointerCancel)
304 touch_event_type = WebInputEvent::kTouchCancel;
305 else if (touch_pointer_event.GetType() == WebInputEvent::kPointerUp)
306 touch_event_type = WebInputEvent::kTouchEnd;
307 }
308
309 for (const WebPointerEvent& coalesced_event :
310 touch_point_attribute->coalesced_events_)
dtapuska 2017/06/20 16:17:21 Need brackets...
Navid Zolghadr 2017/06/20 16:33:00 I don't think it does. The line inside the for loo
dtapuska 2017/06/20 16:44:03 Generally if the condition/loop wraps onto more th
Navid Zolghadr 2017/06/20 17:59:15 Done.
311 all_coalesced_events.push_back(coalesced_event);
312 }
313 event.SetType(touch_event_type);
314 last_coalesced_touch_event_.SetType(touch_event_type);
315
316 // Create all coalesced touch events based on pointerevents
317 struct {
318 bool operator()(const WebPointerEvent& a, const WebPointerEvent& b) {
319 return a.TimeStampSeconds() < b.TimeStampSeconds();
320 }
321 } timestamp_based_event_comparison;
322 std::sort(all_coalesced_events.begin(), all_coalesced_events.end(),
323 timestamp_based_event_comparison);
324 WebCoalescedInputEvent result(event, std::vector<const WebInputEvent*>());
325 for (const auto& web_pointer_event : all_coalesced_events) {
326 if (web_pointer_event.GetType() == WebInputEvent::kPointerDown) {
327 // TODO(crbug.com/732842): Technically we should never receive the
328 // pointerdown twice for the same touch point. But event sender API allows
329 // that. So we should handle it gracefully.
330 WebTouchPoint web_touch_point(web_pointer_event);
331 bool found_existing_id = false;
332 for (unsigned i = 0; i < last_coalesced_touch_event_.touches_length;
333 ++i) {
334 if (last_coalesced_touch_event_.touches[i].id == web_pointer_event.id) {
335 last_coalesced_touch_event_.touches[i] =
336 CreateWebTouchPointFromWebPointerEvent(web_pointer_event, false);
337 found_existing_id = true;
338 break;
339 }
340 }
341 // If the pointerdown point didn't exist add a new point to the array.
342 if (!found_existing_id) {
343 last_coalesced_touch_event_
344 .touches[last_coalesced_touch_event_.touches_length++] =
345 CreateWebTouchPointFromWebPointerEvent(web_pointer_event, false);
346 }
347 struct {
348 bool operator()(const WebTouchPoint& a, const WebTouchPoint& b) {
349 return a.id < b.id;
350 }
351 } id_based_event_comparison;
352 std::sort(last_coalesced_touch_event_.touches,
353 last_coalesced_touch_event_.touches +
354 last_coalesced_touch_event_.touches_length,
355 id_based_event_comparison);
356 result.AddCoalescedEvent(last_coalesced_touch_event_);
357 } else {
358 for (unsigned i = 0; i < last_coalesced_touch_event_.touches_length;
359 ++i) {
360 if (last_coalesced_touch_event_.touches[i].id == web_pointer_event.id) {
361 last_coalesced_touch_event_.touches[i].movement_x =
362 web_pointer_event.movement_x;
363 last_coalesced_touch_event_.touches[i].movement_y =
364 web_pointer_event.movement_y;
365 last_coalesced_touch_event_.SetTimeStampSeconds(
366 web_pointer_event.TimeStampSeconds());
367 last_coalesced_touch_event_.touches[i].state =
368 TouchPointStateFromPointerEventType(web_pointer_event.GetType(),
369 false);
370 result.AddCoalescedEvent(last_coalesced_touch_event_);
371
372 // Remove up and canceled points.
373 unsigned result_size = 0;
374 for (unsigned i = 0; i < last_coalesced_touch_event_.touches_length;
375 i++) {
dtapuska 2017/06/20 16:17:21 This loop uses the same variable name as the outsi
Navid Zolghadr 2017/06/20 17:59:15 Done.
376 if (last_coalesced_touch_event_.touches[i].state !=
377 WebTouchPoint::kStateCancelled &&
378 last_coalesced_touch_event_.touches[i].state !=
379 WebTouchPoint::kStateReleased) {
380 last_coalesced_touch_event_.touches[result_size++] =
381 last_coalesced_touch_event_.touches[i];
382 }
383 }
384 last_coalesced_touch_event_.touches_length = result_size;
385 break;
386 }
387 }
388 }
389
390 for (unsigned i = 0; i < event.touches_length; ++i) {
391 event.touches[i].state = blink::WebTouchPoint::kStateStationary;
392 event.touches[i].movement_x = 0;
393 event.touches[i].movement_y = 0;
394 }
395 }
396
397 return result;
398 }
399
400 WebInputEventResult
401 TouchEventManager::DispatchTouchEventFromAccumulatdTouchPoints() {
190 // Build up the lists to use for the |touches|, |targetTouches| and 402 // Build up the lists to use for the |touches|, |targetTouches| and
191 // |changedTouches| attributes in the JS event. See 403 // |changedTouches| attributes in the JS event. See
192 // http://www.w3.org/TR/touch-events/#touchevent-interface for how these 404 // http://www.w3.org/TR/touch-events/#touchevent-interface for how these
193 // lists fit together. 405 // lists fit together.
194 406
195 if (event.GetType() == WebInputEvent::kTouchEnd || 407 bool new_touch_point_since_last_dispatch = false;
196 event.GetType() == WebInputEvent::kTouchCancel || 408 bool any_touch_canceled_or_ended = false;
197 event.touches_length > 1) { 409 bool all_touch_points_pressed = true;
198 suppressing_touchmoves_within_slop_ = false; 410
411 for (const auto& attr : touch_attribute_map_.Values()) {
412 if (!attr->stale_)
413 new_touch_point_since_last_dispatch = true;
414 if (attr->event_.GetType() == WebInputEvent::kPointerUp ||
415 attr->event_.GetType() == WebInputEvent::kPointerCancel)
416 any_touch_canceled_or_ended = true;
417 if (attr->event_.GetType() != WebInputEvent::kPointerDown)
418 all_touch_points_pressed = false;
199 } 419 }
200 420
201 if (suppressing_touchmoves_within_slop_ && 421 if (!new_touch_point_since_last_dispatch)
202 event.GetType() == WebInputEvent::kTouchMove) { 422 return WebInputEventResult::kNotHandled;
203 if (!event.moved_beyond_slop_region) 423
204 return WebInputEventResult::kHandledSuppressed; 424 if (any_touch_canceled_or_ended || touch_attribute_map_.size() > 1)
205 suppressing_touchmoves_within_slop_ = false; 425 suppressing_touchmoves_within_slop_ = false;
426
427 if (suppressing_touchmoves_within_slop_) {
428 // There is exactly one touch point here otherwise
429 // |suppressing_touchmoves_within_slop_| would have been false.
430 DCHECK_EQ(1U, touch_attribute_map_.size());
431 const auto& touch_point_attribute = touch_attribute_map_.begin()->value;
432 if (touch_point_attribute->event_.GetType() ==
433 WebInputEvent::kPointerMove) {
434 if (!touch_point_attribute->event_.moved_beyond_slop_region)
435 return WebInputEventResult::kHandledSuppressed;
436 suppressing_touchmoves_within_slop_ = false;
437 }
206 } 438 }
207 439
208 // Holds the complete set of touches on the screen. 440 // Holds the complete set of touches on the screen.
209 TouchList* touches = TouchList::Create(); 441 TouchList* touches = TouchList::Create();
210 442
211 // A different view on the 'touches' list above, filtered and grouped by 443 // A different view on the 'touches' list above, filtered and grouped by
212 // event target. Used for the |targetTouches| list in the JS event. 444 // event target. Used for the |targetTouches| list in the JS event.
213 using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>; 445 using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>;
214 TargetTouchesHeapMap touches_by_target; 446 TargetTouchesHeapMap touches_by_target;
215 447
216 // Array of touches per state, used to assemble the |changedTouches| list. 448 // Array of touches per state, used to assemble the |changedTouches| list.
217 ChangedTouches changed_touches[WebTouchPoint::kStateMax + 1]; 449 ChangedTouches changed_touches[WebInputEvent::kPointerTypeLast -
450 WebInputEvent::kPointerTypeFirst + 1];
218 451
219 for (unsigned touch_point_idx = 0; touch_point_idx < event.touches_length; 452 Vector<int> available_ids;
220 touch_point_idx++) { 453 for (const auto& id : touch_attribute_map_.Keys())
221 const WebTouchPoint& point = event.TouchPointInRootFrame(touch_point_idx); 454 available_ids.push_back(id);
222 WebTouchPoint::State point_state = point.state; 455 std::sort(available_ids.begin(), available_ids.end());
456 for (const int& touch_point_id : available_ids) {
457 const auto& touch_point_attribute = touch_attribute_map_.at(touch_point_id);
458 WebInputEvent::Type event_type = touch_point_attribute->event_.GetType();
223 bool known_target; 459 bool known_target;
224 460
225 Touch* touch = CreateDomTouch(point, &known_target); 461 Touch* touch = CreateDomTouch(touch_point_attribute, &known_target);
226 EventTarget* touch_target = touch->target(); 462 EventTarget* touch_target = touch->target();
227 463
228 // Ensure this target's touch list exists, even if it ends up empty, so 464 // Ensure this target's touch list exists, even if it ends up empty, so
229 // it can always be passed to TouchEvent::Create below. 465 // it can always be passed to TouchEvent::Create below.
230 TargetTouchesHeapMap::iterator target_touches_iterator = 466 TargetTouchesHeapMap::iterator target_touches_iterator =
231 touches_by_target.find(touch_target); 467 touches_by_target.find(touch_target);
232 if (target_touches_iterator == touches_by_target.end()) { 468 if (target_touches_iterator == touches_by_target.end()) {
233 touches_by_target.Set(touch_target, TouchList::Create()); 469 touches_by_target.Set(touch_target, TouchList::Create());
234 target_touches_iterator = touches_by_target.find(touch_target); 470 target_touches_iterator = touches_by_target.find(touch_target);
235 } 471 }
236 472
237 // |touches| and |targetTouches| should only contain information about 473 // |touches| and |targetTouches| should only contain information about
238 // touches still on the screen, so if this point is released or 474 // touches still on the screen, so if this point is released or
239 // cancelled it will only appear in the |changedTouches| list. 475 // cancelled it will only appear in the |changedTouches| list.
240 if (point_state != WebTouchPoint::kStateReleased && 476 if (event_type != WebInputEvent::kPointerUp &&
241 point_state != WebTouchPoint::kStateCancelled) { 477 event_type != WebInputEvent::kPointerCancel) {
242 touches->Append(touch); 478 touches->Append(touch);
243 target_touches_iterator->value->Append(touch); 479 target_touches_iterator->value->Append(touch);
244 } 480 }
245 481
246 // Now build up the correct list for |changedTouches|. 482 // Now build up the correct list for |changedTouches|.
247 // Note that any touches that are in the TouchStationary state (e.g. if 483 // Note that any touches that are in the TouchStationary state (e.g. if
248 // the user had several points touched but did not move them all) should 484 // the user had several points touched but did not move them all) should
249 // never be in the |changedTouches| list so we do not handle them 485 // never be in the |changedTouches| list so we do not handle them
250 // explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609 486 // explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609
251 // for further discussion about the TouchStationary state. 487 // for further discussion about the TouchStationary state.
252 if (point_state != WebTouchPoint::kStateStationary && known_target) { 488 if (!touch_point_attribute->stale_ && known_target) {
253 DCHECK_LE(point_state, WebTouchPoint::kStateMax); 489 size_t event_type_idx = event_type - WebInputEvent::kPointerTypeFirst;
254 if (!changed_touches[point_state].touches_) 490 if (!changed_touches[event_type_idx].touches_)
255 changed_touches[point_state].touches_ = TouchList::Create(); 491 changed_touches[event_type_idx].touches_ = TouchList::Create();
256 changed_touches[point_state].touches_->Append(touch); 492 changed_touches[event_type_idx].touches_->Append(touch);
257 changed_touches[point_state].targets_.insert(touch_target); 493 changed_touches[event_type_idx].targets_.insert(touch_target);
258 changed_touches[point_state].pointer_type_ = point.pointer_type;
259 } 494 }
260 } 495 }
261 496
262 if (all_touches_released) { 497 WebInputEventResult event_result = WebInputEventResult::kNotHandled;
263 touch_sequence_document_.Clear();
264 current_touch_action_ = TouchAction::kTouchActionAuto;
265 }
266 498
267 WebInputEventResult event_result = WebInputEventResult::kNotHandled; 499 // First we construct the webcoalescedinputevent containing all the coalesced
268 // First we construct the webcoalescedinputevent contains all the coalesced
269 // touch event. 500 // touch event.
270 std::vector<const WebInputEvent*> coalesced_touches; 501 WebCoalescedInputEvent coalesced_event = GenerateWebCoalescedInputEvent();
271 for (size_t i = 0; i < coalesced_events.size(); ++i) {
272 coalesced_touches.push_back(&coalesced_events[i]);
273 }
274 WebCoalescedInputEvent coalesced_event(event, coalesced_touches);
275 502
276 // Now iterate through the |changedTouches| list and |m_targets| within it, 503 // Now iterate through the |changedTouches| list and |m_targets| within it,
277 // sending TouchEvents to the targets as required. 504 // sending TouchEvents to the targets as required.
278 for (unsigned state = 0; state <= WebTouchPoint::kStateMax; ++state) { 505 for (unsigned action = WebInputEvent::kPointerTypeFirst;
279 if (!changed_touches[state].touches_) 506 action <= WebInputEvent::kPointerTypeLast; ++action) {
507 size_t action_idx = action - WebInputEvent::kPointerTypeFirst;
508 if (!changed_touches[action_idx].touches_)
280 continue; 509 continue;
281 510
282 const AtomicString& event_name(TouchEventNameForTouchPointState( 511 const AtomicString& event_name(TouchEventNameForPointerEventType(
283 static_cast<WebTouchPoint::State>(state))); 512 static_cast<WebInputEvent::Type>(action)));
284 for (const auto& event_target : changed_touches[state].targets_) { 513
514 for (const auto& event_target : changed_touches[action_idx].targets_) {
285 EventTarget* touch_event_target = event_target; 515 EventTarget* touch_event_target = event_target;
286 TouchEvent* touch_event = TouchEvent::Create( 516 TouchEvent* touch_event = TouchEvent::Create(
287 coalesced_event, touches, touches_by_target.at(touch_event_target), 517 coalesced_event, touches, touches_by_target.at(touch_event_target),
288 changed_touches[state].touches_.Get(), event_name, 518 changed_touches[action_idx].touches_.Get(), event_name,
289 touch_event_target->ToNode()->GetDocument().domWindow(), 519 touch_event_target->ToNode()->GetDocument().domWindow(),
290 current_touch_action_); 520 current_touch_action_);
291 521
292 DispatchEventResult dom_dispatch_result = 522 DispatchEventResult dom_dispatch_result =
293 touch_event_target->DispatchEvent(touch_event); 523 touch_event_target->DispatchEvent(touch_event);
294 524
295 // Only report for top level documents with a single touch on 525 // Only report for top level documents with a single touch on
296 // touch-start or the first touch-move. 526 // touch-start or the first touch-move.
297 if (event.touch_start_or_first_touch_move && event.touches_length == 1 && 527 if (touch_attribute_map_.size() == 1 && frame_->IsMainFrame()) {
298 frame_->IsMainFrame()) { 528 const auto& event = touch_attribute_map_.begin()->value->event_;
299 // Record the disposition and latency of touch starts and first touch 529 if (event.touch_start_or_first_touch_move) {
300 // moves before and after the page is fully loaded respectively. 530 // Record the disposition and latency of touch starts and first touch
301 int64_t latency_in_micros = 531 // moves before and after the page is fully loaded respectively.
302 (TimeTicks::Now() - 532 ReportMetricsForTouch(
303 TimeTicks::FromSeconds(event.TimeStampSeconds())) 533 event, dom_dispatch_result,
304 .InMicroseconds(); 534 touch_event->PreventDefaultCalledOnUncancelableEvent(),
305 if (event.IsCancelable()) { 535 frame_->GetDocument()->IsLoadCompleted());
306 if (frame_->GetDocument()->IsLoadCompleted()) {
307 DEFINE_STATIC_LOCAL(EnumerationHistogram,
308 touch_dispositions_after_page_load_histogram,
309 ("Event.Touch.TouchDispositionsAfterPageLoad",
310 kTouchEventDispatchResultTypeMax));
311 touch_dispositions_after_page_load_histogram.Count(
312 (dom_dispatch_result != DispatchEventResult::kNotCanceled)
313 ? kHandledTouches
314 : kUnhandledTouches);
315
316 DEFINE_STATIC_LOCAL(
317 CustomCountHistogram, event_latency_after_page_load_histogram,
318 ("Event.Touch.TouchLatencyAfterPageLoad", 1, 100000000, 50));
319 event_latency_after_page_load_histogram.Count(latency_in_micros);
320 } else {
321 DEFINE_STATIC_LOCAL(EnumerationHistogram,
322 touch_dispositions_before_page_load_histogram,
323 ("Event.Touch.TouchDispositionsBeforePageLoad",
324 kTouchEventDispatchResultTypeMax));
325 touch_dispositions_before_page_load_histogram.Count(
326 (dom_dispatch_result != DispatchEventResult::kNotCanceled)
327 ? kHandledTouches
328 : kUnhandledTouches);
329
330 DEFINE_STATIC_LOCAL(
331 CustomCountHistogram, event_latency_before_page_load_histogram,
332 ("Event.Touch.TouchLatencyBeforePageLoad", 1, 100000000, 50));
333 event_latency_before_page_load_histogram.Count(latency_in_micros);
334 }
335 // Report the touch disposition there is no active fling animation.
336 DEFINE_STATIC_LOCAL(EnumerationHistogram,
337 touch_dispositions_outside_fling_histogram,
338 ("Event.Touch.TouchDispositionsOutsideFling2",
339 kTouchEventDispatchResultTypeMax));
340 touch_dispositions_outside_fling_histogram.Count(
341 (dom_dispatch_result != DispatchEventResult::kNotCanceled)
342 ? kHandledTouches
343 : kUnhandledTouches);
344 }
345
346 // Report the touch disposition when there is an active fling animation.
347 if (event.dispatch_type ==
348 WebInputEvent::kListenersForcedNonBlockingDueToFling) {
349 DEFINE_STATIC_LOCAL(EnumerationHistogram,
350 touch_dispositions_during_fling_histogram,
351 ("Event.Touch.TouchDispositionsDuringFling2",
352 kTouchEventDispatchResultTypeMax));
353 touch_dispositions_during_fling_histogram.Count(
354 touch_event->PreventDefaultCalledOnUncancelableEvent()
355 ? kHandledTouches
356 : kUnhandledTouches);
357 } 536 }
358 } 537 }
359 event_result = EventHandlingUtil::MergeEventResult( 538 event_result = EventHandlingUtil::MergeEventResult(
360 event_result, 539 event_result,
361 EventHandlingUtil::ToWebInputEventResult(dom_dispatch_result)); 540 EventHandlingUtil::ToWebInputEventResult(dom_dispatch_result));
362 } 541 }
363 } 542 }
364 543
365 // Do not suppress any touchmoves if the touchstart is consumed. 544 // Suppress following touchmoves within the slop region if the touchstart is
366 if (IsTouchSequenceStart(event) && 545 // not consumed.
546 if (all_touch_points_pressed &&
367 event_result == WebInputEventResult::kNotHandled) { 547 event_result == WebInputEventResult::kNotHandled) {
368 suppressing_touchmoves_within_slop_ = true; 548 suppressing_touchmoves_within_slop_ = true;
369 } 549 }
370 550
371 return event_result; 551 return event_result;
372 } 552 }
373 553
374 void TouchEventManager::UpdateTargetAndRegionMapsForTouchStart( 554 void TouchEventManager::UpdateTouchAttributeMapsForPointerDown(
375 const WebTouchPoint& touch_point, 555 const WebPointerEvent& event,
376 const EventHandlingUtil::PointerEventTarget& pointer_event_target) { 556 const EventHandlingUtil::PointerEventTarget& pointer_event_target) {
377 // Touch events implicitly capture to the touched node, and don't change 557 // Touch events implicitly capture to the touched node, and don't change
378 // active/hover states themselves (Gesture events do). So we only need 558 // active/hover states themselves (Gesture events do). So we only need
379 // to hit-test on touchstart and when the target could be different than 559 // to hit-test on touchstart and when the target could be different than
380 // the corresponding pointer event target. 560 // the corresponding pointer event target.
381 DCHECK(touch_point.state == WebTouchPoint::kStatePressed); 561 DCHECK(event.GetType() == WebInputEvent::kPointerDown);
562 // Ideally we'd DCHECK(!touch_attribute_map_.Contains(event.id))
563 // since we shouldn't get a touchstart for a touch that's already
564 // down. However EventSender allows this to be violated and there's
565 // some tests that take advantage of it. There may also be edge
566 // cases in the browser where this happens.
567 // See http://crbug.com/345372.
568 touch_attribute_map_.Set(event.id, new TouchPointAttributes(event));
569
382 Node* touch_node = pointer_event_target.target_node; 570 Node* touch_node = pointer_event_target.target_node;
383 String region = pointer_event_target.region; 571 String region = pointer_event_target.region;
384 572
385 HitTestRequest::HitTestRequestType hit_type = HitTestRequest::kTouchEvent | 573 HitTestRequest::HitTestRequestType hit_type = HitTestRequest::kTouchEvent |
386 HitTestRequest::kReadOnly | 574 HitTestRequest::kReadOnly |
387 HitTestRequest::kActive; 575 HitTestRequest::kActive;
388 HitTestResult result; 576 HitTestResult result;
389 // For the touchPressed points hit-testing is done in 577 // For the touchPressed points hit-testing is done in
390 // PointerEventManager. If it was the second touch there is a 578 // PointerEventManager. If it was the second touch there is a
391 // capturing documents for the touch and |m_touchSequenceDocument| 579 // capturing documents for the touch and |m_touchSequenceDocument|
392 // is not null. So if PointerEventManager should hit-test again 580 // is not null. So if PointerEventManager should hit-test again
393 // against |m_touchSequenceDocument| if the target set by 581 // against |m_touchSequenceDocument| if the target set by
394 // PointerEventManager was either null or not in 582 // PointerEventManager was either null or not in
395 // |m_touchSequenceDocument|. 583 // |m_touchSequenceDocument|.
396 if (touch_sequence_document_ && 584 if (touch_sequence_document_ &&
397 (!touch_node || &touch_node->GetDocument() != touch_sequence_document_)) { 585 (!touch_node || &touch_node->GetDocument() != touch_sequence_document_)) {
398 if (touch_sequence_document_->GetFrame()) { 586 if (touch_sequence_document_->GetFrame()) {
399 LayoutPoint frame_point = LayoutPoint( 587 LayoutPoint frame_point = LayoutPoint(
400 touch_sequence_document_->GetFrame()->View()->RootFrameToContents( 588 touch_sequence_document_->GetFrame()->View()->RootFrameToContents(
401 touch_point.PositionInWidget())); 589 event.PositionInWidget()));
402 result = EventHandlingUtil::HitTestResultInFrame( 590 result = EventHandlingUtil::HitTestResultInFrame(
403 touch_sequence_document_->GetFrame(), frame_point, hit_type); 591 touch_sequence_document_->GetFrame(), frame_point, hit_type);
404 Node* node = result.InnerNode(); 592 Node* node = result.InnerNode();
405 if (!node) 593 if (!node)
406 return; 594 return;
407 if (isHTMLCanvasElement(node)) { 595 if (isHTMLCanvasElement(node)) {
408 HitTestCanvasResult* hit_test_canvas_result = 596 HitTestCanvasResult* hit_test_canvas_result =
409 toHTMLCanvasElement(node)->GetControlAndIdIfHitRegionExists( 597 toHTMLCanvasElement(node)->GetControlAndIdIfHitRegionExists(
410 result.PointInInnerNodeFrame()); 598 result.PointInInnerNodeFrame());
411 if (hit_test_canvas_result->GetControl()) 599 if (hit_test_canvas_result->GetControl())
(...skipping 11 matching lines...) Expand all
423 if (!touch_node) 611 if (!touch_node)
424 return; 612 return;
425 if (!touch_sequence_document_) { 613 if (!touch_sequence_document_) {
426 // Keep track of which document should receive all touch events 614 // Keep track of which document should receive all touch events
427 // in the active sequence. This must be a single document to 615 // in the active sequence. This must be a single document to
428 // ensure we don't leak Nodes between documents. 616 // ensure we don't leak Nodes between documents.
429 touch_sequence_document_ = &(touch_node->GetDocument()); 617 touch_sequence_document_ = &(touch_node->GetDocument());
430 DCHECK(touch_sequence_document_->GetFrame()->View()); 618 DCHECK(touch_sequence_document_->GetFrame()->View());
431 } 619 }
432 620
433 // Ideally we'd DCHECK(!m_targetForTouchID.contains(point.id()) 621 TouchPointAttributes* attributes = touch_attribute_map_.at(event.id);
434 // since we shouldn't get a touchstart for a touch that's already 622 attributes->target_ = touch_node;
435 // down. However EventSender allows this to be violated and there's 623 attributes->region_ = region;
436 // some tests that take advantage of it. There may also be edge
437 // cases in the browser where this happens.
438 // See http://crbug.com/345372.
439 target_for_touch_id_.Set(touch_point.id, touch_node);
440
441 region_for_touch_id_.Set(touch_point.id, region);
442 624
443 TouchAction effective_touch_action = 625 TouchAction effective_touch_action =
444 TouchActionUtil::ComputeEffectiveTouchAction(*touch_node); 626 TouchActionUtil::ComputeEffectiveTouchAction(*touch_node);
445 if (effective_touch_action != TouchAction::kTouchActionAuto) { 627 if (effective_touch_action != TouchAction::kTouchActionAuto) {
446 frame_->GetPage()->GetChromeClient().SetTouchAction(frame_, 628 frame_->GetPage()->GetChromeClient().SetTouchAction(frame_,
447 effective_touch_action); 629 effective_touch_action);
448 630
449 // Combine the current touch action sequence with the touch action 631 // Combine the current touch action sequence with the touch action
450 // for the current finger press. 632 // for the current finger press.
451 current_touch_action_ &= effective_touch_action; 633 current_touch_action_ &= effective_touch_action;
452 } 634 }
453 } 635 }
454 636
455 bool TouchEventManager::HitTestTouchPointsIfNeeded( 637 void TouchEventManager::HandleTouchPoint(
456 const WebTouchEvent& event, 638 const WebPointerEvent& event,
457 const HeapVector<EventHandlingUtil::PointerEventTarget>& 639 const Vector<WebPointerEvent>& coalesced_events,
458 pointer_event_targets) { 640 const EventHandlingUtil::PointerEventTarget& pointer_event_target) {
459 bool new_touch_sequence = true; 641 DCHECK_GE(event.GetType(), WebInputEvent::kPointerTypeFirst);
460 bool all_touches_released = true; 642 DCHECK_LE(event.GetType(), WebInputEvent::kPointerTypeLast);
461 643
462 for (unsigned i = 0; i < event.touches_length; ++i) { 644 if (touch_attribute_map_.IsEmpty()) {
463 WebTouchPoint::State state = event.touches[i].state;
464 if (state != WebTouchPoint::kStatePressed)
465 new_touch_sequence = false;
466 if (state != WebTouchPoint::kStateReleased &&
467 state != WebTouchPoint::kStateCancelled)
468 all_touches_released = false;
469 }
470 if (new_touch_sequence) {
471 // Ideally we'd DCHECK(!m_touchSequenceDocument) here since we should 645 // Ideally we'd DCHECK(!m_touchSequenceDocument) here since we should
472 // have cleared the active document when we saw the last release. But we 646 // have cleared the active document when we saw the last release. But we
473 // have some tests that violate this, ClusterFuzz could trigger it, and 647 // have some tests that violate this, ClusterFuzz could trigger it, and
474 // there may be cases where the browser doesn't reliably release all 648 // there may be cases where the browser doesn't reliably release all
475 // touches. http://crbug.com/345372 tracks this. 649 // touches. http://crbug.com/345372 tracks this.
476 touch_sequence_document_.Clear(); 650 allTouchesReleasedCleanup();
477 } 651 }
478 652
479 DCHECK(frame_->View()); 653 DCHECK(frame_->View());
480 if (touch_sequence_document_ && 654 if (touch_sequence_document_ &&
481 (!touch_sequence_document_->GetFrame() || 655 (!touch_sequence_document_->GetFrame() ||
482 !touch_sequence_document_->GetFrame()->View())) { 656 !touch_sequence_document_->GetFrame()->View())) {
483 // If the active touch document has no frame or view, it's probably being 657 // If the active touch document has no frame or view, it's probably being
484 // destroyed so we can't dispatch events. 658 // destroyed so we can't dispatch events.
485 return false; 659 return;
486 } 660 }
487 661
488 for (unsigned i = 0; i < event.touches_length; ++i) { 662 // In touch event model only touch starts can set the target and after that
489 // In touch event model only touch starts can set the target and after that 663 // the touch event always goes to that target.
490 // the touch event always goes to that target. 664 if (event.GetType() == WebInputEvent::kPointerDown) {
491 if (event.touches[i].state == WebTouchPoint::kStatePressed) { 665 UpdateTouchAttributeMapsForPointerDown(event, pointer_event_target);
492 UpdateTargetAndRegionMapsForTouchStart(event.TouchPointInRootFrame(i),
493 pointer_event_targets[i]);
494 }
495 } 666 }
496 667
497 touch_pressed_ = !all_touches_released; 668 // We might not receive the down action for a touch point. In that case we
669 // would have never added them to |touch_attribute_map_| or hit-tested
670 // them. For those just keep them in the map with a null target. Later they
671 // will be targeted at the |touch_sequence_document_|.
672 if (!touch_attribute_map_.Contains(event.id)) {
673 touch_attribute_map_.insert(event.id, new TouchPointAttributes(event));
674 }
675
676 TouchPointAttributes* attributes = touch_attribute_map_.at(event.id);
677 attributes->event_ = event;
678 attributes->coalesced_events_ = coalesced_events;
679 attributes->stale_ = false;
680 }
681
682 WebInputEventResult TouchEventManager::FlushEvents() {
683 WebInputEventResult result = WebInputEventResult::kNotHandled;
498 684
499 // If there's no document receiving touch events, or no handlers on the 685 // If there's no document receiving touch events, or no handlers on the
500 // document set to receive the events, then we can skip all the rest of 686 // document set to receive the events, then we can skip all the rest of
501 // this work. 687 // sending the event.
502 if (!touch_sequence_document_ || !touch_sequence_document_->GetPage() || 688 if (touch_sequence_document_ && touch_sequence_document_->GetPage() &&
503 !HasTouchHandlers( 689 HasTouchHandlers(
504 touch_sequence_document_->GetPage()->GetEventHandlerRegistry()) || 690 touch_sequence_document_->GetPage()->GetEventHandlerRegistry()) &&
505 !touch_sequence_document_->GetFrame()) { 691 touch_sequence_document_->GetFrame() &&
506 if (all_touches_released) { 692 touch_sequence_document_->GetFrame()->View()) {
507 touch_sequence_document_.Clear(); 693 result = DispatchTouchEventFromAccumulatdTouchPoints();
508 }
509 return false;
510 } 694 }
511 695
512 return true; 696 // Cleanup the |touch_attribute_map_| map from released and canceled
697 // touch points.
698 Vector<int> releasedCanceledPoints;
dtapuska 2017/06/20 16:17:21 s/releasedCanceledPoints/released_canceled_points
Navid Zolghadr 2017/06/20 17:59:15 Done.
699 for (auto& attributes : touch_attribute_map_.Values()) {
700 if (attributes->event_.GetType() == WebInputEvent::kPointerUp ||
701 attributes->event_.GetType() == WebInputEvent::kPointerCancel) {
702 releasedCanceledPoints.push_back(attributes->event_.id);
703 } else {
704 attributes->stale_ = true;
705 attributes->event_.movement_x = 0;
706 attributes->event_.movement_y = 0;
707 attributes->coalesced_events_.clear();
708 }
709 }
710 touch_attribute_map_.RemoveAll(releasedCanceledPoints);
711
712 if (touch_attribute_map_.IsEmpty()) {
713 allTouchesReleasedCleanup();
714 }
715
716 return result;
513 } 717 }
514 718
515 WebInputEventResult TouchEventManager::HandleTouchEvent( 719 void TouchEventManager::allTouchesReleasedCleanup() {
dtapuska 2017/06/20 16:17:21 s/all/All
Navid Zolghadr 2017/06/20 17:59:15 Done.
516 const WebTouchEvent& event, 720 touch_sequence_document_.Clear();
517 const Vector<WebTouchEvent>& coalesced_events, 721 current_touch_action_ = TouchAction::kTouchActionAuto;
518 const HeapVector<EventHandlingUtil::PointerEventTarget>& 722 last_coalesced_touch_event_ = WebTouchEvent();
519 pointer_event_targets) {
520 DCHECK(event.touches_length == pointer_event_targets.size());
521
522 if (!HitTestTouchPointsIfNeeded(event, pointer_event_targets))
523 return WebInputEventResult::kNotHandled;
524
525 bool all_touches_released = true;
526 for (unsigned i = 0; i < event.touches_length; ++i) {
527 WebTouchPoint::State state = event.touches[i].state;
528 if (state != WebTouchPoint::kStateReleased &&
529 state != WebTouchPoint::kStateCancelled)
530 all_touches_released = false;
531 }
532
533 return DispatchTouchEvents(event, coalesced_events, all_touches_released);
534 } 723 }
535 724
536 bool TouchEventManager::IsAnyTouchActive() const { 725 bool TouchEventManager::IsAnyTouchActive() const {
537 return touch_pressed_; 726 return !touch_attribute_map_.IsEmpty();
538 } 727 }
539 728
540 } // namespace blink 729 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/input/TouchEventManager.h ('k') | third_party/WebKit/Source/platform/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698