mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-08-02 06:08:53 +00:00
Send PositionMapper to Controller directly
When a new capture starts, send a new PositionMapper to the Controller without using the global Device as an intermediate. Now all Device methods are static. PR #5370 <https://github.com/Genymobile/scrcpy/pull/5370>
This commit is contained in:
parent
f1368d9a8f
commit
7024d38199
5 changed files with 45 additions and 38 deletions
|
@ -139,9 +139,6 @@ public final class Server {
|
||||||
boolean video = options.getVideo();
|
boolean video = options.getVideo();
|
||||||
boolean audio = options.getAudio();
|
boolean audio = options.getAudio();
|
||||||
boolean sendDummyByte = options.getSendDummyByte();
|
boolean sendDummyByte = options.getSendDummyByte();
|
||||||
boolean camera = video && options.getVideoSource() == VideoSource.CAMERA;
|
|
||||||
|
|
||||||
final Device device = camera ? null : new Device();
|
|
||||||
|
|
||||||
Workarounds.apply();
|
Workarounds.apply();
|
||||||
|
|
||||||
|
@ -153,10 +150,11 @@ public final class Server {
|
||||||
connection.sendDeviceMeta(Device.getDeviceName());
|
connection.sendDeviceMeta(Device.getDeviceName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Controller controller = null;
|
||||||
|
|
||||||
if (control) {
|
if (control) {
|
||||||
ControlChannel controlChannel = connection.getControlChannel();
|
ControlChannel controlChannel = connection.getControlChannel();
|
||||||
Controller controller = new Controller(
|
controller = new Controller(options.getDisplayId(), controlChannel, cleanUp, options.getClipboardAutosync(), options.getPowerOn());
|
||||||
device, options.getDisplayId(), controlChannel, cleanUp, options.getClipboardAutosync(), options.getPowerOn());
|
|
||||||
asyncProcessors.add(controller);
|
asyncProcessors.add(controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +184,7 @@ public final class Server {
|
||||||
options.getSendFrameMeta());
|
options.getSendFrameMeta());
|
||||||
SurfaceCapture surfaceCapture;
|
SurfaceCapture surfaceCapture;
|
||||||
if (options.getVideoSource() == VideoSource.DISPLAY) {
|
if (options.getVideoSource() == VideoSource.DISPLAY) {
|
||||||
surfaceCapture = new ScreenCapture(device, options.getDisplayId(), options.getMaxSize(), options.getCrop(),
|
surfaceCapture = new ScreenCapture(controller, options.getDisplayId(), options.getMaxSize(), options.getCrop(),
|
||||||
options.getLockVideoOrientation());
|
options.getLockVideoOrientation());
|
||||||
} else {
|
} else {
|
||||||
surfaceCapture = new CameraCapture(options.getCameraId(), options.getCameraFacing(), options.getCameraSize(),
|
surfaceCapture = new CameraCapture(options.getCameraId(), options.getCameraFacing(), options.getCameraSize(),
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.genymobile.scrcpy.device.Device;
|
||||||
import com.genymobile.scrcpy.device.Point;
|
import com.genymobile.scrcpy.device.Point;
|
||||||
import com.genymobile.scrcpy.device.Position;
|
import com.genymobile.scrcpy.device.Position;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
|
import com.genymobile.scrcpy.video.VirtualDisplayListener;
|
||||||
import com.genymobile.scrcpy.wrappers.ClipboardManager;
|
import com.genymobile.scrcpy.wrappers.ClipboardManager;
|
||||||
import com.genymobile.scrcpy.wrappers.InputManager;
|
import com.genymobile.scrcpy.wrappers.InputManager;
|
||||||
import com.genymobile.scrcpy.wrappers.ServiceManager;
|
import com.genymobile.scrcpy.wrappers.ServiceManager;
|
||||||
|
@ -26,8 +27,9 @@ import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
public class Controller implements AsyncProcessor {
|
public class Controller implements AsyncProcessor, VirtualDisplayListener {
|
||||||
|
|
||||||
private static final int DEFAULT_DEVICE_ID = 0;
|
private static final int DEFAULT_DEVICE_ID = 0;
|
||||||
|
|
||||||
|
@ -40,7 +42,6 @@ public class Controller implements AsyncProcessor {
|
||||||
|
|
||||||
private UhidManager uhidManager;
|
private UhidManager uhidManager;
|
||||||
|
|
||||||
private final Device device;
|
|
||||||
private final int displayId;
|
private final int displayId;
|
||||||
private final boolean supportsInputEvents;
|
private final boolean supportsInputEvents;
|
||||||
private final ControlChannel controlChannel;
|
private final ControlChannel controlChannel;
|
||||||
|
@ -53,6 +54,8 @@ public class Controller implements AsyncProcessor {
|
||||||
|
|
||||||
private final AtomicBoolean isSettingClipboard = new AtomicBoolean();
|
private final AtomicBoolean isSettingClipboard = new AtomicBoolean();
|
||||||
|
|
||||||
|
private final AtomicReference<PositionMapper> positionMapper = new AtomicReference<>();
|
||||||
|
|
||||||
private long lastTouchDown;
|
private long lastTouchDown;
|
||||||
private final PointersState pointersState = new PointersState();
|
private final PointersState pointersState = new PointersState();
|
||||||
private final MotionEvent.PointerProperties[] pointerProperties = new MotionEvent.PointerProperties[PointersState.MAX_POINTERS];
|
private final MotionEvent.PointerProperties[] pointerProperties = new MotionEvent.PointerProperties[PointersState.MAX_POINTERS];
|
||||||
|
@ -60,8 +63,7 @@ public class Controller implements AsyncProcessor {
|
||||||
|
|
||||||
private boolean keepPowerModeOff;
|
private boolean keepPowerModeOff;
|
||||||
|
|
||||||
public Controller(Device device, int displayId, ControlChannel controlChannel, CleanUp cleanUp, boolean clipboardAutosync, boolean powerOn) {
|
public Controller(int displayId, ControlChannel controlChannel, CleanUp cleanUp, boolean clipboardAutosync, boolean powerOn) {
|
||||||
this.device = device;
|
|
||||||
this.displayId = displayId;
|
this.displayId = displayId;
|
||||||
this.controlChannel = controlChannel;
|
this.controlChannel = controlChannel;
|
||||||
this.cleanUp = cleanUp;
|
this.cleanUp = cleanUp;
|
||||||
|
@ -99,6 +101,11 @@ public class Controller implements AsyncProcessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNewVirtualDisplay(PositionMapper positionMapper) {
|
||||||
|
this.positionMapper.set(positionMapper);
|
||||||
|
}
|
||||||
|
|
||||||
private UhidManager getUhidManager() {
|
private UhidManager getUhidManager() {
|
||||||
if (uhidManager == null) {
|
if (uhidManager == null) {
|
||||||
uhidManager = new UhidManager(sender);
|
uhidManager = new UhidManager(sender);
|
||||||
|
@ -299,7 +306,7 @@ public class Controller implements AsyncProcessor {
|
||||||
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) {
|
||||||
long now = SystemClock.uptimeMillis();
|
long now = SystemClock.uptimeMillis();
|
||||||
|
|
||||||
Point point = device.getPhysicalPoint(position);
|
Point point = getPhysicalPoint(position);
|
||||||
if (point == null) {
|
if (point == null) {
|
||||||
Ln.w("Ignore touch event, it was generated for a different device size");
|
Ln.w("Ignore touch event, it was generated for a different device size");
|
||||||
return false;
|
return false;
|
||||||
|
@ -407,9 +414,9 @@ public class Controller implements AsyncProcessor {
|
||||||
|
|
||||||
private boolean injectScroll(Position position, float hScroll, float vScroll, int buttons) {
|
private boolean injectScroll(Position position, float hScroll, float vScroll, int buttons) {
|
||||||
long now = SystemClock.uptimeMillis();
|
long now = SystemClock.uptimeMillis();
|
||||||
Point point = device.getPhysicalPoint(position);
|
Point point = getPhysicalPoint(position);
|
||||||
if (point == null) {
|
if (point == null) {
|
||||||
// ignore event
|
Ln.w("Ignore scroll event, it was generated for a different device size");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,6 +434,17 @@ public class Controller implements AsyncProcessor {
|
||||||
return injectEvent(event, Device.INJECT_MODE_ASYNC);
|
return injectEvent(event, Device.INJECT_MODE_ASYNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Point getPhysicalPoint(Position position) {
|
||||||
|
// it hides the field on purpose, to read it with atomic access
|
||||||
|
@SuppressWarnings("checkstyle:HiddenField")
|
||||||
|
PositionMapper positionMapper = this.positionMapper.get();
|
||||||
|
if (positionMapper == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return positionMapper.map(position);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedule a call to set power mode to off after a small delay.
|
* Schedule a call to set power mode to off after a small delay.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package com.genymobile.scrcpy.device;
|
package com.genymobile.scrcpy.device;
|
||||||
|
|
||||||
import com.genymobile.scrcpy.AndroidVersions;
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.control.PositionMapper;
|
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
import com.genymobile.scrcpy.wrappers.ClipboardManager;
|
import com.genymobile.scrcpy.wrappers.ClipboardManager;
|
||||||
import com.genymobile.scrcpy.wrappers.DisplayControl;
|
import com.genymobile.scrcpy.wrappers.DisplayControl;
|
||||||
|
@ -18,8 +17,6 @@ import android.view.InputEvent;
|
||||||
import android.view.KeyCharacterMap;
|
import android.view.KeyCharacterMap;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
public final class Device {
|
public final class Device {
|
||||||
|
|
||||||
public static final int POWER_MODE_OFF = SurfaceControl.POWER_MODE_OFF;
|
public static final int POWER_MODE_OFF = SurfaceControl.POWER_MODE_OFF;
|
||||||
|
@ -32,17 +29,8 @@ public final class Device {
|
||||||
public static final int LOCK_VIDEO_ORIENTATION_UNLOCKED = -1;
|
public static final int LOCK_VIDEO_ORIENTATION_UNLOCKED = -1;
|
||||||
public static final int LOCK_VIDEO_ORIENTATION_INITIAL = -2;
|
public static final int LOCK_VIDEO_ORIENTATION_INITIAL = -2;
|
||||||
|
|
||||||
private final AtomicReference<PositionMapper> positionMapper = new AtomicReference<>(); // set by the ScreenCapture instance
|
private Device() {
|
||||||
|
// not instantiable
|
||||||
public Point getPhysicalPoint(Position position) {
|
|
||||||
// it hides the field on purpose, to read it with atomic access
|
|
||||||
@SuppressWarnings("checkstyle:HiddenField")
|
|
||||||
PositionMapper positionMapper = this.positionMapper.get();
|
|
||||||
if (positionMapper == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return positionMapper.map(position);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDeviceName() {
|
public static String getDeviceName() {
|
||||||
|
@ -54,10 +42,6 @@ public final class Device {
|
||||||
return displayId == 0 || Build.VERSION.SDK_INT >= AndroidVersions.API_29_ANDROID_10;
|
return displayId == 0 || Build.VERSION.SDK_INT >= AndroidVersions.API_29_ANDROID_10;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPositionMapper(PositionMapper positionMapper) {
|
|
||||||
this.positionMapper.set(positionMapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean injectEvent(InputEvent inputEvent, int displayId, int injectMode) {
|
public static boolean injectEvent(InputEvent inputEvent, int displayId, int injectMode) {
|
||||||
if (!supportsInputEvents(displayId)) {
|
if (!supportsInputEvents(displayId)) {
|
||||||
throw new AssertionError("Could not inject input event if !supportsInputEvents()");
|
throw new AssertionError("Could not inject input event if !supportsInputEvents()");
|
||||||
|
|
|
@ -3,7 +3,6 @@ package com.genymobile.scrcpy.video;
|
||||||
import com.genymobile.scrcpy.AndroidVersions;
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.control.PositionMapper;
|
import com.genymobile.scrcpy.control.PositionMapper;
|
||||||
import com.genymobile.scrcpy.device.ConfigurationException;
|
import com.genymobile.scrcpy.device.ConfigurationException;
|
||||||
import com.genymobile.scrcpy.device.Device;
|
|
||||||
import com.genymobile.scrcpy.device.DisplayInfo;
|
import com.genymobile.scrcpy.device.DisplayInfo;
|
||||||
import com.genymobile.scrcpy.device.Size;
|
import com.genymobile.scrcpy.device.Size;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
|
@ -21,8 +20,7 @@ import android.view.Surface;
|
||||||
|
|
||||||
public class ScreenCapture extends SurfaceCapture {
|
public class ScreenCapture extends SurfaceCapture {
|
||||||
|
|
||||||
private final Device device;
|
private final VirtualDisplayListener vdListener;
|
||||||
|
|
||||||
private final int displayId;
|
private final int displayId;
|
||||||
private int maxSize;
|
private int maxSize;
|
||||||
private final Rect crop;
|
private final Rect crop;
|
||||||
|
@ -37,8 +35,8 @@ public class ScreenCapture extends SurfaceCapture {
|
||||||
private IRotationWatcher rotationWatcher;
|
private IRotationWatcher rotationWatcher;
|
||||||
private IDisplayFoldListener displayFoldListener;
|
private IDisplayFoldListener displayFoldListener;
|
||||||
|
|
||||||
public ScreenCapture(Device device, int displayId, int maxSize, Rect crop, int lockVideoOrientation) {
|
public ScreenCapture(VirtualDisplayListener vdListener, int displayId, int maxSize, Rect crop, int lockVideoOrientation) {
|
||||||
this.device = device;
|
this.vdListener = vdListener;
|
||||||
this.displayId = displayId;
|
this.displayId = displayId;
|
||||||
this.maxSize = maxSize;
|
this.maxSize = maxSize;
|
||||||
this.crop = crop;
|
this.crop = crop;
|
||||||
|
@ -133,8 +131,10 @@ public class ScreenCapture extends SurfaceCapture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PositionMapper positionMapper = PositionMapper.from(screenInfo);
|
if (vdListener != null) {
|
||||||
device.setPositionMapper(positionMapper);
|
PositionMapper positionMapper = PositionMapper.from(screenInfo);
|
||||||
|
vdListener.onNewVirtualDisplay(positionMapper);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.genymobile.scrcpy.video;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.control.PositionMapper;
|
||||||
|
|
||||||
|
public interface VirtualDisplayListener {
|
||||||
|
void onNewVirtualDisplay(PositionMapper positionMapper);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue