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

Unified Diff: third_party/WebKit/Source/core/input/TouchEventManager.cpp

Issue 2860663006: Remove WebTouchEvent from TouchEventManager APIs (Closed)
Patch Set: Apply the comments 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/input/TouchEventManager.cpp
diff --git a/third_party/WebKit/Source/core/input/TouchEventManager.cpp b/third_party/WebKit/Source/core/input/TouchEventManager.cpp
index 6f6476f60c4d100c5cb68e7b6be1f0963f8a3882..970d58c096739eff0266fee82871377da685bb5b 100644
--- a/third_party/WebKit/Source/core/input/TouchEventManager.cpp
+++ b/third_party/WebKit/Source/core/input/TouchEventManager.cpp
@@ -37,19 +37,17 @@ bool HasTouchHandlers(const EventHandlerRegistry& registry) {
EventHandlerRegistry::kTouchEndOrCancelEventPassive);
}
-const AtomicString& TouchEventNameForTouchPointState(
- WebTouchPoint::State state) {
- switch (state) {
- case WebTouchPoint::kStateReleased:
+const AtomicString& TouchEventNameForPointerEventType(
+ WebInputEvent::Type type) {
+ switch (type) {
+ case WebInputEvent::kPointerUp:
return EventTypeNames::touchend;
- case WebTouchPoint::kStateCancelled:
+ case WebInputEvent::kPointerCancel:
return EventTypeNames::touchcancel;
- case WebTouchPoint::kStatePressed:
+ case WebInputEvent::kPointerDown:
return EventTypeNames::touchstart;
- case WebTouchPoint::kStateMoved:
+ case WebInputEvent::kPointerMove:
return EventTypeNames::touchmove;
- case WebTouchPoint::kStateStationary:
- // Fall through to default
default:
NOTREACHED();
return g_empty_atom;
@@ -62,16 +60,24 @@ enum TouchEventDispatchResultType {
kTouchEventDispatchResultTypeMax,
};
-bool IsTouchSequenceStart(const WebTouchEvent& event) {
- if (!event.touches_length)
- return false;
- if (event.GetType() != WebInputEvent::kTouchStart)
- return false;
- for (size_t i = 0; i < event.touches_length; ++i) {
- if (event.touches[i].state != blink::WebTouchPoint::kStatePressed)
- return false;
+WebTouchPoint::State TouchPointStateFromPointerEventType(
+ WebInputEvent::Type type,
+ bool stale) {
+ if (stale)
+ return WebTouchPoint::kStateStationary;
+ switch (type) {
+ case WebInputEvent::Type::kPointerUp:
+ return WebTouchPoint::kStateReleased;
+ case WebInputEvent::Type::kPointerCancel:
+ return WebTouchPoint::kStateCancelled;
+ case WebInputEvent::Type::kPointerDown:
+ return WebTouchPoint::kStatePressed;
+ case WebInputEvent::Type::kPointerMove:
+ return WebTouchPoint::kStateMoved;
+ default:
+ NOTREACHED();
+ return WebTouchPoint::kStateUndefined;
}
- return true;
}
// Defining this class type local to dispatchTouchEvents() and annotating
@@ -92,8 +98,6 @@ class ChangedTouches final {
using EventTargetSet = HeapHashSet<Member<EventTarget>>;
// Set of targets involved in m_touches.
EventTargetSet targets_;
-
- WebPointerProperties::PointerType pointer_type_;
};
} // namespace
@@ -104,9 +108,7 @@ TouchEventManager::TouchEventManager(LocalFrame& frame) : frame_(frame) {
void TouchEventManager::Clear() {
touch_sequence_document_.Clear();
- target_for_touch_id_.clear();
- region_for_touch_id_.clear();
- touch_pressed_ = false;
+ touch_points_attributes_.clear();
suppressing_touchmoves_within_slop_ = false;
current_touch_action_ = TouchAction::kTouchActionAuto;
}
@@ -114,31 +116,18 @@ void TouchEventManager::Clear() {
DEFINE_TRACE(TouchEventManager) {
visitor->Trace(frame_);
visitor->Trace(touch_sequence_document_);
- visitor->Trace(target_for_touch_id_);
+ visitor->Trace(touch_points_attributes_);
}
-Touch* TouchEventManager::CreateDomTouch(const WebTouchPoint& point,
- bool* known_target) {
- Node* touch_node = nullptr;
- String region_id;
+Touch* TouchEventManager::CreateDomTouch(
+ const TouchEventManager::TouchPointAttributes* point_attr,
+ bool* known_target) {
+ Node* touch_node = point_attr->target_;
+ String region_id = point_attr->region_;
*known_target = false;
FloatPoint content_point;
FloatSize adjusted_radius;
- if (point.state == WebTouchPoint::kStateReleased ||
- point.state == WebTouchPoint::kStateCancelled) {
- // The target should be the original target for this touch, so get
- // it from the hashmap. As it's a release or cancel we also remove
- // it from the map.
- touch_node = target_for_touch_id_.Take(point.id);
- region_id = region_for_touch_id_.Take(point.id);
- } else {
- // No hittest is performed on move or stationary, since the target
- // is not allowed to change anyway.
- touch_node = target_for_touch_id_.at(point.id);
- region_id = region_for_touch_id_.at(point.id);
- }
-
LocalFrame* target_frame = nullptr;
if (touch_node) {
Document& doc = touch_node->GetDocument();
@@ -169,40 +158,148 @@ Touch* TouchEventManager::CreateDomTouch(const WebTouchPoint& point,
}
DCHECK(target_frame);
+ WebPointerEvent transformed_event =
+ point_attr->event_.WebPointerEventInRootFrame();
// pagePoint should always be in the target element's document coordinates.
- FloatPoint page_point =
- target_frame->View()->RootFrameToContents(point.PositionInWidget());
+ FloatPoint page_point = target_frame->View()->RootFrameToContents(
+ transformed_event.PositionInWidget());
float scale_factor = 1.0f / target_frame->PageZoomFactor();
content_point = page_point.ScaledBy(scale_factor);
- adjusted_radius =
- FloatSize(point.radius_x, point.radius_y).ScaledBy(scale_factor);
+ adjusted_radius = FloatSize(transformed_event.width, transformed_event.height)
+ .ScaledBy(scale_factor);
+
+ return Touch::Create(target_frame, touch_node, point_attr->event_.id,
+ transformed_event.PositionInScreen(), content_point,
+ adjusted_radius, transformed_event.rotation_angle,
+ transformed_event.force, region_id);
+}
+
+WebCoalescedInputEvent TouchEventManager::GenerateWebCoalescedInputEvent() {
+ DCHECK(!touch_points_attributes_.IsEmpty());
+
+ WebTouchEvent event;
+
+ const auto& first_touch_pointer_event =
+ touch_points_attributes_.begin()->value->event_;
+ event.dispatch_type = first_touch_pointer_event.dispatch_type;
+ event.touch_start_or_first_touch_move =
+ first_touch_pointer_event.touch_start_or_first_touch_move;
+ event.moved_beyond_slop_region =
+ first_touch_pointer_event.moved_beyond_slop_region;
+ event.dispatch_type = first_touch_pointer_event.dispatch_type;
+ event.dispatch_type = first_touch_pointer_event.dispatch_type;
+ event.SetFrameScale(first_touch_pointer_event.FrameScale());
+ event.SetFrameTranslate(first_touch_pointer_event.FrameTranslate());
+ event.SetTimeStampSeconds(first_touch_pointer_event.TimeStampSeconds());
+ event.SetModifiers(first_touch_pointer_event.GetModifiers());
+
+ WebInputEvent::Type touch_event_type = WebInputEvent::kTouchMove;
+ Vector<WebPointerEvent> all_coalesced_events;
+ Vector<int> available_ids;
+ for (const auto& id : touch_points_attributes_.Keys())
+ available_ids.push_back(id);
+ std::sort(available_ids.begin(), available_ids.end());
+ for (const int& touch_point_id : available_ids) {
+ const auto& touch_point_attribute =
+ touch_points_attributes_.at(touch_point_id);
+ const WebPointerEvent& touch_pointer_event = touch_point_attribute->event_;
+ WebTouchPoint web_touch_point(touch_pointer_event);
+ web_touch_point.state = TouchPointStateFromPointerEventType(
+ touch_pointer_event.GetType(), touch_point_attribute->stale_);
+ web_touch_point.radius_x = touch_pointer_event.width;
mustaq 2017/06/09 16:12:27 Repeat the TODO here for radius/width problem.
Navid Zolghadr 2017/06/12 16:17:31 I didn't have TODO anywhere else. I added a TODO h
+ web_touch_point.radius_y = touch_pointer_event.height;
+ web_touch_point.rotation_angle = touch_pointer_event.rotation_angle;
+ event.touches[event.touches_length++] = web_touch_point;
+
+ // Only change the touch event type from move. So if we have two pointers
+ // in up and down state we just set the touch event type to the first one
+ // we see.
+ if (touch_event_type == WebInputEvent::kTouchMove) {
mustaq 2017/06/09 16:12:27 You already hardcoded the event type in Line 197 a
Navid Zolghadr 2017/06/12 16:17:31 This is in a for loop. So the value of the touch_e
+ if (touch_pointer_event.GetType() == WebInputEvent::kPointerDown)
+ touch_event_type = WebInputEvent::kTouchStart;
+ else if (touch_pointer_event.GetType() == WebInputEvent::kPointerCancel)
+ touch_event_type = WebInputEvent::kTouchCancel;
+ else if (touch_pointer_event.GetType() == WebInputEvent::kPointerUp)
+ touch_event_type = WebInputEvent::kTouchEnd;
+ }
+
+ event.SetType(touch_event_type);
+
+ for (const WebPointerEvent& coalesced_event :
+ touch_point_attribute->coalesced_events_)
+ all_coalesced_events.push_back(coalesced_event);
+ }
+
+ // Create all coalesced touch events based on pointerevents
+ struct {
+ bool operator()(const WebPointerEvent& a, const WebPointerEvent& b) {
+ return a.TimeStampSeconds() < b.TimeStampSeconds();
+ }
+ } timestamp_based_event_comparison;
+ std::sort(all_coalesced_events.begin(), all_coalesced_events.end(),
+ timestamp_based_event_comparison);
+ WebCoalescedInputEvent result(event);
+ // This assumes that we only get move events as coalesced events.
mustaq 2017/06/09 16:12:27 This comment also applies to the above hardcoded k
Navid Zolghadr 2017/06/12 16:17:31 I added a DCHECK. However, I also changed the code
+ for (const auto& web_pointer_event : all_coalesced_events) {
+ for (unsigned i = 0; i < event.touches_length; ++i) {
+ if (event.touches[i].id == web_pointer_event.id &&
+ event.touches[i].state == blink::WebTouchPoint::kStateMoved &&
+ web_pointer_event.GetType() == WebInputEvent::kPointerMove) {
+ event.touches[i].movement_x = web_pointer_event.movement_x;
+ event.touches[i].movement_y = web_pointer_event.movement_y;
+ event.SetTimeStampSeconds(web_pointer_event.TimeStampSeconds());
+ result.AddCoalescedEvent(event);
+ break;
+ }
+ }
+ for (unsigned i = 0; i < event.touches_length; ++i) {
mustaq 2017/06/09 16:12:27 After adding to the coalesced events, |event| is n
Navid Zolghadr 2017/06/12 16:17:31 It's used for the next coalesced event (i.e. next
+ event.touches[i].state = blink::WebTouchPoint::kStateStationary;
+ event.touches[i].movement_x = 0;
+ event.touches[i].movement_y = 0;
+ }
+ }
- return Touch::Create(target_frame, touch_node, point.id,
- point.PositionInScreen(), content_point, adjusted_radius,
- point.rotation_angle, point.force, region_id);
+ return result;
}
-WebInputEventResult TouchEventManager::DispatchTouchEvents(
- const WebTouchEvent& event,
- const Vector<WebTouchEvent>& coalesced_events,
- bool all_touches_released) {
+WebInputEventResult TouchEventManager::DispatchTouchEvents() {
// Build up the lists to use for the |touches|, |targetTouches| and
// |changedTouches| attributes in the JS event. See
// http://www.w3.org/TR/touch-events/#touchevent-interface for how these
// lists fit together.
- if (event.GetType() == WebInputEvent::kTouchEnd ||
- event.GetType() == WebInputEvent::kTouchCancel ||
- event.touches_length > 1) {
- suppressing_touchmoves_within_slop_ = false;
+ bool new_touch_point_since_last_raf = false;
mustaq 2017/06/09 16:12:27 Let's not use "raf" here since this method will ev
Navid Zolghadr 2017/06/12 16:17:31 Done.
+ bool any_touch_canceled_ended = false;
mustaq 2017/06/09 16:12:27 ..._canceled_or_ended?
Navid Zolghadr 2017/06/12 16:17:32 Done.
+ bool all_touch_points_pressed = true;
+
+ for (const auto& attr : touch_points_attributes_.Values()) {
+ if (!attr->stale_)
+ new_touch_point_since_last_raf = true;
+ if (attr->event_.GetType() == WebInputEvent::kPointerUp ||
+ attr->event_.GetType() == WebInputEvent::kPointerCancel)
+ any_touch_canceled_ended = true;
+ if (attr->event_.GetType() != WebInputEvent::kPointerDown)
+ all_touch_points_pressed = false;
}
- if (suppressing_touchmoves_within_slop_ &&
- event.GetType() == WebInputEvent::kTouchMove) {
- if (!event.moved_beyond_slop_region)
- return WebInputEventResult::kHandledSuppressed;
+ if (!new_touch_point_since_last_raf)
+ return WebInputEventResult::kNotHandled;
+
+ if (any_touch_canceled_ended || touch_points_attributes_.size() > 1)
suppressing_touchmoves_within_slop_ = false;
+
+ if (suppressing_touchmoves_within_slop_) {
+ // There is exactly one touch point here otherwise
+ // |suppressing_touchmoves_within_slop_| would have been false.
+ DCHECK_EQ(touch_points_attributes_.size(), 1);
+ const auto& touch_point_attribute = touch_points_attributes_.begin()->value;
+ if (touch_point_attribute->event_.GetType() ==
+ WebInputEvent::kPointerMove) {
+ if (!touch_point_attribute->event_.moved_beyond_slop_region)
+ return WebInputEventResult::kHandledSuppressed;
+ suppressing_touchmoves_within_slop_ = false;
+ }
}
// Holds the complete set of touches on the screen.
@@ -214,15 +311,23 @@ WebInputEventResult TouchEventManager::DispatchTouchEvents(
TargetTouchesHeapMap touches_by_target;
// Array of touches per state, used to assemble the |changedTouches| list.
- ChangedTouches changed_touches[WebTouchPoint::kStateMax + 1];
-
- for (unsigned touch_point_idx = 0; touch_point_idx < event.touches_length;
- touch_point_idx++) {
- const WebTouchPoint& point = event.TouchPointInRootFrame(touch_point_idx);
- WebTouchPoint::State point_state = point.state;
+ ChangedTouches changed_touches[WebInputEvent::kPointerTypeLast -
+ WebInputEvent::kPointerTypeFirst + 1];
+
+ Vector<int> available_ids;
+ for (const auto& id : touch_points_attributes_.Keys())
+ available_ids.push_back(id);
+ std::sort(available_ids.begin(), available_ids.end());
+ for (const int& touch_point_id : available_ids) {
+ const auto& touch_point_attribute =
+ touch_points_attributes_.at(touch_point_id);
+ WebInputEvent::Type pointer_action =
mustaq 2017/06/09 16:12:27 s/pointer_action/pointer_event_type/
Navid Zolghadr 2017/06/12 16:17:31 Done.
+ touch_point_attribute->event_.GetType();
+ size_t pointer_action_idx =
mustaq 2017/06/09 16:12:27 event_type_idx?
Navid Zolghadr 2017/06/12 16:17:31 Done.
+ pointer_action - WebInputEvent::kPointerTypeFirst;
bool known_target;
- Touch* touch = CreateDomTouch(point, &known_target);
+ Touch* touch = CreateDomTouch(touch_point_attribute, &known_target);
EventTarget* touch_target = touch->target();
// Ensure this target's touch list exists, even if it ends up empty, so
@@ -237,8 +342,8 @@ WebInputEventResult TouchEventManager::DispatchTouchEvents(
// |touches| and |targetTouches| should only contain information about
// touches still on the screen, so if this point is released or
// cancelled it will only appear in the |changedTouches| list.
- if (point_state != WebTouchPoint::kStateReleased &&
- point_state != WebTouchPoint::kStateCancelled) {
+ if (pointer_action != WebInputEvent::kPointerUp &&
+ pointer_action != WebInputEvent::kPointerCancel) {
touches->Append(touch);
target_touches_iterator->value->Append(touch);
}
@@ -249,43 +354,36 @@ WebInputEventResult TouchEventManager::DispatchTouchEvents(
// never be in the |changedTouches| list so we do not handle them
// explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609
// for further discussion about the TouchStationary state.
- if (point_state != WebTouchPoint::kStateStationary && known_target) {
- DCHECK_LE(point_state, WebTouchPoint::kStateMax);
- if (!changed_touches[point_state].touches_)
- changed_touches[point_state].touches_ = TouchList::Create();
- changed_touches[point_state].touches_->Append(touch);
- changed_touches[point_state].targets_.insert(touch_target);
- changed_touches[point_state].pointer_type_ = point.pointer_type;
+ if (!touch_point_attribute->stale_ && known_target) {
+ if (!changed_touches[pointer_action_idx].touches_)
+ changed_touches[pointer_action_idx].touches_ = TouchList::Create();
+ changed_touches[pointer_action_idx].touches_->Append(touch);
+ changed_touches[pointer_action_idx].targets_.insert(touch_target);
}
}
- if (all_touches_released) {
- touch_sequence_document_.Clear();
- current_touch_action_ = TouchAction::kTouchActionAuto;
- }
-
WebInputEventResult event_result = WebInputEventResult::kNotHandled;
+
// First we construct the webcoalescedinputevent contains all the coalesced
mustaq 2017/06/09 16:12:27 /containing/
Navid Zolghadr 2017/06/12 16:17:31 Done.
// touch event.
- std::vector<const WebInputEvent*> coalesced_touches;
- for (size_t i = 0; i < coalesced_events.size(); ++i) {
- coalesced_touches.push_back(&coalesced_events[i]);
- }
- WebCoalescedInputEvent coalesced_event(event, coalesced_touches);
+ WebCoalescedInputEvent coalesced_event = GenerateWebCoalescedInputEvent();
// Now iterate through the |changedTouches| list and |m_targets| within it,
// sending TouchEvents to the targets as required.
- for (unsigned state = 0; state <= WebTouchPoint::kStateMax; ++state) {
- if (!changed_touches[state].touches_)
+ for (unsigned action = WebInputEvent::kPointerTypeFirst;
+ action <= WebInputEvent::kPointerTypeLast; ++action) {
+ size_t action_idx = action - WebInputEvent::kPointerTypeFirst;
+ if (!changed_touches[action_idx].touches_)
continue;
- const AtomicString& event_name(TouchEventNameForTouchPointState(
- static_cast<WebTouchPoint::State>(state)));
- for (const auto& event_target : changed_touches[state].targets_) {
+ const AtomicString& event_name(TouchEventNameForPointerEventType(
+ static_cast<WebInputEvent::Type>(action)));
+
+ for (const auto& event_target : changed_touches[action_idx].targets_) {
EventTarget* touch_event_target = event_target;
TouchEvent* touch_event = TouchEvent::Create(
coalesced_event, touches, touches_by_target.at(touch_event_target),
- changed_touches[state].touches_.Get(), event_name,
+ changed_touches[action_idx].touches_.Get(), event_name,
touch_event_target->ToNode()->GetDocument().domWindow(),
current_touch_action_);
@@ -294,66 +392,72 @@ WebInputEventResult TouchEventManager::DispatchTouchEvents(
// Only report for top level documents with a single touch on
mustaq 2017/06/09 16:12:27 The UMA block is too long and a bit distracting he
Navid Zolghadr 2017/06/12 16:17:31 Done.
// touch-start or the first touch-move.
- if (event.touch_start_or_first_touch_move && event.touches_length == 1 &&
- frame_->IsMainFrame()) {
- // Record the disposition and latency of touch starts and first touch
- // moves before and after the page is fully loaded respectively.
- int64_t latency_in_micros =
- (TimeTicks::Now() -
- TimeTicks::FromSeconds(event.TimeStampSeconds()))
- .InMicroseconds();
- if (event.IsCancelable()) {
- if (frame_->GetDocument()->IsLoadCompleted()) {
+ if (touch_points_attributes_.size() == 1 && frame_->IsMainFrame()) {
+ const auto& event = touch_points_attributes_.begin()->value->event_;
+ if (event.touch_start_or_first_touch_move) {
+ // Record the disposition and latency of touch starts and first touch
+ // moves before and after the page is fully loaded respectively.
+ int64_t latency_in_micros =
+ (TimeTicks::Now() -
+ TimeTicks::FromSeconds(event.TimeStampSeconds()))
+ .InMicroseconds();
+ if (event.IsCancelable()) {
+ if (frame_->GetDocument()->IsLoadCompleted()) {
+ DEFINE_STATIC_LOCAL(EnumerationHistogram,
+ touch_dispositions_after_page_load_histogram,
+ ("Event.Touch.TouchDispositionsAfterPageLoad",
+ kTouchEventDispatchResultTypeMax));
+ touch_dispositions_after_page_load_histogram.Count(
+ (dom_dispatch_result != DispatchEventResult::kNotCanceled)
+ ? kHandledTouches
+ : kUnhandledTouches);
+
+ DEFINE_STATIC_LOCAL(
+ CustomCountHistogram, event_latency_after_page_load_histogram,
+ ("Event.Touch.TouchLatencyAfterPageLoad", 1, 100000000, 50));
+ event_latency_after_page_load_histogram.Count(latency_in_micros);
+ } else {
+ DEFINE_STATIC_LOCAL(
+ EnumerationHistogram,
+ touch_dispositions_before_page_load_histogram,
+ ("Event.Touch.TouchDispositionsBeforePageLoad",
+ kTouchEventDispatchResultTypeMax));
+ touch_dispositions_before_page_load_histogram.Count(
+ (dom_dispatch_result != DispatchEventResult::kNotCanceled)
+ ? kHandledTouches
+ : kUnhandledTouches);
+
+ DEFINE_STATIC_LOCAL(
+ CustomCountHistogram,
+ event_latency_before_page_load_histogram,
+ ("Event.Touch.TouchLatencyBeforePageLoad", 1, 100000000, 50));
+ event_latency_before_page_load_histogram.Count(latency_in_micros);
+ }
+ // Report the touch disposition there is no active fling animation.
DEFINE_STATIC_LOCAL(EnumerationHistogram,
- touch_dispositions_after_page_load_histogram,
- ("Event.Touch.TouchDispositionsAfterPageLoad",
+ touch_dispositions_outside_fling_histogram,
+ ("Event.Touch.TouchDispositionsOutsideFling2",
kTouchEventDispatchResultTypeMax));
- touch_dispositions_after_page_load_histogram.Count(
+ touch_dispositions_outside_fling_histogram.Count(
(dom_dispatch_result != DispatchEventResult::kNotCanceled)
? kHandledTouches
: kUnhandledTouches);
+ }
- DEFINE_STATIC_LOCAL(
- CustomCountHistogram, event_latency_after_page_load_histogram,
- ("Event.Touch.TouchLatencyAfterPageLoad", 1, 100000000, 50));
- event_latency_after_page_load_histogram.Count(latency_in_micros);
- } else {
+ // Report the touch disposition when there is an active fling
+ // animation.
+ // if (event[0].first.dispatch_type ==
+ if (event.dispatch_type ==
+ WebInputEvent::kListenersForcedNonBlockingDueToFling) {
DEFINE_STATIC_LOCAL(EnumerationHistogram,
- touch_dispositions_before_page_load_histogram,
- ("Event.Touch.TouchDispositionsBeforePageLoad",
+ touch_dispositions_during_fling_histogram,
+ ("Event.Touch.TouchDispositionsDuringFling2",
kTouchEventDispatchResultTypeMax));
- touch_dispositions_before_page_load_histogram.Count(
- (dom_dispatch_result != DispatchEventResult::kNotCanceled)
+ touch_dispositions_during_fling_histogram.Count(
+ touch_event->PreventDefaultCalledOnUncancelableEvent()
? kHandledTouches
: kUnhandledTouches);
-
- DEFINE_STATIC_LOCAL(
- CustomCountHistogram, event_latency_before_page_load_histogram,
- ("Event.Touch.TouchLatencyBeforePageLoad", 1, 100000000, 50));
- event_latency_before_page_load_histogram.Count(latency_in_micros);
}
- // Report the touch disposition there is no active fling animation.
- DEFINE_STATIC_LOCAL(EnumerationHistogram,
- touch_dispositions_outside_fling_histogram,
- ("Event.Touch.TouchDispositionsOutsideFling2",
- kTouchEventDispatchResultTypeMax));
- touch_dispositions_outside_fling_histogram.Count(
- (dom_dispatch_result != DispatchEventResult::kNotCanceled)
- ? kHandledTouches
- : kUnhandledTouches);
- }
-
- // Report the touch disposition when there is an active fling animation.
- if (event.dispatch_type ==
- WebInputEvent::kListenersForcedNonBlockingDueToFling) {
- DEFINE_STATIC_LOCAL(EnumerationHistogram,
- touch_dispositions_during_fling_histogram,
- ("Event.Touch.TouchDispositionsDuringFling2",
- kTouchEventDispatchResultTypeMax));
- touch_dispositions_during_fling_histogram.Count(
- touch_event->PreventDefaultCalledOnUncancelableEvent()
- ? kHandledTouches
- : kUnhandledTouches);
}
}
event_result = EventHandlingUtil::MergeEventResult(
@@ -362,8 +466,9 @@ WebInputEventResult TouchEventManager::DispatchTouchEvents(
}
}
- // Do not suppress any touchmoves if the touchstart is consumed.
- if (IsTouchSequenceStart(event) &&
+ // Suppress following touchmoves within the slop region if the touchstart is
+ // not consumed.
+ if (all_touch_points_pressed &&
event_result == WebInputEventResult::kNotHandled) {
suppressing_touchmoves_within_slop_ = true;
}
@@ -371,14 +476,22 @@ WebInputEventResult TouchEventManager::DispatchTouchEvents(
return event_result;
}
-void TouchEventManager::UpdateTargetAndRegionMapsForTouchStart(
- const WebTouchPoint& touch_point,
+void TouchEventManager::UpdateTouchAttributeMapsForPointerDown(
+ const WebPointerEvent& event,
const EventHandlingUtil::PointerEventTarget& pointer_event_target) {
// Touch events implicitly capture to the touched node, and don't change
// active/hover states themselves (Gesture events do). So we only need
// to hit-test on touchstart and when the target could be different than
// the corresponding pointer event target.
- DCHECK(touch_point.state == WebTouchPoint::kStatePressed);
+ DCHECK(event.GetType() == WebInputEvent::kPointerDown);
+ // Ideally we'd DCHECK(!touch_points_attributes_.Contains(event.id))
+ // since we shouldn't get a touchstart for a touch that's already
+ // down. However EventSender allows this to be violated and there's
+ // some tests that take advantage of it. There may also be edge
+ // cases in the browser where this happens.
+ // See http://crbug.com/345372.
+ touch_points_attributes_.Set(event.id, new TouchPointAttributes(event));
+
Node* touch_node = pointer_event_target.target_node;
String region = pointer_event_target.region;
@@ -398,7 +511,7 @@ void TouchEventManager::UpdateTargetAndRegionMapsForTouchStart(
if (touch_sequence_document_->GetFrame()) {
LayoutPoint frame_point = LayoutPoint(
touch_sequence_document_->GetFrame()->View()->RootFrameToContents(
- touch_point.PositionInWidget()));
+ event.PositionInWidget()));
result = EventHandlingUtil::HitTestResultInFrame(
touch_sequence_document_->GetFrame(), frame_point, hit_type);
Node* node = result.InnerNode();
@@ -430,15 +543,9 @@ void TouchEventManager::UpdateTargetAndRegionMapsForTouchStart(
DCHECK(touch_sequence_document_->GetFrame()->View());
}
- // Ideally we'd DCHECK(!m_targetForTouchID.contains(point.id())
- // since we shouldn't get a touchstart for a touch that's already
- // down. However EventSender allows this to be violated and there's
- // some tests that take advantage of it. There may also be edge
- // cases in the browser where this happens.
- // See http://crbug.com/345372.
- target_for_touch_id_.Set(touch_point.id, touch_node);
-
- region_for_touch_id_.Set(touch_point.id, region);
+ TouchPointAttributes* attributes = touch_points_attributes_.at(event.id);
+ attributes->target_ = touch_node;
+ attributes->region_ = region;
TouchAction effective_touch_action =
TouchActionUtil::ComputeEffectiveTouchAction(*touch_node);
@@ -452,28 +559,20 @@ void TouchEventManager::UpdateTargetAndRegionMapsForTouchStart(
}
}
-bool TouchEventManager::HitTestTouchPointsIfNeeded(
- const WebTouchEvent& event,
- const HeapVector<EventHandlingUtil::PointerEventTarget>&
- pointer_event_targets) {
- bool new_touch_sequence = true;
- bool all_touches_released = true;
-
- for (unsigned i = 0; i < event.touches_length; ++i) {
- WebTouchPoint::State state = event.touches[i].state;
- if (state != WebTouchPoint::kStatePressed)
- new_touch_sequence = false;
- if (state != WebTouchPoint::kStateReleased &&
- state != WebTouchPoint::kStateCancelled)
- all_touches_released = false;
- }
- if (new_touch_sequence) {
+void TouchEventManager::HandleTouchPoint(
+ const WebPointerEvent& event,
+ const Vector<WebPointerEvent>& coalesced_events,
+ const EventHandlingUtil::PointerEventTarget& pointer_event_target) {
+ DCHECK_GE(event.GetType(), WebInputEvent::kPointerTypeFirst);
+ DCHECK_LE(event.GetType(), WebInputEvent::kPointerTypeLast);
+
+ if (touch_points_attributes_.IsEmpty()) {
// Ideally we'd DCHECK(!m_touchSequenceDocument) here since we should
// have cleared the active document when we saw the last release. But we
// have some tests that violate this, ClusterFuzz could trigger it, and
// there may be cases where the browser doesn't reliably release all
// touches. http://crbug.com/345372 tracks this.
- touch_sequence_document_.Clear();
+ allTouchesReleasedCleanup();
}
DCHECK(frame_->View());
@@ -482,59 +581,73 @@ bool TouchEventManager::HitTestTouchPointsIfNeeded(
!touch_sequence_document_->GetFrame()->View())) {
// If the active touch document has no frame or view, it's probably being
// destroyed so we can't dispatch events.
- return false;
+ return;
}
- for (unsigned i = 0; i < event.touches_length; ++i) {
- // In touch event model only touch starts can set the target and after that
- // the touch event always goes to that target.
- if (event.touches[i].state == WebTouchPoint::kStatePressed) {
- UpdateTargetAndRegionMapsForTouchStart(event.TouchPointInRootFrame(i),
- pointer_event_targets[i]);
- }
+ // In touch event model only touch starts can set the target and after that
+ // the touch event always goes to that target.
+ if (event.GetType() == WebInputEvent::kPointerDown) {
+ UpdateTouchAttributeMapsForPointerDown(event, pointer_event_target);
}
- touch_pressed_ = !all_touches_released;
-
- // If there's no document receiving touch events, or no handlers on the
- // document set to receive the events, then we can skip all the rest of
- // this work.
- if (!touch_sequence_document_ || !touch_sequence_document_->GetPage() ||
- !HasTouchHandlers(
- touch_sequence_document_->GetPage()->GetEventHandlerRegistry()) ||
- !touch_sequence_document_->GetFrame()) {
- if (all_touches_released) {
- touch_sequence_document_.Clear();
- }
- return false;
+ // We might not receive the down action for a touch point. In that case we
+ // would have never added them to |touch_points_attributes_| or hit-tested
+ // them. For those just keep them in the map with a null target. Later they
+ // will be targeted at the |touch_sequence_document_|.
+ if (!touch_points_attributes_.Contains(event.id)) {
+ touch_points_attributes_.insert(event.id, new TouchPointAttributes(event));
}
- return true;
+ TouchPointAttributes* attributes = touch_points_attributes_.at(event.id);
+ attributes->event_ = event;
+ attributes->coalesced_events_ = coalesced_events;
+ attributes->stale_ = false;
}
-WebInputEventResult TouchEventManager::HandleTouchEvent(
- const WebTouchEvent& event,
- const Vector<WebTouchEvent>& coalesced_events,
- const HeapVector<EventHandlingUtil::PointerEventTarget>&
- pointer_event_targets) {
- DCHECK(event.touches_length == pointer_event_targets.size());
+WebInputEventResult TouchEventManager::HandleVSyncSignal() {
+ // If there's no document receiving touch events, or no handlers on the
+ // document set to receive the events, then we can skip all the rest of
+ // sending the event.
+ WebInputEventResult result = WebInputEventResult::kNotHandled;
+ if (touch_sequence_document_ && touch_sequence_document_->GetPage() &&
+ HasTouchHandlers(
+ touch_sequence_document_->GetPage()->GetEventHandlerRegistry()) &&
+ touch_sequence_document_->GetFrame() &&
+ touch_sequence_document_->GetFrame()->View()) {
+ result = DispatchTouchEvents();
+ }
- if (!HitTestTouchPointsIfNeeded(event, pointer_event_targets))
- return WebInputEventResult::kNotHandled;
+ // Cleanup the |touch_points_attributes_| map from released and canceled
+ // touch points.
+ Vector<int> releasedCanceledPoints;
+ for (auto& attributes : touch_points_attributes_.Values()) {
+ if (attributes->event_.GetType() == WebInputEvent::kPointerUp ||
+ attributes->event_.GetType() == WebInputEvent::kPointerCancel) {
+ releasedCanceledPoints.push_back(attributes->event_.id);
+ } else {
+ attributes->stale_ = true;
+ attributes->event_.movement_x = 0;
+ attributes->event_.movement_y = 0;
+ }
+ }
+ for (int id : releasedCanceledPoints) {
+ touch_points_attributes_.erase(id);
mustaq 2017/06/09 16:12:27 Can use .erase(releasedCanceledPoints) instead?
Navid Zolghadr 2017/06/12 16:17:31 Not quite. But there seems to be a RemoveAll funct
+ }
- bool all_touches_released = true;
- for (unsigned i = 0; i < event.touches_length; ++i) {
- WebTouchPoint::State state = event.touches[i].state;
- if (state != WebTouchPoint::kStateReleased &&
- state != WebTouchPoint::kStateCancelled)
- all_touches_released = false;
+ if (touch_points_attributes_.IsEmpty()) {
+ allTouchesReleasedCleanup();
}
- return DispatchTouchEvents(event, coalesced_events, all_touches_released);
+ return result;
+}
+
+void TouchEventManager::allTouchesReleasedCleanup() {
+ touch_sequence_document_.Clear();
+ current_touch_action_ = TouchAction::kTouchActionAuto;
}
bool TouchEventManager::IsAnyTouchActive() const {
- return touch_pressed_;
+ return !touch_points_attributes_.IsEmpty();
}
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698