Accept positional control events without display

The position of touch and scroll must normally be "resolved" with a
"position mapper" associated to the display.

But to support the injection of such events with scrcpy-server alone
without video, handle the case where there is no display.

Fixes #5542 <https://github.com/Genymobile/scrcpy/issues/5542>
This commit is contained in:
Romain Vimont 2024-11-28 21:10:06 +01:00
parent 4317ee3d68
commit 9f4dc10e11

View File

@ -355,9 +355,14 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener {
// it hides the field on purpose, to read it with atomic access // it hides the field on purpose, to read it with atomic access
@SuppressWarnings("checkstyle:HiddenField") @SuppressWarnings("checkstyle:HiddenField")
DisplayData displayData = this.displayData.get(); DisplayData displayData = this.displayData.get();
assert displayData != null : "Cannot receive a positional event without a display"; // In scrcpy, displayData should never be null (a touch event can only be generated from the client when a video frame is present).
// However, it is possible to send events without video playback when using scrcpy-server alone (except for virtual displays).
assert displayData != null || displayId != Device.DISPLAY_ID_NONE : "Cannot receive a positional event without a display";
Point point = displayData.positionMapper.map(position); Point point;
int targetDisplayId;
if (displayData != null) {
point = displayData.positionMapper.map(position);
if (point == null) { if (point == null) {
if (Ln.isEnabled(Ln.Level.VERBOSE)) { if (Ln.isEnabled(Ln.Level.VERBOSE)) {
Size eventSize = position.getScreenSize(); Size eventSize = position.getScreenSize();
@ -366,8 +371,14 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener {
} }
return null; return null;
} }
targetDisplayId = displayData.virtualDisplayId;
} else {
// No display, use the raw coordinates
point = position.getPoint();
targetDisplayId = displayId;
}
return Pair.create(point, displayData.virtualDisplayId); return Pair.create(point, targetDisplayId);
} }
private boolean injectTouch(int action, long pointerId, Position position, float pressure, int actionButton, int buttons) { private boolean injectTouch(int action, long pointerId, Position position, float pressure, int actionButton, int buttons) {