Introduce PositionMapper
Extract the function that converts coordinates from video space to display space into a separate component. It only requires the specific data it uses and does not need a full ScreenInfo object (although it can be created from a ScreenInfo instance). PR #5370 <https://github.com/Genymobile/scrcpy/pull/5370>
This commit is contained in:
parent
d916429566
commit
f1368d9a8f
@ -0,0 +1,48 @@
|
|||||||
|
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 videoSize;
|
||||||
|
private final Rect contentRect;
|
||||||
|
private final int coordsRotation;
|
||||||
|
|
||||||
|
public PositionMapper(Size videoSize, Rect contentRect, int videoRotation) {
|
||||||
|
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();
|
||||||
|
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();
|
||||||
|
return new Point(convertedX, convertedY);
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
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.video.ScreenInfo;
|
|
||||||
import com.genymobile.scrcpy.wrappers.ClipboardManager;
|
import com.genymobile.scrcpy.wrappers.ClipboardManager;
|
||||||
import com.genymobile.scrcpy.wrappers.DisplayControl;
|
import com.genymobile.scrcpy.wrappers.DisplayControl;
|
||||||
import com.genymobile.scrcpy.wrappers.InputManager;
|
import com.genymobile.scrcpy.wrappers.InputManager;
|
||||||
@ -10,7 +10,6 @@ import com.genymobile.scrcpy.wrappers.ServiceManager;
|
|||||||
import com.genymobile.scrcpy.wrappers.SurfaceControl;
|
import com.genymobile.scrcpy.wrappers.SurfaceControl;
|
||||||
import com.genymobile.scrcpy.wrappers.WindowManager;
|
import com.genymobile.scrcpy.wrappers.WindowManager;
|
||||||
|
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
@ -33,34 +32,17 @@ 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<ScreenInfo> screenInfo = new AtomicReference<>(); // set by the ScreenCapture instance
|
private final AtomicReference<PositionMapper> positionMapper = new AtomicReference<>(); // set by the ScreenCapture instance
|
||||||
|
|
||||||
public Point getPhysicalPoint(Position position) {
|
public Point getPhysicalPoint(Position position) {
|
||||||
// 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")
|
||||||
ScreenInfo screenInfo = this.screenInfo.get();
|
PositionMapper positionMapper = this.positionMapper.get();
|
||||||
if (screenInfo == null) {
|
if (positionMapper == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore the locked video orientation, the events will apply in coordinates considered in the physical device orientation
|
return positionMapper.map(position);
|
||||||
Size unlockedVideoSize = screenInfo.getUnlockedVideoSize();
|
|
||||||
|
|
||||||
int reverseVideoRotation = screenInfo.getReverseVideoRotation();
|
|
||||||
// reverse the video rotation to apply the events
|
|
||||||
Position devicePosition = position.rotate(reverseVideoRotation);
|
|
||||||
|
|
||||||
Size clientVideoSize = devicePosition.getScreenSize();
|
|
||||||
if (!unlockedVideoSize.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;
|
|
||||||
}
|
|
||||||
Rect contentRect = screenInfo.getContentRect();
|
|
||||||
Point point = devicePosition.getPoint();
|
|
||||||
int convertedX = contentRect.left + point.getX() * contentRect.width() / unlockedVideoSize.getWidth();
|
|
||||||
int convertedY = contentRect.top + point.getY() * contentRect.height() / unlockedVideoSize.getHeight();
|
|
||||||
return new Point(convertedX, convertedY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDeviceName() {
|
public static String getDeviceName() {
|
||||||
@ -72,8 +54,8 @@ 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 setScreenInfo(ScreenInfo screenInfo) {
|
public void setPositionMapper(PositionMapper positionMapper) {
|
||||||
this.screenInfo.set(screenInfo);
|
this.positionMapper.set(positionMapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean injectEvent(InputEvent inputEvent, int displayId, int injectMode) {
|
public static boolean injectEvent(InputEvent inputEvent, int displayId, int injectMode) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.genymobile.scrcpy.video;
|
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.device.ConfigurationException;
|
import com.genymobile.scrcpy.device.ConfigurationException;
|
||||||
import com.genymobile.scrcpy.device.Device;
|
import com.genymobile.scrcpy.device.Device;
|
||||||
import com.genymobile.scrcpy.device.DisplayInfo;
|
import com.genymobile.scrcpy.device.DisplayInfo;
|
||||||
@ -132,7 +133,8 @@ public class ScreenCapture extends SurfaceCapture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
device.setScreenInfo(screenInfo);
|
PositionMapper positionMapper = PositionMapper.from(screenInfo);
|
||||||
|
device.setPositionMapper(positionMapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user