diff --git a/server/src/main/java/com/genymobile/scrcpy/Device.java b/server/src/main/java/com/genymobile/scrcpy/Device.java index fdc6725d..855263f1 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Device.java +++ b/server/src/main/java/com/genymobile/scrcpy/Device.java @@ -19,15 +19,30 @@ public final class Device { private ScreenInfo screenInfo; private RotationListener rotationListener; + private boolean rotated; public Device(Options options) { - options.setCrop(new Rect(100, 100, 300, 250)); - screenInfo = computeScreenInfo(options.getMaxSize(), options.getCrop()); + options.setCrop(new Rect(0, 960, 1080, 1920)); + + final int maxSize = options.getMaxSize(); + final Rect crop = options.getCrop(); + + DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo(); + rotated = (displayInfo.getRotation() & 1) != 0; + + screenInfo = ScreenInfo.create(displayInfo.getSize(), maxSize, crop, rotated); registerRotationWatcher(new IRotationWatcher.Stub() { @Override - public void onRotationChanged(int rotation) throws RemoteException { + public void onRotationChanged(int rotation) { + boolean rotated = (rotation & 1) != 0; synchronized (Device.this) { - screenInfo = screenInfo.withRotation(rotation); + // Do not call getDisplayInfo(), the resulting rotation may be inconsistent with + // the rotation parameter (race condition). + // Instead, compute the new size from the (rotated) old size. + Size oldSize = screenInfo.getDeviceSize(); + Size newSize = rotated != Device.this.rotated ? oldSize.rotate() : oldSize; + screenInfo = ScreenInfo.create(newSize, maxSize, crop, rotated); + Device.this.rotated = rotated; // notify if (rotationListener != null) { @@ -42,14 +57,9 @@ public final class Device { return screenInfo; } - private ScreenInfo computeScreenInfo(int maxSize, Rect crop) { - DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo(); - return ScreenInfo.create(displayInfo, maxSize, crop); - } - public Point getPhysicalPoint(Position position) { @SuppressWarnings("checkstyle:HiddenField") // it hides the field on purpose, to read it with a lock - ScreenInfo screenInfo = getScreenInfo(); // read with synchronization + ScreenInfo screenInfo = getScreenInfo(); // read with synchronization Size videoSize = screenInfo.getVideoSize(); Size clientVideoSize = position.getScreenSize(); if (!videoSize.equals(clientVideoSize)) { diff --git a/server/src/main/java/com/genymobile/scrcpy/DisplayInfo.java b/server/src/main/java/com/genymobile/scrcpy/DisplayInfo.java index 639869b5..a8096da9 100644 --- a/server/src/main/java/com/genymobile/scrcpy/DisplayInfo.java +++ b/server/src/main/java/com/genymobile/scrcpy/DisplayInfo.java @@ -16,5 +16,16 @@ public final class DisplayInfo { public int getRotation() { return rotation; } + + public DisplayInfo withRotation(int rotation) { + if (rotation == this.rotation) { + return this; + } + Size newSize = size; + if ((rotation & 1) != (this.rotation & 1)) { + newSize = size.rotate(); + } + return new DisplayInfo(newSize, rotation); + } } diff --git a/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java b/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java index 7c9725cd..e2ee8122 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java +++ b/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java @@ -57,7 +57,6 @@ public class ScreenEncoder implements Device.RotationListener { MediaCodec codec = createCodec(); IBinder display = createDisplay(); Rect contentRect = device.getScreenInfo().getContentRect(); - System.out.println(contentRect); Rect videoRect = device.getScreenInfo().getVideoSize().toRect(); setSize(format, videoRect.width(), videoRect.height()); configure(codec, format); diff --git a/server/src/main/java/com/genymobile/scrcpy/ScreenInfo.java b/server/src/main/java/com/genymobile/scrcpy/ScreenInfo.java index 9ca8dbe3..f140cd3f 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ScreenInfo.java +++ b/server/src/main/java/com/genymobile/scrcpy/ScreenInfo.java @@ -6,26 +6,22 @@ public final class ScreenInfo { private final Size deviceSize; private final Size videoSize; private final Rect crop; - private final boolean rotated; private ScreenInfo(Size deviceSize, Size videoSize, Rect crop, boolean rotated) { this.deviceSize = deviceSize; this.videoSize = videoSize; - this.rotated = rotated; this.crop = crop; } - public static ScreenInfo create(DisplayInfo displayInfo, int maxSize, Rect crop) { - boolean rotated = (displayInfo.getRotation() & 1) != 0; - // the device size (provided by the system) takes the rotation into account - Size deviceSize = displayInfo.getSize(); + public static ScreenInfo create(Size deviceSize, int maxSize, Rect crop, boolean rotated) { Size inputSize; if (crop == null) { inputSize = deviceSize; } else { if (rotated) { // the crop (provided by the user) is expressed in the natural orientation - crop = rotateCrop(crop, deviceSize.rotate()); + // the device size (provided by the system) already takes the rotation into account + crop = rotateCrop(crop, deviceSize); } inputSize = new Size(crop.width(), crop.height()); } @@ -78,27 +74,8 @@ public final class ScreenInfo { return crop != null ? crop : deviceSize.toRect(); } - public ScreenInfo withRotation(int rotation) { - boolean newRotated = (rotation & 1) != 0; - if (rotated == newRotated) { - return this; - } - Rect newCrop = null; - if (crop != null) { - // the crop has typically a meaning only in one dimension, but we must rotate it so that the - // video size matches on rotation - newCrop = newRotated ? rotateCrop(crop, deviceSize) : unrotateCrop(crop, deviceSize); - } - return new ScreenInfo(deviceSize.rotate(), videoSize.rotate(), newCrop, newRotated); - } - - private static Rect rotateCrop(Rect crop, Size deviceSize) { - int w = deviceSize.getWidth(); + private static Rect rotateCrop(Rect crop, Size rotatedSize) { + int w = rotatedSize.getHeight(); // the size is already rotated return new Rect(crop.top, w - crop.right, crop.bottom, w - crop.left); } - - private static Rect unrotateCrop(Rect crop, Size deviceSize) { - int h = deviceSize.getHeight(); - return new Rect(h - crop.bottom, crop.left, h - crop.top, crop.right); - } }