1
1
package io .flutter .embedding .android ;
2
2
3
+ import android .graphics .Matrix ;
3
4
import android .os .Build ;
4
5
import android .view .InputDevice ;
5
6
import android .view .MotionEvent ;
@@ -69,6 +70,8 @@ public class AndroidTouchProcessor {
69
70
70
71
private static final int _POINTER_BUTTON_PRIMARY = 1 ;
71
72
73
+ private static final Matrix IDENTITY_TRANSFORM = new Matrix ();
74
+
72
75
private final boolean trackMotionEvents ;
73
76
74
77
/**
@@ -83,8 +86,12 @@ public AndroidTouchProcessor(@NonNull FlutterRenderer renderer, boolean trackMot
83
86
this .trackMotionEvents = trackMotionEvents ;
84
87
}
85
88
86
- /** Sends the given {@link MotionEvent} data to Flutter in a format that Flutter understands. */
87
89
public boolean onTouchEvent (@ NonNull MotionEvent event ) {
90
+ return onTouchEvent (event , IDENTITY_TRANSFORM );
91
+ }
92
+
93
+ /** Sends the given {@link MotionEvent} data to Flutter in a format that Flutter understands. */
94
+ public boolean onTouchEvent (@ NonNull MotionEvent event , Matrix transformMatrix ) {
88
95
int pointerCount = event .getPointerCount ();
89
96
90
97
// Prepare a data packet of the appropriate size and order.
@@ -102,26 +109,27 @@ public boolean onTouchEvent(@NonNull MotionEvent event) {
102
109
|| maskedAction == MotionEvent .ACTION_POINTER_UP );
103
110
if (updateForSinglePointer ) {
104
111
// ACTION_DOWN and ACTION_POINTER_DOWN always apply to a single pointer only.
105
- addPointerForIndex (event , event .getActionIndex (), pointerChange , 0 , packet );
112
+ addPointerForIndex (event , event .getActionIndex (), pointerChange , 0 , transformMatrix , packet );
106
113
} else if (updateForMultiplePointers ) {
107
114
// ACTION_UP and ACTION_POINTER_UP may contain position updates for other pointers.
108
115
// We are converting these updates to move events here in order to preserve this data.
109
116
// We also mark these events with a flag in order to help the framework reassemble
110
117
// the original Android event later, should it need to forward it to a PlatformView.
111
118
for (int p = 0 ; p < pointerCount ; p ++) {
112
119
if (p != event .getActionIndex () && event .getToolType (p ) == MotionEvent .TOOL_TYPE_FINGER ) {
113
- addPointerForIndex (event , p , PointerChange .MOVE , POINTER_DATA_FLAG_BATCHED , packet );
120
+ addPointerForIndex (
121
+ event , p , PointerChange .MOVE , POINTER_DATA_FLAG_BATCHED , transformMatrix , packet );
114
122
}
115
123
}
116
124
// It's important that we're sending the UP event last. This allows PlatformView
117
125
// to correctly batch everything back into the original Android event if needed.
118
- addPointerForIndex (event , event .getActionIndex (), pointerChange , 0 , packet );
126
+ addPointerForIndex (event , event .getActionIndex (), pointerChange , 0 , transformMatrix , packet );
119
127
} else {
120
128
// ACTION_MOVE may not actually mean all pointers have moved
121
129
// but it's the responsibility of a later part of the system to
122
130
// ignore 0-deltas if desired.
123
131
for (int p = 0 ; p < pointerCount ; p ++) {
124
- addPointerForIndex (event , p , pointerChange , 0 , packet );
132
+ addPointerForIndex (event , p , pointerChange , 0 , transformMatrix , packet );
125
133
}
126
134
}
127
135
@@ -163,7 +171,7 @@ public boolean onGenericMotionEvent(@NonNull MotionEvent event) {
163
171
packet .order (ByteOrder .LITTLE_ENDIAN );
164
172
165
173
// ACTION_HOVER_MOVE always applies to a single pointer only.
166
- addPointerForIndex (event , event .getActionIndex (), pointerChange , 0 , packet );
174
+ addPointerForIndex (event , event .getActionIndex (), pointerChange , 0 , IDENTITY_TRANSFORM , packet );
167
175
if (packet .position () % (POINTER_DATA_FIELD_COUNT * BYTES_PER_FIELD ) != 0 ) {
168
176
throw new AssertionError ("Packet position is not on field boundary." );
169
177
}
@@ -174,7 +182,12 @@ public boolean onGenericMotionEvent(@NonNull MotionEvent event) {
174
182
// TODO(mattcarroll): consider creating a PointerPacket class instead of using a procedure that
175
183
// mutates inputs.
176
184
private void addPointerForIndex (
177
- MotionEvent event , int pointerIndex , int pointerChange , int pointerData , ByteBuffer packet ) {
185
+ MotionEvent event ,
186
+ int pointerIndex ,
187
+ int pointerChange ,
188
+ int pointerData ,
189
+ Matrix transformMatrix ,
190
+ ByteBuffer packet ) {
178
191
if (pointerChange == -1 ) {
179
192
return ;
180
193
}
@@ -201,8 +214,14 @@ private void addPointerForIndex(
201
214
packet .putLong (signalKind ); // signal_kind
202
215
packet .putLong (event .getPointerId (pointerIndex )); // device
203
216
packet .putLong (0 ); // pointer_identifier, will be generated in pointer_data_packet_converter.cc.
204
- packet .putDouble (event .getRawX (pointerIndex )); // physical_x
205
- packet .putDouble (event .getRawY (pointerIndex )); // physical_y
217
+
218
+ // We use this in lieu of using event.getRawX and event.getRawY as we wish to support
219
+ // earlier versions than API level 29.
220
+ float viewToScreenCoords [] = {event .getX (pointerIndex ), event .getY (pointerIndex )};
221
+ transformMatrix .mapPoints (viewToScreenCoords );
222
+ packet .putDouble (viewToScreenCoords [0 ]); // physical_x
223
+ packet .putDouble (viewToScreenCoords [1 ]); // physical_y
224
+
206
225
packet .putDouble (
207
226
0.0 ); // physical_delta_x, will be generated in pointer_data_packet_converter.cc.
208
227
packet .putDouble (
0 commit comments