summaryrefslogtreecommitdiff
path: root/chromium/content/renderer/input/input_event_prediction.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/renderer/input/input_event_prediction.cc')
-rw-r--r--chromium/content/renderer/input/input_event_prediction.cc160
1 files changed, 160 insertions, 0 deletions
diff --git a/chromium/content/renderer/input/input_event_prediction.cc b/chromium/content/renderer/input/input_event_prediction.cc
new file mode 100644
index 00000000000..89636c9736d
--- /dev/null
+++ b/chromium/content/renderer/input/input_event_prediction.cc
@@ -0,0 +1,160 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/input/input_event_prediction.h"
+
+#include "base/feature_list.h"
+#include "content/public/common/content_features.h"
+#include "ui/events/blink/prediction/empty_predictor.h"
+
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebPointerEvent;
+using blink::WebPointerProperties;
+using blink::WebTouchEvent;
+
+namespace content {
+
+namespace {
+
+std::unique_ptr<ui::InputPredictor> SetUpPredictor() {
+ return std::make_unique<ui::EmptyPredictor>();
+}
+
+} // namespace
+
+InputEventPrediction::InputEventPrediction() {
+ mouse_predictor_ = SetUpPredictor();
+}
+
+InputEventPrediction::~InputEventPrediction() {}
+
+void InputEventPrediction::HandleEvents(
+ const blink::WebCoalescedInputEvent& coalesced_event,
+ base::TimeTicks frame_time,
+ blink::WebInputEvent* event) {
+ switch (event->GetType()) {
+ case WebInputEvent::kMouseMove:
+ case WebInputEvent::kTouchMove:
+ case WebInputEvent::kPointerMove: {
+ size_t coalesced_size = coalesced_event.CoalescedEventSize();
+ for (size_t i = 0; i < coalesced_size; i++)
+ UpdatePrediction(coalesced_event.CoalescedEvent(i));
+
+ ApplyResampling(frame_time, event);
+ break;
+ }
+ case WebInputEvent::kTouchScrollStarted:
+ case WebInputEvent::kPointerCausedUaAction:
+ pointer_id_predictor_map_.clear();
+ break;
+ default:
+ ResetPredictor(*event);
+ }
+}
+
+void InputEventPrediction::UpdatePrediction(const WebInputEvent& event) {
+ if (WebInputEvent::IsTouchEventType(event.GetType())) {
+ DCHECK(event.GetType() == WebInputEvent::kTouchMove);
+ const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event);
+ for (unsigned i = 0; i < touch_event.touches_length; ++i) {
+ if (touch_event.touches[i].state == blink::WebTouchPoint::kStateMoved) {
+ UpdateSinglePointer(touch_event.touches[i], touch_event.TimeStamp());
+ }
+ }
+ } else if (WebInputEvent::IsMouseEventType(event.GetType())) {
+ DCHECK(event.GetType() == WebInputEvent::kMouseMove);
+ UpdateSinglePointer(static_cast<const WebMouseEvent&>(event),
+ event.TimeStamp());
+ } else if (WebInputEvent::IsPointerEventType(event.GetType())) {
+ DCHECK(event.GetType() == WebInputEvent::kPointerMove);
+ UpdateSinglePointer(static_cast<const WebPointerEvent&>(event),
+ event.TimeStamp());
+ }
+}
+
+void InputEventPrediction::ApplyResampling(base::TimeTicks frame_time,
+ WebInputEvent* event) {
+ if (event->GetType() == WebInputEvent::kTouchMove) {
+ WebTouchEvent* touch_event = static_cast<WebTouchEvent*>(event);
+ for (unsigned i = 0; i < touch_event->touches_length; ++i) {
+ if (ResampleSinglePointer(frame_time, &touch_event->touches[i]))
+ event->SetTimeStamp(frame_time);
+ }
+ } else if (event->GetType() == WebInputEvent::kMouseMove) {
+ if (ResampleSinglePointer(frame_time, static_cast<WebMouseEvent*>(event)))
+ event->SetTimeStamp(frame_time);
+ } else if (event->GetType() == WebInputEvent::kPointerMove) {
+ if (ResampleSinglePointer(frame_time, static_cast<WebPointerEvent*>(event)))
+ event->SetTimeStamp(frame_time);
+ }
+}
+
+void InputEventPrediction::ResetPredictor(const WebInputEvent& event) {
+ if (WebInputEvent::IsTouchEventType(event.GetType())) {
+ const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event);
+ for (unsigned i = 0; i < touch_event.touches_length; ++i) {
+ if (touch_event.touches[i].state != blink::WebTouchPoint::kStateMoved &&
+ touch_event.touches[i].state !=
+ blink::WebTouchPoint::kStateStationary)
+ pointer_id_predictor_map_.erase(touch_event.touches[i].id);
+ }
+ } else if (WebInputEvent::IsMouseEventType(event.GetType())) {
+ ResetSinglePredictor(static_cast<const WebMouseEvent&>(event));
+ } else if (WebInputEvent::IsPointerEventType(event.GetType())) {
+ ResetSinglePredictor(static_cast<const WebPointerEvent&>(event));
+ }
+}
+
+void InputEventPrediction::UpdateSinglePointer(
+ const WebPointerProperties& event,
+ base::TimeTicks event_time) {
+ ui::InputPredictor::InputData data = {event.PositionInWidget().x,
+ event.PositionInWidget().y, event_time};
+ if (event.pointer_type == WebPointerProperties::PointerType::kMouse)
+ mouse_predictor_->Update(data);
+ else {
+ auto predictor = pointer_id_predictor_map_.find(event.id);
+ if (predictor != pointer_id_predictor_map_.end()) {
+ predictor->second->Update(data);
+ } else {
+ pointer_id_predictor_map_.insert({event.id, SetUpPredictor()});
+ pointer_id_predictor_map_[event.id]->Update(data);
+ }
+ }
+}
+
+bool InputEventPrediction::ResampleSinglePointer(base::TimeTicks frame_time,
+ WebPointerProperties* event) {
+ ui::InputPredictor::InputData predict_result;
+ if (event->pointer_type == WebPointerProperties::PointerType::kMouse) {
+ if (mouse_predictor_->HasPrediction() &&
+ mouse_predictor_->GeneratePrediction(frame_time, &predict_result)) {
+ event->SetPositionInWidget(predict_result.pos_x, predict_result.pos_y);
+ return true;
+ }
+ } else {
+ // Reset mouse predictor if pointer type is touch or stylus
+ mouse_predictor_->Reset();
+
+ auto predictor = pointer_id_predictor_map_.find(event->id);
+ if (predictor != pointer_id_predictor_map_.end() &&
+ predictor->second->HasPrediction() &&
+ predictor->second->GeneratePrediction(frame_time, &predict_result)) {
+ event->SetPositionInWidget(predict_result.pos_x, predict_result.pos_y);
+ return true;
+ }
+ }
+ return false;
+}
+
+void InputEventPrediction::ResetSinglePredictor(
+ const WebPointerProperties& event) {
+ if (event.pointer_type == WebPointerProperties::PointerType::kMouse)
+ mouse_predictor_->Reset();
+ else
+ pointer_id_predictor_map_.erase(event.id);
+}
+
+} // namespace content