Skip to content

Commit

Permalink
Accept positional control events without display
Browse files Browse the repository at this point in the history
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 <#5542>
  • Loading branch information
rom1v committed Dec 1, 2024
1 parent b2cdaa4 commit 3b2b362
Showing 1 changed file with 21 additions and 10 deletions.
31 changes: 21 additions & 10 deletions server/src/main/java/com/genymobile/scrcpy/control/Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -355,19 +355,30 @@ private Pair<Point, Integer> getEventPointAndDisplayId(Position position) {
// it hides the field on purpose, to read it with atomic access
@SuppressWarnings("checkstyle:HiddenField")
DisplayData displayData = this.displayData.get();
assert displayData != null : "Cannot receive a positional event without a display";

Point point = displayData.positionMapper.map(position);
if (point == null) {
if (Ln.isEnabled(Ln.Level.VERBOSE)) {
Size eventSize = position.getScreenSize();
Size currentSize = displayData.positionMapper.getVideoSize();
Ln.v("Ignore positional event generated for size " + eventSize + " (current size is " + currentSize + ")");
// 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;
int targetDisplayId;
if (displayData != null) {
point = displayData.positionMapper.map(position);
if (point == null) {
if (Ln.isEnabled(Ln.Level.VERBOSE)) {
Size eventSize = position.getScreenSize();
Size currentSize = displayData.positionMapper.getVideoSize();
Ln.v("Ignore positional event generated for size " + eventSize + " (current size is " + currentSize + ")");
}
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) {
Expand Down

0 comments on commit 3b2b362

Please sign in to comment.