Commit 058c4c7e authored by chongz's avatar chongz Committed by Commit bot

[Compositor event queue] Coalesce gesture scroll&pinch of the same sequence

It is possible to have |GestureScrollUpdate| and |GesturePinchUpdate| in the same
|GestureScrollBegin/End| sequence. This CL coalesces multiple GSUs and GPUs into 1
GSU and 1 GPU using matrix transformation.

e.g.
|GSB| -> |GSU| -> |GSU| -> |GPU| -> |GSU| -> |GSE|
becomes
|GSB| -> |GSU|* -> |GPU|* -> |GSE|

* means coalesced events.

Note that we have to go through the matrix when there are 2 adjacent pinch events
with different pinch point as they would coalesce to 1 scroll event and 1 pinch event.

BUG=661601

Review-Url: https://codereview.chromium.org/2552853002
Cr-Commit-Position: refs/heads/master@{#438534}
parent 0cc860d2
...@@ -13,47 +13,6 @@ using blink::WebGestureEvent; ...@@ -13,47 +13,6 @@ using blink::WebGestureEvent;
using blink::WebInputEvent; using blink::WebInputEvent;
namespace content { namespace content {
namespace {
// Whether |event_in_queue| is GesturePinchUpdate or GestureScrollUpdate and
// has the same modifiers/source as the new scroll/pinch event. Compatible
// scroll and pinch event pairs can be logically coalesced.
bool IsCompatibleScrollorPinch(
const GestureEventWithLatencyInfo& new_event,
const GestureEventWithLatencyInfo& event_in_queue) {
DCHECK(new_event.event.type == WebInputEvent::GestureScrollUpdate ||
new_event.event.type == WebInputEvent::GesturePinchUpdate)
<< "Invalid event type for pinch/scroll coalescing: "
<< WebInputEvent::GetName(new_event.event.type);
DLOG_IF(WARNING, new_event.event.timeStampSeconds <
event_in_queue.event.timeStampSeconds)
<< "Event time not monotonic?\n";
return (event_in_queue.event.type == WebInputEvent::GestureScrollUpdate ||
event_in_queue.event.type == WebInputEvent::GesturePinchUpdate) &&
event_in_queue.event.modifiers == new_event.event.modifiers &&
event_in_queue.event.sourceDevice == new_event.event.sourceDevice;
}
// Returns the transform matrix corresponding to the gesture event.
gfx::Transform GetTransformForEvent(
const GestureEventWithLatencyInfo& gesture_event) {
gfx::Transform gesture_transform;
if (gesture_event.event.type == WebInputEvent::GestureScrollUpdate) {
gesture_transform.Translate(gesture_event.event.data.scrollUpdate.deltaX,
gesture_event.event.data.scrollUpdate.deltaY);
} else if (gesture_event.event.type == WebInputEvent::GesturePinchUpdate) {
float scale = gesture_event.event.data.pinchUpdate.scale;
gesture_transform.Translate(-gesture_event.event.x, -gesture_event.event.y);
gesture_transform.Scale(scale, scale);
gesture_transform.Translate(gesture_event.event.x, gesture_event.event.y);
} else {
NOTREACHED() << "Invalid event type for transform retrieval: "
<< WebInputEvent::GetName(gesture_event.event.type);
}
return gesture_transform;
}
} // namespace
GestureEventQueue::Config::Config() { GestureEventQueue::Config::Config() {
} }
...@@ -335,7 +294,8 @@ void GestureEventQueue::QueueScrollOrPinchAndForwardIfNecessary( ...@@ -335,7 +294,8 @@ void GestureEventQueue::QueueScrollOrPinchAndForwardIfNecessary(
const GestureEventWithLatencyInfo& first_event = const GestureEventWithLatencyInfo& first_event =
coalesced_gesture_events_.front(); coalesced_gesture_events_.front();
if (gesture_event.event.type != first_event.event.type && if (gesture_event.event.type != first_event.event.type &&
IsCompatibleScrollorPinch(gesture_event, first_event)) { ui::IsCompatibleScrollorPinch(gesture_event.event,
first_event.event)) {
ignore_next_ack_ = true; ignore_next_ack_ = true;
client_->SendGestureEventImmediately(gesture_event); client_->SendGestureEventImmediately(gesture_event);
} }
...@@ -349,63 +309,50 @@ void GestureEventQueue::QueueScrollOrPinchAndForwardIfNecessary( ...@@ -349,63 +309,50 @@ void GestureEventQueue::QueueScrollOrPinchAndForwardIfNecessary(
return; return;
} }
if (!IsCompatibleScrollorPinch(gesture_event, *last_event)) { if (!ui::IsCompatibleScrollorPinch(gesture_event.event, last_event->event)) {
coalesced_gesture_events_.push_back(gesture_event); coalesced_gesture_events_.push_back(gesture_event);
return; return;
} }
// Extract the last event in queue.
blink::WebGestureEvent last_gesture_event =
coalesced_gesture_events_.back().event;
DCHECK_LE(coalesced_gesture_events_.back().latency.trace_id(),
gesture_event.latency.trace_id());
ui::LatencyInfo oldest_latency = coalesced_gesture_events_.back().latency;
oldest_latency.set_coalesced();
coalesced_gesture_events_.pop_back();
// Extract the second last event in queue.
ui::ScopedWebInputEvent second_last_gesture_event = nullptr;
if (unsent_events_count > 1 &&
ui::IsCompatibleScrollorPinch(gesture_event.event,
coalesced_gesture_events_.back().event)) {
second_last_gesture_event =
ui::WebInputEventTraits::Clone(coalesced_gesture_events_.back().event);
DCHECK_LE(coalesced_gesture_events_.back().latency.trace_id(),
oldest_latency.trace_id());
oldest_latency = coalesced_gesture_events_.back().latency;
oldest_latency.set_coalesced();
coalesced_gesture_events_.pop_back();
}
std::pair<blink::WebGestureEvent, blink::WebGestureEvent> coalesced_events =
ui::CoalesceScrollAndPinch(
second_last_gesture_event
? &ui::ToWebGestureEvent(*second_last_gesture_event)
: nullptr,
last_gesture_event, gesture_event.event);
GestureEventWithLatencyInfo scroll_event; GestureEventWithLatencyInfo scroll_event;
scroll_event.event = coalesced_events.first;
scroll_event.latency = oldest_latency;
GestureEventWithLatencyInfo pinch_event; GestureEventWithLatencyInfo pinch_event;
scroll_event.event.modifiers |= gesture_event.event.modifiers; pinch_event.event = coalesced_events.second;
scroll_event.event.sourceDevice = gesture_event.event.sourceDevice; pinch_event.latency = oldest_latency;
scroll_event.event.timeStampSeconds = gesture_event.event.timeStampSeconds;
// Keep the oldest LatencyInfo.
DCHECK_LE(last_event->latency.trace_id(), gesture_event.latency.trace_id());
scroll_event.latency = last_event->latency;
pinch_event = scroll_event;
scroll_event.event.type = WebInputEvent::GestureScrollUpdate;
pinch_event.event.type = WebInputEvent::GesturePinchUpdate;
pinch_event.event.x = gesture_event.event.type ==
WebInputEvent::GesturePinchUpdate ?
gesture_event.event.x : last_event->event.x;
pinch_event.event.y = gesture_event.event.type ==
WebInputEvent::GesturePinchUpdate ?
gesture_event.event.y : last_event->event.y;
gfx::Transform combined_scroll_pinch = GetTransformForEvent(*last_event);
// Only include the second-to-last event in the coalesced pair if it exists
// and can be combined with the new event.
if (unsent_events_count > 1) {
const GestureEventWithLatencyInfo& second_last_event =
coalesced_gesture_events_[coalesced_gesture_events_.size() - 2];
if (IsCompatibleScrollorPinch(gesture_event, second_last_event)) {
// Keep the oldest LatencyInfo.
DCHECK_LE(second_last_event.latency.trace_id(),
scroll_event.latency.trace_id());
scroll_event.latency = second_last_event.latency;
pinch_event.latency = second_last_event.latency;
combined_scroll_pinch.PreconcatTransform(
GetTransformForEvent(second_last_event));
coalesced_gesture_events_.pop_back();
}
}
combined_scroll_pinch.ConcatTransform(GetTransformForEvent(gesture_event));
coalesced_gesture_events_.pop_back();
float combined_scale =
SkMScalarToFloat(combined_scroll_pinch.matrix().get(0, 0));
float combined_scroll_pinch_x =
SkMScalarToFloat(combined_scroll_pinch.matrix().get(0, 3));
float combined_scroll_pinch_y =
SkMScalarToFloat(combined_scroll_pinch.matrix().get(1, 3));
scroll_event.event.data.scrollUpdate.deltaX =
(combined_scroll_pinch_x + pinch_event.event.x) / combined_scale -
pinch_event.event.x;
scroll_event.event.data.scrollUpdate.deltaY =
(combined_scroll_pinch_y + pinch_event.event.y) / combined_scale -
pinch_event.event.y;
coalesced_gesture_events_.push_back(scroll_event); coalesced_gesture_events_.push_back(scroll_event);
pinch_event.event.data.pinchUpdate.scale = combined_scale;
coalesced_gesture_events_.push_back(pinch_event); coalesced_gesture_events_.push_back(pinch_event);
} }
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "content/common/input/input_event_ack_state.h" #include "content/common/input/input_event_ack_state.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h" #include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/gfx/transform.h"
namespace content { namespace content {
class GestureEventQueueTest; class GestureEventQueueTest;
......
...@@ -37,6 +37,7 @@ source_set("blink") { ...@@ -37,6 +37,7 @@ source_set("blink") {
"//ui/events:dom_keycode_converter", "//ui/events:dom_keycode_converter",
"//ui/events:events_base", "//ui/events:events_base",
"//ui/events:gesture_detection", "//ui/events:gesture_detection",
"//ui/gfx",
"//ui/gfx/geometry", "//ui/gfx/geometry",
] ]
......
...@@ -14,6 +14,7 @@ include_rules = [ ...@@ -14,6 +14,7 @@ include_rules = [
"+third_party/WebKit/public/web/WebActiveWheelFlingParameters.h", "+third_party/WebKit/public/web/WebActiveWheelFlingParameters.h",
"+ui/display/win", "+ui/display/win",
"+ui/gfx",
"+ui/gfx/geometry", "+ui/gfx/geometry",
"+ui/events" "+ui/events"
] ]
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "third_party/WebKit/public/platform/WebGestureEvent.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h" #include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/base_event_utils.h" #include "ui/events/base_event_utils.h"
#include "ui/events/event_constants.h" #include "ui/events/event_constants.h"
...@@ -26,6 +25,7 @@ ...@@ -26,6 +25,7 @@
#include "ui/events/keycodes/dom/keycode_converter.h" #include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/gfx/geometry/safe_integer_conversions.h" #include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/transform.h"
using blink::WebGestureEvent; using blink::WebGestureEvent;
using blink::WebInputEvent; using blink::WebInputEvent;
...@@ -381,6 +381,24 @@ void Coalesce(const WebGestureEvent& event_to_coalesce, ...@@ -381,6 +381,24 @@ void Coalesce(const WebGestureEvent& event_to_coalesce,
} }
} }
// Returns the transform matrix corresponding to the gesture event.
gfx::Transform GetTransformForEvent(const WebGestureEvent& gesture_event) {
gfx::Transform gesture_transform;
if (gesture_event.type == WebInputEvent::GestureScrollUpdate) {
gesture_transform.Translate(gesture_event.data.scrollUpdate.deltaX,
gesture_event.data.scrollUpdate.deltaY);
} else if (gesture_event.type == WebInputEvent::GesturePinchUpdate) {
float scale = gesture_event.data.pinchUpdate.scale;
gesture_transform.Translate(-gesture_event.x, -gesture_event.y);
gesture_transform.Scale(scale, scale);
gesture_transform.Translate(gesture_event.x, gesture_event.y);
} else {
NOTREACHED() << "Invalid event type for transform retrieval: "
<< WebInputEvent::GetName(gesture_event.type);
}
return gesture_transform;
}
} // namespace } // namespace
bool CanCoalesce(const blink::WebInputEvent& event_to_coalesce, bool CanCoalesce(const blink::WebInputEvent& event_to_coalesce,
...@@ -439,6 +457,73 @@ void Coalesce(const blink::WebInputEvent& event_to_coalesce, ...@@ -439,6 +457,73 @@ void Coalesce(const blink::WebInputEvent& event_to_coalesce,
} }
} }
// Whether |event_in_queue| is GesturePinchUpdate or GestureScrollUpdate and
// has the same modifiers/source as the new scroll/pinch event. Compatible
// scroll and pinch event pairs can be logically coalesced.
bool IsCompatibleScrollorPinch(const WebGestureEvent& new_event,
const WebGestureEvent& event_in_queue) {
DCHECK(new_event.type == WebInputEvent::GestureScrollUpdate ||
new_event.type == WebInputEvent::GesturePinchUpdate)
<< "Invalid event type for pinch/scroll coalescing: "
<< WebInputEvent::GetName(new_event.type);
DLOG_IF(WARNING, new_event.timeStampSeconds < event_in_queue.timeStampSeconds)
<< "Event time not monotonic?\n";
return (event_in_queue.type == WebInputEvent::GestureScrollUpdate ||
event_in_queue.type == WebInputEvent::GesturePinchUpdate) &&
event_in_queue.modifiers == new_event.modifiers &&
event_in_queue.sourceDevice == new_event.sourceDevice;
}
std::pair<WebGestureEvent, WebGestureEvent> CoalesceScrollAndPinch(
const WebGestureEvent* second_last_event,
const WebGestureEvent& last_event,
const WebGestureEvent& new_event) {
DCHECK(!CanCoalesce(new_event, last_event))
<< "New event can be coalesced with the last event in queue directly.";
DCHECK(IsContinuousGestureEvent(new_event.type));
DCHECK(IsCompatibleScrollorPinch(new_event, last_event));
DCHECK(!second_last_event ||
IsCompatibleScrollorPinch(new_event, *second_last_event));
WebGestureEvent scroll_event;
WebGestureEvent pinch_event;
scroll_event.modifiers |= new_event.modifiers;
scroll_event.sourceDevice = new_event.sourceDevice;
scroll_event.timeStampSeconds = new_event.timeStampSeconds;
pinch_event = scroll_event;
scroll_event.type = WebInputEvent::GestureScrollUpdate;
pinch_event.type = WebInputEvent::GesturePinchUpdate;
pinch_event.x = new_event.type == WebInputEvent::GesturePinchUpdate
? new_event.x
: last_event.x;
pinch_event.y = new_event.type == WebInputEvent::GesturePinchUpdate
? new_event.y
: last_event.y;
gfx::Transform combined_scroll_pinch = GetTransformForEvent(last_event);
if (second_last_event) {
combined_scroll_pinch.PreconcatTransform(
GetTransformForEvent(*second_last_event));
}
combined_scroll_pinch.ConcatTransform(GetTransformForEvent(new_event));
float combined_scale =
SkMScalarToFloat(combined_scroll_pinch.matrix().get(0, 0));
float combined_scroll_pinch_x =
SkMScalarToFloat(combined_scroll_pinch.matrix().get(0, 3));
float combined_scroll_pinch_y =
SkMScalarToFloat(combined_scroll_pinch.matrix().get(1, 3));
scroll_event.data.scrollUpdate.deltaX =
(combined_scroll_pinch_x + pinch_event.x) / combined_scale -
pinch_event.x;
scroll_event.data.scrollUpdate.deltaY =
(combined_scroll_pinch_y + pinch_event.y) / combined_scale -
pinch_event.y;
pinch_event.data.pinchUpdate.scale = combined_scale;
return std::make_pair(scroll_event, pinch_event);
}
blink::WebTouchEvent CreateWebTouchEventFromMotionEvent( blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
const MotionEvent& event, const MotionEvent& event,
bool moved_beyond_slop_region) { bool moved_beyond_slop_region) {
......
...@@ -7,12 +7,11 @@ ...@@ -7,12 +7,11 @@
#include <memory> #include <memory>
#include "third_party/WebKit/public/platform/WebGestureEvent.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h" #include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/gesture_detection/motion_event.h" #include "ui/events/gesture_detection/motion_event.h"
namespace blink { namespace blink {
class WebGestureEvent;
class WebInputEvent;
class WebTouchEvent; class WebTouchEvent;
} }
...@@ -33,6 +32,16 @@ bool CanCoalesce(const blink::WebInputEvent& event_to_coalesce, ...@@ -33,6 +32,16 @@ bool CanCoalesce(const blink::WebInputEvent& event_to_coalesce,
void Coalesce(const blink::WebInputEvent& event_to_coalesce, void Coalesce(const blink::WebInputEvent& event_to_coalesce,
blink::WebInputEvent* event); blink::WebInputEvent* event);
bool IsCompatibleScrollorPinch(const blink::WebGestureEvent& new_event,
const blink::WebGestureEvent& event_in_queue);
// Coalesces 3 GestureScroll/PinchUpdate into 2 events.
// Returns <GestureScrollUpdate, GesturePinchUpdate>.
std::pair<blink::WebGestureEvent, blink::WebGestureEvent>
CoalesceScrollAndPinch(const blink::WebGestureEvent* second_last_event,
const blink::WebGestureEvent& last_event,
const blink::WebGestureEvent& new_event);
blink::WebTouchEvent CreateWebTouchEventFromMotionEvent( blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
const MotionEvent& event, const MotionEvent& event,
bool may_cause_scrolling); bool may_cause_scrolling);
...@@ -84,6 +93,12 @@ bool IsGestureScollOrPinch(blink::WebInputEvent::Type); ...@@ -84,6 +93,12 @@ bool IsGestureScollOrPinch(blink::WebInputEvent::Type);
bool IsContinuousGestureEvent(blink::WebInputEvent::Type); bool IsContinuousGestureEvent(blink::WebInputEvent::Type);
inline const blink::WebGestureEvent& ToWebGestureEvent(
const blink::WebInputEvent& event) {
DCHECK(IsGestureScollOrPinch(event.type));
return static_cast<const blink::WebGestureEvent&>(event);
}
} // namespace ui } // namespace ui
#endif // UI_EVENTS_BLINK_BLINK_EVENT_UTIL_H_ #endif // UI_EVENTS_BLINK_BLINK_EVENT_UTIL_H_
...@@ -4,22 +4,82 @@ ...@@ -4,22 +4,82 @@
#include "ui/events/blink/compositor_thread_event_queue.h" #include "ui/events/blink/compositor_thread_event_queue.h"
#include "base/memory/ptr_util.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/blink/web_input_event_traits.h"
namespace ui { namespace ui {
CompositorThreadEventQueue::CompositorThreadEventQueue() {} CompositorThreadEventQueue::CompositorThreadEventQueue() {}
CompositorThreadEventQueue::~CompositorThreadEventQueue() {} CompositorThreadEventQueue::~CompositorThreadEventQueue() {}
// TODO(chongz): Support coalescing events across interleaved boundaries. void CompositorThreadEventQueue::Queue(
// https://crbug.com/661601 std::unique_ptr<EventWithCallback> new_event,
void CompositorThreadEventQueue::Queue(std::unique_ptr<EventWithCallback> event, base::TimeTicks timestamp_now) {
base::TimeTicks timestamp_now) { if (queue_.empty() || !IsContinuousGestureEvent(new_event->event().type) ||
if (!queue_.empty() && queue_.back()->CanCoalesceWith(*event)) { !IsCompatibleScrollorPinch(ToWebGestureEvent(new_event->event()),
queue_.back()->CoalesceWith(event.get(), timestamp_now); ToWebGestureEvent(queue_.back()->event()))) {
queue_.emplace_back(std::move(new_event));
return; return;
} }
queue_.emplace_back(std::move(event)); if (queue_.back()->CanCoalesceWith(*new_event)) {
queue_.back()->CoalesceWith(new_event.get(), timestamp_now);
return;
}
// Extract the last event in queue.
std::unique_ptr<EventWithCallback> last_event = std::move(queue_.back());
queue_.pop_back();
DCHECK_LE(last_event->latency_info().trace_id(),
new_event->latency_info().trace_id());
LatencyInfo oldest_latency = last_event->latency_info();
oldest_latency.set_coalesced();
base::TimeTicks oldest_creation_timestamp = last_event->creation_timestamp();
auto combined_original_events =
base::MakeUnique<EventWithCallback::OriginalEventList>();
combined_original_events->splice(combined_original_events->end(),
last_event->original_events());
combined_original_events->splice(combined_original_events->end(),
new_event->original_events());
// Extract the second last event in queue.
std::unique_ptr<EventWithCallback> second_last_event = nullptr;
if (!queue_.empty() &&
IsCompatibleScrollorPinch(ToWebGestureEvent(new_event->event()),
ToWebGestureEvent(queue_.back()->event()))) {
second_last_event = std::move(queue_.back());
queue_.pop_back();
DCHECK_LE(second_last_event->latency_info().trace_id(),
oldest_latency.trace_id());
oldest_latency = second_last_event->latency_info();
oldest_latency.set_coalesced();
oldest_creation_timestamp = second_last_event->creation_timestamp();
combined_original_events->splice(combined_original_events->begin(),
second_last_event->original_events());
}
std::pair<blink::WebGestureEvent, blink::WebGestureEvent> coalesced_events =
CoalesceScrollAndPinch(
second_last_event ? &ToWebGestureEvent(second_last_event->event())
: nullptr,
ToWebGestureEvent(last_event->event()),
ToWebGestureEvent(new_event->event()));
std::unique_ptr<EventWithCallback> scroll_event =
base::MakeUnique<EventWithCallback>(
WebInputEventTraits::Clone(coalesced_events.first), oldest_latency,
oldest_creation_timestamp, timestamp_now, nullptr);
std::unique_ptr<EventWithCallback> pinch_event =
base::MakeUnique<EventWithCallback>(
WebInputEventTraits::Clone(coalesced_events.second), oldest_latency,
oldest_creation_timestamp, timestamp_now,
std::move(combined_original_events));
queue_.emplace_back(std::move(scroll_event));
queue_.emplace_back(std::move(pinch_event));
} }
std::unique_ptr<EventWithCallback> CompositorThreadEventQueue::Pop() { std::unique_ptr<EventWithCallback> CompositorThreadEventQueue::Pop() {
......
...@@ -26,6 +26,20 @@ EventWithCallback::EventWithCallback( ...@@ -26,6 +26,20 @@ EventWithCallback::EventWithCallback(
original_events_.emplace_back(std::move(event), callback); original_events_.emplace_back(std::move(event), callback);
} }
EventWithCallback::EventWithCallback(
ScopedWebInputEvent event,
const LatencyInfo& latency,
base::TimeTicks creation_timestamp,
base::TimeTicks last_coalesced_timestamp,
std::unique_ptr<OriginalEventList> original_events)
: event_(std::move(event)),
latency_(latency),
creation_timestamp_(creation_timestamp),
last_coalesced_timestamp_(last_coalesced_timestamp) {
if (original_events)
original_events_.splice(original_events_.end(), *original_events);
}
EventWithCallback::~EventWithCallback() {} EventWithCallback::~EventWithCallback() {}
bool EventWithCallback::CanCoalesceWith(const EventWithCallback& other) const { bool EventWithCallback::CanCoalesceWith(const EventWithCallback& other) const {
......
...@@ -18,11 +18,26 @@ class InputHandlerProxyEventQueueTest; ...@@ -18,11 +18,26 @@ class InputHandlerProxyEventQueueTest;
class EventWithCallback { class EventWithCallback {
public: public:
struct OriginalEventWithCallback {
OriginalEventWithCallback(
ScopedWebInputEvent event,
const InputHandlerProxy::EventDispositionCallback& callback);
~OriginalEventWithCallback();
ScopedWebInputEvent event_;
InputHandlerProxy::EventDispositionCallback callback_;
};
using OriginalEventList = std::list<OriginalEventWithCallback>;
EventWithCallback( EventWithCallback(
ScopedWebInputEvent event, ScopedWebInputEvent event,
const LatencyInfo& latency, const LatencyInfo& latency,
base::TimeTicks timestamp_now, base::TimeTicks timestamp_now,
const InputHandlerProxy::EventDispositionCallback& callback); const InputHandlerProxy::EventDispositionCallback& callback);
EventWithCallback(ScopedWebInputEvent event,
const LatencyInfo& latency,
base::TimeTicks creation_timestamp,
base::TimeTicks last_coalesced_timestamp,
std::unique_ptr<OriginalEventList> original_events);
~EventWithCallback(); ~EventWithCallback();
bool CanCoalesceWith(const EventWithCallback& other) const WARN_UNUSED_RESULT; bool CanCoalesceWith(const EventWithCallback& other) const WARN_UNUSED_RESULT;
...@@ -39,23 +54,16 @@ class EventWithCallback { ...@@ -39,23 +54,16 @@ class EventWithCallback {
return last_coalesced_timestamp_; return last_coalesced_timestamp_;
} }
size_t coalesced_count() const { return original_events_.size(); } size_t coalesced_count() const { return original_events_.size(); }
OriginalEventList& original_events() { return original_events_; }
private: private:
friend class test::InputHandlerProxyEventQueueTest; friend class test::InputHandlerProxyEventQueueTest;
struct OriginalEventWithCallback {
OriginalEventWithCallback(
ScopedWebInputEvent event,
const InputHandlerProxy::EventDispositionCallback& callback);
~OriginalEventWithCallback();
ScopedWebInputEvent event_;
InputHandlerProxy::EventDispositionCallback callback_;
};
void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock); void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock);
ScopedWebInputEvent event_; ScopedWebInputEvent event_;
LatencyInfo latency_; LatencyInfo latency_;
std::list<OriginalEventWithCallback> original_events_; OriginalEventList original_events_;
base::TimeTicks creation_timestamp_; base::TimeTicks creation_timestamp_;
base::TimeTicks last_coalesced_timestamp_; base::TimeTicks last_coalesced_timestamp_;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "third_party/WebKit/public/platform/WebGestureCurve.h" #include "third_party/WebKit/public/platform/WebGestureCurve.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h" #include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "third_party/WebKit/public/platform/WebPoint.h" #include "third_party/WebKit/public/platform/WebPoint.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/blink/compositor_thread_event_queue.h" #include "ui/events/blink/compositor_thread_event_queue.h"
#include "ui/events/blink/did_overscroll_params.h" #include "ui/events/blink/did_overscroll_params.h"
#include "ui/events/blink/event_with_callback.h" #include "ui/events/blink/event_with_callback.h"
...@@ -3087,6 +3088,54 @@ TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedQueueingTime) { ...@@ -3087,6 +3088,54 @@ TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedQueueingTime) {
1); 1);
} }
TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedCoalesceScrollAndPinch) {
// Start scroll in the first frame.
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
.WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
// GSUs and GPUs in one sequence should be coalesced into 1 GSU and 1 GPU.
HandleGestureEvent(WebInputEvent::GestureScrollBegin);
HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -20);
HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -7);
HandleGestureEvent(WebInputEvent::GesturePinchUpdate, 2.0f, 13, 10);
HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -10);
HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -6);
HandleGestureEvent(WebInputEvent::GestureScrollEnd);
HandleGestureEvent(WebInputEvent::GesturePinchBegin);
HandleGestureEvent(WebInputEvent::GesturePinchUpdate, 0.2f, 2, 20);
HandleGestureEvent(WebInputEvent::GesturePinchUpdate, 10.0f, 1, 10);
HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -30);
HandleGestureEvent(WebInputEvent::GesturePinchUpdate, 0.25f, 3, 30);
HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -10);
HandleGestureEvent(WebInputEvent::GesturePinchEnd);
// Only the first GSB was dispatched.
EXPECT_EQ(7ul, event_queue().size());
EXPECT_EQ(1ul, event_disposition_recorder_.size());
EXPECT_EQ(WebInputEvent::GestureScrollUpdate, event_queue()[0]->event().type);
EXPECT_EQ(
-35,
ToWebGestureEvent(event_queue()[0]->event()).data.scrollUpdate.deltaY);
EXPECT_EQ(WebInputEvent::GesturePinchUpdate, event_queue()[1]->event().type);
EXPECT_EQ(
2.0f,
ToWebGestureEvent(event_queue()[1]->event()).data.pinchUpdate.scale);
EXPECT_EQ(WebInputEvent::GestureScrollEnd, event_queue()[2]->event().type);
EXPECT_EQ(WebInputEvent::GesturePinchBegin, event_queue()[3]->event().type);
EXPECT_EQ(WebInputEvent::GestureScrollUpdate, event_queue()[4]->event().type);
EXPECT_EQ(
-85,
ToWebGestureEvent(event_queue()[4]->event()).data.scrollUpdate.deltaY);
EXPECT_EQ(WebInputEvent::GesturePinchUpdate, event_queue()[5]->event().type);
EXPECT_EQ(
0.5f,
ToWebGestureEvent(event_queue()[5]->event()).data.pinchUpdate.scale);
EXPECT_EQ(WebInputEvent::GesturePinchEnd, event_queue()[6]->event().type);
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
}
INSTANTIATE_TEST_CASE_P(AnimateInput, INSTANTIATE_TEST_CASE_P(AnimateInput,
InputHandlerProxyTest, InputHandlerProxyTest,
testing::ValuesIn(test_types)); testing::ValuesIn(test_types));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment