Unverified Commit ba4cf054 authored by Stanislav Baranov's avatar Stanislav Baranov Committed by GitHub

Propagate positions of secondary pointers in UP events on Android (#23797)

parent 7245c4a6
88cb78cdf62ceb206e740853d3afd060bb8d781c b5758d0d3848d8ed77308d97734b9a7933c3844f
...@@ -95,23 +95,6 @@ void diffPointerCoordsList(StringBuffer diffBuffer, ...@@ -95,23 +95,6 @@ void diffPointerCoordsList(StringBuffer diffBuffer,
return; return;
} }
if (isSinglePointerAction(originalEvent['action'])) {
final int idx = getPointerIdx(originalEvent['action']);
final Map<String, dynamic> expected =
expectedList[idx].cast<String, dynamic>();
final Map<String, dynamic> actual = actualList[idx].cast<String, dynamic>();
diffPointerCoords(expected, actual, idx, diffBuffer);
// For POINTER_UP and POINTER_DOWN events the engine drops the data for all pointers
// but for the pointer that was taken up/down.
// See: https://github.com/flutter/flutter/issues/19882
//
// Until that issue is resolved, we only compare the pointer for which the action
// applies to here.
//
// TODO(amirh): Compare all pointers once the issue mentioned above is resolved.
return;
}
for (int i = 0; i < expectedList.length; i++) { for (int i = 0; i < expectedList.length; i++) {
final Map<String, dynamic> expected = final Map<String, dynamic> expected =
expectedList[i].cast<String, dynamic>(); expectedList[i].cast<String, dynamic>();
...@@ -151,12 +134,6 @@ void diffMaps( ...@@ -151,12 +134,6 @@ void diffMaps(
} }
} }
bool isSinglePointerAction(int action) {
final int actionMasked = getActionMasked(action);
return actionMasked == 5 || // POINTER_DOWN
actionMasked == 6; // POINTER_UP
}
int getActionMasked(int action) => action & 0xff; int getActionMasked(int action) => action & 0xff;
int getPointerIdx(int action) => (action >> 8) & 0xff; int getPointerIdx(int action) => (action >> 8) & 0xff;
......
...@@ -239,7 +239,8 @@ class PointerEventConverter { ...@@ -239,7 +239,8 @@ class PointerEventConverter {
radiusMin: radiusMin, radiusMin: radiusMin,
radiusMax: radiusMax, radiusMax: radiusMax,
orientation: datum.orientation, orientation: datum.orientation,
tilt: datum.tilt tilt: datum.tilt,
platformData: datum.platformData,
); );
break; break;
case ui.PointerChange.up: case ui.PointerChange.up:
......
...@@ -115,6 +115,7 @@ abstract class PointerEvent { ...@@ -115,6 +115,7 @@ abstract class PointerEvent {
this.radiusMax = 0.0, this.radiusMax = 0.0,
this.orientation = 0.0, this.orientation = 0.0,
this.tilt = 0.0, this.tilt = 0.0,
this.platformData = 0,
this.synthesized = false, this.synthesized = false,
}); });
...@@ -245,6 +246,9 @@ abstract class PointerEvent { ...@@ -245,6 +246,9 @@ abstract class PointerEvent {
/// the stylus is flat on that surface). /// the stylus is flat on that surface).
final double tilt; final double tilt;
/// Opaque platform-specific data associated with the event.
final int platformData;
/// We occasionally synthesize PointerEvents that aren't exact translations /// We occasionally synthesize PointerEvents that aren't exact translations
/// of [ui.PointerData] from the engine to cover small cross-OS discrepancies /// of [ui.PointerData] from the engine to cover small cross-OS discrepancies
/// in pointer behaviors. /// in pointer behaviors.
...@@ -285,6 +289,7 @@ abstract class PointerEvent { ...@@ -285,6 +289,7 @@ abstract class PointerEvent {
'radiusMax: $radiusMax, ' 'radiusMax: $radiusMax, '
'orientation: $orientation, ' 'orientation: $orientation, '
'tilt: $tilt, ' 'tilt: $tilt, '
'platformData: $platformData, '
'synthesized: $synthesized' 'synthesized: $synthesized'
')'; ')';
} }
...@@ -495,6 +500,7 @@ class PointerMoveEvent extends PointerEvent { ...@@ -495,6 +500,7 @@ class PointerMoveEvent extends PointerEvent {
double radiusMax = 0.0, double radiusMax = 0.0,
double orientation = 0.0, double orientation = 0.0,
double tilt = 0.0, double tilt = 0.0,
int platformData = 0,
bool synthesized = false, bool synthesized = false,
}) : super( }) : super(
timeStamp: timeStamp, timeStamp: timeStamp,
...@@ -518,6 +524,7 @@ class PointerMoveEvent extends PointerEvent { ...@@ -518,6 +524,7 @@ class PointerMoveEvent extends PointerEvent {
radiusMax: radiusMax, radiusMax: radiusMax,
orientation: orientation, orientation: orientation,
tilt: tilt, tilt: tilt,
platformData: platformData,
synthesized: synthesized, synthesized: synthesized,
); );
} }
......
...@@ -447,16 +447,21 @@ class _MotionEventsDispatcher { ...@@ -447,16 +447,21 @@ class _MotionEventsDispatcher {
final int pointerIdx = pointers.indexOf(event.pointer); final int pointerIdx = pointers.indexOf(event.pointer);
final int numPointers = pointers.length; final int numPointers = pointers.length;
// This value must match the value in engine's FlutterView.java.
// This flag indicates whether the original Android pointer events were batched together.
const int kPointerDataFlagBatched = 1;
// Android MotionEvent objects can batch information on multiple pointers. // Android MotionEvent objects can batch information on multiple pointers.
// Flutter breaks these such batched events into multiple PointerEvent objects. // Flutter breaks these such batched events into multiple PointerEvent objects.
// When there are multiple active pointers we accumulate the information for all pointers // When there are multiple active pointers we accumulate the information for all pointers
// as we get PointerEvents, and only send it to the embedded Android view when // as we get PointerEvents, and only send it to the embedded Android view when
// we see the last pointer. This way we achieve the same batching as Android. // we see the last pointer. This way we achieve the same batching as Android.
if(isSinglePointerAction(event) && pointerIdx < numPointers - 1) if (event.platformData == kPointerDataFlagBatched ||
(isSinglePointerAction(event) && pointerIdx < numPointers - 1))
return; return;
int action; int action;
switch(event.runtimeType){ switch (event.runtimeType) {
case PointerDownEvent: case PointerDownEvent:
action = numPointers == 1 ? AndroidViewController.kActionDown action = numPointers == 1 ? AndroidViewController.kActionDown
: AndroidViewController.pointerAction(pointerIdx, AndroidViewController.kActionPointerDown); : AndroidViewController.pointerAction(pointerIdx, AndroidViewController.kActionPointerDown);
......
...@@ -1806,6 +1806,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1806,6 +1806,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
await expectLater( await expectLater(
layer.toImage(renderObject.semanticBounds.inflate(50.0)), layer.toImage(renderObject.semanticBounds.inflate(50.0)),
matchesGoldenFile('inspector.repaint_boundary_margin.png'), matchesGoldenFile('inspector.repaint_boundary_margin.png'),
skip: !Platform.isLinux,
); );
// Regression test for how rendering with a pixel scale other than 1.0 // Regression test for how rendering with a pixel scale other than 1.0
...@@ -1816,6 +1817,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1816,6 +1817,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
pixelRatio: 0.5, pixelRatio: 0.5,
), ),
matchesGoldenFile('inspector.repaint_boundary_margin_small.png'), matchesGoldenFile('inspector.repaint_boundary_margin_small.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -1824,6 +1826,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1824,6 +1826,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
pixelRatio: 2.0, pixelRatio: 2.0,
), ),
matchesGoldenFile('inspector.repaint_boundary_margin_large.png'), matchesGoldenFile('inspector.repaint_boundary_margin_large.png'),
skip: !Platform.isLinux,
); );
final Layer layerParent = layer.parent; final Layer layerParent = layer.parent;
...@@ -1839,6 +1842,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1839,6 +1842,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 300.0, height: 300.0,
), ),
matchesGoldenFile('inspector.repaint_boundary.png'), matchesGoldenFile('inspector.repaint_boundary.png'),
skip: !Platform.isLinux,
); );
// Verify that taking a screenshot didn't change the layers associated with // Verify that taking a screenshot didn't change the layers associated with
...@@ -1856,6 +1860,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1856,6 +1860,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
margin: 50.0, margin: 50.0,
), ),
matchesGoldenFile('inspector.repaint_boundary_margin.png'), matchesGoldenFile('inspector.repaint_boundary_margin.png'),
skip: !Platform.isLinux,
); );
// Verify that taking a screenshot didn't change the layers associated with // Verify that taking a screenshot didn't change the layers associated with
...@@ -1876,6 +1881,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1876,6 +1881,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
debugPaint: true, debugPaint: true,
), ),
matchesGoldenFile('inspector.repaint_boundary_debugPaint.png'), matchesGoldenFile('inspector.repaint_boundary_debugPaint.png'),
skip: !Platform.isLinux,
); );
// Verify that taking a screenshot with debug paint on did not change // Verify that taking a screenshot with debug paint on did not change
// the number of children the layer has. // the number of children the layer has.
...@@ -1886,6 +1892,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1886,6 +1892,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
await expectLater( await expectLater(
find.byType(RepaintBoundaryWithDebugPaint), find.byType(RepaintBoundaryWithDebugPaint),
matchesGoldenFile('inspector.repaint_boundary.png'), matchesGoldenFile('inspector.repaint_boundary.png'),
skip: !Platform.isLinux,
); );
expect(renderObject.debugLayer, equals(layer)); expect(renderObject.debugLayer, equals(layer));
...@@ -1899,6 +1906,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1899,6 +1906,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 100.0, height: 100.0,
), ),
matchesGoldenFile('inspector.container.png'), matchesGoldenFile('inspector.container.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -1909,6 +1917,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1909,6 +1917,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
debugPaint: true, debugPaint: true,
), ),
matchesGoldenFile('inspector.container_debugPaint.png'), matchesGoldenFile('inspector.container_debugPaint.png'),
skip: !Platform.isLinux,
); );
{ {
...@@ -1929,6 +1938,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1929,6 +1938,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
debugPaint: true, debugPaint: true,
), ),
matchesGoldenFile('inspector.container_debugPaint.png'), matchesGoldenFile('inspector.container_debugPaint.png'),
skip: !Platform.isLinux,
); );
expect(container.debugNeedsLayout, isFalse); expect(container.debugNeedsLayout, isFalse);
} }
...@@ -1941,6 +1951,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1941,6 +1951,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 100.0, height: 100.0,
), ),
matchesGoldenFile('inspector.container_small.png'), matchesGoldenFile('inspector.container_small.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -1951,6 +1962,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1951,6 +1962,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
maxPixelRatio: 3.0, maxPixelRatio: 3.0,
), ),
matchesGoldenFile('inspector.container_large.png'), matchesGoldenFile('inspector.container_large.png'),
skip: !Platform.isLinux,
); );
// This screenshot will show the clip rect debug paint but no other // This screenshot will show the clip rect debug paint but no other
...@@ -1963,6 +1975,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1963,6 +1975,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
debugPaint: true, debugPaint: true,
), ),
matchesGoldenFile('inspector.clipRect_debugPaint.png'), matchesGoldenFile('inspector.clipRect_debugPaint.png'),
skip: !Platform.isLinux,
); );
final Element clipRect = find.byType(ClipRRect).evaluate().single; final Element clipRect = find.byType(ClipRRect).evaluate().single;
...@@ -2007,6 +2020,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2007,6 +2020,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
await expectLater( await expectLater(
screenshotImage, screenshotImage,
matchesReferenceImage(await clipRectScreenshot), matchesReferenceImage(await clipRectScreenshot),
skip: !Platform.isLinux,
); );
// Test with a very visible debug paint // Test with a very visible debug paint
...@@ -2018,6 +2032,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2018,6 +2032,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
debugPaint: true, debugPaint: true,
), ),
matchesGoldenFile('inspector.padding_debugPaint.png'), matchesGoldenFile('inspector.padding_debugPaint.png'),
skip: !Platform.isLinux,
); );
// The bounds for this box crop its rendered content. // The bounds for this box crop its rendered content.
...@@ -2029,6 +2044,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2029,6 +2044,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
debugPaint: true, debugPaint: true,
), ),
matchesGoldenFile('inspector.sizedBox_debugPaint.png'), matchesGoldenFile('inspector.sizedBox_debugPaint.png'),
skip: !Platform.isLinux,
); );
// Verify that setting a margin includes the previously cropped content. // Verify that setting a margin includes the previously cropped content.
...@@ -2041,6 +2057,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2041,6 +2057,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
debugPaint: true, debugPaint: true,
), ),
matchesGoldenFile('inspector.sizedBox_debugPaint_margin.png'), matchesGoldenFile('inspector.sizedBox_debugPaint_margin.png'),
skip: !Platform.isLinux,
); );
}); });
...@@ -2112,6 +2129,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2112,6 +2129,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
await expectLater( await expectLater(
find.byKey(mainStackKey), find.byKey(mainStackKey),
matchesGoldenFile('inspector.composited_transform.only_offsets.png'), matchesGoldenFile('inspector.composited_transform.only_offsets.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -2121,11 +2139,13 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2121,11 +2139,13 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 500.0, height: 500.0,
), ),
matchesGoldenFile('inspector.composited_transform.only_offsets_follower.png'), matchesGoldenFile('inspector.composited_transform.only_offsets_follower.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
WidgetInspectorService.instance.screenshot(find.byType(Stack).evaluate().first, width: 300.0, height: 300.0), WidgetInspectorService.instance.screenshot(find.byType(Stack).evaluate().first, width: 300.0, height: 300.0),
matchesGoldenFile('inspector.composited_transform.only_offsets_small.png'), matchesGoldenFile('inspector.composited_transform.only_offsets_small.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -2135,6 +2155,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2135,6 +2155,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 500.0, height: 500.0,
), ),
matchesGoldenFile('inspector.composited_transform.only_offsets_target.png'), matchesGoldenFile('inspector.composited_transform.only_offsets_target.png'),
skip: !Platform.isLinux,
); );
}); });
...@@ -2207,6 +2228,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2207,6 +2228,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
await expectLater( await expectLater(
find.byKey(mainStackKey), find.byKey(mainStackKey),
matchesGoldenFile('inspector.composited_transform.with_rotations.png'), matchesGoldenFile('inspector.composited_transform.with_rotations.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -2216,6 +2238,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2216,6 +2238,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 500.0, height: 500.0,
), ),
matchesGoldenFile('inspector.composited_transform.with_rotations_small.png'), matchesGoldenFile('inspector.composited_transform.with_rotations_small.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -2225,6 +2248,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2225,6 +2248,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 500.0, height: 500.0,
), ),
matchesGoldenFile('inspector.composited_transform.with_rotations_target.png'), matchesGoldenFile('inspector.composited_transform.with_rotations_target.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -2234,6 +2258,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2234,6 +2258,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 500.0, height: 500.0,
), ),
matchesGoldenFile('inspector.composited_transform.with_rotations_follower.png'), matchesGoldenFile('inspector.composited_transform.with_rotations_follower.png'),
skip: !Platform.isLinux,
); );
// Make sure taking screenshots hasn't modified the positions of the // Make sure taking screenshots hasn't modified the positions of the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment