Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 5b92f4b

Browse files
LoveJelloxiaohu.hxh
authored andcommitted
Fix unexpected pointer change (#129765)
MotionEvent.isFromSource() is not mockable because it's from super class in InputEvent. So we need to change if condition from "if (!isPointerEvent || !isMovementEvent)" to "if (isPointerEvent || isMovementEvent)". Without this change, this test case will end up with "wanted but not invoked" error. Signed-off-by: Xiaohu Hu <huxiaohu2007@gmail.com>
1 parent e40995d commit 5b92f4b

File tree

2 files changed

+80
-19
lines changed

2 files changed

+80
-19
lines changed

shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -192,23 +192,23 @@ public boolean onGenericMotionEvent(@NonNull MotionEvent event) {
192192
boolean isMovementEvent =
193193
(event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE
194194
|| event.getActionMasked() == MotionEvent.ACTION_SCROLL);
195-
if (!isPointerEvent || !isMovementEvent) {
196-
return false;
197-
}
198-
199-
int pointerChange = getPointerChangeForAction(event.getActionMasked());
200-
ByteBuffer packet =
201-
ByteBuffer.allocateDirect(
202-
event.getPointerCount() * POINTER_DATA_FIELD_COUNT * BYTES_PER_FIELD);
203-
packet.order(ByteOrder.LITTLE_ENDIAN);
204195

205-
// ACTION_HOVER_MOVE always applies to a single pointer only.
206-
addPointerForIndex(event, event.getActionIndex(), pointerChange, 0, IDENTITY_TRANSFORM, packet);
207-
if (packet.position() % (POINTER_DATA_FIELD_COUNT * BYTES_PER_FIELD) != 0) {
208-
throw new AssertionError("Packet position is not on field boundary.");
196+
if (isPointerEvent || isMovementEvent) {
197+
int pointerChange = getPointerChangeForAction(event.getActionMasked());
198+
ByteBuffer packet =
199+
ByteBuffer.allocateDirect(
200+
event.getPointerCount() * POINTER_DATA_FIELD_COUNT * BYTES_PER_FIELD);
201+
packet.order(ByteOrder.LITTLE_ENDIAN);
202+
203+
// ACTION_HOVER_MOVE always applies to a single pointer only.
204+
addPointerForIndex(event, event.getActionIndex(), pointerChange, 0, IDENTITY_TRANSFORM, packet);
205+
if (packet.position() % (POINTER_DATA_FIELD_COUNT * BYTES_PER_FIELD) != 0) {
206+
throw new AssertionError("Packet position is not on field boundary.");
207+
}
208+
renderer.dispatchPointerDataPacket(packet, packet.position());
209+
return true;
209210
}
210-
renderer.dispatchPointerDataPacket(packet, packet.position());
211-
return true;
211+
return false;
212212
}
213213

214214
// TODO(mattcarroll): consider creating a PointerPacket class instead of using a procedure that
@@ -252,6 +252,7 @@ private void addPointerForIndex(
252252
buttons = 0;
253253
}
254254

255+
int panZoomType = -1;
255256
boolean isTrackpadPan = ongoingPans.containsKey(event.getPointerId(pointerIndex));
256257

257258
int signalKind =
@@ -264,7 +265,8 @@ private void addPointerForIndex(
264265
packet.putLong(motionEventId); // motionEventId
265266
packet.putLong(timeStamp); // time_stamp
266267
if (isTrackpadPan) {
267-
packet.putLong(getPointerChangeForPanZoom(pointerChange)); // change
268+
panZoomType = getPointerChangeForPanZoom(pointerChange);
269+
packet.putLong(panZoomType); // change
268270
packet.putLong(PointerDeviceKind.TRACKPAD); // kind
269271
} else {
270272
packet.putLong(pointerChange); // change
@@ -355,7 +357,7 @@ private void addPointerForIndex(
355357
packet.putDouble(1.0); // scale
356358
packet.putDouble(0.0); // rotation
357359

358-
if (isTrackpadPan && getPointerChangeForPanZoom(pointerChange) == PointerChange.PAN_ZOOM_END) {
360+
if (isTrackpadPan && (panZoomType == PointerChange.PAN_ZOOM_END)) {
359361
ongoingPans.remove(event.getPointerId(pointerIndex));
360362
}
361363
}
@@ -396,12 +398,12 @@ private int getPointerChangeForAction(int maskedAction) {
396398
private int getPointerChangeForPanZoom(int pointerChange) {
397399
if (pointerChange == PointerChange.DOWN) {
398400
return PointerChange.PAN_ZOOM_START;
399-
} else if (pointerChange == PointerChange.MOVE) {
401+
} else if (pointerChange == PointerChange.MOVE || pointerChange == PointerChange.HOVER) {
400402
return PointerChange.PAN_ZOOM_UPDATE;
401403
} else if (pointerChange == PointerChange.UP || pointerChange == PointerChange.CANCEL) {
402404
return PointerChange.PAN_ZOOM_END;
403405
}
404-
throw new AssertionError("Unexpected pointer change");
406+
return -1;
405407
}
406408

407409
@PointerDeviceKind

shell/platform/android/test/io/flutter/embedding/android/AndroidTouchProcessorTest.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,4 +218,63 @@ public void unexpectedMaskedAction() {
218218
touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_BUTTON_PRESS, 0.0f, 0.0f, 0));
219219
verify(mockRenderer, never()).dispatchPointerDataPacket(ByteBuffer.allocate(0), 0);
220220
}
221+
222+
@Test
223+
public void unexpectedPointerChange() {
224+
// Regression test for https://github.com/flutter/flutter/issues/129765
225+
226+
MotionEventMocker mocker =
227+
new MotionEventMocker(0, InputDevice.SOURCE_MOUSE, MotionEvent.TOOL_TYPE_MOUSE);
228+
229+
touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_DOWN, 0.0f, 0.0f, 0));
230+
InOrder inOrder = inOrder(mockRenderer);
231+
inOrder
232+
.verify(mockRenderer)
233+
.dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
234+
ByteBuffer packet = packetCaptor.getValue();
235+
assertEquals(AndroidTouchProcessor.PointerChange.PAN_ZOOM_START, readPointerChange(packet));
236+
assertEquals(AndroidTouchProcessor.PointerDeviceKind.TRACKPAD, readPointerDeviceKind(packet));
237+
assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
238+
assertEquals(0.0, readPointerPhysicalX(packet));
239+
assertEquals(0.0, readPointerPhysicalY(packet));
240+
241+
touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_MOVE, 10.0f, 5.0f, 0));
242+
inOrder
243+
.verify(mockRenderer)
244+
.dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
245+
packet = packetCaptor.getValue();
246+
assertEquals(AndroidTouchProcessor.PointerChange.PAN_ZOOM_UPDATE, readPointerChange(packet));
247+
assertEquals(AndroidTouchProcessor.PointerDeviceKind.TRACKPAD, readPointerDeviceKind(packet));
248+
assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
249+
assertEquals(0.0, readPointerPhysicalX(packet));
250+
assertEquals(0.0, readPointerPhysicalY(packet));
251+
assertEquals(10.0, readPointerPanX(packet));
252+
assertEquals(5.0, readPointerPanY(packet));
253+
254+
touchProcessor.onGenericMotionEvent(mocker.mockEvent(MotionEvent.ACTION_SCROLL, 0.0f, 0.0f, 0));
255+
inOrder
256+
.verify(mockRenderer)
257+
.dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
258+
packet = packetCaptor.getValue();
259+
assertEquals(AndroidTouchProcessor.PointerChange.PAN_ZOOM_UPDATE, readPointerChange(packet));
260+
assertEquals(AndroidTouchProcessor.PointerDeviceKind.TRACKPAD, readPointerDeviceKind(packet));
261+
assertEquals(AndroidTouchProcessor.PointerSignalKind.SCROLL, readPointerSignalKind(packet));
262+
assertEquals(0.0, readPointerPhysicalX(packet));
263+
assertEquals(0.0, readPointerPhysicalY(packet));
264+
assertEquals(0.0, readPointerPanX(packet));
265+
assertEquals(0.0, readPointerPanY(packet));
266+
267+
touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_UP, 10.0f, 5.0f, 0));
268+
inOrder
269+
.verify(mockRenderer)
270+
.dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
271+
packet = packetCaptor.getValue();
272+
assertEquals(AndroidTouchProcessor.PointerChange.PAN_ZOOM_END, readPointerChange(packet));
273+
assertEquals(AndroidTouchProcessor.PointerDeviceKind.TRACKPAD, readPointerDeviceKind(packet));
274+
assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
275+
assertEquals(0.0, readPointerPhysicalX(packet));
276+
assertEquals(0.0, readPointerPhysicalY(packet));
277+
inOrder.verifyNoMoreInteractions();
278+
}
279+
221280
}

0 commit comments

Comments
 (0)