diff --git a/server/src/main/java/com/genymobile/scrcpy/Controller.java b/server/src/main/java/com/genymobile/scrcpy/Controller.java
index 9fd4455e..326198ad 100644
--- a/server/src/main/java/com/genymobile/scrcpy/Controller.java
+++ b/server/src/main/java/com/genymobile/scrcpy/Controller.java
@@ -199,24 +199,35 @@ public class Controller {
// ignore event
return false;
}
- Finger finger = fingersState.get(fingerId);
- if (finger == null) {
+
+ int fingerIndex = fingersState.getFingerIndex(fingerId);
+ if (fingerIndex == -1) {
Ln.w("Too many fingers for touch event");
return false;
}
+ Finger finger = fingersState.get(fingerIndex);
finger.setPoint(point);
finger.setPressure(pressure);
finger.setUp(action == MotionEvent.ACTION_UP);
// FAIL: action_up will always remove the finger, and the event will not be written!
int pointerCount = fingersState.update(touchPointerProperties, touchPointerCoords);
+ fingersState.cleanUp();
Ln.d("pointerCount = " + pointerCount);
for (int i = 0; i < pointerCount; ++i) {
Ln.d("props = " + touchPointerProperties[i].id);
Ln.d("coords = " + touchPointerCoords[i].x + "," + touchPointerCoords[i].y);
}
- MotionEvent event = MotionEvent.obtain(lastTouchDown, now, action | (finger.getLocalId() << 8), pointerCount, touchPointerProperties, touchPointerCoords, 0, 0, 1f, 1f, 0, 0,
+
+ if (pointerCount > 1) {
+ if (action == MotionEvent.ACTION_UP) {
+ action = MotionEvent.ACTION_POINTER_UP | (fingerIndex << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
+ } else if (action == MotionEvent.ACTION_DOWN) {
+ action = MotionEvent.ACTION_POINTER_DOWN | (fingerIndex << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
+ }
+ }
+ MotionEvent event = MotionEvent.obtain(lastTouchDown, now, action, pointerCount, touchPointerProperties, touchPointerCoords, 0, 0, 1f, 1f, 0, 0,
InputDevice.SOURCE_TOUCHSCREEN, 0);
return injectEvent(event);
}
diff --git a/server/src/main/java/com/genymobile/scrcpy/FingersState.java b/server/src/main/java/com/genymobile/scrcpy/FingersState.java
index c08fff6a..1961e1f2 100644
--- a/server/src/main/java/com/genymobile/scrcpy/FingersState.java
+++ b/server/src/main/java/com/genymobile/scrcpy/FingersState.java
@@ -2,56 +2,70 @@ package com.genymobile.scrcpy;
import android.view.MotionEvent;
+import java.util.ArrayList;
+import java.util.List;
+
public class FingersState {
- /**
- * Array of enabled fingers (can contain "null" holes).
- *
- * Once a Finger (identified by its id received from the client) is enabled, it is never moved.
- *
- * Its index is its local identifier injected into MotionEvents.
- */
- private final Finger[] fingers;
+ private final List fingers = new ArrayList<>();
+ private int maxFingers;
public FingersState(int maxFingers) {
- fingers = new Finger[maxFingers];
+ this.maxFingers = maxFingers;
}
private int indexOf(long id) {
- for (int i = 0; i < fingers.length; ++i) {
- Finger finger = fingers[i];
- if (finger != null && finger.getId() == id) {
+ for (int i = 0; i < fingers.size(); ++i) {
+ Finger finger = fingers.get(i);
+ if (finger.getId() == id) {
return i;
}
}
return -1;
}
- private int indexOfFirstEmpty() {
- for (int i = 0; i < fingers.length; ++i) {
- if (fingers[i] == null) {
- return i;
+ private boolean isLocalIdAvailable(int localId) {
+ for (int i = 0; i < fingers.size(); ++i) {
+ Finger finger = fingers.get(i);
+ if (finger.getLocalId() == localId) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private int nextUnusedLocalId() {
+ for (int localId = 0; localId < maxFingers; ++localId) {
+ if (isLocalIdAvailable(localId)) {
+ return localId;
}
}
return -1;
}
- public Finger get(long id) {
+ public Finger get(int index) {
+ return fingers.get(index);
+ }
+
+ public int getFingerIndex(long id) {
int index = indexOf(id);
if (index != -1) {
// already exists, return it
- return fingers[index];
+ return index;
}
- index = indexOfFirstEmpty();
- if (index == -1) {
+ if (fingers.size() >= maxFingers) {
// it's full
- return null;
+ return -1;
}
// id 0 is reserved for mouse events
- int localId = index;// + 1;
+ int localId = nextUnusedLocalId();
+ if (localId == -1) {
+ throw new AssertionError("fingers.size() < maxFingers implies that a local id is available");
+ }
Finger finger = new Finger(id, localId);
- fingers[index] = finger;
- return finger;
+ fingers.add(finger);
+ // return the index of the finger
+ return fingers.size() - 1;
}
/**
@@ -62,27 +76,26 @@ public class FingersState {
* @return The number of items initialized (the number of fingers).
*/
public int update(MotionEvent.PointerProperties[] props, MotionEvent.PointerCoords[] coords) {
- int count = 0;
- for (int i = 0; i < fingers.length; ++i) {
- Finger finger = fingers[i];
- if (finger != null) {
- // id 0 is reserved for mouse events
- props[count].id = finger.getLocalId();
- Ln.d("update id = " + finger.getLocalId());
+ for (int i = 0; i < fingers.size(); ++i) {
+ Finger finger = fingers.get(i);
- Point point = finger.getPoint();
- coords[count].x = point.getX();
- coords[count].y = point.getY();
- coords[count].pressure = finger.getPressure();
+ // id 0 is reserved for mouse events
+ props[i].id = finger.getLocalId();
- if (finger.isUp()) {
- // remove it
- fingers[i] = null;
- }
+ Point point = finger.getPoint();
+ coords[i].x = point.getX();
+ coords[i].y = point.getY();
+ coords[i].pressure = finger.getPressure();
+ }
+ return fingers.size();
+ }
- ++count;
+ public void cleanUp() {
+ for (int i = fingers.size() - 1; i >= 0; --i) {
+ Finger finger = fingers.get(i);
+ if (finger.isUp()) {
+ fingers.remove(i);
}
}
- return count;
}
}