diff --git a/server/src/main/java/com/genymobile/scrcpy/control/PositionMapper.java b/server/src/main/java/com/genymobile/scrcpy/control/PositionMapper.java index 2ebb5961..7b546652 100644 --- a/server/src/main/java/com/genymobile/scrcpy/control/PositionMapper.java +++ b/server/src/main/java/com/genymobile/scrcpy/control/PositionMapper.java @@ -3,46 +3,28 @@ package com.genymobile.scrcpy.control; import com.genymobile.scrcpy.device.Point; import com.genymobile.scrcpy.device.Position; import com.genymobile.scrcpy.device.Size; -import com.genymobile.scrcpy.video.ScreenInfo; - -import android.graphics.Rect; public final class PositionMapper { + private final Size sourceSize; private final Size videoSize; - private final Rect contentRect; - private final int coordsRotation; - public PositionMapper(Size videoSize, Rect contentRect, int videoRotation) { + public PositionMapper(Size sourceSize, Size videoSize) { + this.sourceSize = sourceSize; this.videoSize = videoSize; - this.contentRect = contentRect; - this.coordsRotation = reverseRotation(videoRotation); - } - - public static PositionMapper from(ScreenInfo screenInfo) { - // ignore the locked video orientation, the events will apply in coordinates considered in the physical device orientation - Size videoSize = screenInfo.getUnlockedVideoSize(); - return new PositionMapper(videoSize, screenInfo.getContentRect(), screenInfo.getVideoRotation()); - } - - private static int reverseRotation(int rotation) { - return (4 - rotation) % 4; } public Point map(Position position) { - // reverse the video rotation to apply the events - Position devicePosition = position.rotate(coordsRotation); - - Size clientVideoSize = devicePosition.getScreenSize(); + Size clientVideoSize = position.getScreenSize(); if (!videoSize.equals(clientVideoSize)) { // The client sends a click relative to a video with wrong dimensions, // the device may have been rotated since the event was generated, so ignore the event return null; } - Point point = devicePosition.getPoint(); - int convertedX = contentRect.left + point.getX() * contentRect.width() / videoSize.getWidth(); - int convertedY = contentRect.top + point.getY() * contentRect.height() / videoSize.getHeight(); + Point point = position.getPoint(); + int convertedX = point.getX() * sourceSize.getWidth() / videoSize.getWidth(); + int convertedY = point.getY() * sourceSize.getHeight() / videoSize.getHeight(); return new Point(convertedX, convertedY); } } diff --git a/server/src/main/java/com/genymobile/scrcpy/video/NewDisplayCapture.java b/server/src/main/java/com/genymobile/scrcpy/video/NewDisplayCapture.java index b9cecbe4..f657d1a8 100644 --- a/server/src/main/java/com/genymobile/scrcpy/video/NewDisplayCapture.java +++ b/server/src/main/java/com/genymobile/scrcpy/video/NewDisplayCapture.java @@ -9,7 +9,6 @@ import com.genymobile.scrcpy.device.Size; import com.genymobile.scrcpy.util.Ln; import com.genymobile.scrcpy.wrappers.ServiceManager; -import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.hardware.display.VirtualDisplay; import android.os.Build; @@ -107,8 +106,7 @@ public class NewDisplayCapture extends SurfaceCapture { } if (vdListener != null) { - Rect contentRect = new Rect(0, 0, size.getWidth(), size.getHeight()); - PositionMapper positionMapper = new PositionMapper(size, contentRect, 0); + PositionMapper positionMapper = new PositionMapper(size, size); vdListener.onNewVirtualDisplay(virtualDisplayId, positionMapper); } } diff --git a/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java b/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java index 00d855bd..00ee89d8 100644 --- a/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java +++ b/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java @@ -28,11 +28,9 @@ public class ScreenCapture extends SurfaceCapture { private final VirtualDisplayListener vdListener; private final int displayId; private int maxSize; - private final Rect crop; - private final int lockVideoOrientation; private DisplayInfo displayInfo; - private ScreenInfo screenInfo; + private Size videoSize; // Source display size (before resizing/crop) for the current session private Size sessionDisplaySize; @@ -55,8 +53,6 @@ public class ScreenCapture extends SurfaceCapture { this.displayId = options.getDisplayId(); assert displayId != Device.DISPLAY_ID_NONE; this.maxSize = options.getMaxSize(); - this.crop = options.getCrop(); - this.lockVideoOrientation = options.getLockVideoOrientation(); } @Override @@ -126,8 +122,9 @@ public class ScreenCapture extends SurfaceCapture { Ln.w("Display doesn't have FLAG_SUPPORTS_PROTECTED_BUFFERS flag, mirroring can be restricted"); } - setSessionDisplaySize(displayInfo.getSize()); - screenInfo = ScreenInfo.computeScreenInfo(displayInfo.getRotation(), displayInfo.getSize(), crop, maxSize, lockVideoOrientation); + Size displaySize = displayInfo.getSize(); + setSessionDisplaySize(displaySize); + videoSize = displaySize.limit(maxSize).round8(); } @Override @@ -144,28 +141,22 @@ public class ScreenCapture extends SurfaceCapture { int virtualDisplayId; PositionMapper positionMapper; try { - Size videoSize = screenInfo.getVideoSize(); virtualDisplay = ServiceManager.getDisplayManager() .createVirtualDisplay("scrcpy", videoSize.getWidth(), videoSize.getHeight(), displayId, surface); virtualDisplayId = virtualDisplay.getDisplay().getDisplayId(); - Rect contentRect = new Rect(0, 0, videoSize.getWidth(), videoSize.getHeight()); // The position are relative to the virtual display, not the original display - positionMapper = new PositionMapper(videoSize, contentRect, 0); + positionMapper = new PositionMapper(videoSize, videoSize); Ln.d("Display: using DisplayManager API"); } catch (Exception displayManagerException) { try { display = createDisplay(); - Rect contentRect = screenInfo.getContentRect(); - - // does not include the locked video orientation - Rect unlockedVideoRect = screenInfo.getUnlockedVideoSize().toRect(); - int videoRotation = screenInfo.getVideoRotation(); + Size deviceSize = displayInfo.getSize(); int layerStack = displayInfo.getLayerStack(); - setDisplaySurface(display, surface, videoRotation, contentRect, unlockedVideoRect, layerStack); + setDisplaySurface(display, surface, deviceSize.toRect(), videoSize.toRect(), layerStack); virtualDisplayId = displayId; - positionMapper = PositionMapper.from(screenInfo); + positionMapper = new PositionMapper(deviceSize, videoSize); Ln.d("Display: using SurfaceControl API"); } catch (Exception surfaceControlException) { Ln.e("Could not create display using DisplayManager", displayManagerException); @@ -206,7 +197,7 @@ public class ScreenCapture extends SurfaceCapture { @Override public Size getSize() { - return screenInfo.getVideoSize(); + return videoSize; } @Override @@ -223,11 +214,11 @@ public class ScreenCapture extends SurfaceCapture { return SurfaceControl.createDisplay("scrcpy", secure); } - private static void setDisplaySurface(IBinder display, Surface surface, int orientation, Rect deviceRect, Rect displayRect, int layerStack) { + private static void setDisplaySurface(IBinder display, Surface surface, Rect deviceRect, Rect displayRect, int layerStack) { SurfaceControl.openTransaction(); try { SurfaceControl.setDisplaySurface(display, surface); - SurfaceControl.setDisplayProjection(display, orientation, deviceRect, displayRect); + SurfaceControl.setDisplayProjection(display, 0, deviceRect, displayRect); SurfaceControl.setDisplayLayerStack(display, layerStack); } finally { SurfaceControl.closeTransaction(); diff --git a/server/src/main/java/com/genymobile/scrcpy/video/ScreenInfo.java b/server/src/main/java/com/genymobile/scrcpy/video/ScreenInfo.java deleted file mode 100644 index 010ab59a..00000000 --- a/server/src/main/java/com/genymobile/scrcpy/video/ScreenInfo.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.genymobile.scrcpy.video; - -import com.genymobile.scrcpy.device.Device; -import com.genymobile.scrcpy.device.Size; -import com.genymobile.scrcpy.util.Ln; - -import android.graphics.Rect; - -public final class ScreenInfo { - /** - * Device (physical) size, possibly cropped - */ - private final Rect contentRect; // device size, possibly cropped - - /** - * Video size, possibly smaller than the device size, already taking the device rotation and crop into account. - *
- * However, it does not include the locked video orientation. - */ - private final Size unlockedVideoSize; - - /** - * Device rotation, related to the natural device orientation (0, 1, 2 or 3) - */ - private final int deviceRotation; - - /** - * The locked video orientation (-1: disabled, 0: normal, 1: 90° CCW, 2: 180°, 3: 90° CW) - */ - private final int lockedVideoOrientation; - - public ScreenInfo(Rect contentRect, Size unlockedVideoSize, int deviceRotation, int lockedVideoOrientation) { - this.contentRect = contentRect; - this.unlockedVideoSize = unlockedVideoSize; - this.deviceRotation = deviceRotation; - this.lockedVideoOrientation = lockedVideoOrientation; - } - - public Rect getContentRect() { - return contentRect; - } - - /** - * Return the video size as if locked video orientation was not set. - * - * @return the unlocked video size - */ - public Size getUnlockedVideoSize() { - return unlockedVideoSize; - } - - /** - * Return the actual video size if locked video orientation is set. - * - * @return the actual video size - */ - public Size getVideoSize() { - if (getVideoRotation() % 2 == 0) { - return unlockedVideoSize; - } - - return unlockedVideoSize.rotate(); - } - - public static ScreenInfo computeScreenInfo(int rotation, Size deviceSize, Rect crop, int maxSize, int lockedVideoOrientation) { - if (lockedVideoOrientation == Device.LOCK_VIDEO_ORIENTATION_INITIAL) { - // The user requested to lock the video orientation to the current orientation - lockedVideoOrientation = rotation; - } - - Rect contentRect = new Rect(0, 0, deviceSize.getWidth(), deviceSize.getHeight()); - if (crop != null) { - if (rotation % 2 != 0) { // 180s preserve dimensions - // the crop (provided by the user) is expressed in the natural orientation - crop = flipRect(crop); - } - if (!contentRect.intersect(crop)) { - // intersect() changes contentRect so that it is intersected with crop - Ln.w("Crop rectangle (" + formatCrop(crop) + ") does not intersect device screen (" + formatCrop(deviceSize.toRect()) + ")"); - contentRect = new Rect(); // empty - } - } - - Size videoSize = new Size(contentRect.width(), contentRect.height()).limit(maxSize).round8(); - return new ScreenInfo(contentRect, videoSize, rotation, lockedVideoOrientation); - } - - private static String formatCrop(Rect rect) { - return rect.width() + ":" + rect.height() + ":" + rect.left + ":" + rect.top; - } - - private static Rect flipRect(Rect crop) { - return new Rect(crop.top, crop.left, crop.bottom, crop.right); - } - - /** - * Return the rotation to apply to the device rotation to get the requested locked video orientation - * - * @return the rotation offset - */ - public int getVideoRotation() { - if (lockedVideoOrientation == -1) { - // no offset - return 0; - } - return (deviceRotation + 4 - lockedVideoOrientation) % 4; - } - - /** - * Return the rotation to apply to the requested locked video orientation to get the device rotation - * - * @return the (reverse) rotation offset - */ - public int getReverseVideoRotation() { - if (lockedVideoOrientation == -1) { - // no offset - return 0; - } - return (lockedVideoOrientation + 4 - deviceRotation) % 4; - } -}