Skip to content

Commit

Permalink
Add rotation support for non-default display
Browse files Browse the repository at this point in the history
  • Loading branch information
eiyooooo authored and rom1v committed Feb 26, 2024
1 parent 746eaea commit d894e27
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 15 deletions.
2 changes: 1 addition & 1 deletion server/src/main/java/com/genymobile/scrcpy/Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ private void handleEvent() throws IOException {
}
break;
case ControlMessage.TYPE_ROTATE_DEVICE:
Device.rotateDevice();
device.rotateDevice();
break;
default:
// do nothing
Expand Down
19 changes: 14 additions & 5 deletions server/src/main/java/com/genymobile/scrcpy/Device.java
Original file line number Diff line number Diff line change
Expand Up @@ -359,21 +359,30 @@ public static boolean powerOffScreen(int displayId) {
/**
* Disable auto-rotation (if enabled), set the screen rotation and re-enable auto-rotation (if it was enabled).
*/
public static void rotateDevice() {
public void rotateDevice() {
WindowManager wm = ServiceManager.getWindowManager();

boolean accelerometerRotation = !wm.isRotationFrozen();
boolean accelerometerRotation = !wm.isRotationFrozen(displayId);

int currentRotation = wm.getRotation();
int currentRotation = getCurrentRotation(displayId);
int newRotation = (currentRotation & 1) ^ 1; // 0->1, 1->0, 2->1, 3->0
String newRotationString = newRotation == 0 ? "portrait" : "landscape";

Ln.i("Device rotation requested: " + newRotationString);
wm.freezeRotation(newRotation);
wm.freezeRotation(displayId, newRotation);

// restore auto-rotate if necessary
if (accelerometerRotation) {
wm.thawRotation();
wm.thawRotation(displayId);
}
}

private static int getCurrentRotation(int displayId) {
if (displayId == 0) {
return ServiceManager.getWindowManager().getRotation();
}

DisplayInfo displayInfo = ServiceManager.getDisplayManager().getDisplayInfo(displayId);
return displayInfo.getRotation();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ public final class WindowManager {
private final IInterface manager;
private Method getRotationMethod;
private Method freezeRotationMethod;
private Method freezeDisplayRotationMethod;
private Method isRotationFrozenMethod;
private Method isDisplayRotationFrozenMethod;
private Method thawRotationMethod;
private Method thawDisplayRotationMethod;

static WindowManager create() {
IInterface manager = ServiceManager.getService("window", "android.view.IWindowManager");
Expand Down Expand Up @@ -47,20 +50,47 @@ private Method getFreezeRotationMethod() throws NoSuchMethodException {
return freezeRotationMethod;
}

// New method added by this commit:
// <https://android.googlesource.com/platform/frameworks/base/+/90c9005e687aa0f63f1ac391adc1e8878ab31759%5E%21/>
private Method getFreezeDisplayRotationMethod() throws NoSuchMethodException {
if (freezeDisplayRotationMethod == null) {
freezeDisplayRotationMethod = manager.getClass().getMethod("freezeDisplayRotation", int.class, int.class);
}
return freezeDisplayRotationMethod;
}

private Method getIsRotationFrozenMethod() throws NoSuchMethodException {
if (isRotationFrozenMethod == null) {
isRotationFrozenMethod = manager.getClass().getMethod("isRotationFrozen");
}
return isRotationFrozenMethod;
}

// New method added by this commit:
// <https://android.googlesource.com/platform/frameworks/base/+/90c9005e687aa0f63f1ac391adc1e8878ab31759%5E%21/>
private Method getIsDisplayRotationFrozenMethod() throws NoSuchMethodException {
if (isDisplayRotationFrozenMethod == null) {
isDisplayRotationFrozenMethod = manager.getClass().getMethod("isDisplayRotationFrozen", int.class);
}
return isDisplayRotationFrozenMethod;
}

private Method getThawRotationMethod() throws NoSuchMethodException {
if (thawRotationMethod == null) {
thawRotationMethod = manager.getClass().getMethod("thawRotation");
}
return thawRotationMethod;
}

// New method added by this commit:
// <https://android.googlesource.com/platform/frameworks/base/+/90c9005e687aa0f63f1ac391adc1e8878ab31759%5E%21/>
private Method getThawDisplayRotationMethod() throws NoSuchMethodException {
if (thawDisplayRotationMethod == null) {
thawDisplayRotationMethod = manager.getClass().getMethod("thawDisplayRotation", int.class);
}
return thawDisplayRotationMethod;
}

public int getRotation() {
try {
Method method = getGetRotationMethod();
Expand All @@ -71,29 +101,57 @@ public int getRotation() {
}
}

public void freezeRotation(int rotation) {
public void freezeRotation(int displayId, int rotation) {
try {
Method method = getFreezeRotationMethod();
method.invoke(manager, rotation);
try {
Method method = getFreezeDisplayRotationMethod();
method.invoke(manager, displayId, rotation);
} catch (ReflectiveOperationException e) {
if (displayId == 0) {
Method method = getFreezeRotationMethod();
method.invoke(manager, rotation);
} else {
Ln.e("Could not invoke method", e);
}
}
} catch (ReflectiveOperationException e) {
Ln.e("Could not invoke method", e);
}
}

public boolean isRotationFrozen() {
public boolean isRotationFrozen(int displayId) {
try {
Method method = getIsRotationFrozenMethod();
return (boolean) method.invoke(manager);
try {
Method method = getIsDisplayRotationFrozenMethod();
return (boolean) method.invoke(manager, displayId);
} catch (ReflectiveOperationException e) {
if (displayId == 0) {
Method method = getIsRotationFrozenMethod();
return (boolean) method.invoke(manager);
} else {
Ln.e("Could not invoke method", e);
return false;
}
}
} catch (ReflectiveOperationException e) {
Ln.e("Could not invoke method", e);
return false;
}
}

public void thawRotation() {
public void thawRotation(int displayId) {
try {
Method method = getThawRotationMethod();
method.invoke(manager);
try {
Method method = getThawDisplayRotationMethod();
method.invoke(manager, displayId);
} catch (ReflectiveOperationException e) {
if (displayId == 0) {
Method method = getThawRotationMethod();
method.invoke(manager);
} else {
Ln.e("Could not invoke method", e);
}
}
} catch (ReflectiveOperationException e) {
Ln.e("Could not invoke method", e);
}
Expand Down

0 comments on commit d894e27

Please sign in to comment.