15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/events/gesture_detection/motion_event_buffer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/debug/trace_event.h"
83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/events/gesture_detection/motion_event.h"
93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/events/gesture_detection/motion_event_generic.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace ui {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Latency added during resampling. A few milliseconds doesn't hurt much but
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reduces the impact of mispredicted touch positions.
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kResampleLatencyMs = 5;
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Minimum time difference between consecutive samples before attempting to
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// resample.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kResampleMinDeltaMs = 2;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Maximum time to predict forward from the last known state, to avoid
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// predicting too far into the future.  This time is further bounded by 50% of
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the last time delta.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kResampleMaxPredictionMs = 8;
26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdochtypedef ScopedVector<MotionEvent> MotionEventVector;
28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdochfloat Lerp(float a, float b, float alpha) {
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return a + alpha * (b - a);
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool CanAddSample(const MotionEvent& event0, const MotionEvent& event1) {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(event0.GetAction(), MotionEvent::ACTION_MOVE);
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (event1.GetAction() != MotionEvent::ACTION_MOVE)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t pointer_count = event0.GetPointerCount();
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (pointer_count != event1.GetPointerCount())
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t event0_i = 0; event0_i < pointer_count; ++event0_i) {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const int id = event0.GetPointerId(event0_i);
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const int event1_i = event1.FindPointerIndexOfId(id);
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (event1_i == -1)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (event0.GetToolType(event0_i) != event1.GetToolType(event1_i))
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ShouldResampleTool(MotionEvent::ToolType tool) {
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return tool == MotionEvent::TOOL_TYPE_UNKNOWN ||
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         tool == MotionEvent::TOOL_TYPE_FINGER;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t CountSamplesNoLaterThan(const MotionEventVector& batch,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               base::TimeTicks time) {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t count = 0;
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (count < batch.size() && batch[count]->GetEventTime() <= time)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ++count;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return count;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MotionEventVector ConsumeSamplesNoLaterThan(MotionEventVector* batch,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            base::TimeTicks time) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(batch);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t count = CountSamplesNoLaterThan(*batch, time);
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GE(batch->size(), count);
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (count == 0)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return MotionEventVector();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (count == batch->size())
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return batch->Pass();
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(jdduke): Use a ScopedDeque to work around this mess.
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MotionEventVector unconsumed_batch;
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unconsumed_batch.insert(
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      unconsumed_batch.begin(), batch->begin() + count, batch->end());
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  batch->weak_erase(batch->begin() + count, batch->end());
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unconsumed_batch.swap(*batch);
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_GE(unconsumed_batch.size(), 1U);
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return unconsumed_batch.Pass();
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PointerProperties PointerFromMotionEvent(const MotionEvent& event,
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         size_t pointer_index) {
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PointerProperties result;
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result.id = event.GetPointerId(pointer_index);
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result.tool_type = event.GetToolType(pointer_index);
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result.x = event.GetX(pointer_index);
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result.y = event.GetY(pointer_index);
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result.raw_x = event.GetRawX(pointer_index);
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result.raw_y = event.GetRawY(pointer_index);
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result.pressure = event.GetPressure(pointer_index);
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result.touch_major = event.GetTouchMajor(pointer_index);
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result.touch_minor = event.GetTouchMinor(pointer_index);
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result.orientation = event.GetOrientation(pointer_index);
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return result;
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PointerProperties ResamplePointer(const MotionEvent& event0,
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  const MotionEvent& event1,
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  size_t event0_pointer_index,
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  size_t event1_pointer_index,
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  float alpha) {
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(event0.GetPointerId(event0_pointer_index),
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            event1.GetPointerId(event1_pointer_index));
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If the tool should not be resampled, use the latest event in the valid
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // horizon (i.e., the event no later than the time interpolated by alpha).
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!ShouldResampleTool(event0.GetToolType(event0_pointer_index))) {
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (alpha > 1)
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return PointerFromMotionEvent(event1, event1_pointer_index);
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    else
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return PointerFromMotionEvent(event0, event0_pointer_index);
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PointerProperties p(PointerFromMotionEvent(event0, event0_pointer_index));
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  p.x = Lerp(p.x, event1.GetX(event1_pointer_index), alpha);
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  p.y = Lerp(p.y, event1.GetY(event1_pointer_index), alpha);
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  p.raw_x = Lerp(p.raw_x, event1.GetRawX(event1_pointer_index), alpha);
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  p.raw_y = Lerp(p.raw_y, event1.GetRawY(event1_pointer_index), alpha);
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return p;
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<MotionEvent> ResampleMotionEvent(const MotionEvent& event0,
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                            const MotionEvent& event1,
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            base::TimeTicks resample_time) {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(MotionEvent::ACTION_MOVE, event0.GetAction());
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(event0.GetPointerCount(), event1.GetPointerCount());
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::TimeTicks time0 = event0.GetEventTime();
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::TimeTicks time1 = event1.GetEventTime();
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(time0 < time1);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(time0 <= resample_time);
13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const float alpha = (resample_time - time0).InMillisecondsF() /
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      (time1 - time0).InMillisecondsF();
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MotionEventGeneric> event;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t pointer_count = event0.GetPointerCount();
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(pointer_count, event1.GetPointerCount());
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t event0_i = 0; event0_i < pointer_count; ++event0_i) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int event1_i = event1.FindPointerIndexOfId(event0.GetPointerId(event0_i));
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_NE(event1_i, -1);
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PointerProperties pointer = ResamplePointer(
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event0, event1, event0_i, static_cast<size_t>(event1_i), alpha);
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (event0_i == 0) {
15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      event.reset(new MotionEventGeneric(
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          MotionEvent::ACTION_MOVE, resample_time, pointer));
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      event->PushPointer(pointer);
15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(event);
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event->set_id(event0.GetId());
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event->set_action_index(event0.GetActionIndex());
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  event->set_button_state(event0.GetButtonState());
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return event.PassAs<MotionEvent>();
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MotionEvent implementation for storing multiple events, with the most
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// recent event used as the base event, and prior events used as the history.
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class CompoundMotionEvent : public ui::MotionEvent {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit CompoundMotionEvent(MotionEventVector events)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : events_(events.Pass()) {
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_GE(events_.size(), 1U);
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~CompoundMotionEvent() {}
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual int GetId() const OVERRIDE { return latest().GetId(); }
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual Action GetAction() const OVERRIDE { return latest().GetAction(); }
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual int GetActionIndex() const OVERRIDE {
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return latest().GetActionIndex();
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual size_t GetPointerCount() const OVERRIDE {
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return latest().GetPointerCount();
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual int GetPointerId(size_t pointer_index) const OVERRIDE {
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return latest().GetPointerId(pointer_index);
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual float GetX(size_t pointer_index) const OVERRIDE {
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return latest().GetX(pointer_index);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual float GetY(size_t pointer_index) const OVERRIDE {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return latest().GetY(pointer_index);
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual float GetRawX(size_t pointer_index) const OVERRIDE {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return latest().GetRawX(pointer_index);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual float GetRawY(size_t pointer_index) const OVERRIDE {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return latest().GetRawY(pointer_index);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual float GetTouchMajor(size_t pointer_index) const OVERRIDE {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return latest().GetTouchMajor(pointer_index);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual float GetTouchMinor(size_t pointer_index) const OVERRIDE {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return latest().GetTouchMinor(pointer_index);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual float GetOrientation(size_t pointer_index) const OVERRIDE {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return latest().GetOrientation(pointer_index);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual float GetPressure(size_t pointer_index) const OVERRIDE {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return latest().GetPressure(pointer_index);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ToolType GetToolType(size_t pointer_index) const OVERRIDE {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return latest().GetToolType(pointer_index);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetButtonState() const OVERRIDE {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return latest().GetButtonState();
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetFlags() const OVERRIDE { return latest().GetFlags(); }
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual base::TimeTicks GetEventTime() const OVERRIDE {
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return latest().GetEventTime();
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual size_t GetHistorySize() const OVERRIDE { return events_.size() - 1; }
241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual base::TimeTicks GetHistoricalEventTime(
243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      size_t historical_index) const OVERRIDE {
244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DCHECK_LT(historical_index, GetHistorySize());
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return events_[historical_index]->GetEventTime();
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual float GetHistoricalTouchMajor(
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      size_t pointer_index,
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      size_t historical_index) const OVERRIDE {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LT(historical_index, GetHistorySize());
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return events_[historical_index]->GetTouchMajor();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual float GetHistoricalX(size_t pointer_index,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               size_t historical_index) const OVERRIDE {
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_LT(historical_index, GetHistorySize());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return events_[historical_index]->GetX(pointer_index);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual float GetHistoricalY(size_t pointer_index,
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               size_t historical_index) const OVERRIDE {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LT(historical_index, GetHistorySize());
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return events_[historical_index]->GetY(pointer_index);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual scoped_ptr<MotionEvent> Clone() const OVERRIDE {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MotionEventVector cloned_events;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cloned_events.reserve(events_.size());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < events_.size(); ++i)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cloned_events.push_back(events_[i]->Clone().release());
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return scoped_ptr<MotionEvent>(
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new CompoundMotionEvent(cloned_events.Pass()));
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual scoped_ptr<MotionEvent> Cancel() const OVERRIDE {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return latest().Cancel();
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the new, resampled event, or NULL if none was created.
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jdduke): Revisit resampling to handle cases where alternating frames
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are resampled or resampling is otherwise inconsistent, e.g., a 90hz input
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and 60hz frame signal could phase-align such that even frames yield an
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extrapolated event and odd frames are not resampled, crbug.com/399381.
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const MotionEvent* TryResample(base::TimeTicks resample_time,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const ui::MotionEvent* next) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(GetAction(), ACTION_MOVE);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ui::MotionEvent* event0 = NULL;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ui::MotionEvent* event1 = NULL;
29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (next) {
29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      DCHECK(resample_time < next->GetEventTime());
29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // Interpolate between current sample and future sample.
29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      event0 = events_.back();
29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      event1 = next;
29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    } else if (events_.size() >= 2) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Extrapolate future sample using current sample and past sample.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event0 = events_[events_.size() - 2];
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      event1 = events_[events_.size() - 1];
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::TimeTicks time1 = event1->GetEventTime();
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeTicks max_predict =
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          time1 +
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          std::min((event1->GetEventTime() - event0->GetEventTime()) / 2,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::TimeDelta::FromMilliseconds(kResampleMaxPredictionMs));
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (resample_time > max_predict) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TRACE_EVENT_INSTANT2("input",
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "MotionEventBuffer::TryResample prediction adjust",
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             TRACE_EVENT_SCOPE_THREAD,
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             "original(ms)",
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             (resample_time - time1).InMilliseconds(),
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "adjusted(ms)",
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             (max_predict - time1).InMilliseconds());
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resample_time = max_predict;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TRACE_EVENT_INSTANT0("input",
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           "MotionEventBuffer::TryResample insufficient data",
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           TRACE_EVENT_SCOPE_THREAD);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK(event0);
32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK(event1);
32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const base::TimeTicks time0 = event0->GetEventTime();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::TimeTicks time1 = event1->GetEventTime();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta delta = time1 - time0;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delta < base::TimeDelta::FromMilliseconds(kResampleMinDeltaMs)) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TRACE_EVENT_INSTANT1("input",
32958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           "MotionEventBuffer::TryResample failure",
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           TRACE_EVENT_SCOPE_THREAD,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           "event_delta_too_small(ms)",
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           delta.InMilliseconds());
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    events_.push_back(
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ResampleMotionEvent(*event0, *event1, resample_time).release());
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return events_.back();
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t samples() const { return events_.size(); }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const MotionEvent& latest() const { return *events_.back(); }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Events are in order from oldest to newest.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MotionEventVector events_;
3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CompoundMotionEvent);
3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
3513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace
3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)MotionEventBuffer::MotionEventBuffer(MotionEventBufferClient* client,
3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     bool enable_resampling)
3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : client_(client), resample_(enable_resampling) {
3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)MotionEventBuffer::~MotionEventBuffer() {
3603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void MotionEventBuffer::OnMotionEvent(const MotionEvent& event) {
3633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (event.GetAction() != MotionEvent::ACTION_MOVE) {
3643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    last_extrapolated_event_time_ = base::TimeTicks();
3653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!buffered_events_.empty())
3663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FlushWithoutResampling(buffered_events_.Pass());
3673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    client_->ForwardMotionEvent(event);
3683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
3693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Guard against events that are *older* than the last one that may have been
3723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // artificially synthesized.
3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!last_extrapolated_event_time_.is_null()) {
3743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DCHECK(buffered_events_.empty());
3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (event.GetEventTime() < last_extrapolated_event_time_)
3763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
3773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    last_extrapolated_event_time_ = base::TimeTicks();
3783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<MotionEvent> clone = event.Clone();
3813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (buffered_events_.empty()) {
3823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    buffered_events_.push_back(clone.release());
3833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    client_->SetNeedsFlush();
3843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
3853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (CanAddSample(*buffered_events_.front(), *clone)) {
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(buffered_events_.back()->GetEventTime() <= clone->GetEventTime());
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FlushWithoutResampling(buffered_events_.Pass());
3913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  buffered_events_.push_back(clone.release());
3943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // No need to request another flush as the first event will have requested it.
39558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
39658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
39758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void MotionEventBuffer::Flush(base::TimeTicks frame_time) {
39858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (buffered_events_.empty())
39958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
40058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
40158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Shifting the sample time back slightly minimizes the potential for
40258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // misprediction when extrapolating events.
40358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (resample_)
40458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    frame_time -= base::TimeDelta::FromMilliseconds(kResampleLatencyMs);
40558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
40658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // TODO(jdduke): Use a persistent MotionEventVector vector for temporary
40758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // storage.
40858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  MotionEventVector events(
40958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ConsumeSamplesNoLaterThan(&buffered_events_, frame_time));
41058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (events.empty()) {
41158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK(!buffered_events_.empty());
41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    client_->SetNeedsFlush();
41358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
41458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
41558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
41658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!resample_ || (events.size() == 1 && buffered_events_.empty())) {
41758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    FlushWithoutResampling(events.Pass());
41858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!buffered_events_.empty())
41958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      client_->SetNeedsFlush();
4201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
42158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
42258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
42358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CompoundMotionEvent resampled_event(events.Pass());
42458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::TimeTicks original_event_time = resampled_event.GetEventTime();
42558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const MotionEvent* next_event =
42658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      !buffered_events_.empty() ? buffered_events_.front() : NULL;
42758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
42858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Try to interpolate/extrapolate a new event at |frame_time|. Note that
42958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |new_event|, if non-NULL, is owned by |resampled_event_|.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const MotionEvent* new_event =
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      resampled_event.TryResample(frame_time, next_event);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Log the extrapolated event time, guarding against subsequently queued
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // events that might have an earlier timestamp.
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!next_event && new_event &&
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_event->GetEventTime() > original_event_time) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_extrapolated_event_time_ = new_event->GetEventTime();
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_extrapolated_event_time_ = base::TimeTicks();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_->ForwardMotionEvent(resampled_event);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!buffered_events_.empty())
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_->SetNeedsFlush();
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MotionEventBuffer::FlushWithoutResampling(MotionEventVector events) {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_extrapolated_event_time_ = base::TimeTicks();
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (events.empty())
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (events.size() == 1) {
45358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Avoid CompoundEvent creation to prevent unnecessary allocations.
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<MotionEvent> event(events.front());
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events.weak_clear();
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_->ForwardMotionEvent(*event);
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompoundMotionEvent compound_event(events.Pass());
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_->ForwardMotionEvent(compound_event);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ui
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)