/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
TEST_F(TouchResamplerTest, BasicExtrapolation) { // Execute the following sequence: // // 0----------10-------16-----20---------------32------------ // * touchstart at (10, 10) // * touchmove at (20, 20) // * frame // * touchend at (20, 20) // * frame // // And expect the following output: // // 0----------10-------16-----20---------------32------------ // * touchstart at (10, 10) // * touchmove at (26, 26) // * touchmove at (20, 20) // * touchend at (20, 20) // // The first frame should emit an extrapolated touchmove from the position // data in the touchstart and touchmove events. // The touchend should force a synthesized touchmove that returns back to a // non-resampled position.
EXPECT_FALSE(resampler.InTouchingState());
auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
ScreenIntPoint(10, 10));
EXPECT_TRUE(resampler.InTouchingState()); auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(10.0),
ScreenIntPoint(20, 20));
// No more events should be produced from here on out.
resampler.NotifyFrame(Time(32.0)); auto outgoing = resampler.ConsumeOutgoingEvents();
EXPECT_TRUE(outgoing.empty());
}
TEST_F(TouchResamplerTest, BasicInterpolation) { // Same test as BasicExtrapolation, but with a frame time that's 10ms earlier. // // Execute the following sequence: // // 0------6---10-----------20--22------------30------------- // * touchstart at (10, 10) // * touchmove at (20, 20) // * frame // * touchend at (20, 20) // * frame // // And expect the following output: // // 0------6---10-----------20--22------------30------------- // * touchstart at (10, 10) // * touchmove (16, 16) // * touchmove (20, 20) // * touchend at (20, 20) // // The first frame should emit an interpolated touchmove from the position // data in the touchstart and touchmove events. // The touchend should create a touchmove that returns back to a non-resampled // position.
auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
ScreenIntPoint(10, 10));
EXPECT_TRUE(resampler.InTouchingState()); auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(10.0),
ScreenIntPoint(20, 20));
// No more events should be produced from here on out.
resampler.NotifyFrame(Time(22.0)); auto outgoing = resampler.ConsumeOutgoingEvents();
EXPECT_TRUE(outgoing.empty());
}
TEST_F(TouchResamplerTest, InterpolationFromHistoricalData) { // Interpolate from the historical data in a touch move event. // // Execute the following sequence: // // 0----------10-------16-----20-----------30--32------------ // * touchstart at (10, 10) // * [hist] at (20, 25) for // `---------------* touchmove at (30, 30) // * frame // * touchend at (30, 30) // * frame // // And expect the following output: // // 0----------10-------16-----20-----------30--32------------ // * touchstart at (10, 10) // * [hist] at (20, 25) for // `--------* touchmove at (26, 28) // * touchmove at (30, 30) // * touchend at (30, 30) // // The first frame should emit an interpolated touchmove from the position // data in the touchmove event, and integrate the historical data point into // the resampled event. // The touchend should force a synthesized touchmove that returns back to a // non-resampled position.
// This also tests that interpolation works for both x and y, by giving the // historical datapoint different values for x and y. // (26, 28) is 60% of the way from (20, 25) to (30, 30).
auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
ScreenIntPoint(10, 10)); auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
{{Time(10.0), ScreenIntPoint(20, 25)}},
Time(20.0), ScreenIntPoint(30, 30));
resampler.NotifyFrame(Time(16.0)); auto idEnd2 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(30.0),
ScreenIntPoint(30, 30));
resampler.NotifyFrame(Time(32.0));
auto outgoingMove1 = std::move(outgoing.front());
outgoing.pop();
EXPECT_EQ(outgoingMove1.mEventId, Some(idMove1)); // (26, 28) is 60% of the way from (20, 25) to (30, 30).
CheckEvent(outgoingMove1.mEvent, MultiTouchInput::MULTITOUCH_MOVE,
{{Time(10.0), ScreenIntPoint(20, 25)}}, Time(16.0),
ScreenIntPoint(26, 28));
auto outgoingStart3 = std::move(outgoing.front());
outgoing.pop();
EXPECT_EQ(outgoingStart3.mEventId, Some(idStart3));
EXPECT_EQ(outgoingStart3.mEvent.mType, MultiTouchInput::MULTITOUCH_START);
CheckTime(outgoingStart3.mEvent.mTimeStamp, Time(30.0));
EXPECT_EQ(outgoingStart3.mEvent.mTouches.Length(), size_t(2)); // touch order should be taken from the original touch start event
EXPECT_EQ(outgoingStart3.mEvent.mTouches[0].mIdentifier, 2);
EXPECT_EQ(outgoingStart3.mEvent.mTouches[0].mScreenPoint,
ScreenIntPoint(100, 10));
EXPECT_EQ(outgoingStart3.mEvent.mTouches[1].mIdentifier, 1);
EXPECT_EQ(outgoingStart3.mEvent.mTouches[1].mScreenPoint,
ScreenIntPoint(30, 40));
auto outgoingMove4 = std::move(outgoing.front());
outgoing.pop();
EXPECT_EQ(outgoingMove4.mEventId, Some(idMove4));
EXPECT_EQ(outgoingMove4.mEvent.mType, MultiTouchInput::MULTITOUCH_MOVE);
CheckTime(outgoingMove4.mEvent.mTimeStamp, Time(32.0));
EXPECT_EQ(outgoingMove4.mEvent.mTouches.Length(), size_t(2)); // Touch order should be taken from the original touch move event. // Both touches should be resampled.
EXPECT_EQ(outgoingMove4.mEvent.mTouches[0].mIdentifier, 1);
EXPECT_EQ(outgoingMove4.mEvent.mTouches[0].mScreenPoint,
ScreenIntPoint(30, 42));
EXPECT_EQ(outgoingMove4.mEvent.mTouches[1].mIdentifier, 2);
EXPECT_EQ(outgoingMove4.mEvent.mTouches[1].mScreenPoint,
ScreenIntPoint(100, 14));
auto outgoingMove5 = std::move(outgoing.front());
outgoing.pop();
EXPECT_EQ(outgoingMove5.mEventId, Some(idMove5));
EXPECT_EQ(outgoingMove5.mEvent.mType, MultiTouchInput::MULTITOUCH_MOVE);
CheckTime(outgoingMove5.mEvent.mTimeStamp, Time(50.0));
EXPECT_EQ(outgoingMove5.mEvent.mTouches.Length(), size_t(2)); // touch order should be taken from the original touch move event
EXPECT_EQ(outgoingMove5.mEvent.mTouches[0].mIdentifier, 1);
EXPECT_EQ(outgoingMove5.mEvent.mTouches[0].mScreenPoint,
ScreenIntPoint(30, 60));
EXPECT_EQ(outgoingMove5.mEvent.mTouches[0].mHistoricalData.Length(),
size_t(1));
CheckTime(outgoingMove5.mEvent.mTouches[0].mHistoricalData[0].mTimeStamp,
Time(40.0));
EXPECT_EQ(outgoingMove5.mEvent.mTouches[0].mHistoricalData[0].mScreenPoint,
ScreenIntPoint(30, 50));
EXPECT_EQ(outgoingMove5.mEvent.mTouches[1].mIdentifier, 2);
EXPECT_EQ(outgoingMove5.mEvent.mTouches[1].mScreenPoint,
ScreenIntPoint(100, 40));
EXPECT_EQ(outgoingMove5.mEvent.mTouches[1].mHistoricalData.Length(),
size_t(1));
CheckTime(outgoingMove5.mEvent.mTouches[1].mHistoricalData[0].mTimeStamp,
Time(40.0));
EXPECT_EQ(outgoingMove5.mEvent.mTouches[1].mHistoricalData[0].mScreenPoint,
ScreenIntPoint(100, 30));
auto outgoingMove7 = std::move(outgoing.front());
outgoing.pop();
EXPECT_EQ(outgoingMove7.mEventId, Some(idMove7)); // No extrapolation because the frame at 64.0 cleared the data points because // there was no pending touch move event at that point
CheckEvent(outgoingMove7.mEvent, MultiTouchInput::MULTITOUCH_MOVE, {},
Time(60.0), ScreenIntPoint(100, 60));
EXPECT_EQ(outgoingMove7.mEvent.mTouches[0].mIdentifier, 2);
// There was no event between two frames here, so we expect a reset event, // so that we pause at a non-resampled position.
{Nothing(),
MultiTouchInput::MULTITOUCH_MOVE,
{},
Time(48.0),
ScreenIntPoint(50, 40)},
TEST_F(TouchResamplerTest, MultipleMoveEvents) { // Test what happens if multiple touch move events appear between two frames. // This scenario shouldn't occur on Android but we should be able to deal with // it anyway. Check that we don't discard any event IDs. auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
ScreenIntPoint(0, 0)); auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(10.0),
ScreenIntPoint(0, 10));
resampler.NotifyFrame(Time(11.0)); // 16 - 5 auto idMove2 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
{{Time(20.0), ScreenIntPoint(0, 20)}}, Time(30.0),
ScreenIntPoint(0, 30)); auto idMove3 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(40.0),
ScreenIntPoint(0, 40)); auto idMove4 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
{{Time(45.0), ScreenIntPoint(0, 45)}}, Time(50.0),
ScreenIntPoint(0, 50)); auto idMove5 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(55.0),
ScreenIntPoint(0, 55));
resampler.NotifyFrame(Time(43.0)); // 48 - 5
resampler.NotifyFrame(Time(59.0)); // 64 - 5 auto idEnd5 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(70.0),
ScreenIntPoint(0, 60));
// kTouchResampleMaxPredictMs == 8 // Refuse to predict more than 8ms into the future, the fingers might have // paused. Make an event for time 52 (= 44 + 8) instead of 59.
{Some(idMove1),
MultiTouchInput::MULTITOUCH_MOVE,
{{Time(20.0), ScreenIntPoint(0, 20)},
{Time(32.0), ScreenIntPoint(0, 32)},
{Time(44.0), ScreenIntPoint(0, 44)}},
Time(52.0),
ScreenIntPoint(0, 52)},
TEST_F(TouchResamplerTest, LimitBacksampling) { auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
ScreenIntPoint(0, 0)); // Fingers move until time 44, then pause. UI thread is occupied until 64. // Then we get a frame callback with a very outdated frametime. auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
{{Time(20.0), ScreenIntPoint(0, 20)},
{Time(32.0), ScreenIntPoint(0, 32)}},
Time(44.0), ScreenIntPoint(0, 44));
resampler.NotifyFrame(Time(11.0)); // 16 - 5 auto idEnd2 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(70.0),
ScreenIntPoint(0, 44));
// kTouchResampleMaxBacksampleMs == 20 // Refuse to sample further back than 20ms before the last data point. // Make an event for time 24 (= 44 - 20) instead of time 11.
{Some(idMove1),
MultiTouchInput::MULTITOUCH_MOVE,
{{Time(20.0), ScreenIntPoint(0, 20)}},
Time(24.0),
ScreenIntPoint(0, 24)},
// kTouchResampleOldTouchThresholdMs == 17 // Refuse to extrapolate from a data point that's more than 17ms older // than the frame time.
{Some(idMove1),
MultiTouchInput::MULTITOUCH_MOVE,
{{Time(20.0), ScreenIntPoint(0, 20)},
{Time(30.0), ScreenIntPoint(0, 30)}},
Time(40.0),
ScreenIntPoint(0, 40)},
// kTouchResampleWindowSize == 40 // Refuse to resample between two data points that are more than 40ms // apart.
{Some(idMove1),
MultiTouchInput::MULTITOUCH_MOVE,
{{Time(10.0), ScreenIntPoint(0, 10)}},
Time(55.0),
ScreenIntPoint(0, 55)},
// kTouchResampleWindowSize == 40 // Refuse to resample between two data points that are more than 40ms // apart.
{Some(idMove1),
MultiTouchInput::MULTITOUCH_MOVE,
{{Time(10.0), ScreenIntPoint(0, 10)}},
Time(60.0),
ScreenIntPoint(0, 60)},
// Discard the historical data point from time 18, because we've already // sent out an event with time 20 and don't want to go back before that.
{Some(idMove2),
MultiTouchInput::MULTITOUCH_MOVE,
{},
Time(25.0),
ScreenIntPoint(0, 25)},
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.