Skip to content

Commit

Permalink
Restart capture when screen resolution changes
Browse files Browse the repository at this point in the history
  • Loading branch information
yume-chan committed Nov 27, 2023
1 parent 4135c41 commit a1869de
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 2 deletions.
38 changes: 36 additions & 2 deletions server/src/main/java/com/genymobile/scrcpy/Device.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.genymobile.scrcpy.wrappers.ClipboardManager;
import com.genymobile.scrcpy.wrappers.DisplayControl;
import com.genymobile.scrcpy.wrappers.DisplayManager;
import com.genymobile.scrcpy.wrappers.InputManager;
import com.genymobile.scrcpy.wrappers.ServiceManager;
import com.genymobile.scrcpy.wrappers.SurfaceControl;
Expand All @@ -10,6 +11,8 @@
import android.content.IOnPrimaryClipChangedListener;
import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.SystemClock;
import android.view.IDisplayFoldListener;
Expand Down Expand Up @@ -45,11 +48,11 @@ public interface ClipboardListener {
void onClipboardTextChanged(String text);
}

private final Size deviceSize;
private final Rect crop;
private int maxSize;
private final int lockVideoOrientation;

private Size deviceSize;
private ScreenInfo screenInfo;
private RotationListener rotationListener;
private FoldListener foldListener;
Expand Down Expand Up @@ -78,14 +81,45 @@ public Device(Options options) throws ConfigurationException {

int displayInfoFlags = displayInfo.getFlags();

deviceSize = displayInfo.getSize();
crop = options.getCrop();
maxSize = options.getMaxSize();
lockVideoOrientation = options.getLockVideoOrientation();

deviceSize = displayInfo.getSize();
screenInfo = ScreenInfo.computeScreenInfo(displayInfo.getRotation(), deviceSize, crop, maxSize, lockVideoOrientation);
layerStack = displayInfo.getLayerStack();

HandlerThread displayListenerThread = new HandlerThread("DisplayListenerThread");
displayListenerThread.start();

Handler displayListenerHandler = new Handler(displayListenerThread.getLooper());
ServiceManager.getDisplayManager().registerDisplayListener(new DisplayManager.DisplayListener() {
@Override
public void onDisplayAdded(int displayId) {
// nothing to do
}

@Override
public void onDisplayRemoved(int displayId) {
// nothing to do
}

@Override
public void onDisplayChanged(int displayId) {
if (Device.this.displayId != displayId) {
return;
}

DisplayInfo displayInfo = ServiceManager.getDisplayManager().getDisplayInfo(displayId);
deviceSize = displayInfo.getSize();
screenInfo = ScreenInfo.computeScreenInfo(displayInfo.getRotation(), deviceSize, crop, maxSize, lockVideoOrientation);

if (foldListener != null) {
foldListener.onFoldChanged(displayId, false);
}
}
}, displayListenerHandler);

ServiceManager.getWindowManager().registerRotationWatcher(new IRotationWatcher.Stub() {
@Override
public void onRotationChanged(int rotation) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
import com.genymobile.scrcpy.Ln;
import com.genymobile.scrcpy.Size;

import android.os.Handler;
import android.view.Display;

import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.WeakHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -94,4 +97,61 @@ public int[] getDisplayIds() {
throw new AssertionError(e);
}
}

public void registerDisplayListener(DisplayListener listener, Handler handler) {
try {
Class<?> displayListenerClass = Class.forName("android.hardware.display.DisplayManager$DisplayListener");
Object displayListenerProxy = Proxy.newProxyInstance(
ClassLoader.getSystemClassLoader(),
new Class[]{ displayListenerClass },
(proxy, method, args) -> {
switch (method.getName()) {
case "onDisplayAdded":
listener.onDisplayAdded((int) args[0]);
break;
case "onDisplayRemoved":
listener.onDisplayRemoved((int) args[0]);
break;
case "onDisplayChanged":
listener.onDisplayChanged((int) args[0]);
break;
default:
throw new AssertionError("Unexpected method: " + method.getName());
}
return null;
});
manager
.getClass()
.getMethod("registerDisplayListener", displayListenerClass, Handler.class)
.invoke(manager, displayListenerProxy, handler);
} catch (Exception e) {
throw new AssertionError(e);
}
}

public interface DisplayListener {
/**
* Called whenever a logical display has been added to the system.
* Use {@link DisplayManager#getDisplay} to get more information about
* the display.
*
* @param displayId The id of the logical display that was added.
*/
void onDisplayAdded(int displayId);

/**
* Called whenever a logical display has been removed from the system.
*
* @param displayId The id of the logical display that was removed.
*/
void onDisplayRemoved(int displayId);

/**
* Called whenever the properties of a logical {@link android.view.Display},
* such as size and density, have changed.
*
* @param displayId The id of the logical display that changed.
*/
void onDisplayChanged(int displayId);
}
}

0 comments on commit a1869de

Please sign in to comment.