diff --git a/engine/src/flutter/lib/ui/pointer.dart b/engine/src/flutter/lib/ui/pointer.dart index b199d2bafa1..438eccea8bc 100644 --- a/engine/src/flutter/lib/ui/pointer.dart +++ b/engine/src/flutter/lib/ui/pointer.dart @@ -129,6 +129,9 @@ enum PointerSignalKind { /// A pointer-generated scroll (e.g., mouse wheel or trackpad scroll). scroll, + /// A pointer-generated scroll-inertia cancel. + scrollInertiaCancel, + /// An unknown pointer signal kind. unknown } diff --git a/engine/src/flutter/lib/ui/window/pointer_data.h b/engine/src/flutter/lib/ui/window/pointer_data.h index 5c8776d1730..4386fd184fd 100644 --- a/engine/src/flutter/lib/ui/window/pointer_data.h +++ b/engine/src/flutter/lib/ui/window/pointer_data.h @@ -60,6 +60,7 @@ struct alignas(8) PointerData { enum class SignalKind : int64_t { kNone, kScroll, + kScrollInertiaCancel, }; int64_t embedder_id; diff --git a/engine/src/flutter/lib/ui/window/pointer_data_packet_converter.cc b/engine/src/flutter/lib/ui/window/pointer_data_packet_converter.cc index 2d54d710114..e98558d4902 100644 --- a/engine/src/flutter/lib/ui/window/pointer_data_packet_converter.cc +++ b/engine/src/flutter/lib/ui/window/pointer_data_packet_converter.cc @@ -297,7 +297,8 @@ void PointerDataPacketConverter::ConvertPointerData( } } else { switch (pointer_data.signal_kind) { - case PointerData::SignalKind::kScroll: { + case PointerData::SignalKind::kScroll: + case PointerData::SignalKind::kScrollInertiaCancel: { // Makes sure we have an existing pointer auto iter = states_.find(pointer_data.device); PointerState state; diff --git a/engine/src/flutter/lib/ui/window/pointer_data_packet_converter_unittests.cc b/engine/src/flutter/lib/ui/window/pointer_data_packet_converter_unittests.cc index 108310f0cbd..8a78aa40982 100644 --- a/engine/src/flutter/lib/ui/window/pointer_data_packet_converter_unittests.cc +++ b/engine/src/flutter/lib/ui/window/pointer_data_packet_converter_unittests.cc @@ -554,114 +554,117 @@ TEST(PointerDataPacketConverterTest, CanHandleThreeFingerGesture) { // Third cancel should be dropped } -TEST(PointerDataPacketConverterTest, CanConvetScroll) { - PointerDataPacketConverter converter; - auto packet = std::make_unique(6); - PointerData data; - CreateSimulatedMousePointerData(data, PointerData::Change::kAdd, - PointerData::SignalKind::kNone, 0, 0.0, 0.0, - 0.0, 0.0, 0); - packet->SetPointerData(0, data); - CreateSimulatedMousePointerData(data, PointerData::Change::kAdd, - PointerData::SignalKind::kNone, 1, 0.0, 0.0, - 0.0, 0.0, 0); - packet->SetPointerData(1, data); - CreateSimulatedMousePointerData(data, PointerData::Change::kDown, - PointerData::SignalKind::kNone, 1, 0.0, 0.0, - 0.0, 0.0, 1); - packet->SetPointerData(2, data); - CreateSimulatedMousePointerData(data, PointerData::Change::kHover, - PointerData::SignalKind::kScroll, 0, 34.0, - 34.0, 30.0, 0.0, 0); - packet->SetPointerData(3, data); - CreateSimulatedMousePointerData(data, PointerData::Change::kHover, - PointerData::SignalKind::kScroll, 1, 49.0, - 49.0, 50.0, 0.0, 0); - packet->SetPointerData(4, data); - CreateSimulatedMousePointerData(data, PointerData::Change::kHover, - PointerData::SignalKind::kScroll, 2, 10.0, - 20.0, 30.0, 40.0, 0); - packet->SetPointerData(5, data); - auto converted_packet = converter.Convert(std::move(packet)); +TEST(PointerDataPacketConverterTest, CanConvertPointerSignals) { + PointerData::SignalKind signal_kinds[] = { + PointerData::SignalKind::kScroll, + PointerData::SignalKind::kScrollInertiaCancel, + }; + for (const PointerData::SignalKind& kind : signal_kinds) { + PointerDataPacketConverter converter; + auto packet = std::make_unique(6); + PointerData data; + CreateSimulatedMousePointerData(data, PointerData::Change::kAdd, + PointerData::SignalKind::kNone, 0, 0.0, 0.0, + 0.0, 0.0, 0); + packet->SetPointerData(0, data); + CreateSimulatedMousePointerData(data, PointerData::Change::kAdd, + PointerData::SignalKind::kNone, 1, 0.0, 0.0, + 0.0, 0.0, 0); + packet->SetPointerData(1, data); + CreateSimulatedMousePointerData(data, PointerData::Change::kDown, + PointerData::SignalKind::kNone, 1, 0.0, 0.0, + 0.0, 0.0, 1); + packet->SetPointerData(2, data); + CreateSimulatedMousePointerData(data, PointerData::Change::kHover, kind, 0, + 34.0, 34.0, 30.0, 0.0, 0); + packet->SetPointerData(3, data); + CreateSimulatedMousePointerData(data, PointerData::Change::kHover, kind, 1, + 49.0, 49.0, 50.0, 0.0, 0); + packet->SetPointerData(4, data); + CreateSimulatedMousePointerData(data, PointerData::Change::kHover, kind, 2, + 10.0, 20.0, 30.0, 40.0, 0); + packet->SetPointerData(5, data); + auto converted_packet = converter.Convert(std::move(packet)); - std::vector result; - UnpackPointerPacket(result, std::move(converted_packet)); + std::vector result; + UnpackPointerPacket(result, std::move(converted_packet)); - ASSERT_EQ(result.size(), (size_t)9); - ASSERT_EQ(result[0].change, PointerData::Change::kAdd); - ASSERT_EQ(result[0].signal_kind, PointerData::SignalKind::kNone); - ASSERT_EQ(result[0].device, 0); - ASSERT_EQ(result[0].physical_x, 0.0); - ASSERT_EQ(result[0].physical_y, 0.0); - ASSERT_EQ(result[0].synthesized, 0); + ASSERT_EQ(result.size(), (size_t)9); + ASSERT_EQ(result[0].change, PointerData::Change::kAdd); + ASSERT_EQ(result[0].signal_kind, PointerData::SignalKind::kNone); + ASSERT_EQ(result[0].device, 0); + ASSERT_EQ(result[0].physical_x, 0.0); + ASSERT_EQ(result[0].physical_y, 0.0); + ASSERT_EQ(result[0].synthesized, 0); - ASSERT_EQ(result[1].change, PointerData::Change::kAdd); - ASSERT_EQ(result[1].signal_kind, PointerData::SignalKind::kNone); - ASSERT_EQ(result[1].device, 1); - ASSERT_EQ(result[1].physical_x, 0.0); - ASSERT_EQ(result[1].physical_y, 0.0); - ASSERT_EQ(result[1].synthesized, 0); + ASSERT_EQ(result[1].change, PointerData::Change::kAdd); + ASSERT_EQ(result[1].signal_kind, PointerData::SignalKind::kNone); + ASSERT_EQ(result[1].device, 1); + ASSERT_EQ(result[1].physical_x, 0.0); + ASSERT_EQ(result[1].physical_y, 0.0); + ASSERT_EQ(result[1].synthesized, 0); - ASSERT_EQ(result[2].change, PointerData::Change::kDown); - ASSERT_EQ(result[2].signal_kind, PointerData::SignalKind::kNone); - ASSERT_EQ(result[2].device, 1); - ASSERT_EQ(result[2].physical_x, 0.0); - ASSERT_EQ(result[2].physical_y, 0.0); - ASSERT_EQ(result[2].synthesized, 0); + ASSERT_EQ(result[2].change, PointerData::Change::kDown); + ASSERT_EQ(result[2].signal_kind, PointerData::SignalKind::kNone); + ASSERT_EQ(result[2].device, 1); + ASSERT_EQ(result[2].physical_x, 0.0); + ASSERT_EQ(result[2].physical_y, 0.0); + ASSERT_EQ(result[2].synthesized, 0); - // Converter will synthesize a hover to position for device 0. - ASSERT_EQ(result[3].change, PointerData::Change::kHover); - ASSERT_EQ(result[3].signal_kind, PointerData::SignalKind::kNone); - ASSERT_EQ(result[3].device, 0); - ASSERT_EQ(result[3].physical_x, 34.0); - ASSERT_EQ(result[3].physical_y, 34.0); - ASSERT_EQ(result[3].physical_delta_x, 34.0); - ASSERT_EQ(result[3].physical_delta_y, 34.0); - ASSERT_EQ(result[3].buttons, 0); - ASSERT_EQ(result[3].synthesized, 1); + // Converter will synthesize a hover to position for device 0. + ASSERT_EQ(result[3].change, PointerData::Change::kHover); + ASSERT_EQ(result[3].signal_kind, PointerData::SignalKind::kNone); + ASSERT_EQ(result[3].device, 0); + ASSERT_EQ(result[3].physical_x, 34.0); + ASSERT_EQ(result[3].physical_y, 34.0); + ASSERT_EQ(result[3].physical_delta_x, 34.0); + ASSERT_EQ(result[3].physical_delta_y, 34.0); + ASSERT_EQ(result[3].buttons, 0); + ASSERT_EQ(result[3].synthesized, 1); - ASSERT_EQ(result[4].change, PointerData::Change::kHover); - ASSERT_EQ(result[4].signal_kind, PointerData::SignalKind::kScroll); - ASSERT_EQ(result[4].device, 0); - ASSERT_EQ(result[4].physical_x, 34.0); - ASSERT_EQ(result[4].physical_y, 34.0); - ASSERT_EQ(result[4].scroll_delta_x, 30.0); - ASSERT_EQ(result[4].scroll_delta_y, 0.0); + ASSERT_EQ(result[4].change, PointerData::Change::kHover); + ASSERT_EQ(result[4].signal_kind, kind); + ASSERT_EQ(result[4].device, 0); + ASSERT_EQ(result[4].physical_x, 34.0); + ASSERT_EQ(result[4].physical_y, 34.0); + ASSERT_EQ(result[4].scroll_delta_x, 30.0); + ASSERT_EQ(result[4].scroll_delta_y, 0.0); - // Converter will synthesize a move to position for device 1. - ASSERT_EQ(result[5].change, PointerData::Change::kMove); - ASSERT_EQ(result[5].signal_kind, PointerData::SignalKind::kNone); - ASSERT_EQ(result[5].device, 1); - ASSERT_EQ(result[5].physical_x, 49.0); - ASSERT_EQ(result[5].physical_y, 49.0); - ASSERT_EQ(result[5].physical_delta_x, 49.0); - ASSERT_EQ(result[5].physical_delta_y, 49.0); - ASSERT_EQ(result[5].buttons, 1); - ASSERT_EQ(result[5].synthesized, 1); + // Converter will synthesize a move to position for device 1. + ASSERT_EQ(result[5].change, PointerData::Change::kMove); + ASSERT_EQ(result[5].signal_kind, PointerData::SignalKind::kNone); + ASSERT_EQ(result[5].device, 1); + ASSERT_EQ(result[5].physical_x, 49.0); + ASSERT_EQ(result[5].physical_y, 49.0); + ASSERT_EQ(result[5].physical_delta_x, 49.0); + ASSERT_EQ(result[5].physical_delta_y, 49.0); + ASSERT_EQ(result[5].buttons, 1); + ASSERT_EQ(result[5].synthesized, 1); - ASSERT_EQ(result[6].change, PointerData::Change::kHover); - ASSERT_EQ(result[6].signal_kind, PointerData::SignalKind::kScroll); - ASSERT_EQ(result[6].device, 1); - ASSERT_EQ(result[6].physical_x, 49.0); - ASSERT_EQ(result[6].physical_y, 49.0); - ASSERT_EQ(result[6].scroll_delta_x, 50.0); - ASSERT_EQ(result[6].scroll_delta_y, 0.0); + ASSERT_EQ(result[6].change, PointerData::Change::kHover); + ASSERT_EQ(result[6].signal_kind, kind); + ASSERT_EQ(result[6].device, 1); + ASSERT_EQ(result[6].physical_x, 49.0); + ASSERT_EQ(result[6].physical_y, 49.0); + ASSERT_EQ(result[6].scroll_delta_x, 50.0); + ASSERT_EQ(result[6].scroll_delta_y, 0.0); - // Converter will synthesize an add for device 2. - ASSERT_EQ(result[7].change, PointerData::Change::kAdd); - ASSERT_EQ(result[7].signal_kind, PointerData::SignalKind::kNone); - ASSERT_EQ(result[7].device, 2); - ASSERT_EQ(result[7].physical_x, 10.0); - ASSERT_EQ(result[7].physical_y, 20.0); - ASSERT_EQ(result[7].synthesized, 1); + // Converter will synthesize an add for device 2. + ASSERT_EQ(result[7].change, PointerData::Change::kAdd); + ASSERT_EQ(result[7].signal_kind, PointerData::SignalKind::kNone); + ASSERT_EQ(result[7].device, 2); + ASSERT_EQ(result[7].physical_x, 10.0); + ASSERT_EQ(result[7].physical_y, 20.0); + ASSERT_EQ(result[7].synthesized, 1); - ASSERT_EQ(result[8].change, PointerData::Change::kHover); - ASSERT_EQ(result[8].signal_kind, PointerData::SignalKind::kScroll); - ASSERT_EQ(result[8].device, 2); - ASSERT_EQ(result[8].physical_x, 10.0); - ASSERT_EQ(result[8].physical_y, 20.0); - ASSERT_EQ(result[8].scroll_delta_x, 30.0); - ASSERT_EQ(result[8].scroll_delta_y, 40.0); + ASSERT_EQ(result[8].change, PointerData::Change::kHover); + ASSERT_EQ(result[8].signal_kind, kind); + ASSERT_EQ(result[8].device, 2); + ASSERT_EQ(result[8].physical_x, 10.0); + ASSERT_EQ(result[8].physical_y, 20.0); + ASSERT_EQ(result[8].scroll_delta_x, 30.0); + ASSERT_EQ(result[8].scroll_delta_y, 40.0); + } } TEST(PointerDataPacketConverterTest, CanConvertTrackpadGesture) { diff --git a/engine/src/flutter/lib/web_ui/lib/pointer.dart b/engine/src/flutter/lib/web_ui/lib/pointer.dart index f65e8a13e11..9ae23779043 100644 --- a/engine/src/flutter/lib/web_ui/lib/pointer.dart +++ b/engine/src/flutter/lib/web_ui/lib/pointer.dart @@ -29,6 +29,7 @@ enum PointerDeviceKind { enum PointerSignalKind { none, scroll, + scrollInertiaCancel, unknown } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/pointer_converter.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/pointer_converter.dart index 7fa0ec4e881..5b9974d039d 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/pointer_converter.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/pointer_converter.dart @@ -623,6 +623,7 @@ class PointerDataConverter { } else { switch (signalKind) { case ui.PointerSignalKind.scroll: + case ui.PointerSignalKind.scrollInertiaCancel: final bool alreadyAdded = _pointers.containsKey(device); _ensureStateForPointer(device, physicalX, physicalY); if (!alreadyAdded) { diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java index 544828236d2..99179fcb306 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java @@ -61,11 +61,17 @@ public class AndroidTouchProcessor { } // Must match the PointerSignalKind enum in pointer.dart. - @IntDef({PointerSignalKind.NONE, PointerSignalKind.SCROLL, PointerSignalKind.UNKNOWN}) + @IntDef({ + PointerSignalKind.NONE, + PointerSignalKind.SCROLL, + PointerSignalKind.SCROLL_INERTIA_CANCEL, + PointerSignalKind.UNKNOWN + }) public @interface PointerSignalKind { int NONE = 0; int SCROLL = 1; - int UNKNOWN = 2; + int SCROLL_INERTIA_CANCEL = 2; + int UNKNOWN = 3; } // Must match the unpacking code in hooks.dart. diff --git a/engine/src/flutter/shell/platform/embedder/embedder.cc b/engine/src/flutter/shell/platform/embedder/embedder.cc index 9d606cfbbb1..fea4882cc15 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder.cc +++ b/engine/src/flutter/shell/platform/embedder/embedder.cc @@ -1750,6 +1750,8 @@ inline flutter::PointerData::SignalKind ToPointerDataSignalKind( return flutter::PointerData::SignalKind::kNone; case kFlutterPointerSignalKindScroll: return flutter::PointerData::SignalKind::kScroll; + case kFlutterPointerSignalKindScrollInertiaCancel: + return flutter::PointerData::SignalKind::kScrollInertiaCancel; } return flutter::PointerData::SignalKind::kNone; } diff --git a/engine/src/flutter/shell/platform/embedder/embedder.h b/engine/src/flutter/shell/platform/embedder/embedder.h index 66a25c7f30c..7cc732a8b53 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder.h +++ b/engine/src/flutter/shell/platform/embedder/embedder.h @@ -773,6 +773,7 @@ typedef enum { typedef enum { kFlutterPointerSignalKindNone, kFlutterPointerSignalKindScroll, + kFlutterPointerSignalKindScrollInertiaCancel, } FlutterPointerSignalKind; typedef struct {