This commit is contained in:
Romain Vimont 2019-09-29 22:06:30 +02:00
commit 7e21f28f2c
2 changed files with 68 additions and 44 deletions

View file

@ -199,24 +199,35 @@ public class Controller {
// ignore event // ignore event
return false; 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"); Ln.w("Too many fingers for touch event");
return false; return false;
} }
Finger finger = fingersState.get(fingerIndex);
finger.setPoint(point); finger.setPoint(point);
finger.setPressure(pressure); finger.setPressure(pressure);
finger.setUp(action == MotionEvent.ACTION_UP); finger.setUp(action == MotionEvent.ACTION_UP);
// FAIL: action_up will always remove the finger, and the event will not be written! // FAIL: action_up will always remove the finger, and the event will not be written!
int pointerCount = fingersState.update(touchPointerProperties, touchPointerCoords); int pointerCount = fingersState.update(touchPointerProperties, touchPointerCoords);
fingersState.cleanUp();
Ln.d("pointerCount = " + pointerCount); Ln.d("pointerCount = " + pointerCount);
for (int i = 0; i < pointerCount; ++i) { for (int i = 0; i < pointerCount; ++i) {
Ln.d("props = " + touchPointerProperties[i].id); Ln.d("props = " + touchPointerProperties[i].id);
Ln.d("coords = " + touchPointerCoords[i].x + "," + touchPointerCoords[i].y); 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); InputDevice.SOURCE_TOUCHSCREEN, 0);
return injectEvent(event); return injectEvent(event);
} }

View file

@ -2,56 +2,70 @@ package com.genymobile.scrcpy;
import android.view.MotionEvent; import android.view.MotionEvent;
import java.util.ArrayList;
import java.util.List;
public class FingersState { public class FingersState {
/** private final List<Finger> fingers = new ArrayList<>();
* Array of enabled fingers (can contain "null" holes). private int maxFingers;
* <p>
* Once a Finger (identified by its id received from the client) is enabled, it is never moved.
* <p>
* Its index is its local identifier injected into MotionEvents.
*/
private final Finger[] fingers;
public FingersState(int maxFingers) { public FingersState(int maxFingers) {
fingers = new Finger[maxFingers]; this.maxFingers = maxFingers;
} }
private int indexOf(long id) { private int indexOf(long id) {
for (int i = 0; i < fingers.length; ++i) { for (int i = 0; i < fingers.size(); ++i) {
Finger finger = fingers[i]; Finger finger = fingers.get(i);
if (finger != null && finger.getId() == id) { if (finger.getId() == id) {
return i; return i;
} }
} }
return -1; return -1;
} }
private int indexOfFirstEmpty() { private boolean isLocalIdAvailable(int localId) {
for (int i = 0; i < fingers.length; ++i) { for (int i = 0; i < fingers.size(); ++i) {
if (fingers[i] == null) { Finger finger = fingers.get(i);
return 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; 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); int index = indexOf(id);
if (index != -1) { if (index != -1) {
// already exists, return it // already exists, return it
return fingers[index]; return index;
} }
index = indexOfFirstEmpty(); if (fingers.size() >= maxFingers) {
if (index == -1) {
// it's full // it's full
return null; return -1;
} }
// id 0 is reserved for mouse events // 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); Finger finger = new Finger(id, localId);
fingers[index] = finger; fingers.add(finger);
return 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). * @return The number of items initialized (the number of fingers).
*/ */
public int update(MotionEvent.PointerProperties[] props, MotionEvent.PointerCoords[] coords) { public int update(MotionEvent.PointerProperties[] props, MotionEvent.PointerCoords[] coords) {
int count = 0; for (int i = 0; i < fingers.size(); ++i) {
for (int i = 0; i < fingers.length; ++i) { Finger finger = fingers.get(i);
Finger finger = fingers[i];
if (finger != null) {
// id 0 is reserved for mouse events // id 0 is reserved for mouse events
props[count].id = finger.getLocalId(); props[i].id = finger.getLocalId();
Ln.d("update id = " + finger.getLocalId());
Point point = finger.getPoint(); Point point = finger.getPoint();
coords[count].x = point.getX(); coords[i].x = point.getX();
coords[count].y = point.getY(); coords[i].y = point.getY();
coords[count].pressure = finger.getPressure(); coords[i].pressure = finger.getPressure();
}
return fingers.size();
}
public void cleanUp() {
for (int i = fingers.size() - 1; i >= 0; --i) {
Finger finger = fingers.get(i);
if (finger.isUp()) { if (finger.isUp()) {
// remove it fingers.remove(i);
fingers[i] = null;
}
++count;
} }
} }
return count;
} }
} }