diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-06-18 14:10:49 +0200 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> | 2015-06-18 13:53:24 +0000 |
commit | 813fbf95af77a531c57a8c497345ad2c61d475b3 (patch) | |
tree | 821b2c8de8365f21b6c9ba17a236fb3006a1d506 /chromium/ui/events/gesture_detection | |
parent | af6588f8d723931a298c995fa97259bb7f7deb55 (diff) | |
download | qtwebengine-chromium-813fbf95af77a531c57a8c497345ad2c61d475b3.tar.gz |
BASELINE: Update chromium to 44.0.2403.47
Change-Id: Ie056fedba95cf5e5c76b30c4b2c80fca4764aa2f
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Diffstat (limited to 'chromium/ui/events/gesture_detection')
30 files changed, 966 insertions, 491 deletions
diff --git a/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc b/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc index 76ee5201d1a..7be795a9b06 100644 --- a/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc +++ b/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc @@ -10,35 +10,53 @@ namespace ui { +FilteredGestureProvider::TouchHandlingResult::TouchHandlingResult() + : succeeded(false), did_generate_scroll(false) { +} + FilteredGestureProvider::FilteredGestureProvider( const GestureProvider::Config& config, GestureProviderClient* client) : client_(client), gesture_provider_(config, this), gesture_filter_(this), - handling_event_(false) {} + handling_event_(false), + last_touch_event_did_generate_scroll_(false) { +} -bool FilteredGestureProvider::OnTouchEvent(const MotionEvent& event) { +FilteredGestureProvider::TouchHandlingResult +FilteredGestureProvider::OnTouchEvent(const MotionEvent& event) { DCHECK(!handling_event_); base::AutoReset<bool> handling_event(&handling_event_, true); pending_gesture_packet_ = GestureEventDataPacket::FromTouch(event); - + last_touch_event_did_generate_scroll_ = false; if (!gesture_provider_.OnTouchEvent(event)) - return false; + return TouchHandlingResult(); - TouchDispositionGestureFilter::PacketResult result = + TouchDispositionGestureFilter::PacketResult filter_result = gesture_filter_.OnGesturePacket(pending_gesture_packet_); - if (result != TouchDispositionGestureFilter::SUCCESS) { + if (filter_result != TouchDispositionGestureFilter::SUCCESS) { NOTREACHED() << "Invalid touch gesture sequence detected."; - return false; + return TouchHandlingResult(); } - return true; + TouchHandlingResult result; + result.succeeded = true; + result.did_generate_scroll = last_touch_event_did_generate_scroll_; + return result; +} + +void FilteredGestureProvider::OnAsyncTouchEventAck(bool event_consumed) { + gesture_filter_.OnTouchEventAckForQueueFront(event_consumed); +} + +void FilteredGestureProvider::OnSyncTouchEventAck(bool event_consumed) { + gesture_filter_.OnTouchEventAckForQueueBack(event_consumed); } -void FilteredGestureProvider::OnTouchEventAck(bool event_consumed) { - gesture_filter_.OnTouchEventAck(event_consumed); +void FilteredGestureProvider::ResetDetection() { + gesture_provider_.ResetDetection(); } void FilteredGestureProvider::SetMultiTouchZoomSupportEnabled( @@ -61,6 +79,11 @@ const ui::MotionEvent* FilteredGestureProvider::GetCurrentDownEvent() const { void FilteredGestureProvider::OnGestureEvent(const GestureEventData& event) { if (handling_event_) { + if (event.details.type() == ui::ET_GESTURE_SCROLL_BEGIN || + event.details.type() == ui::ET_GESTURE_SCROLL_UPDATE || + event.details.type() == ui::ET_SCROLL_FLING_START) { + last_touch_event_did_generate_scroll_ = true; + } pending_gesture_packet_.Push(event); return; } diff --git a/chromium/ui/events/gesture_detection/filtered_gesture_provider.h b/chromium/ui/events/gesture_detection/filtered_gesture_provider.h index 231e62bf7fa..21b9a961472 100644 --- a/chromium/ui/events/gesture_detection/filtered_gesture_provider.h +++ b/chromium/ui/events/gesture_detection/filtered_gesture_provider.h @@ -6,6 +6,7 @@ #define UI_EVENTS_GESTURE_DETECTION_FILTERED_GESTURE_PROVIDER_H_ #include "base/basictypes.h" +#include "base/compiler_specific.h" #include "ui/events/gesture_detection/gesture_event_data_packet.h" #include "ui/events/gesture_detection/gesture_provider.h" #include "ui/events/gesture_detection/touch_disposition_gesture_filter.h" @@ -23,16 +24,32 @@ class GESTURE_DETECTION_EXPORT FilteredGestureProvider FilteredGestureProvider(const GestureProvider::Config& config, GestureProviderClient* client); - // Returns true if |event| was both valid and successfully handled by the - // gesture provider. Otherwise, returns false, in which case the caller - // should drop |event|, not forwarding it to the renderer. - bool OnTouchEvent(const MotionEvent& event); + struct TouchHandlingResult { + TouchHandlingResult(); - // To be called upon ack of an event that was forwarded after a successful - // call to |OnTouchEvent()|. - void OnTouchEventAck(bool event_consumed); + // True if |event| was both valid and successfully handled by the + // gesture provider. Otherwise, false, in which case the caller should drop + // |event| and cease further propagation. + bool succeeded; + + // Whether |event| produced scrolling motion, either the start of a scroll, + // subsequent scroll movement or a fling event. + // TODO(jdduke): Figure out a way to guarantee that this bit propagates with + // the processed touch event as it moves downstream. + bool did_generate_scroll; + }; + TouchHandlingResult OnTouchEvent(const MotionEvent& event) WARN_UNUSED_RESULT; + + // To be called upon asynchronous ack of an event that was forwarded + // after a successful call to |OnTouchEvent()|. + void OnAsyncTouchEventAck(bool event_consumed); + + // To be called upon synchronous ack of an event that was forwarded + // after a successful call to |OnTouchEvent()|. + void OnSyncTouchEventAck(bool event_consumed); // Methods delegated to |gesture_provider_|. + void ResetDetection(); void SetMultiTouchZoomSupportEnabled(bool enabled); void SetDoubleTapSupportForPlatformEnabled(bool enabled); void SetDoubleTapSupportForPageEnabled(bool enabled); @@ -51,6 +68,7 @@ class GESTURE_DETECTION_EXPORT FilteredGestureProvider ui::TouchDispositionGestureFilter gesture_filter_; bool handling_event_; + bool last_touch_event_did_generate_scroll_; ui::GestureEventDataPacket pending_gesture_packet_; DISALLOW_COPY_AND_ASSIGN(FilteredGestureProvider); diff --git a/chromium/ui/events/gesture_detection/filtered_gesture_provider_unittest.cc b/chromium/ui/events/gesture_detection/filtered_gesture_provider_unittest.cc new file mode 100644 index 00000000000..d60490ce71b --- /dev/null +++ b/chromium/ui/events/gesture_detection/filtered_gesture_provider_unittest.cc @@ -0,0 +1,84 @@ +// Copyright 2014 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 "base/basictypes.h" +#include "base/message_loop/message_loop.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/gesture_detection/filtered_gesture_provider.h" +#include "ui/events/test/motion_event_test_utils.h" + +namespace ui { + +class FilteredGestureProviderTest : public GestureProviderClient, + public testing::Test { + public: + FilteredGestureProviderTest() {} + ~FilteredGestureProviderTest() override {} + + // GestureProviderClient implementation. + void OnGestureEvent(const GestureEventData&) override {} + + private: + base::MessageLoopForUI message_loop_; +}; + +TEST_F(FilteredGestureProviderTest, TouchDidGenerateScroll) { + GestureProvider::Config config; + FilteredGestureProvider provider(config, this); + + const float kSlopRegion = config.gesture_detector_config.touch_slop; + + test::MockMotionEvent event; + event.set_event_time(base::TimeTicks::Now()); + event.PressPoint(0, 0); + auto result = provider.OnTouchEvent(event); + EXPECT_TRUE(result.succeeded); + EXPECT_FALSE(result.did_generate_scroll); + + event.MovePoint(0, kSlopRegion / 2.f, 0); + result = provider.OnTouchEvent(event); + EXPECT_TRUE(result.succeeded); + EXPECT_FALSE(result.did_generate_scroll); + + // Exceeding the slop should triggering scrolling and be reflected in the API. + event.MovePoint(0, kSlopRegion * 2.f, 0); + result = provider.OnTouchEvent(event); + EXPECT_TRUE(result.succeeded); + EXPECT_TRUE(result.did_generate_scroll); + + // No movement should indicate no scrolling. + result = provider.OnTouchEvent(event); + EXPECT_TRUE(result.succeeded); + EXPECT_FALSE(result.did_generate_scroll); + + // Nonzero movement should reflect scrolling after exceeding the slop region. + event.MovePoint(0, 0, 0); + result = provider.OnTouchEvent(event); + EXPECT_TRUE(result.succeeded); + EXPECT_TRUE(result.did_generate_scroll); + + // Ending a touch with no fling should not indicate scrolling. + event.ReleasePoint(); + result = provider.OnTouchEvent(event); + EXPECT_TRUE(result.succeeded); + EXPECT_FALSE(result.did_generate_scroll); + + // Ending a touch with a fling *should* indicate scrolling. + base::TimeTicks time = base::TimeTicks::Now(); + event.PressPoint(0, 0); + event.set_event_time(time); + ASSERT_TRUE(provider.OnTouchEvent(event).succeeded); + + time += base::TimeDelta::FromMilliseconds(10); + event.MovePoint(0, kSlopRegion * 50, 0); + event.set_event_time(time); + ASSERT_TRUE(provider.OnTouchEvent(event).succeeded); + + event.ReleasePoint(); + result = provider.OnTouchEvent(event); + EXPECT_TRUE(result.succeeded); + EXPECT_TRUE(result.did_generate_scroll); +} + +} // namespace ui diff --git a/chromium/ui/events/gesture_detection/gesture_configuration.cc b/chromium/ui/events/gesture_detection/gesture_configuration.cc index b93ab06f91f..3e5ae290a1a 100644 --- a/chromium/ui/events/gesture_detection/gesture_configuration.cc +++ b/chromium/ui/events/gesture_detection/gesture_configuration.cc @@ -5,9 +5,28 @@ #include "ui/events/gesture_detection/gesture_configuration.h" namespace ui { +namespace { + +GestureConfiguration* instance = nullptr; + +} // namespace + +// static +void GestureConfiguration::SetInstance(GestureConfiguration* config) { + instance = config; +} + +// static +GestureConfiguration* GestureConfiguration::GetInstance() { + if (instance) + return instance; + + return GestureConfiguration::GetPlatformSpecificInstance(); +} GestureConfiguration::GestureConfiguration() : default_radius_(25), + double_tap_enabled_(false), double_tap_timeout_in_ms_(400), fling_max_cancel_to_down_time_in_ms_(400), fling_max_tap_gap_time_in_ms_(200), @@ -32,9 +51,8 @@ GestureConfiguration::GestureConfiguration() // The default value of min_scaling_touch_major_ is 2 * default_radius_. min_scaling_touch_major_(50), min_swipe_velocity_(20), - velocity_tracker_strategy_(VelocityTracker::Strategy::STRATEGY_DEFAULT), -// TODO(jdduke): Disable and remove entirely when issues with intermittent -// scroll end detection on the Pixel are resolved, crbug.com/353702. + // TODO(jdduke): Disable and remove entirely when issues with intermittent + // scroll end detection on the Pixel are resolved, crbug.com/353702. #if defined(OS_CHROMEOS) scroll_debounce_interval_in_ms_(30), #else @@ -47,7 +65,8 @@ GestureConfiguration::GestureConfiguration() span_slop_(30), swipe_enabled_(false), tab_scrub_activation_delay_in_ms_(200), - two_finger_tap_enabled_(false) { + two_finger_tap_enabled_(false), + velocity_tracker_strategy_(VelocityTracker::Strategy::STRATEGY_DEFAULT) { } GestureConfiguration::~GestureConfiguration() { diff --git a/chromium/ui/events/gesture_detection/gesture_configuration.h b/chromium/ui/events/gesture_detection/gesture_configuration.h index de05e111454..78234a02dd2 100644 --- a/chromium/ui/events/gesture_detection/gesture_configuration.h +++ b/chromium/ui/events/gesture_detection/gesture_configuration.h @@ -6,7 +6,6 @@ #define UI_EVENTS_GESTURE_DETECTION_GESTURE_CONFIGURATION_H_ #include "base/basictypes.h" -#include "base/memory/singleton.h" #include "ui/events/gesture_detection/gesture_detection_export.h" #include "ui/events/gesture_detection/velocity_tracker.h" @@ -14,6 +13,8 @@ namespace ui { class GESTURE_DETECTION_EXPORT GestureConfiguration { public: + // Sets the shared instance. This does not take ownership of |config|. + static void SetInstance(GestureConfiguration* config); // Returns the singleton GestureConfiguration. static GestureConfiguration* GetInstance(); @@ -24,6 +25,8 @@ class GESTURE_DETECTION_EXPORT GestureConfiguration { min_scaling_touch_major_ = default_radius_ * 2; min_gesture_bounds_length_ = default_radius_; } + bool double_tap_enabled() const { return double_tap_enabled_; } + void set_double_tap_enabled(bool enabled) { double_tap_enabled_ = enabled; } int double_tap_timeout_in_ms() const { return double_tap_timeout_in_ms_; } int fling_max_cancel_to_down_time_in_ms() const { return fling_max_cancel_to_down_time_in_ms_; @@ -40,6 +43,9 @@ class GESTURE_DETECTION_EXPORT GestureConfiguration { bool gesture_begin_end_types_enabled() const { return gesture_begin_end_types_enabled_; } + void set_gesture_begin_end_types_enabled(bool val) { + gesture_begin_end_types_enabled_ = val; + } int long_press_time_in_ms() const { return long_press_time_in_ms_; } void set_long_press_time_in_ms(int val) { long_press_time_in_ms_ = val; } float max_distance_between_taps_for_double_tap() const { @@ -59,6 +65,9 @@ class GESTURE_DETECTION_EXPORT GestureConfiguration { float max_gesture_bounds_length() const { return max_gesture_bounds_length_; } + void set_max_gesture_bounds_length(float val) { + max_gesture_bounds_length_ = val; + } float max_separation_for_gesture_touches_in_pixels() const { return max_separation_for_gesture_touches_in_pixels_; } @@ -68,6 +77,9 @@ class GESTURE_DETECTION_EXPORT GestureConfiguration { float max_swipe_deviation_angle() const { return max_swipe_deviation_angle_; } + void set_max_swipe_deviation_angle(float val) { + max_swipe_deviation_angle_ = val; + } int max_time_between_double_click_in_ms() const { return max_time_between_double_click_in_ms_; } @@ -94,6 +106,7 @@ class GESTURE_DETECTION_EXPORT GestureConfiguration { min_distance_for_pinch_scroll_in_pixels_ = val; } float min_fling_velocity() const { return min_fling_velocity_; } + void set_min_fling_velocity(float val) { min_fling_velocity_ = val; } float min_gesture_bounds_length() const { return min_gesture_bounds_length_; } @@ -106,6 +119,9 @@ class GESTURE_DETECTION_EXPORT GestureConfiguration { float min_scaling_span_in_pixels() const { return min_scaling_span_in_pixels_; } + void set_min_scaling_span_in_pixels(float val) { + min_scaling_span_in_pixels_ = val; + } float min_scaling_touch_major() const { return min_scaling_touch_major_; } float min_swipe_velocity() const { return min_swipe_velocity_; } void set_min_swipe_velocity(float val) { min_swipe_velocity_ = val; } @@ -118,9 +134,6 @@ class GESTURE_DETECTION_EXPORT GestureConfiguration { int semi_long_press_time_in_ms() const { return semi_long_press_time_in_ms_; } - VelocityTracker::Strategy velocity_tracker_strategy() const { - return velocity_tracker_strategy_; - } void set_semi_long_press_time_in_ms(int val) { semi_long_press_time_in_ms_ = val; double_tap_timeout_in_ms_ = val; @@ -131,6 +144,7 @@ class GESTURE_DETECTION_EXPORT GestureConfiguration { } float span_slop() const { return span_slop_; } bool swipe_enabled() const { return swipe_enabled_; } + void set_swipe_enabled(bool val) { swipe_enabled_ = val; } // TODO(davemoore): Move into chrome/browser/ui. int tab_scrub_activation_delay_in_ms() const { @@ -140,47 +154,48 @@ class GESTURE_DETECTION_EXPORT GestureConfiguration { tab_scrub_activation_delay_in_ms_ = val; } bool two_finger_tap_enabled() const { return two_finger_tap_enabled_; } + void set_two_finger_tap_enabled(bool val) { two_finger_tap_enabled_ = val; } + VelocityTracker::Strategy velocity_tracker_strategy() const { + return velocity_tracker_strategy_; + } + void set_velocity_tracker_strategy(VelocityTracker::Strategy val) { + velocity_tracker_strategy_ = val; + } protected: GestureConfiguration(); virtual ~GestureConfiguration(); + // The below configuration parameters are dependent on other parameters, + // whose setter functions will setup these values as well, so we will not + // provide public setter functions for them. void set_double_tap_timeout_in_ms(int val) { double_tap_timeout_in_ms_ = val; } - void set_gesture_begin_end_types_enabled(bool val) { - gesture_begin_end_types_enabled_ = val; - } - void set_max_gesture_bounds_length(float val) { - max_gesture_bounds_length_ = val; - } - void set_max_swipe_deviation_angle(float val) { - max_swipe_deviation_angle_ = val; - } - void set_min_fling_velocity(float val) { min_fling_velocity_ = val; } void set_min_gesture_bounds_length(float val) { min_gesture_bounds_length_ = val; } - void set_min_scaling_span_in_pixels(float val) { - min_scaling_span_in_pixels_ = val; - } void set_min_scaling_touch_major(float val) { min_scaling_touch_major_ = val; } - void set_velocity_tracker_strategy(VelocityTracker::Strategy val) { - velocity_tracker_strategy_ = val; - } void set_span_slop(float val) { span_slop_ = val; } - void set_swipe_enabled(bool val) { swipe_enabled_ = val; } - void set_two_finger_tap_enabled(bool val) { two_finger_tap_enabled_ = val; } private: + // Returns the platform specific instance. This is invoked if a specific + // instance has not been set. + static GestureConfiguration* GetPlatformSpecificInstance(); + // These are listed in alphabetical order ignoring underscores. + // NOTE: Adding new configuration parameters requires initializing + // corresponding entries in aura_test_base.cc's SetUp(). // The default touch radius length used when the only information given // by the device is the touch center. float default_radius_; + + bool double_tap_enabled_; int double_tap_timeout_in_ms_; + // Maximum time between a GestureFlingCancel and a mousedown such that the // mousedown is considered associated with the cancel event. int fling_max_cancel_to_down_time_in_ms_; @@ -211,7 +226,6 @@ class GESTURE_DETECTION_EXPORT GestureConfiguration { float min_scaling_span_in_pixels_; float min_scaling_touch_major_; float min_swipe_velocity_; - VelocityTracker::Strategy velocity_tracker_strategy_; int scroll_debounce_interval_in_ms_; int semi_long_press_time_in_ms_; int show_press_delay_in_ms_; @@ -221,8 +235,8 @@ class GESTURE_DETECTION_EXPORT GestureConfiguration { // TODO(davemoore): Move into chrome/browser/ui. int tab_scrub_activation_delay_in_ms_; bool two_finger_tap_enabled_; + VelocityTracker::Strategy velocity_tracker_strategy_; - friend struct DefaultSingletonTraits<GestureConfiguration>; DISALLOW_COPY_AND_ASSIGN(GestureConfiguration); }; diff --git a/chromium/ui/events/gesture_detection/gesture_configuration_android.cc b/chromium/ui/events/gesture_detection/gesture_configuration_android.cc index d4a7e8e23ae..2cf29aa643a 100644 --- a/chromium/ui/events/gesture_detection/gesture_configuration_android.cc +++ b/chromium/ui/events/gesture_detection/gesture_configuration_android.cc @@ -4,6 +4,7 @@ #include "ui/events/gesture_detection/gesture_configuration.h" +#include "base/memory/singleton.h" #include "ui/gfx/android/view_configuration.h" #include "ui/gfx/screen.h" @@ -33,6 +34,7 @@ class GestureConfigurationAndroid : public GestureConfiguration { float raw_pixel_to_dip_ratio = 1.f / gfx::Screen::GetNativeScreen() ->GetPrimaryDisplay() .device_scale_factor(); + set_double_tap_enabled(true); set_double_tap_timeout_in_ms(ViewConfiguration::GetDoubleTapTimeoutInMs()); set_gesture_begin_end_types_enabled(false); set_long_press_time_in_ms(ViewConfiguration::GetLongPressTimeoutInMs()); @@ -67,7 +69,7 @@ class GestureConfigurationAndroid : public GestureConfiguration { } // namespace // Create a GestureConfigurationAura singleton instance when using Android. -GestureConfiguration* GestureConfiguration::GetInstance() { +GestureConfiguration* GestureConfiguration::GetPlatformSpecificInstance() { return GestureConfigurationAndroid::GetInstance(); } diff --git a/chromium/ui/events/gesture_detection/gesture_configuration_aura.cc b/chromium/ui/events/gesture_detection/gesture_configuration_aura.cc index 55616889587..df4bcf471ac 100644 --- a/chromium/ui/events/gesture_detection/gesture_configuration_aura.cc +++ b/chromium/ui/events/gesture_detection/gesture_configuration_aura.cc @@ -5,6 +5,7 @@ #include "ui/events/gesture_detection/gesture_configuration.h" #include "base/command_line.h" +#include "base/memory/singleton.h" #include "ui/events/event_switches.h" namespace ui { @@ -21,13 +22,15 @@ class GestureConfigurationAura : public GestureConfiguration { private: GestureConfigurationAura() : GestureConfiguration() { + set_double_tap_enabled(false); set_double_tap_timeout_in_ms(semi_long_press_time_in_ms()); set_gesture_begin_end_types_enabled(true); set_min_gesture_bounds_length(default_radius()); set_min_pinch_update_span_delta( - CommandLine::ForCurrentProcess()->HasSwitch( + base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kCompensateForUnstablePinchZoom) - ? 5 : 0); + ? 5 + : 0); set_min_scaling_touch_major(default_radius() * 2); set_velocity_tracker_strategy(VelocityTracker::Strategy::LSQ2_RESTRICTED); set_span_slop(max_touch_move_in_pixels_for_click() * 2); @@ -42,7 +45,7 @@ class GestureConfigurationAura : public GestureConfiguration { } // namespace // Create a GestureConfigurationAura singleton instance when using aura. -GestureConfiguration* GestureConfiguration::GetInstance() { +GestureConfiguration* GestureConfiguration::GetPlatformSpecificInstance() { return GestureConfigurationAura::GetInstance(); } diff --git a/chromium/ui/events/gesture_detection/gesture_configuration_default.cc b/chromium/ui/events/gesture_detection/gesture_configuration_default.cc index 7ef8501dc6e..5442ad027be 100644 --- a/chromium/ui/events/gesture_detection/gesture_configuration_default.cc +++ b/chromium/ui/events/gesture_detection/gesture_configuration_default.cc @@ -4,13 +4,32 @@ #include "ui/events/gesture_detection/gesture_configuration.h" +#include "base/memory/singleton.h" #include "ui/gfx/screen.h" namespace ui { +namespace { +class GestureConfigurationDefault : public GestureConfiguration { + public: + ~GestureConfigurationDefault() override { + } -// Create a GestureConfigurationAura singleton instance when using Mac. -GestureConfiguration* GestureConfiguration::GetInstance() { - return Singleton<GestureConfiguration>::get(); + static GestureConfigurationDefault* GetInstance() { + return Singleton<GestureConfigurationDefault>::get(); + } + + private: + GestureConfigurationDefault() {} + + friend struct DefaultSingletonTraits<GestureConfigurationDefault>; + DISALLOW_COPY_AND_ASSIGN(GestureConfigurationDefault); +}; + +} // namespace + +// Create a GestureConfiguration singleton instance when using Mac. +GestureConfiguration* GestureConfiguration::GetPlatformSpecificInstance() { + return GestureConfigurationDefault::GetInstance(); } } // namespace ui diff --git a/chromium/ui/events/gesture_detection/gesture_detector.cc b/chromium/ui/events/gesture_detection/gesture_detector.cc index 50cae59fce9..3dc8283db65 100644 --- a/chromium/ui/events/gesture_detection/gesture_detector.cc +++ b/chromium/ui/events/gesture_detection/gesture_detector.cc @@ -38,7 +38,8 @@ enum TimeoutEvent { } // namespace // Note: These constants were taken directly from the default (unscaled) -// versions found in Android's ViewConfiguration. +// versions found in Android's ViewConfiguration. Do not change these default +// values without explicitly consulting an OWNER. GestureDetector::Config::Config() : longpress_timeout(base::TimeDelta::FromMilliseconds(500)), showpress_timeout(base::TimeDelta::FromMilliseconds(180)), @@ -435,10 +436,12 @@ void GestureDetector::OnLongPressTimeout() { void GestureDetector::OnTapTimeout() { if (!double_tap_listener_) return; - if (!still_down_) - double_tap_listener_->OnSingleTapConfirmed(*current_down_event_); - else + if (!still_down_) { + CHECK(previous_up_event_); + double_tap_listener_->OnSingleTapConfirmed(*previous_up_event_); + } else { defer_confirm_single_tap_ = true; + } } void GestureDetector::Cancel() { diff --git a/chromium/ui/events/gesture_detection/gesture_event_data.cc b/chromium/ui/events/gesture_detection/gesture_event_data.cc index 2102f230c7a..b166ffa0a13 100644 --- a/chromium/ui/events/gesture_detection/gesture_event_data.cc +++ b/chromium/ui/events/gesture_detection/gesture_event_data.cc @@ -36,7 +36,7 @@ GestureEventData::GestureEventData(const GestureEventDetails& details, GestureEventData::GestureEventData(EventType type, const GestureEventData& other) - : details(type), + : details(type, other.details), motion_event_id(other.motion_event_id), primary_tool_type(other.primary_tool_type), time(other.time), diff --git a/chromium/ui/events/gesture_detection/gesture_event_data_packet.cc b/chromium/ui/events/gesture_detection/gesture_event_data_packet.cc index 265300cc1fc..aac1d4edc19 100644 --- a/chromium/ui/events/gesture_detection/gesture_event_data_packet.cc +++ b/chromium/ui/events/gesture_detection/gesture_event_data_packet.cc @@ -33,7 +33,7 @@ GestureEventDataPacket::GestureSource ToGestureSource( } // namespace GestureEventDataPacket::GestureEventDataPacket() - : gesture_source_(UNDEFINED) { + : gesture_source_(UNDEFINED), ack_state_(AckState::PENDING) { } GestureEventDataPacket::GestureEventDataPacket( @@ -44,7 +44,8 @@ GestureEventDataPacket::GestureEventDataPacket( : timestamp_(timestamp), touch_location_(touch_location), raw_touch_location_(raw_touch_location), - gesture_source_(source) { + gesture_source_(source), + ack_state_(AckState::PENDING) { DCHECK_NE(gesture_source_, UNDEFINED); } @@ -54,7 +55,8 @@ GestureEventDataPacket::GestureEventDataPacket( gestures_(other.gestures_), touch_location_(other.touch_location_), raw_touch_location_(other.raw_touch_location_), - gesture_source_(other.gesture_source_) { + gesture_source_(other.gesture_source_), + ack_state_(AckState::PENDING) { } GestureEventDataPacket::~GestureEventDataPacket() { @@ -67,6 +69,7 @@ GestureEventDataPacket& GestureEventDataPacket::operator=( touch_location_ = other.touch_location_; raw_touch_location_ = other.raw_touch_location_; gestures_ = other.gestures_; + ack_state_ = other.ack_state_; return *this; } @@ -93,4 +96,9 @@ GestureEventDataPacket GestureEventDataPacket::FromTouchTimeout( return packet; } +void GestureEventDataPacket::Ack(bool event_consumed) { + DCHECK_EQ(static_cast<int>(ack_state_), static_cast<int>(AckState::PENDING)); + ack_state_ = event_consumed ? AckState::CONSUMED : AckState::UNCONSUMED; +} + } // namespace ui diff --git a/chromium/ui/events/gesture_detection/gesture_event_data_packet.h b/chromium/ui/events/gesture_detection/gesture_event_data_packet.h index 9b115de9ca7..25424b60e48 100644 --- a/chromium/ui/events/gesture_detection/gesture_event_data_packet.h +++ b/chromium/ui/events/gesture_detection/gesture_event_data_packet.h @@ -29,6 +29,12 @@ class GESTURE_DETECTION_EXPORT GestureEventDataPacket { TOUCH_TIMEOUT, // Timeout from an existing gesture sequence. }; + enum class AckState { + PENDING, + CONSUMED, + UNCONSUMED, + }; + GestureEventDataPacket(); GestureEventDataPacket(const GestureEventDataPacket& other); ~GestureEventDataPacket(); @@ -48,6 +54,11 @@ class GESTURE_DETECTION_EXPORT GestureEventDataPacket { const gfx::PointF& touch_location() const { return touch_location_; } const gfx::PointF& raw_touch_location() const { return raw_touch_location_; } + // We store the ack with the packet until the packet reaches the + // head of the queue, and then we handle the ack. + void Ack(bool event_consumed); + AckState ack_state() { return ack_state_; } + private: GestureEventDataPacket(base::TimeTicks timestamp, GestureSource source, @@ -60,6 +71,7 @@ class GESTURE_DETECTION_EXPORT GestureEventDataPacket { gfx::PointF touch_location_; gfx::PointF raw_touch_location_; GestureSource gesture_source_; + AckState ack_state_; }; } // namespace ui diff --git a/chromium/ui/events/gesture_detection/gesture_provider.cc b/chromium/ui/events/gesture_detection/gesture_provider.cc index 3535ad604af..271ec06e5ed 100644 --- a/chromium/ui/events/gesture_detection/gesture_provider.cc +++ b/chromium/ui/events/gesture_detection/gesture_provider.cc @@ -7,11 +7,12 @@ #include <cmath> #include "base/auto_reset.h" -#include "base/debug/trace_event.h" +#include "base/trace_event/trace_event.h" #include "ui/events/event_constants.h" #include "ui/events/gesture_detection/gesture_event_data.h" #include "ui/events/gesture_detection/gesture_listeners.h" #include "ui/events/gesture_detection/motion_event.h" +#include "ui/events/gesture_detection/motion_event_generic.h" #include "ui/events/gesture_detection/scale_gesture_listeners.h" #include "ui/gfx/geometry/point_f.h" @@ -64,6 +65,7 @@ gfx::RectF ClampBoundingBox(const gfx::RectF& bounds, GestureProvider::Config::Config() : display(gfx::Display::kInvalidDisplayID, gfx::Rect(1, 1)), disable_click_delay(false), + double_tap_support_for_platform_enabled(true), gesture_begin_end_types_enabled(false), min_gesture_bounds_length(0), max_gesture_bounds_length(0) { @@ -215,7 +217,7 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener, return false; if (!pinch_event_sent_) { Send(CreateGesture(ET_GESTURE_PINCH_BEGIN, - e.GetId(), + e.GetPointerId(), e.GetToolType(), detector.GetEventTime(), detector.GetFocusX(), @@ -251,7 +253,7 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener, GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE); pinch_details.set_scale(scale); Send(CreateGesture(pinch_details, - e.GetId(), + e.GetPointerId(), e.GetToolType(), detector.GetEventTime(), detector.GetFocusX(), @@ -302,7 +304,7 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener, // Use the co-ordinates from the touch down, as these co-ordinates are // used to determine which layer the scroll should affect. Send(CreateGesture(scroll_details, - e2.GetId(), + e2.GetPointerId(), e2.GetToolType(), e2.GetEventTime(), e1.GetX(), @@ -331,7 +333,7 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener, const gfx::PointF raw_center = center + gfx::Vector2dF(e2.GetRawOffsetX(), e2.GetRawOffsetY()); Send(CreateGesture(scroll_details, - e2.GetId(), + e2.GetPointerId(), e2.GetToolType(), e2.GetEventTime(), center.x(), @@ -391,7 +393,7 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener, GestureEventDetails two_finger_tap_details( ET_GESTURE_TWO_FINGER_TAP, e1.GetTouchMajor(), e1.GetTouchMajor()); Send(CreateGesture(two_finger_tap_details, - e2.GetId(), + e2.GetPointerId(), e2.GetToolType(), e2.GetEventTime(), e1.GetX(), @@ -539,7 +541,7 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener, GestureEventData CreateGesture(const GestureEventDetails& details, const MotionEvent& event) { return GestureEventData(details, - event.GetId(), + event.GetPointerId(), event.GetToolType(), event.GetEventTime(), event.GetX(), @@ -679,7 +681,8 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener, GestureProvider::GestureProvider(const Config& config, GestureProviderClient* client) : double_tap_support_for_page_(true), - double_tap_support_for_platform_(true), + double_tap_support_for_platform_( + config.double_tap_support_for_platform_enabled), gesture_begin_end_types_enabled_(config.gesture_begin_end_types_enabled) { DCHECK(client); DCHECK(!config.min_gesture_bounds_length || @@ -711,6 +714,13 @@ bool GestureProvider::OnTouchEvent(const MotionEvent& event) { return true; } +void GestureProvider::ResetDetection() { + MotionEventGeneric generic_cancel_event(MotionEvent::ACTION_CANCEL, + base::TimeTicks::Now(), + PointerProperties()); + OnTouchEvent(generic_cancel_event); +} + void GestureProvider::SetMultiTouchZoomSupportEnabled(bool enabled) { gesture_listener_->SetMultiTouchZoomEnabled(enabled); } @@ -762,7 +772,7 @@ void GestureProvider::OnTouchEventHandlingBegin(const MotionEvent& event) { const int action_index = event.GetActionIndex(); gesture_listener_->Send(gesture_listener_->CreateGesture( ET_GESTURE_BEGIN, - event.GetId(), + event.GetPointerId(), event.GetToolType(), event.GetEventTime(), event.GetX(action_index), diff --git a/chromium/ui/events/gesture_detection/gesture_provider.h b/chromium/ui/events/gesture_detection/gesture_provider.h index 74749677133..a9534d54a6a 100644 --- a/chromium/ui/events/gesture_detection/gesture_provider.h +++ b/chromium/ui/events/gesture_detection/gesture_provider.h @@ -41,6 +41,10 @@ class GESTURE_DETECTION_EXPORT GestureProvider { // events. bool disable_click_delay; + // Whether double-tap detection is supported by the platform. If disabled, + // there will be no delay before tap events. Defaults to true. + bool double_tap_support_for_platform_enabled; + // If |gesture_begin_end_types_enabled| is true, fire an ET_GESTURE_BEGIN // event for every added touch point, and an ET_GESTURE_END event for every // removed touch point. This requires one ACTION_CANCEL event to be sent per @@ -64,6 +68,11 @@ class GESTURE_DETECTION_EXPORT GestureProvider { // be handled. bool OnTouchEvent(const MotionEvent& event); + // Reset any active gesture detection, including detection of timeout-based + // events (e.g., double-tap or delayed tap) for which the pointer has already + // been released. + void ResetDetection(); + // Update whether multi-touch pinch zoom is supported by the platform. void SetMultiTouchZoomSupportEnabled(bool enabled); diff --git a/chromium/ui/events/gesture_detection/gesture_provider_config_helper.cc b/chromium/ui/events/gesture_detection/gesture_provider_config_helper.cc index 537bd725353..6b1dad0932b 100644 --- a/chromium/ui/events/gesture_detection/gesture_provider_config_helper.cc +++ b/chromium/ui/events/gesture_detection/gesture_provider_config_helper.cc @@ -10,63 +10,89 @@ namespace ui { namespace { -GestureDetector::Config DefaultGestureDetectorConfig( - GestureConfiguration* gesture_config) { +class GenericDesktopGestureConfiguration : public GestureConfiguration { + public: + // The default GestureConfiguration parameters are already tailored for a + // desktop environment (Aura). + GenericDesktopGestureConfiguration() {} + ~GenericDesktopGestureConfiguration() override {} +}; + +GestureDetector::Config BuildGestureDetectorConfig( + const GestureConfiguration& gesture_config) { GestureDetector::Config config; - config.longpress_timeout = base::TimeDelta::FromMilliseconds( - gesture_config->long_press_time_in_ms()); + config.longpress_timeout = + base::TimeDelta::FromMilliseconds(gesture_config.long_press_time_in_ms()); config.showpress_timeout = base::TimeDelta::FromMilliseconds( - gesture_config->show_press_delay_in_ms()); + gesture_config.show_press_delay_in_ms()); config.double_tap_timeout = base::TimeDelta::FromMilliseconds( - gesture_config->double_tap_timeout_in_ms()); - config.touch_slop = gesture_config->max_touch_move_in_pixels_for_click(); + gesture_config.double_tap_timeout_in_ms()); + config.touch_slop = gesture_config.max_touch_move_in_pixels_for_click(); config.double_tap_slop = - gesture_config->max_distance_between_taps_for_double_tap(); - config.minimum_fling_velocity = gesture_config->min_fling_velocity(); - config.maximum_fling_velocity = gesture_config->max_fling_velocity(); - config.swipe_enabled = gesture_config->swipe_enabled(); - config.minimum_swipe_velocity = gesture_config->min_swipe_velocity(); + gesture_config.max_distance_between_taps_for_double_tap(); + config.minimum_fling_velocity = gesture_config.min_fling_velocity(); + config.maximum_fling_velocity = gesture_config.max_fling_velocity(); + config.swipe_enabled = gesture_config.swipe_enabled(); + config.minimum_swipe_velocity = gesture_config.min_swipe_velocity(); config.maximum_swipe_deviation_angle = - gesture_config->max_swipe_deviation_angle(); - config.two_finger_tap_enabled = gesture_config->two_finger_tap_enabled(); + gesture_config.max_swipe_deviation_angle(); + config.two_finger_tap_enabled = gesture_config.two_finger_tap_enabled(); config.two_finger_tap_max_separation = - gesture_config->max_distance_for_two_finger_tap_in_pixels(); + gesture_config.max_distance_for_two_finger_tap_in_pixels(); config.two_finger_tap_timeout = base::TimeDelta::FromMilliseconds( - gesture_config->max_touch_down_duration_for_click_in_ms()); - config.velocity_tracker_strategy = - gesture_config->velocity_tracker_strategy(); + gesture_config.max_touch_down_duration_for_click_in_ms()); + config.velocity_tracker_strategy = gesture_config.velocity_tracker_strategy(); return config; } -ScaleGestureDetector::Config DefaultScaleGestureDetectorConfig( - GestureConfiguration* gesture_config) { +ScaleGestureDetector::Config BuildScaleGestureDetectorConfig( + const GestureConfiguration& gesture_config) { ScaleGestureDetector::Config config; - config.span_slop = gesture_config->span_slop(); - config.min_scaling_touch_major = gesture_config->min_scaling_touch_major(); - config.min_scaling_span = gesture_config->min_scaling_span_in_pixels(); + config.span_slop = gesture_config.span_slop(); + config.min_scaling_touch_major = gesture_config.min_scaling_touch_major(); + config.min_scaling_span = gesture_config.min_scaling_span_in_pixels(); config.min_pinch_update_span_delta = - gesture_config->min_pinch_update_span_delta(); + gesture_config.min_pinch_update_span_delta(); + return config; +} + +GestureProvider::Config BuildGestureProviderConfig( + const GestureConfiguration& gesture_config) { + GestureProvider::Config config; + config.gesture_detector_config = BuildGestureDetectorConfig(gesture_config); + config.scale_gesture_detector_config = + BuildScaleGestureDetectorConfig(gesture_config); + config.double_tap_support_for_platform_enabled = + gesture_config.double_tap_enabled(); + config.gesture_begin_end_types_enabled = + gesture_config.gesture_begin_end_types_enabled(); + config.min_gesture_bounds_length = gesture_config.min_gesture_bounds_length(); + config.max_gesture_bounds_length = gesture_config.max_gesture_bounds_length(); return config; } } // namespace -GestureProvider::Config DefaultGestureProviderConfig() { - GestureConfiguration* gesture_config = GestureConfiguration::GetInstance(); +GestureProvider::Config GetGestureProviderConfig( + GestureProviderConfigType type) { GestureProvider::Config config; + switch (type) { + case GestureProviderConfigType::CURRENT_PLATFORM: + config = BuildGestureProviderConfig(*GestureConfiguration::GetInstance()); + break; + case GestureProviderConfigType::GENERIC_DESKTOP: + config = BuildGestureProviderConfig(GenericDesktopGestureConfiguration()); + break; + case GestureProviderConfigType::GENERIC_MOBILE: + // The default GestureProvider::Config embeds a mobile configuration. + break; + } + gfx::Screen* screen = gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE); // |screen| is sometimes NULL during tests. if (screen) config.display = screen->GetPrimaryDisplay(); - config.gesture_detector_config = DefaultGestureDetectorConfig(gesture_config); - config.scale_gesture_detector_config = - DefaultScaleGestureDetectorConfig(gesture_config); - config.gesture_begin_end_types_enabled = - gesture_config->gesture_begin_end_types_enabled(); - config.min_gesture_bounds_length = - gesture_config->min_gesture_bounds_length(); - config.max_gesture_bounds_length = - gesture_config->max_gesture_bounds_length(); + return config; } diff --git a/chromium/ui/events/gesture_detection/gesture_provider_config_helper.h b/chromium/ui/events/gesture_detection/gesture_provider_config_helper.h index 8e5a4f2372c..bfbe2182234 100644 --- a/chromium/ui/events/gesture_detection/gesture_provider_config_helper.h +++ b/chromium/ui/events/gesture_detection/gesture_provider_config_helper.h @@ -12,7 +12,14 @@ namespace ui { -GESTURE_DETECTION_EXPORT GestureProvider::Config DefaultGestureProviderConfig(); +enum class GestureProviderConfigType { + CURRENT_PLATFORM, // Parameters tailored for the current platform. + GENERIC_DESKTOP, // Parameters typical for a desktop machine. + GENERIC_MOBILE // Parameters typical for a mobile device (phone/tablet). +}; + +GESTURE_DETECTION_EXPORT GestureProvider::Config GetGestureProviderConfig( + GestureProviderConfigType); } // namespace ui diff --git a/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc b/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc index 4c4dedd0ec9..d49efc8f029 100644 --- a/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc +++ b/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc @@ -143,9 +143,10 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient { } void ResetGestureDetection() { - CancelActiveTouchSequence(); + gesture_provider_->ResetDetection(); gestures_.clear(); } + bool CancelActiveTouchSequence() { if (!gesture_provider_->current_down_event()) return false; @@ -273,12 +274,12 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient { base::TimeTicks event_time = base::TimeTicks::Now(); const float scroll_to_x = kFakeCoordX + 100; const float scroll_to_y = kFakeCoordY + 100; - int motion_event_id = 0; + int motion_event_id = 3; int motion_event_flags = EF_SHIFT_DOWN | EF_CAPS_LOCK_DOWN; MockMotionEvent event = ObtainMotionEvent(event_time, MotionEvent::ACTION_DOWN); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); event.set_flags(motion_event_flags); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); @@ -289,7 +290,7 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient { scroll_to_x, scroll_to_y); event.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); event.set_flags(motion_event_flags); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); @@ -314,7 +315,7 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient { event = ObtainMotionEvent( event_time + kOneSecond, end_action_type, scroll_to_x, scroll_to_y); event.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); gesture_provider_->OnTouchEvent(event); EXPECT_FALSE(gesture_provider_->IsScrollInProgress()); @@ -415,7 +416,7 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient { // Verify that a DOWN followed shortly by an UP will trigger a single tap. TEST_F(GestureProviderTest, GestureTap) { base::TimeTicks event_time = base::TimeTicks::Now(); - int motion_event_id = 0; + int motion_event_id = 6; int motion_event_flags = EF_CONTROL_DOWN | EF_ALT_DOWN; gesture_provider_->SetDoubleTapSupportForPlatformEnabled(false); @@ -423,7 +424,7 @@ TEST_F(GestureProviderTest, GestureTap) { MockMotionEvent event = ObtainMotionEvent(event_time, MotionEvent::ACTION_DOWN); event.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); event.set_flags(motion_event_flags); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); @@ -438,7 +439,7 @@ TEST_F(GestureProviderTest, GestureTap) { event = ObtainMotionEvent(event_time + kOneMicrosecond, MotionEvent::ACTION_UP); event.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); event.set_flags(motion_event_flags); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); @@ -458,14 +459,14 @@ TEST_F(GestureProviderTest, GestureTap) { // a ET_GESTURE_TAP_UNCONFIRMED event if double-tap is enabled. TEST_F(GestureProviderTest, GestureTapWithDelay) { base::TimeTicks event_time = base::TimeTicks::Now(); - int motion_event_id = 0; + int motion_event_id = 6; int motion_event_flags = EF_CONTROL_DOWN | EF_ALT_DOWN | EF_CAPS_LOCK_DOWN; gesture_provider_->SetDoubleTapSupportForPlatformEnabled(true); MockMotionEvent event = ObtainMotionEvent(event_time, MotionEvent::ACTION_DOWN); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); event.set_flags(motion_event_flags); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); @@ -478,7 +479,7 @@ TEST_F(GestureProviderTest, GestureTapWithDelay) { event = ObtainMotionEvent(event_time + kOneMicrosecond, MotionEvent::ACTION_UP); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); event.set_flags(motion_event_flags); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); @@ -490,22 +491,25 @@ TEST_F(GestureProviderTest, GestureTapWithDelay) { EXPECT_EQ(1, GetMostRecentGestureEvent().details.touch_points()); EXPECT_EQ(BoundsForSingleMockTouchAtLocation(kFakeCoordX, kFakeCoordY), GetMostRecentGestureEvent().details.bounding_box()); + EXPECT_EQ(event.GetEventTime(), GetMostRecentGestureEvent().time); EXPECT_FALSE(HasReceivedGesture(ET_GESTURE_TAP)); RunTasksAndWait(GetDoubleTapTimeout()); EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_TAP)); + EXPECT_EQ(motion_event_id, GetMostRecentGestureEvent().motion_event_id); + EXPECT_EQ(event.GetEventTime(), GetMostRecentGestureEvent().time); } // Verify that a DOWN followed by a MOVE will trigger fling (but not LONG). TEST_F(GestureProviderTest, GestureFlingAndCancelLongPress) { base::TimeTicks event_time = TimeTicks::Now(); base::TimeDelta delta_time = kDeltaTimeForFlingSequences; - int motion_event_id = 0; + int motion_event_id = 6; int motion_event_flags = EF_ALT_DOWN; MockMotionEvent event = ObtainMotionEvent(event_time, MotionEvent::ACTION_DOWN); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); event.set_flags(motion_event_flags); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); @@ -518,7 +522,7 @@ TEST_F(GestureProviderTest, GestureFlingAndCancelLongPress) { MotionEvent::ACTION_MOVE, kFakeCoordX * 10, kFakeCoordY * 10); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); event.set_flags(motion_event_flags); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); @@ -526,7 +530,7 @@ TEST_F(GestureProviderTest, GestureFlingAndCancelLongPress) { MotionEvent::ACTION_UP, kFakeCoordX * 10, kFakeCoordY * 10); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); event.set_flags(motion_event_flags); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); @@ -563,11 +567,11 @@ TEST_F(GestureProviderTest, ScrollEventActionCancelSequence) { TEST_F(GestureProviderTest, FlingEventSequence) { base::TimeTicks event_time = base::TimeTicks::Now(); base::TimeDelta delta_time = kDeltaTimeForFlingSequences; - int motion_event_id = 0; + int motion_event_id = 6; MockMotionEvent event = ObtainMotionEvent(event_time, MotionEvent::ACTION_DOWN); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); @@ -575,7 +579,7 @@ TEST_F(GestureProviderTest, FlingEventSequence) { MotionEvent::ACTION_MOVE, kFakeCoordX * 5, kFakeCoordY * 5); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_TRUE(gesture_provider_->IsScrollInProgress()); @@ -597,7 +601,7 @@ TEST_F(GestureProviderTest, FlingEventSequence) { MotionEvent::ACTION_UP, kFakeCoordX * 10, kFakeCoordY * 10); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_FALSE(gesture_provider_->IsScrollInProgress()); @@ -609,7 +613,7 @@ TEST_F(GestureProviderTest, FlingEventSequence) { << "FlingStart should have the time of the ACTION_UP"; } -TEST_F(GestureProviderTest, GestureCancelledWhenWindowFocusLost) { +TEST_F(GestureProviderTest, GestureCancelledOnCancelEvent) { const base::TimeTicks event_time = TimeTicks::Now(); MockMotionEvent event = @@ -622,7 +626,8 @@ TEST_F(GestureProviderTest, GestureCancelledWhenWindowFocusLost) { EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SHOW_PRESS)); EXPECT_EQ(ET_GESTURE_LONG_PRESS, GetMostRecentGestureEventType()); - // The long press triggers window focus loss by opening a context menu. + // A cancellation event may be triggered for a number of reasons, e.g., + // from a context-menu-triggering long press resulting in loss of focus. EXPECT_TRUE(CancelActiveTouchSequence()); EXPECT_FALSE(HasDownEvent()); @@ -632,6 +637,28 @@ TEST_F(GestureProviderTest, GestureCancelledWhenWindowFocusLost) { EXPECT_FALSE(gesture_provider_->OnTouchEvent(event)); } +TEST_F(GestureProviderTest, GestureCancelledOnDetectionReset) { + const base::TimeTicks event_time = TimeTicks::Now(); + + MockMotionEvent event = + ObtainMotionEvent(event_time, MotionEvent::ACTION_DOWN); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + EXPECT_EQ(ET_GESTURE_TAP_DOWN, GetMostRecentGestureEventType()); + + RunTasksAndWait(GetLongPressTimeout() + GetShowPressTimeout() + + kOneMicrosecond); + EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SHOW_PRESS)); + EXPECT_EQ(ET_GESTURE_LONG_PRESS, GetMostRecentGestureEventType()); + + ResetGestureDetection(); + EXPECT_FALSE(HasDownEvent()); + + // A final ACTION_UP should have no effect. + event = ObtainMotionEvent(event_time + kOneMicrosecond * 2, + MotionEvent::ACTION_UP); + EXPECT_FALSE(gesture_provider_->OnTouchEvent(event)); +} + TEST_F(GestureProviderTest, NoTapAfterScrollBegins) { base::TimeTicks event_time = base::TimeTicks::Now(); @@ -841,7 +868,7 @@ TEST_F(GestureProviderTest, FractionalScroll) { // Now move up slowly, mostly vertically but with a (fractional) bit of // horizontal motion. - for(int i = 1; i <= 10; i++) { + for (int i = 1; i <= 10; i++) { event = ObtainMotionEvent(event_time + kOneMicrosecond * i, MotionEvent::ACTION_MOVE, kFakeCoordX + delta_x * i, @@ -898,7 +925,7 @@ TEST_F(GestureProviderTest, ScrollBeginValues) { EXPECT_TRUE(gesture_provider_->IsScrollInProgress()); const GestureEventData* scroll_begin_gesture = GetActiveScrollBeginEvent(); - ASSERT_TRUE(!!scroll_begin_gesture); + ASSERT_TRUE(scroll_begin_gesture); EXPECT_EQ(delta_x, scroll_begin_gesture->details.scroll_x_hint()); EXPECT_EQ(delta_y, scroll_begin_gesture->details.scroll_y_hint()); } @@ -985,7 +1012,7 @@ TEST_F(GestureProviderTest, GestureLongPressDoesNotPreventScrolling) { TEST_F(GestureProviderTest, NoGestureLongPressDuringDoubleTap) { base::TimeTicks event_time = base::TimeTicks::Now(); - int motion_event_id = 0; + int motion_event_id = 6; MockMotionEvent event = ObtainMotionEvent( event_time, MotionEvent::ACTION_DOWN, kFakeCoordX, kFakeCoordY); @@ -1018,7 +1045,7 @@ TEST_F(GestureProviderTest, NoGestureLongPressDuringDoubleTap) { MotionEvent::ACTION_MOVE, kFakeCoordX + 20, kFakeCoordY + 20); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_EQ(ET_GESTURE_PINCH_BEGIN, GetMostRecentGestureEventType()); @@ -1030,7 +1057,7 @@ TEST_F(GestureProviderTest, NoGestureLongPressDuringDoubleTap) { MotionEvent::ACTION_UP, kFakeCoordX, kFakeCoordY + 1); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_EQ(ET_GESTURE_SCROLL_END, GetMostRecentGestureEventType()); EXPECT_EQ(motion_event_id, GetMostRecentGestureEvent().motion_event_id); @@ -1464,7 +1491,7 @@ TEST_F(GestureProviderTest, PinchZoom) { const float touch_slop = GetTouchSlop(); const float raw_offset_x = 3.2f; const float raw_offset_y = 4.3f; - int motion_event_id = 0; + int motion_event_id = 6; gesture_provider_->SetDoubleTapSupportForPageEnabled(false); gesture_provider_->SetDoubleTapSupportForPlatformEnabled(true); @@ -1475,7 +1502,7 @@ TEST_F(GestureProviderTest, PinchZoom) { MockMotionEvent event = ObtainMotionEvent(event_time, MotionEvent::ACTION_DOWN); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); event.SetRawOffset(raw_offset_x, raw_offset_y); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_EQ(ET_GESTURE_TAP_DOWN, GetMostRecentGestureEventType()); @@ -1496,7 +1523,7 @@ TEST_F(GestureProviderTest, PinchZoom) { kFakeCoordY, secondary_coord_x, secondary_coord_y); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); event.SetRawOffset(raw_offset_x, raw_offset_y); gesture_provider_->OnTouchEvent(event); @@ -1513,7 +1540,7 @@ TEST_F(GestureProviderTest, PinchZoom) { kFakeCoordY, secondary_coord_x, secondary_coord_y); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); event.SetRawOffset(raw_offset_x, raw_offset_y); // Toggling double-tap support should not take effect until the next sequence. @@ -1548,7 +1575,7 @@ TEST_F(GestureProviderTest, PinchZoom) { kFakeCoordY, secondary_coord_x, secondary_coord_y); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); // Toggling double-tap support should not take effect until the next sequence. gesture_provider_->SetDoubleTapSupportForPageEnabled(true); @@ -1572,7 +1599,7 @@ TEST_F(GestureProviderTest, PinchZoom) { kFakeCoordY, secondary_coord_x, secondary_coord_y); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_EQ(motion_event_id, GetMostRecentGestureEvent().motion_event_id); @@ -1811,14 +1838,14 @@ TEST_F(GestureProviderTest, GesturesCancelledAfterLongPressCausesLostFocus) { // gesture sequence cancellation. TEST_F(GestureProviderTest, CancelActiveTouchSequence) { base::TimeTicks event_time = base::TimeTicks::Now(); - int motion_event_id = 0; + int motion_event_id = 6; EXPECT_FALSE(CancelActiveTouchSequence()); EXPECT_EQ(0U, GetReceivedGestureCount()); MockMotionEvent event = ObtainMotionEvent(event_time, MotionEvent::ACTION_DOWN); - event.set_id(++motion_event_id); + event.SetPrimaryPointerId(motion_event_id); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_EQ(ET_GESTURE_TAP_DOWN, GetMostRecentGestureEventType()); EXPECT_EQ(motion_event_id, GetMostRecentGestureEvent().motion_event_id); diff --git a/chromium/ui/events/gesture_detection/motion_event.cc b/chromium/ui/events/gesture_detection/motion_event.cc index 3c25a7af41b..1d8f7c5269a 100644 --- a/chromium/ui/events/gesture_detection/motion_event.cc +++ b/chromium/ui/events/gesture_detection/motion_event.cc @@ -46,6 +46,11 @@ int MotionEvent::FindPointerIndexOfId(int id) const { return -1; } +int MotionEvent::GetSourceDeviceId(size_t pointer_index) const { + NOTIMPLEMENTED(); + return 0; +} + scoped_ptr<MotionEvent> MotionEvent::Clone() const { return MotionEventGeneric::CloneEvent(*this); } diff --git a/chromium/ui/events/gesture_detection/motion_event.h b/chromium/ui/events/gesture_detection/motion_event.h index 469b656f890..a6028fbdee5 100644 --- a/chromium/ui/events/gesture_detection/motion_event.h +++ b/chromium/ui/events/gesture_detection/motion_event.h @@ -46,7 +46,8 @@ class GESTURE_DETECTION_EXPORT MotionEvent { virtual ~MotionEvent() {} - virtual int GetId() const = 0; + // An unique identifier this motion event. + virtual uint32 GetUniqueEventId() const = 0; virtual Action GetAction() const = 0; // Only valid if |GetAction()| returns ACTION_POINTER_UP or // ACTION_POINTER_DOWN. @@ -76,7 +77,11 @@ class GESTURE_DETECTION_EXPORT MotionEvent { virtual float GetHistoricalY(size_t pointer_index, size_t historical_index) const; + // Get the id of the device which created the event. Currently Aura only. + virtual int GetSourceDeviceId(size_t pointer_index) const; + // Utility accessor methods for convenience. + int GetPointerId() const { return GetPointerId(0); } float GetX() const { return GetX(0); } float GetY() const { return GetY(0); } float GetRawX() const { return GetRawX(0); } diff --git a/chromium/ui/events/gesture_detection/motion_event_buffer.cc b/chromium/ui/events/gesture_detection/motion_event_buffer.cc index d1dec707015..e217d86b5c1 100644 --- a/chromium/ui/events/gesture_detection/motion_event_buffer.cc +++ b/chromium/ui/events/gesture_detection/motion_event_buffer.cc @@ -4,7 +4,7 @@ #include "ui/events/gesture_detection/motion_event_buffer.h" -#include "base/debug/trace_event.h" +#include "base/trace_event/trace_event.h" #include "ui/events/gesture_detection/motion_event_generic.h" namespace ui { @@ -146,8 +146,6 @@ scoped_ptr<MotionEventGeneric> ResampleMotionEvent( } DCHECK(event); - event->set_id(event0.GetId()); - event->set_action_index(event0.GetActionIndex()); event->set_button_state(event0.GetButtonState()); return event.Pass(); } diff --git a/chromium/ui/events/gesture_detection/motion_event_buffer_unittest.cc b/chromium/ui/events/gesture_detection/motion_event_buffer_unittest.cc index ba018b2c9ca..5e23bd529fd 100644 --- a/chromium/ui/events/gesture_detection/motion_event_buffer_unittest.cc +++ b/chromium/ui/events/gesture_detection/motion_event_buffer_unittest.cc @@ -81,9 +81,11 @@ class MotionEventBufferTest : public testing::Test, static void ExpectEqualsImpl(const MotionEvent& a, const MotionEvent& b, bool ignore_history) { - EXPECT_EQ(a.GetId(), b.GetId()); EXPECT_EQ(a.GetAction(), b.GetAction()); - EXPECT_EQ(a.GetActionIndex(), b.GetActionIndex()); + if (a.GetAction() == MotionEvent::ACTION_POINTER_DOWN || + a.GetAction() == MotionEvent::ACTION_POINTER_UP) { + EXPECT_EQ(a.GetActionIndex(), b.GetActionIndex()); + } EXPECT_EQ(a.GetButtonState(), b.GetButtonState()); EXPECT_EQ(a.GetEventTime(), b.GetEventTime()); diff --git a/chromium/ui/events/gesture_detection/motion_event_generic.cc b/chromium/ui/events/gesture_detection/motion_event_generic.cc index 6b4b61d746f..19262aa6e95 100644 --- a/chromium/ui/events/gesture_detection/motion_event_generic.cc +++ b/chromium/ui/events/gesture_detection/motion_event_generic.cc @@ -5,20 +5,12 @@ #include "ui/events/gesture_detection/motion_event_generic.h" #include "base/logging.h" +#include "ui/events/base_event_utils.h" namespace ui { PointerProperties::PointerProperties() - : id(0), - tool_type(MotionEvent::TOOL_TYPE_UNKNOWN), - x(0), - y(0), - raw_x(0), - raw_y(0), - pressure(0), - touch_major(0), - touch_minor(0), - orientation(0) { + : PointerProperties(0, 0, 0) { } PointerProperties::PointerProperties(float x, float y, float touch_major) @@ -31,7 +23,8 @@ PointerProperties::PointerProperties(float x, float y, float touch_major) pressure(0), touch_major(touch_major), touch_minor(0), - orientation(0) { + orientation(0), + source_device_id(0) { } PointerProperties::PointerProperties(const MotionEvent& event, @@ -45,7 +38,8 @@ PointerProperties::PointerProperties(const MotionEvent& event, pressure(event.GetPressure(pointer_index)), touch_major(event.GetTouchMajor(pointer_index)), touch_minor(event.GetTouchMinor(pointer_index)), - orientation(event.GetOrientation(pointer_index)) { + orientation(event.GetOrientation(pointer_index)), + source_device_id(0) { } MotionEventGeneric::MotionEventGeneric(Action action, @@ -53,7 +47,7 @@ MotionEventGeneric::MotionEventGeneric(Action action, const PointerProperties& pointer) : action_(action), event_time_(event_time), - id_(0), + unique_event_id_(ui::GetNextTouchEventId()), action_index_(0), button_state_(0), flags_(0) { @@ -63,7 +57,7 @@ MotionEventGeneric::MotionEventGeneric(Action action, MotionEventGeneric::MotionEventGeneric(const MotionEventGeneric& other) : action_(other.action_), event_time_(other.event_time_), - id_(other.id_), + unique_event_id_(other.unique_event_id_), action_index_(other.action_index_), button_state_(other.button_state_), flags_(other.flags_), @@ -76,8 +70,8 @@ MotionEventGeneric::MotionEventGeneric(const MotionEventGeneric& other) MotionEventGeneric::~MotionEventGeneric() { } -int MotionEventGeneric::GetId() const { - return id_; +uint32 MotionEventGeneric::GetUniqueEventId() const { + return unique_event_id_; } MotionEvent::Action MotionEventGeneric::GetAction() const { @@ -85,6 +79,9 @@ MotionEvent::Action MotionEventGeneric::GetAction() const { } int MotionEventGeneric::GetActionIndex() const { + DCHECK(action_ == ACTION_POINTER_DOWN || action_ == ACTION_POINTER_UP); + DCHECK_GE(action_index_, 0); + DCHECK_LT(action_index_, static_cast<int>(pointers_->size())); return action_index_; } @@ -198,12 +195,19 @@ scoped_ptr<MotionEventGeneric> MotionEventGeneric::CancelEvent( scoped_ptr<MotionEventGeneric> cancel_event( new MotionEventGeneric(event, with_history)); cancel_event->set_action(ACTION_CANCEL); + cancel_event->set_unique_event_id(ui::GetNextTouchEventId()); return cancel_event.Pass(); } -void MotionEventGeneric::PushPointer(const PointerProperties& pointer) { +size_t MotionEventGeneric::PushPointer(const PointerProperties& pointer) { DCHECK_EQ(0U, GetHistorySize()); pointers_->push_back(pointer); + return pointers_->size() - 1; +} + +void MotionEventGeneric::RemovePointerAt(size_t index) { + DCHECK_LT(index, pointers_->size()); + pointers_->erase(pointers_->begin() + index); } void MotionEventGeneric::PushHistoricalEvent(scoped_ptr<MotionEvent> event) { @@ -217,14 +221,17 @@ void MotionEventGeneric::PushHistoricalEvent(scoped_ptr<MotionEvent> event) { } MotionEventGeneric::MotionEventGeneric() - : action_(ACTION_CANCEL), id_(0), action_index_(0), button_state_(0) { + : action_(ACTION_CANCEL), + unique_event_id_(ui::GetNextTouchEventId()), + action_index_(0), + button_state_(0) { } MotionEventGeneric::MotionEventGeneric(const MotionEvent& event, bool with_history) : action_(event.GetAction()), event_time_(event.GetEventTime()), - id_(event.GetId()), + unique_event_id_(event.GetUniqueEventId()), action_index_( (action_ == ACTION_POINTER_UP || action_ == ACTION_POINTER_DOWN) ? event.GetActionIndex() @@ -257,7 +264,7 @@ MotionEventGeneric& MotionEventGeneric::operator=( const MotionEventGeneric& other) { action_ = other.action_; event_time_ = other.event_time_; - id_ = other.id_; + unique_event_id_ = other.unique_event_id_; action_index_ = other.action_index_; button_state_ = other.button_state_; flags_ = other.flags_; diff --git a/chromium/ui/events/gesture_detection/motion_event_generic.h b/chromium/ui/events/gesture_detection/motion_event_generic.h index 359a651a041..635734208bd 100644 --- a/chromium/ui/events/gesture_detection/motion_event_generic.h +++ b/chromium/ui/events/gesture_detection/motion_event_generic.h @@ -28,6 +28,8 @@ struct GESTURE_DETECTION_EXPORT PointerProperties { float touch_major; float touch_minor; float orientation; + // source_device_id is only used on Aura. + int source_device_id; }; // A generic MotionEvent implementation. @@ -41,7 +43,7 @@ class GESTURE_DETECTION_EXPORT MotionEventGeneric : public MotionEvent { ~MotionEventGeneric() override; // MotionEvent implementation. - int GetId() const override; + uint32 GetUniqueEventId() const override; Action GetAction() const override; int GetActionIndex() const override; size_t GetPointerCount() const override; @@ -68,7 +70,16 @@ class GESTURE_DETECTION_EXPORT MotionEventGeneric : public MotionEvent { float GetHistoricalY(size_t pointer_index, size_t historical_index) const override; - void PushPointer(const PointerProperties& pointer); + // Adds |pointer| to the set of pointers returning the index it was added at. + size_t PushPointer(const PointerProperties& pointer); + + // Removes the PointerProperties at |index|. + void RemovePointerAt(size_t index); + + PointerProperties& pointer(size_t index) { return pointers_[index]; } + const PointerProperties& pointer(size_t index) const { + return pointers_[index]; + } // Add an event to the history. |this| and |event| must have the same pointer // count and must both have an action of ACTION_MOVE. @@ -76,7 +87,9 @@ class GESTURE_DETECTION_EXPORT MotionEventGeneric : public MotionEvent { void set_action(Action action) { action_ = action; } void set_event_time(base::TimeTicks event_time) { event_time_ = event_time; } - void set_id(int id) { id_ = id; } + void set_unique_event_id(uint32 unique_event_id) { + unique_event_id_ = unique_event_id; + } void set_action_index(int action_index) { action_index_ = action_index; } void set_button_state(int button_state) { button_state_ = button_state; } void set_flags(int flags) { flags_ = flags; } @@ -91,17 +104,12 @@ class GESTURE_DETECTION_EXPORT MotionEventGeneric : public MotionEvent { void PopPointer(); - PointerProperties& pointer(size_t index) { return pointers_[index]; } - const PointerProperties& pointer(size_t index) const { - return pointers_[index]; - } - private: enum { kTypicalMaxPointerCount = 5 }; Action action_; base::TimeTicks event_time_; - int id_; + uint32 unique_event_id_; int action_index_; int button_state_; int flags_; diff --git a/chromium/ui/events/gesture_detection/motion_event_generic_unittest.cc b/chromium/ui/events/gesture_detection/motion_event_generic_unittest.cc index 23762e3f14a..182eb1e4833 100644 --- a/chromium/ui/events/gesture_detection/motion_event_generic_unittest.cc +++ b/chromium/ui/events/gesture_detection/motion_event_generic_unittest.cc @@ -17,6 +17,10 @@ TEST(MotionEventGenericTest, Basic) { EXPECT_EQ(0U, event.GetHistorySize()); EXPECT_EQ(event_time, event.GetEventTime()); + DCHECK_NE(0U, event.GetUniqueEventId()); + event.set_unique_event_id(123456U); + EXPECT_EQ(123456U, event.GetUniqueEventId()); + event.PushPointer(PointerProperties(8.3f, 4.7f, 0.9f)); ASSERT_EQ(2U, event.GetPointerCount()); EXPECT_EQ(8.3f, event.GetX(1)); @@ -27,8 +31,8 @@ TEST(MotionEventGenericTest, Basic) { EXPECT_EQ(2.3f, event.GetX(2)); EXPECT_EQ(-3.7f, event.GetY(2)); - event.set_id(1); - EXPECT_EQ(1, event.GetId()); + event.pointer(0).id = 3; + EXPECT_EQ(3, event.GetPointerId(0)); event.set_action(MotionEvent::ACTION_POINTER_DOWN); EXPECT_EQ(MotionEvent::ACTION_POINTER_DOWN, event.GetAction()); @@ -78,11 +82,11 @@ TEST(MotionEventGenericTest, Clone) { MotionEventGeneric event(MotionEvent::ACTION_DOWN, base::TimeTicks::Now(), PointerProperties(8.3f, 4.7f, 2.f)); - event.set_id(1); event.set_button_state(MotionEvent::BUTTON_PRIMARY); scoped_ptr<MotionEvent> clone = event.Clone(); ASSERT_TRUE(clone); + EXPECT_EQ(event.GetUniqueEventId(), clone->GetUniqueEventId()); EXPECT_EQ(test::ToString(event), test::ToString(*clone)); } @@ -103,6 +107,7 @@ TEST(MotionEventGenericTest, CloneWithHistory) { scoped_ptr<MotionEvent> clone = event.Clone(); ASSERT_TRUE(clone); + EXPECT_EQ(event.GetUniqueEventId(), clone->GetUniqueEventId()); EXPECT_EQ(test::ToString(event), test::ToString(*clone)); } @@ -110,12 +115,12 @@ TEST(MotionEventGenericTest, Cancel) { MotionEventGeneric event(MotionEvent::ACTION_UP, base::TimeTicks::Now(), PointerProperties(8.7f, 4.3f, 1.f)); - event.set_id(2); event.set_button_state(MotionEvent::BUTTON_SECONDARY); scoped_ptr<MotionEvent> cancel = event.Cancel(); event.set_action(MotionEvent::ACTION_CANCEL); ASSERT_TRUE(cancel); + EXPECT_NE(event.GetUniqueEventId(), cancel->GetUniqueEventId()); EXPECT_EQ(test::ToString(event), test::ToString(*cancel)); } @@ -130,7 +135,7 @@ TEST(MotionEventGenericTest, FindPointerIndexOfId) { MotionEventGeneric event1(event0); pointer.id = 7; - event1.PushPointer(pointer); + EXPECT_EQ(1u, event1.PushPointer(pointer)); EXPECT_EQ(0, event1.FindPointerIndexOfId(0)); EXPECT_EQ(1, event1.FindPointerIndexOfId(7)); EXPECT_EQ(-1, event1.FindPointerIndexOfId(6)); @@ -138,7 +143,7 @@ TEST(MotionEventGenericTest, FindPointerIndexOfId) { MotionEventGeneric event2(event1); pointer.id = 3; - event2.PushPointer(pointer); + EXPECT_EQ(2u, event2.PushPointer(pointer)); EXPECT_EQ(0, event2.FindPointerIndexOfId(0)); EXPECT_EQ(1, event2.FindPointerIndexOfId(7)); EXPECT_EQ(2, event2.FindPointerIndexOfId(3)); @@ -146,6 +151,32 @@ TEST(MotionEventGenericTest, FindPointerIndexOfId) { EXPECT_EQ(-1, event2.FindPointerIndexOfId(2)); } +TEST(MotionEventGenericTest, RemovePointerAt) { + base::TimeTicks event_time = base::TimeTicks::Now(); + PointerProperties pointer; + pointer.id = 0; + MotionEventGeneric event(MotionEvent::ACTION_DOWN, event_time, pointer); + + pointer.id = 7; + EXPECT_EQ(1u, event.PushPointer(pointer)); + EXPECT_EQ(2u, event.GetPointerCount()); + + // Remove from the end. + event.RemovePointerAt(1); + EXPECT_EQ(1u, event.GetPointerCount()); + EXPECT_EQ(-1, event.FindPointerIndexOfId(7)); + EXPECT_EQ(0, event.FindPointerIndexOfId(0)); + + EXPECT_EQ(1u, event.PushPointer(pointer)); + EXPECT_EQ(2u, event.GetPointerCount()); + + // Remove from the beginning. + event.RemovePointerAt(0); + EXPECT_EQ(1u, event.GetPointerCount()); + EXPECT_EQ(0, event.FindPointerIndexOfId(7)); + EXPECT_EQ(-1, event.FindPointerIndexOfId(0)); +} + TEST(MotionEventGenericTest, ToString) { base::TimeTicks event_time = base::TimeTicks::Now(); base::TimeTicks historical_event_time0 = diff --git a/chromium/ui/events/gesture_detection/scale_gesture_detector.cc b/chromium/ui/events/gesture_detection/scale_gesture_detector.cc index 7afe91fd3af..fb27cd9458e 100644 --- a/chromium/ui/events/gesture_detection/scale_gesture_detector.cc +++ b/chromium/ui/events/gesture_detection/scale_gesture_detector.cc @@ -5,9 +5,9 @@ #include "ui/events/gesture_detection/scale_gesture_detector.h" #include <limits.h> + #include <cmath> -#include "base/float_util.h" #include "base/logging.h" #include "ui/events/gesture_detection/motion_event.h" #include "ui/events/gesture_detection/scale_gesture_listeners.h" @@ -30,7 +30,8 @@ const float kScaleFactor = .5f; } // namespace // Note: These constants were taken directly from the default (unscaled) -// versions found in Android's ViewConfiguration. +// versions found in Android's ViewConfiguration. Do not change these default +// values without explicitly consulting an OWNER. ScaleGestureDetector::Config::Config() : span_slop(16), min_scaling_touch_major(48), @@ -285,7 +286,7 @@ void ScaleGestureDetector::AddTouchHistory(const MotionEvent& ev) { float total = 0; int sample_count = 0; for (int i = 0; i < count; i++) { - const bool has_last_accepted = !base::IsNaN(touch_history_last_accepted_); + const bool has_last_accepted = !std::isnan(touch_history_last_accepted_); const int history_size = static_cast<int>(ev.GetHistorySize()); const int pointersample_count = history_size + 1; for (int h = 0; h < pointersample_count; h++) { @@ -301,10 +302,10 @@ void ScaleGestureDetector::AddTouchHistory(const MotionEvent& ev) { major = touch_max_major_; total += major; - if (base::IsNaN(touch_upper_) || major > touch_upper_) { + if (std::isnan(touch_upper_) || major > touch_upper_) { touch_upper_ = major; } - if (base::IsNaN(touch_lower_) || major < touch_lower_) { + if (std::isnan(touch_lower_) || major < touch_lower_) { touch_lower_ = major; } diff --git a/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.cc b/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.cc index fcb92d495d4..b4c25cadc23 100644 --- a/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.cc +++ b/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.cc @@ -12,8 +12,8 @@ namespace ui { namespace { // A BitSet32 is used for tracking dropped gesture types. -COMPILE_ASSERT(ET_GESTURE_TYPE_END - ET_GESTURE_TYPE_START < 32, - gesture_type_count_too_large); +static_assert(ET_GESTURE_TYPE_END - ET_GESTURE_TYPE_START < 32, + "gesture type count too large"); GestureEventData CreateGesture(EventType type, int motion_event_id, @@ -170,20 +170,43 @@ TouchDispositionGestureFilter::OnGesturePacket( return SUCCESS; } -void TouchDispositionGestureFilter::OnTouchEventAck(bool event_consumed) { - // Spurious touch acks from the renderer should not trigger a crash. +void TouchDispositionGestureFilter::OnTouchEventAckForQueueFront( + bool event_consumed) { + // Spurious asynchronous acks should not trigger a crash. if (IsEmpty() || (Head().empty() && sequences_.size() == 1)) return; if (Head().empty()) PopGestureSequence(); - GestureSequence& sequence = Head(); + Head().front().Ack(event_consumed); + SendAckedEvents(); +} + +void TouchDispositionGestureFilter::OnTouchEventAckForQueueBack( + bool event_consumed) { + // Make sure there is an event to ack. + CHECK(!IsEmpty()); + CHECK(!Tail().empty()); + + Tail().back().Ack(event_consumed); + + if (Head().empty()) + PopGestureSequence(); + + if (sequences_.size() == 1 && Tail().size() == 1) + SendAckedEvents(); +} - // Dispatch the packet corresponding to the ack'ed touch, as well as any - // additional timeout-based packets queued before the ack was received. +void TouchDispositionGestureFilter::SendAckedEvents() { + // Dispatch all packets corresponding to ack'ed touches, as well as + // any pending timeout-based packets. bool touch_packet_for_current_ack_handled = false; - while (!sequence.empty()) { + while (!IsEmpty() && (!Head().empty() || sequences_.size() != 1)) { + if (Head().empty()) + PopGestureSequence(); + GestureSequence& sequence = Head(); + DCHECK_NE(sequence.front().gesture_source(), GestureEventDataPacket::UNDEFINED); DCHECK_NE(sequence.front().gesture_source(), @@ -191,17 +214,21 @@ void TouchDispositionGestureFilter::OnTouchEventAck(bool event_consumed) { GestureEventDataPacket::GestureSource source = sequence.front().gesture_source(); + GestureEventDataPacket::AckState ack_state = sequence.front().ack_state(); + if (source != GestureEventDataPacket::TOUCH_TIMEOUT) { - // We should handle at most one non-timeout based packet. - if (touch_packet_for_current_ack_handled) + // We've sent all packets which aren't pending their ack. + if (ack_state == GestureEventDataPacket::AckState::PENDING) break; - state_.OnTouchEventAck(event_consumed, IsTouchStartEvent(source)); - touch_packet_for_current_ack_handled = true; + state_.OnTouchEventAck( + ack_state == GestureEventDataPacket::AckState::CONSUMED, + IsTouchStartEvent(source)); } // We need to pop the current sequence before sending the packet, because // sending the packet could result in this method being re-entered (e.g. on // Aura, we could trigger a touch-cancel). As popping the sequence destroys // the packet, we copy the packet before popping it. + touch_packet_for_current_ack_handled = true; const GestureEventDataPacket packet = sequence.front(); sequence.pop(); FilterAndSendPacket(packet); @@ -314,6 +341,15 @@ void TouchDispositionGestureFilter::SendGesture( ending_event_primary_tool_type_ = event.primary_tool_type; needs_scroll_ending_event_ = true; break; + case ET_GESTURE_SCROLL_UPDATE: + if (state_.HasFilteredGestureType(ET_GESTURE_SCROLL_UPDATE)) { + GestureEventData modified_event(ET_GESTURE_SCROLL_UPDATE, event); + modified_event.details + .mark_previous_scroll_update_in_sequence_prevented(); + client_->ForwardGestureEvent(modified_event); + return; + } + break; case ET_GESTURE_SCROLL_END: needs_scroll_ending_event_ = false; break; @@ -418,10 +454,17 @@ bool TouchDispositionGestureFilter::GestureHandlingState::Filter( last_gesture_of_type_dropped_.has_bit( GetGestureTypeIndex(antecedent_event_type)))) { last_gesture_of_type_dropped_.mark_bit(GetGestureTypeIndex(gesture_type)); + any_gesture_of_type_dropped_.mark_bit(GetGestureTypeIndex(gesture_type)); return true; } last_gesture_of_type_dropped_.clear_bit(GetGestureTypeIndex(gesture_type)); return false; } +bool TouchDispositionGestureFilter::GestureHandlingState:: + HasFilteredGestureType(EventType gesture_type) const { + return any_gesture_of_type_dropped_.has_bit( + GetGestureTypeIndex(gesture_type)); +} + } // namespace content diff --git a/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.h b/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.h index 290afaaf6a8..d2d8583791d 100644 --- a/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.h +++ b/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.h @@ -42,8 +42,10 @@ class GESTURE_DETECTION_EXPORT TouchDispositionGestureFilter { }; PacketResult OnGesturePacket(const GestureEventDataPacket& packet); - // To be called upon receipt of *all* touch event acks. - void OnTouchEventAck(bool event_consumed); + // One of |OnTouchEventAckForQueue*| must be called upon receipt of + // every touch event ack. + void OnTouchEventAckForQueueFront(bool event_consumed); + void OnTouchEventAckForQueueBack(bool event_consumed); // Whether there are any active gesture sequences still queued in the filter. bool IsEmpty() const; @@ -66,14 +68,18 @@ class GESTURE_DETECTION_EXPORT TouchDispositionGestureFilter { // Returns true iff the gesture should be dropped. bool Filter(EventType type); + // Whether an event of |type| has been filtered from the current sequence. + bool HasFilteredGestureType(EventType type) const; + private: // True iff the sequence has had any touch down event consumed. bool start_touch_consumed_; // True iff the most recently ack'ed touch event was consumed. bool current_touch_consumed_; - // If the previous gesture of a given type was dropped instead of being - // dispatched, its type will occur in this set. + // Indicates whether the previous gesture of a given type was dropped. BitSet32 last_gesture_of_type_dropped_; + // Indicates whether *any* previous gesture of a given type was dropped. + BitSet32 any_gesture_of_type_dropped_; }; void FilterAndSendPacket(const GestureEventDataPacket& packet); @@ -83,6 +89,7 @@ class GESTURE_DETECTION_EXPORT TouchDispositionGestureFilter { void CancelFlingIfNecessary(const GestureEventDataPacket& packet); void EndScrollIfNecessary(const GestureEventDataPacket& packet); void PopGestureSequence(); + void SendAckedEvents(); GestureSequence& Head(); GestureSequence& Tail(); diff --git a/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc b/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc index 5d823b72d3f..b01a69f7629 100644 --- a/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc +++ b/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc @@ -42,7 +42,7 @@ class TouchDispositionGestureFilterTest show_press_bounding_box_ = event.details.bounding_box(); if (cancel_after_next_gesture_) { cancel_after_next_gesture_ = false; - CancelTouchPoint(); + SendPacket(CancelTouchPoint(), NoGestures()); SendTouchNotConsumedAck(); } } @@ -71,6 +71,8 @@ class TouchDispositionGestureFilterTest return ::testing::AssertionSuccess(); } + GestureList NoGestures() { return GestureList(0); } + GestureList Gestures(EventType type) { return GestureList(1, type); } @@ -104,14 +106,6 @@ class TouchDispositionGestureFilterTest return gestures; } - void SendTouchGestures() { - touch_event_.set_event_time(base::TimeTicks::Now()); - EXPECT_EQ(TouchDispositionGestureFilter::SUCCESS, - SendTouchGestures(touch_event_, pending_gesture_packet_)); - GestureEventDataPacket gesture_packet; - std::swap(gesture_packet, pending_gesture_packet_); - } - TouchDispositionGestureFilter::PacketResult SendTouchGestures(const MotionEvent& touch, const GestureEventDataPacket& packet) { @@ -134,13 +128,25 @@ class TouchDispositionGestureFilterTest } void SendTouchEventAck(bool event_consumed) { - queue_->OnTouchEventAck(event_consumed); + queue_->OnTouchEventAckForQueueFront(event_consumed); } void SendTouchConsumedAck() { SendTouchEventAck(true); } void SendTouchNotConsumedAck() { SendTouchEventAck(false); } + void SendTouchEventAckForQueueBack(bool event_consumed) { + queue_->OnTouchEventAckForQueueBack(event_consumed); + } + + void SendTouchConsumedAckForQueueBack() { + SendTouchEventAckForQueueBack(true); + } + + void SendTouchNotConsumedAckForQueueBack() { + SendTouchEventAckForQueueBack(false); + } + void PushGesture(EventType type) { pending_gesture_packet_.Push(CreateGesture(type)); } @@ -149,39 +155,60 @@ class TouchDispositionGestureFilterTest pending_gesture_packet_.Push(CreateGesture(type, x, y, diameter)); } - void PressTouchPoint(int x, int y) { + const MockMotionEvent& PressTouchPoint(float x, float y) { touch_event_.PressPoint(x, y); touch_event_.SetRawOffset(raw_offset_.x(), raw_offset_.y()); - SendTouchGestures(); + return touch_event_; } - void MoveTouchPoint(size_t index, int x, int y) { - touch_event_.MovePoint(index, x, y); - touch_event_.SetRawOffset(raw_offset_.x(), raw_offset_.y()); - SendTouchGestures(); + const MockMotionEvent& PressTouchPoint() { return PressTouchPoint(0, 0); } + + const MockMotionEvent& MoveTouchPoint() { + touch_event_.MovePoint(0, 0, 0); + touch_event_.set_event_time(base::TimeTicks::Now()); + return touch_event_; } - void ReleaseTouchPoint() { + const MockMotionEvent& ReleaseTouchPoint() { touch_event_.ReleasePoint(); - SendTouchGestures(); + touch_event_.set_event_time(base::TimeTicks::Now()); + return touch_event_; } - void CancelTouchPoint() { + const MockMotionEvent& CancelTouchPoint() { touch_event_.CancelPoint(); - SendTouchGestures(); + touch_event_.set_event_time(base::TimeTicks::Now()); + return touch_event_; + } + + void SendPacket(const MockMotionEvent& touch_event, + GestureList gesture_list) { + GestureEventDataPacket gesture_packet; + for (EventType type : gesture_list) + gesture_packet.Push(CreateGesture(type)); + + EXPECT_EQ(TouchDispositionGestureFilter::SUCCESS, + SendTouchGestures(touch_event, gesture_packet)); } void SetRawTouchOffset(const gfx::Vector2dF& raw_offset) { raw_offset_ = raw_offset; } - void ResetTouchPoints() { touch_event_ = MockMotionEvent(); } + const MockMotionEvent& ResetTouchPoints() { + touch_event_ = MockMotionEvent(); + return touch_event_; + } bool GesturesSent() const { return !sent_gestures_.empty(); } - base::TimeTicks LastSentGestureTime() const { + const GestureEventData& last_sent_gesture() const { CHECK(last_sent_gesture_); - return last_sent_gesture_->time; + return *last_sent_gesture_; + } + + base::TimeTicks LastSentGestureTime() const { + return last_sent_gesture().time; } base::TimeTicks CurrentTouchTime() const { @@ -197,18 +224,15 @@ class TouchDispositionGestureFilterTest } gfx::PointF LastSentGestureLocation() const { - CHECK(last_sent_gesture_); - return gfx::PointF(last_sent_gesture_->x, last_sent_gesture_->y); + return gfx::PointF(last_sent_gesture().x, last_sent_gesture().y); } gfx::PointF LastSentGestureRawLocation() const { - CHECK(last_sent_gesture_); - return gfx::PointF(last_sent_gesture_->raw_x, last_sent_gesture_->raw_y); + return gfx::PointF(last_sent_gesture().raw_x, last_sent_gesture().raw_y); } int LastSentGestureFlags() const { - CHECK(last_sent_gesture_); - return last_sent_gesture_->flags; + return last_sent_gesture().flags; } const gfx::RectF& ShowPressBoundingBox() const { @@ -228,15 +252,8 @@ class TouchDispositionGestureFilterTest float y, float diameter) { return GestureEventData( - GestureEventDetails(type), - 0, - MotionEvent::TOOL_TYPE_FINGER, - base::TimeTicks(), - touch_event_.GetX(0), - touch_event_.GetY(0), - touch_event_.GetRawX(0), - touch_event_.GetRawY(0), - 1, + GestureEventDetails(type), 0, MotionEvent::TOOL_TYPE_FINGER, + base::TimeTicks(), x, y, 0, 0, 1, gfx::RectF(x - diameter / 2, y - diameter / 2, diameter, diameter), kDefaultEventFlags); } @@ -254,10 +271,10 @@ class TouchDispositionGestureFilterTest }; TEST_F(TouchDispositionGestureFilterTest, BasicNoGestures) { - PressTouchPoint(1, 1); + PressTouchPoint(); EXPECT_FALSE(GesturesSent()); - MoveTouchPoint(0, 2, 2); + MoveTouchPoint(); EXPECT_FALSE(GesturesSent()); // No gestures should be dispatched by the ack, as the queued packets @@ -273,99 +290,83 @@ TEST_F(TouchDispositionGestureFilterTest, BasicNoGestures) { } TEST_F(TouchDispositionGestureFilterTest, BasicGestures) { + GestureList press_gestures = + Gestures(ET_GESTURE_BEGIN, ET_GESTURE_SCROLL_BEGIN); // An unconsumed touch's gesture should be sent. - PushGesture(ET_GESTURE_BEGIN); - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), press_gestures); EXPECT_FALSE(GesturesSent()); SendTouchNotConsumedAck(); - EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_BEGIN, ET_GESTURE_SCROLL_BEGIN), - GetAndResetSentGestures())); + EXPECT_TRUE(GesturesMatch(press_gestures, GetAndResetSentGestures())); // Multiple gestures can be queued for a single event. - PushGesture(ET_SCROLL_FLING_START); - PushGesture(ET_SCROLL_FLING_CANCEL); - PushGesture(ET_GESTURE_END); - ReleaseTouchPoint(); + GestureList release_gestures = + Gestures(ET_SCROLL_FLING_START, ET_SCROLL_FLING_CANCEL, ET_GESTURE_END); + SendPacket(ReleaseTouchPoint(), release_gestures); EXPECT_FALSE(GesturesSent()); SendTouchNotConsumedAck(); - EXPECT_TRUE(GesturesMatch(Gestures(ET_SCROLL_FLING_START, - ET_SCROLL_FLING_CANCEL, - ET_GESTURE_END), - GetAndResetSentGestures())); + EXPECT_TRUE(GesturesMatch(release_gestures, GetAndResetSentGestures())); } TEST_F(TouchDispositionGestureFilterTest, BasicGesturesConsumed) { // A consumed touch's gesture should not be sent. - PushGesture(ET_GESTURE_BEGIN); - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), + Gestures(ET_GESTURE_BEGIN, ET_GESTURE_SCROLL_BEGIN)); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_GESTURE_SCROLL_UPDATE); - MoveTouchPoint(0, 2, 2); + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_SCROLL_FLING_START); - PushGesture(ET_SCROLL_FLING_CANCEL); - PushGesture(ET_GESTURE_END); - ReleaseTouchPoint(); + SendPacket( + ReleaseTouchPoint(), + Gestures(ET_SCROLL_FLING_START, ET_SCROLL_FLING_CANCEL, ET_GESTURE_END)); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); } TEST_F(TouchDispositionGestureFilterTest, ConsumedThenNotConsumed) { // A consumed touch's gesture should not be sent. - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); // Even if the subsequent touch is not consumed, continue dropping gestures. - PushGesture(ET_GESTURE_SCROLL_UPDATE); - MoveTouchPoint(0, 2, 2); + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); SendTouchNotConsumedAck(); EXPECT_FALSE(GesturesSent()); // Even if the subsequent touch had no consumer, continue dropping gestures. - PushGesture(ET_SCROLL_FLING_START); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_SCROLL_FLING_START)); SendTouchNotConsumedAck(); EXPECT_FALSE(GesturesSent()); } TEST_F(TouchDispositionGestureFilterTest, NotConsumedThenConsumed) { // A not consumed touch's gesture should be sent. - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_BEGIN), GetAndResetSentGestures())); // A newly consumed gesture should not be sent. - PushGesture(ET_GESTURE_PINCH_BEGIN); - PressTouchPoint(10, 10); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_PINCH_BEGIN)); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); // And subsequent non-consumed pinch updates should not be sent. - PushGesture(ET_GESTURE_SCROLL_UPDATE); - PushGesture(ET_GESTURE_PINCH_UPDATE); - MoveTouchPoint(0, 2, 2); + SendPacket(MoveTouchPoint(), + Gestures(ET_GESTURE_SCROLL_UPDATE, ET_GESTURE_PINCH_UPDATE)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_UPDATE), GetAndResetSentGestures())); // End events dispatched only when their start events were. - PushGesture(ET_GESTURE_PINCH_END); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_PINCH_END)); SendTouchNotConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_GESTURE_SCROLL_END); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_SCROLL_END)); SendTouchConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_END), GetAndResetSentGestures())); @@ -373,27 +374,23 @@ TEST_F(TouchDispositionGestureFilterTest, NotConsumedThenConsumed) { TEST_F(TouchDispositionGestureFilterTest, ScrollAlternatelyConsumed) { // A consumed touch's gesture should not be sent. - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_BEGIN), GetAndResetSentGestures())); for (size_t i = 0; i < 3; ++i) { - PushGesture(ET_GESTURE_SCROLL_UPDATE); - MoveTouchPoint(0, 2, 2); + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_GESTURE_SCROLL_UPDATE); - MoveTouchPoint(0, 3, 3); + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_UPDATE), GetAndResetSentGestures())); } - PushGesture(ET_GESTURE_SCROLL_END); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_SCROLL_END)); SendTouchConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_END), GetAndResetSentGestures())); @@ -401,73 +398,63 @@ TEST_F(TouchDispositionGestureFilterTest, ScrollAlternatelyConsumed) { TEST_F(TouchDispositionGestureFilterTest, NotConsumedThenNoConsumer) { // An unconsumed touch's gesture should be sent. - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_BEGIN), GetAndResetSentGestures())); // If the subsequent touch has no consumer (e.g., a secondary pointer is // pressed but not on a touch handling rect), send the gesture. - PushGesture(ET_GESTURE_PINCH_BEGIN); - PressTouchPoint(2, 2); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_PINCH_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_PINCH_BEGIN), GetAndResetSentGestures())); // End events should be dispatched when their start events were, independent // of the ack state. - PushGesture(ET_GESTURE_PINCH_END); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_PINCH_END)); SendTouchConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_PINCH_END), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_SCROLL_END); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_SCROLL_END)); SendTouchConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_END), GetAndResetSentGestures())); } TEST_F(TouchDispositionGestureFilterTest, EndingEventsSent) { - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_BEGIN), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_PINCH_BEGIN); - PressTouchPoint(2, 2); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_PINCH_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_PINCH_BEGIN), GetAndResetSentGestures())); // Consuming the touchend event can't suppress the match end gesture. - PushGesture(ET_GESTURE_PINCH_END); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_PINCH_END)); SendTouchConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_PINCH_END), GetAndResetSentGestures())); // But other events in the same packet are still suppressed. - PushGesture(ET_GESTURE_SCROLL_UPDATE); - PushGesture(ET_GESTURE_SCROLL_END); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), + Gestures(ET_GESTURE_SCROLL_UPDATE, ET_GESTURE_SCROLL_END)); SendTouchConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_END), GetAndResetSentGestures())); // ET_GESTURE_SCROLL_END and ET_SCROLL_FLING_START behave the same in this // regard. - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_BEGIN), GetAndResetSentGestures())); - PushGesture(ET_SCROLL_FLING_START); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_SCROLL_FLING_START)); SendTouchConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_SCROLL_FLING_START), GetAndResetSentGestures())); @@ -475,121 +462,99 @@ TEST_F(TouchDispositionGestureFilterTest, EndingEventsSent) { TEST_F(TouchDispositionGestureFilterTest, EndingEventsNotSent) { // Consuming a begin event ensures no end events are sent. - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_GESTURE_PINCH_BEGIN); - PressTouchPoint(2, 2); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_PINCH_BEGIN)); SendTouchNotConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_GESTURE_PINCH_END); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_PINCH_END)); SendTouchNotConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_GESTURE_SCROLL_END); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_SCROLL_END)); SendTouchNotConsumedAck(); EXPECT_FALSE(GesturesSent()); } TEST_F(TouchDispositionGestureFilterTest, UpdateEventsSuppressedPerEvent) { - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_BEGIN), GetAndResetSentGestures())); // Consuming a single scroll or pinch update should suppress only that event. - PushGesture(ET_GESTURE_SCROLL_UPDATE); - MoveTouchPoint(0, 2, 2); + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_GESTURE_PINCH_BEGIN); - PressTouchPoint(2, 2); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_PINCH_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_PINCH_BEGIN), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_PINCH_UPDATE); - MoveTouchPoint(1, 2, 3); + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_PINCH_UPDATE)); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); // Subsequent updates should not be affected. - PushGesture(ET_GESTURE_SCROLL_UPDATE); - MoveTouchPoint(0, 4, 4); + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_UPDATE), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_PINCH_UPDATE); - MoveTouchPoint(0, 4, 5); + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_PINCH_UPDATE)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_PINCH_UPDATE), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_PINCH_END); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_PINCH_END)); SendTouchConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_PINCH_END), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_SCROLL_END); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_SCROLL_END)); SendTouchConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_END), GetAndResetSentGestures())); } TEST_F(TouchDispositionGestureFilterTest, UpdateEventsDependOnBeginEvents) { - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); // Scroll and pinch gestures depend on the scroll begin gesture being // dispatched. - PushGesture(ET_GESTURE_SCROLL_UPDATE); - MoveTouchPoint(0, 2, 2); + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); SendTouchNotConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_GESTURE_PINCH_BEGIN); - PressTouchPoint(2, 2); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_PINCH_BEGIN)); SendTouchNotConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_GESTURE_PINCH_UPDATE); - MoveTouchPoint(1, 2, 3); + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_PINCH_UPDATE)); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_GESTURE_PINCH_END); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_PINCH_END)); SendTouchNotConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_GESTURE_SCROLL_END); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_SCROLL_END)); SendTouchNotConsumedAck(); EXPECT_FALSE(GesturesSent()); } TEST_F(TouchDispositionGestureFilterTest, MultipleTouchSequences) { // Queue two touch-to-gestures sequences. - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); - PushGesture(ET_GESTURE_TAP); - ReleaseTouchPoint(); - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); - PushGesture(ET_GESTURE_SCROLL_END); - ReleaseTouchPoint(); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_TAP_DOWN)); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_TAP)); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_SCROLL_END)); // The first gesture sequence should not be allowed. SendTouchConsumedAck(); @@ -609,56 +574,53 @@ TEST_F(TouchDispositionGestureFilterTest, FlingCancelledOnNewTouchSequence) { SetRawTouchOffset(raw_offset); // Simulate a fling. - PushGesture(ET_GESTURE_TAP_DOWN); - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), + Gestures(ET_GESTURE_TAP_DOWN, ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch( Gestures( ET_GESTURE_TAP_DOWN, ET_GESTURE_TAP_CANCEL, ET_GESTURE_SCROLL_BEGIN), GetAndResetSentGestures())); - PushGesture(ET_SCROLL_FLING_START); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_SCROLL_FLING_START)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_SCROLL_FLING_START), GetAndResetSentGestures())); // A new touch sequence should cancel the outstanding fling. - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(1, 1), NoGestures()); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_SCROLL_FLING_CANCEL), GetAndResetSentGestures())); EXPECT_EQ(CurrentTouchTime(), LastSentGestureTime()); EXPECT_EQ(LastSentGestureLocation(), gfx::PointF(1, 1)); EXPECT_EQ(LastSentGestureRawLocation(), gfx::PointF(1, 1) + raw_offset); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), NoGestures()); SendTouchNotConsumedAck(); EXPECT_FALSE(GesturesSent()); } TEST_F(TouchDispositionGestureFilterTest, ScrollEndedOnTouchReleaseIfNoFling) { // Simulate a scroll. - PushGesture(ET_GESTURE_TAP_DOWN); - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + // Touch position will be used for synthesized scroll end gesture. + SendPacket(PressTouchPoint(2, 3), + Gestures(ET_GESTURE_TAP_DOWN, ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch( Gestures( ET_GESTURE_TAP_DOWN, ET_GESTURE_TAP_CANCEL, ET_GESTURE_SCROLL_BEGIN), GetAndResetSentGestures())); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), NoGestures()); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_END), GetAndResetSentGestures())); EXPECT_EQ(CurrentTouchTime(), LastSentGestureTime()); - EXPECT_EQ(LastSentGestureLocation(), gfx::PointF(1, 1)); + EXPECT_EQ(LastSentGestureLocation(), gfx::PointF(2, 3)); } TEST_F(TouchDispositionGestureFilterTest, ScrollEndedOnNewTouchSequence) { // Simulate a scroll. - PushGesture(ET_GESTURE_TAP_DOWN); - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), + Gestures(ET_GESTURE_TAP_DOWN, ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch( Gestures( @@ -667,7 +629,9 @@ TEST_F(TouchDispositionGestureFilterTest, ScrollEndedOnNewTouchSequence) { // A new touch sequence should end the outstanding scroll. ResetTouchPoints(); - PressTouchPoint(2, 3); + + // Touch position will be used for synthesized scroll end gesture. + SendPacket(PressTouchPoint(2, 3), NoGestures()); SendTouchConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_END), GetAndResetSentGestures())); @@ -677,10 +641,9 @@ TEST_F(TouchDispositionGestureFilterTest, ScrollEndedOnNewTouchSequence) { TEST_F(TouchDispositionGestureFilterTest, FlingCancelledOnScrollBegin) { // Simulate a fling sequence. - PushGesture(ET_GESTURE_TAP_DOWN); - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PushGesture(ET_SCROLL_FLING_START); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), + Gestures(ET_GESTURE_TAP_DOWN, ET_GESTURE_SCROLL_BEGIN, + ET_SCROLL_FLING_START)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN, ET_GESTURE_TAP_CANCEL, @@ -689,9 +652,8 @@ TEST_F(TouchDispositionGestureFilterTest, FlingCancelledOnScrollBegin) { GetAndResetSentGestures())); // The new fling should cancel the preceding one. - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PushGesture(ET_SCROLL_FLING_START); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), + Gestures(ET_GESTURE_SCROLL_BEGIN, ET_SCROLL_FLING_START)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_SCROLL_FLING_CANCEL, ET_GESTURE_SCROLL_BEGIN, @@ -701,14 +663,13 @@ TEST_F(TouchDispositionGestureFilterTest, FlingCancelledOnScrollBegin) { TEST_F(TouchDispositionGestureFilterTest, FlingNotCancelledIfGFCEventReceived) { // Simulate a fling that is started then cancelled. - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); - PushGesture(ET_SCROLL_FLING_START); - MoveTouchPoint(0, 2, 3); + SendPacket(MoveTouchPoint(), Gestures(ET_SCROLL_FLING_START)); SendTouchNotConsumedAck(); - PushGesture(ET_SCROLL_FLING_CANCEL); - ReleaseTouchPoint(); + GestureEventDataPacket packet; + packet.Push(CreateGesture(ET_SCROLL_FLING_CANCEL, 2, 3, 0)); + SendTouchGestures(ReleaseTouchPoint(), packet); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_BEGIN, ET_SCROLL_FLING_START, @@ -718,23 +679,21 @@ TEST_F(TouchDispositionGestureFilterTest, FlingNotCancelledIfGFCEventReceived) { // A new touch sequence will not inject a ET_SCROLL_FLING_CANCEL, as the fling // has already been cancelled. - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), NoGestures()); SendTouchNotConsumedAck(); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), NoGestures()); SendTouchNotConsumedAck(); EXPECT_FALSE(GesturesSent()); } TEST_F(TouchDispositionGestureFilterTest, TapCancelledWhenScrollBegins) { - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_TAP_DOWN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN), GetAndResetSentGestures())); // If the subsequent touch turns into a scroll, the tap should be cancelled. - PushGesture(ET_GESTURE_SCROLL_BEGIN); - MoveTouchPoint(0, 2, 2); + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_CANCEL, ET_GESTURE_SCROLL_BEGIN), @@ -742,38 +701,37 @@ TEST_F(TouchDispositionGestureFilterTest, TapCancelledWhenScrollBegins) { } TEST_F(TouchDispositionGestureFilterTest, TapCancelledWhenTouchConsumed) { - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_TAP_DOWN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN), GetAndResetSentGestures())); // If the subsequent touch is consumed, the tap should be cancelled. - PushGesture(ET_GESTURE_SCROLL_BEGIN); - MoveTouchPoint(0, 2, 2); + GestureEventDataPacket packet; + packet.Push(CreateGesture(ET_GESTURE_SCROLL_BEGIN, 2, 3, 0)); + SendTouchGestures(MoveTouchPoint(), packet); + SendTouchConsumedAck(); EXPECT_TRUE( GesturesMatch(Gestures(ET_GESTURE_TAP_CANCEL, ET_GESTURE_SCROLL_BEGIN), GetAndResetSentGestures())); - EXPECT_EQ(LastSentGestureLocation(), gfx::PointF(1, 1)); + EXPECT_EQ(LastSentGestureLocation(), gfx::PointF(2, 3)); } TEST_F(TouchDispositionGestureFilterTest, TapNotCancelledIfTapEndingEventReceived) { - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_TAP_DOWN)); SendTouchNotConsumedAck(); EXPECT_TRUE( GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_TAP); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_TAP)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SHOW_PRESS, ET_GESTURE_TAP), GetAndResetSentGestures())); // The tap should not be cancelled as it was terminated by a |ET_GESTURE_TAP|. - PressTouchPoint(2, 2); + SendPacket(PressTouchPoint(), NoGestures()); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); } @@ -781,8 +739,7 @@ TEST_F(TouchDispositionGestureFilterTest, TEST_F(TouchDispositionGestureFilterTest, TimeoutGestures) { // If the sequence is allowed, and there are no preceding gestures, the // timeout gestures should be forwarded immediately. - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_TAP_DOWN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN), GetAndResetSentGestures())); @@ -795,8 +752,7 @@ TEST_F(TouchDispositionGestureFilterTest, TimeoutGestures) { EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_LONG_PRESS), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_LONG_TAP); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_LONG_TAP)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_CANCEL, ET_GESTURE_LONG_TAP), @@ -804,20 +760,18 @@ TEST_F(TouchDispositionGestureFilterTest, TimeoutGestures) { // If the sequence is disallowed, and there are no preceding gestures, the // timeout gestures should be dropped immediately. - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_TAP_DOWN)); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); SendTimeoutGesture(ET_GESTURE_SHOW_PRESS); EXPECT_FALSE(GesturesSent()); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), NoGestures()); SendTouchNotConsumedAck(); // If the sequence has a pending ack, the timeout gestures should // remain queued until the ack is received. - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_TAP_DOWN)); EXPECT_FALSE(GesturesSent()); SendTimeoutGesture(ET_GESTURE_LONG_PRESS); @@ -835,10 +789,8 @@ TEST_F(TouchDispositionGestureFilterTest, SpuriousAcksIgnored) { SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); - PushGesture(ET_GESTURE_SCROLL_UPDATE); - MoveTouchPoint(0, 3,3); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); SendTouchNotConsumedAck(); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_BEGIN, @@ -868,16 +820,14 @@ TEST_F(TouchDispositionGestureFilterTest, PacketsWithInvalidOrderIgnored) { TEST_F(TouchDispositionGestureFilterTest, ConsumedTouchCancel) { // An unconsumed touch's gesture should be sent. - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_TAP_DOWN)); EXPECT_FALSE(GesturesSent()); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_TAP_CANCEL); - PushGesture(ET_GESTURE_SCROLL_END); - CancelTouchPoint(); + SendPacket(CancelTouchPoint(), + Gestures(ET_GESTURE_TAP_CANCEL, ET_GESTURE_SCROLL_END)); EXPECT_FALSE(GesturesSent()); SendTouchConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_CANCEL, @@ -886,12 +836,11 @@ TEST_F(TouchDispositionGestureFilterTest, ConsumedTouchCancel) { } TEST_F(TouchDispositionGestureFilterTest, TimeoutEventAfterRelease) { - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), NoGestures()); SendTouchNotConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_GESTURE_TAP_DOWN); - PushGesture(ET_GESTURE_TAP_UNCONFIRMED); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), + Gestures(ET_GESTURE_TAP_DOWN, ET_GESTURE_TAP_UNCONFIRMED)); SendTouchNotConsumedAck(); EXPECT_TRUE( GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN, ET_GESTURE_TAP_UNCONFIRMED), @@ -903,8 +852,7 @@ TEST_F(TouchDispositionGestureFilterTest, TimeoutEventAfterRelease) { } TEST_F(TouchDispositionGestureFilterTest, ShowPressInsertedBeforeTap) { - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_TAP_DOWN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN), GetAndResetSentGestures())); @@ -913,8 +861,7 @@ TEST_F(TouchDispositionGestureFilterTest, ShowPressInsertedBeforeTap) { EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_UNCONFIRMED), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_TAP); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_TAP)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SHOW_PRESS, ET_GESTURE_TAP), @@ -922,8 +869,7 @@ TEST_F(TouchDispositionGestureFilterTest, ShowPressInsertedBeforeTap) { } TEST_F(TouchDispositionGestureFilterTest, ShowPressNotInsertedIfAlreadySent) { - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_TAP_DOWN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN), GetAndResetSentGestures())); @@ -932,8 +878,7 @@ TEST_F(TouchDispositionGestureFilterTest, ShowPressNotInsertedIfAlreadySent) { EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SHOW_PRESS), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_TAP); - ReleaseTouchPoint(); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_TAP)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP), GetAndResetSentGestures())); @@ -943,14 +888,13 @@ TEST_F(TouchDispositionGestureFilterTest, TapAndScrollCancelledOnTouchCancel) { const gfx::Vector2dF raw_offset(1.3f, 3.7f); SetRawTouchOffset(raw_offset); - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(1, 1), Gestures(ET_GESTURE_TAP_DOWN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN), GetAndResetSentGestures())); // A cancellation motion event should cancel the tap. - CancelTouchPoint(); + SendPacket(CancelTouchPoint(), NoGestures()); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_CANCEL), GetAndResetSentGestures())); @@ -958,15 +902,14 @@ TEST_F(TouchDispositionGestureFilterTest, TapAndScrollCancelledOnTouchCancel) { EXPECT_EQ(LastSentGestureLocation(), gfx::PointF(1, 1)); EXPECT_EQ(LastSentGestureRawLocation(), gfx::PointF(1, 1) + raw_offset); - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(1, 1), Gestures(ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_BEGIN), GetAndResetSentGestures())); // A cancellation motion event should end the scroll, even if the touch was // consumed. - CancelTouchPoint(); + SendPacket(CancelTouchPoint(), NoGestures()); SendTouchConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_END), GetAndResetSentGestures())); @@ -978,59 +921,58 @@ TEST_F(TouchDispositionGestureFilterTest, TapAndScrollCancelledOnTouchCancel) { TEST_F(TouchDispositionGestureFilterTest, ConsumedScrollUpdateMakesFlingScrollEnd) { // A consumed touch's gesture should not be sent. - PushGesture(ET_GESTURE_BEGIN); - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), + Gestures(ET_GESTURE_BEGIN, ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE( GesturesMatch(Gestures(ET_GESTURE_BEGIN, ET_GESTURE_SCROLL_BEGIN), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_SCROLL_UPDATE); - MoveTouchPoint(0, 2, 2); + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); - PushGesture(ET_SCROLL_FLING_START); - PushGesture(ET_SCROLL_FLING_CANCEL); - PushGesture(ET_GESTURE_END); - ReleaseTouchPoint(); + GestureEventDataPacket packet; + packet.Push(CreateGesture(ET_SCROLL_FLING_START)); + packet.Push(CreateGesture(ET_SCROLL_FLING_CANCEL)); + packet.Push(CreateGesture(ET_GESTURE_END, 2, 3, 0)); + SendTouchGestures(ReleaseTouchPoint(), packet); + SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_END, ET_GESTURE_END), GetAndResetSentGestures())); - EXPECT_EQ(LastSentGestureLocation(), gfx::PointF(2, 2)); + EXPECT_EQ(LastSentGestureLocation(), gfx::PointF(2, 3)); - PushGesture(ET_GESTURE_BEGIN); - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), + Gestures(ET_GESTURE_BEGIN, ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_BEGIN, ET_GESTURE_SCROLL_BEGIN), GetAndResetSentGestures())); } TEST_F(TouchDispositionGestureFilterTest, TapCancelledOnTouchCancel) { - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + // Touch position is used for synthesized tap cancel. + SendPacket(PressTouchPoint(2, 3), Gestures(ET_GESTURE_TAP_DOWN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN), GetAndResetSentGestures())); // A cancellation motion event should cancel the tap. - CancelTouchPoint(); + SendPacket(CancelTouchPoint(), NoGestures()); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_CANCEL), GetAndResetSentGestures())); EXPECT_EQ(CurrentTouchTime(), LastSentGestureTime()); - EXPECT_EQ(LastSentGestureLocation(), gfx::PointF(1, 1)); + EXPECT_EQ(LastSentGestureLocation(), gfx::PointF(2, 3)); } // Test that a GestureEvent whose dispatch causes a cancel event to be fired // won't cause a crash. TEST_F(TouchDispositionGestureFilterTest, TestCancelMidGesture) { SetCancelAfterNextGesture(true); - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + // Synthesized tap cancel uses touch position. + SendPacket(PressTouchPoint(1, 1), Gestures(ET_GESTURE_TAP_DOWN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN, ET_GESTURE_TAP_CANCEL), @@ -1040,20 +982,17 @@ TEST_F(TouchDispositionGestureFilterTest, TestCancelMidGesture) { // Test that a MultiFingerSwipe event is dispatched when appropriate. TEST_F(TouchDispositionGestureFilterTest, TestAllowedMultiFingerSwipe) { - PushGesture(ET_GESTURE_SCROLL_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_BEGIN), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_PINCH_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_PINCH_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_PINCH_BEGIN), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_SWIPE); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SWIPE)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SWIPE), GetAndResetSentGestures())); @@ -1061,49 +1000,49 @@ TEST_F(TouchDispositionGestureFilterTest, TestAllowedMultiFingerSwipe) { // Test that a MultiFingerSwipe event is dispatched when appropriate. TEST_F(TouchDispositionGestureFilterTest, TestDisallowedMultiFingerSwipe) { - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), NoGestures()); SendTouchNotConsumedAck(); - PushGesture(ET_GESTURE_SCROLL_BEGIN); - MoveTouchPoint(0, 0, 0); + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); SendTouchConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SCROLL_BEGIN), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_PINCH_BEGIN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_PINCH_BEGIN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_PINCH_BEGIN), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_SWIPE); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_SWIPE)); SendTouchConsumedAck(); EXPECT_FALSE(GesturesSent()); } TEST_F(TouchDispositionGestureFilterTest, TapCancelOnSecondFingerDown) { - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_TAP_DOWN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN), GetAndResetSentGestures())); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), NoGestures()); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_CANCEL), GetAndResetSentGestures())); } TEST_F(TouchDispositionGestureFilterTest, ShowPressBoundingBox) { - PushGesture(ET_GESTURE_TAP_DOWN, 9, 9, 8); - PressTouchPoint(9, 9); + GestureEventDataPacket press_packet; + press_packet.Push(CreateGesture(ET_GESTURE_TAP_DOWN, 9, 9, 8)); + SendTouchGestures(PressTouchPoint(), press_packet); + SendTouchNotConsumedAck(); EXPECT_TRUE( GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_TAP, 10, 10, 10); - ReleaseTouchPoint(); + GestureEventDataPacket release_packet; + release_packet.Push(CreateGesture(ET_GESTURE_TAP, 10, 10, 10)); + SendTouchGestures(ReleaseTouchPoint(), release_packet); + SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_SHOW_PRESS, ET_GESTURE_TAP), GetAndResetSentGestures())); @@ -1111,9 +1050,8 @@ TEST_F(TouchDispositionGestureFilterTest, ShowPressBoundingBox) { } TEST_F(TouchDispositionGestureFilterTest, TapCancelledBeforeGestureEnd) { - PushGesture(ET_GESTURE_BEGIN); - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), + Gestures(ET_GESTURE_BEGIN, ET_GESTURE_TAP_DOWN)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_BEGIN, ET_GESTURE_TAP_DOWN), GetAndResetSentGestures())); @@ -1124,8 +1062,7 @@ TEST_F(TouchDispositionGestureFilterTest, TapCancelledBeforeGestureEnd) { SendTimeoutGesture(ET_GESTURE_LONG_PRESS); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_LONG_PRESS), GetAndResetSentGestures())); - PushGesture(ET_GESTURE_END); - CancelTouchPoint(); + SendPacket(CancelTouchPoint(), Gestures(ET_GESTURE_END)); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_CANCEL, ET_GESTURE_END), GetAndResetSentGestures())); @@ -1133,19 +1070,166 @@ TEST_F(TouchDispositionGestureFilterTest, TapCancelledBeforeGestureEnd) { TEST_F(TouchDispositionGestureFilterTest, EventFlagPropagation) { // Real gestures should propagate flags from their causal touches. - PushGesture(ET_GESTURE_TAP_DOWN); - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_TAP_DOWN)); SendTouchNotConsumedAck(); EXPECT_TRUE( GesturesMatch(Gestures(ET_GESTURE_TAP_DOWN), GetAndResetSentGestures())); EXPECT_EQ(kDefaultEventFlags, LastSentGestureFlags()); // Synthetic gestures lack flags. - PressTouchPoint(1, 1); + SendPacket(PressTouchPoint(), NoGestures()); SendTouchNotConsumedAck(); EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_TAP_CANCEL), GetAndResetSentGestures())); EXPECT_EQ(0, LastSentGestureFlags()); } + +TEST_F(TouchDispositionGestureFilterTest, PreviousScrollPrevented) { + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_BEGIN)); + EXPECT_FALSE(GesturesSent()); + SendTouchNotConsumedAck(); + EXPECT_TRUE( + GesturesMatch(Gestures(ET_GESTURE_BEGIN), GetAndResetSentGestures())); + + // The sent scroll update should always reflect whether any preceding scroll + // update has been dropped. + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); + SendTouchNotConsumedAck(); + ASSERT_TRUE(GesturesSent()); + EXPECT_FALSE(last_sent_gesture() + .details.previous_scroll_update_in_sequence_prevented()); + GetAndResetSentGestures(); + + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); + SendTouchConsumedAck(); + EXPECT_FALSE(GesturesSent()); + + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); + SendTouchNotConsumedAck(); + ASSERT_TRUE(GesturesSent()); + EXPECT_TRUE(last_sent_gesture() + .details.previous_scroll_update_in_sequence_prevented()); + GetAndResetSentGestures(); + + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); + SendTouchNotConsumedAck(); + ASSERT_TRUE(GesturesSent()); + EXPECT_TRUE(last_sent_gesture() + .details.previous_scroll_update_in_sequence_prevented()); +} + +TEST_F(TouchDispositionGestureFilterTest, AckQueueBack) { + SendPacket(PressTouchPoint(1, 1), Gestures(ET_GESTURE_BEGIN)); + SendTouchNotConsumedAck(); + + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_BEGIN)); + SendTouchNotConsumedAck(); + GetAndResetSentGestures(); + + // Pending touch move. + GestureEventDataPacket packet1; + packet1.Push(CreateGesture(ET_GESTURE_SCROLL_UPDATE, 2, 3, 0)); + SendTouchGestures(MoveTouchPoint(), packet1); + EXPECT_FALSE(GesturesSent()); + + // Additional pending touch move. + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); + + // Ack back of the queue consumed. + SendTouchConsumedAckForQueueBack(); + + // Ack the pending touch. + GetAndResetSentGestures(); + SendTouchNotConsumedAck(); + + // The consumed touch doesn't produce a gesture. + EXPECT_TRUE(GesturesMatch( + Gestures(ET_GESTURE_SCROLL_UPDATE), + GetAndResetSentGestures())); + EXPECT_EQ(gfx::PointF(2, 3), LastSentGestureLocation()); + + // Pending touch move. + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); + EXPECT_FALSE(GesturesSent()); + + // Ack back of the queue unconsumed (twice). + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); + SendTouchNotConsumedAckForQueueBack(); + + GestureEventDataPacket packet2; + packet2.Push(CreateGesture(ET_GESTURE_SCROLL_UPDATE, 7, 8, 0)); + SendTouchGestures(MoveTouchPoint(), packet2); + EXPECT_FALSE(GesturesSent()); + + SendTouchNotConsumedAckForQueueBack(); + + // Ack the pending touch. + GetAndResetSentGestures(); + SendTouchNotConsumedAck(); + + // Both touches have now been acked. + EXPECT_TRUE( + GesturesMatch(Gestures(ET_GESTURE_SCROLL_UPDATE, ET_GESTURE_SCROLL_UPDATE, + ET_GESTURE_SCROLL_UPDATE), + GetAndResetSentGestures())); + EXPECT_EQ(gfx::PointF(7, 8), LastSentGestureLocation()); +} + +TEST_F(TouchDispositionGestureFilterTest, AckQueueGestureAtBack) { + // Send gesture sequence + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_BEGIN)); + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_END)); + + // Send second gesture sequence, and synchronously ack it. + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_BEGIN)); + SendTouchNotConsumedAckForQueueBack(); + + GestureEventDataPacket packet; + packet.Push(CreateGesture(ET_GESTURE_END, 2, 3, 0)); + SendTouchGestures(ReleaseTouchPoint(), packet); + SendTouchNotConsumedAckForQueueBack(); + + // The second gesture sequence is blocked on the first. + EXPECT_FALSE(GesturesSent()); + + SendTouchNotConsumedAck(); + SendTouchNotConsumedAck(); + + // Both gestures have now been acked. + EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_BEGIN, ET_GESTURE_END, + ET_GESTURE_BEGIN, ET_GESTURE_END), + GetAndResetSentGestures())); + EXPECT_EQ(gfx::PointF(2, 3), LastSentGestureLocation()); +} + +TEST_F(TouchDispositionGestureFilterTest, + SyncAcksOnlyTriggerAppropriateGestures) { + // Queue a touch press. + SendPacket(PressTouchPoint(), Gestures(ET_GESTURE_BEGIN)); + + // Send and synchronously ack two touch moves. + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); + SendTouchNotConsumedAckForQueueBack(); + + SendPacket(MoveTouchPoint(), Gestures(ET_GESTURE_SCROLL_UPDATE)); + SendTouchNotConsumedAckForQueueBack(); + + // Queue a touch release. + SendPacket(ReleaseTouchPoint(), Gestures(ET_GESTURE_END)); + + EXPECT_FALSE(GesturesSent()); + + // Ack the touch press. All events but the release should be acked. + SendTouchNotConsumedAck(); + EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_BEGIN, ET_GESTURE_SCROLL_UPDATE, + ET_GESTURE_SCROLL_UPDATE), + GetAndResetSentGestures())); + + // The touch release still requires an ack. + SendTouchNotConsumedAck(); + EXPECT_TRUE(GesturesMatch(Gestures(ET_GESTURE_END), + GetAndResetSentGestures())); +} + } // namespace ui diff --git a/chromium/ui/events/gesture_detection/velocity_tracker.cc b/chromium/ui/events/gesture_detection/velocity_tracker.cc index 782d9265699..64583fdc25a 100644 --- a/chromium/ui/events/gesture_detection/velocity_tracker.cc +++ b/chromium/ui/events/gesture_detection/velocity_tracker.cc @@ -32,7 +32,7 @@ class VelocityTrackerStrategy { namespace { -COMPILE_ASSERT(MotionEvent::MAX_POINTER_ID < 32, max_pointer_id_too_large); +static_assert(MotionEvent::MAX_POINTER_ID < 32, "max pointer id too large"); // Threshold between ACTION_MOVE events for determining that a pointer has // stopped moving. Some input devices do not send ACTION_MOVE events in the case diff --git a/chromium/ui/events/gesture_detection/velocity_tracker_unittest.cc b/chromium/ui/events/gesture_detection/velocity_tracker_unittest.cc index 85a1f5d98f1..564bcd95a28 100644 --- a/chromium/ui/events/gesture_detection/velocity_tracker_unittest.cc +++ b/chromium/ui/events/gesture_detection/velocity_tracker_unittest.cc @@ -34,7 +34,7 @@ const char* GetStrategyName(VelocityTracker::Strategy strategy) { case VelocityTracker::WLSQ2_RECENT: return "WLSQ2_RECENT"; case VelocityTracker::INT1: return "INT1"; case VelocityTracker::INT2: return "INT2"; - }; + } NOTREACHED() << "Invalid strategy"; return ""; } @@ -48,21 +48,21 @@ class VelocityTrackerTest : public testing::Test { protected: static MockMotionEvent Sample(MotionEvent::Action action, - gfx::PointF p0, + const gfx::PointF& p0, TimeTicks t0, - gfx::Vector2dF v, + const gfx::Vector2dF& v, TimeDelta dt) { const gfx::PointF p = p0 + ScaleVector2d(v, dt.InSecondsF()); return MockMotionEvent(action, t0 + dt, p.x(), p.y()); } static void ApplyMovementSequence(VelocityTrackerState* state, - gfx::PointF p0, - gfx::Vector2dF v, + const gfx::PointF& p0, + const gfx::Vector2dF& v, TimeTicks t0, TimeDelta t, size_t samples) { - EXPECT_TRUE(!!samples); + EXPECT_TRUE(samples); if (!samples) return; const base::TimeDelta dt = t / samples; @@ -72,12 +72,12 @@ class VelocityTrackerTest : public testing::Test { } static void ApplyMovement(VelocityTrackerState* state, - gfx::PointF p0, - gfx::Vector2dF v, + const gfx::PointF& p0, + const gfx::Vector2dF& v, TimeTicks t0, TimeDelta t, size_t samples) { - EXPECT_TRUE(!!samples); + EXPECT_TRUE(samples); if (!samples) return; const base::TimeDelta dt = t / samples; |