Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restart capture when screen resolution changes #4469

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why notifying fold changed? (btw, in theory, the size might change but folded might remain true)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot to add a new event.

If Device.RotationListener, Device.FoldListener and this new listener all do the same thing, maybe merge into one is enough?

}
}
}, 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,11 @@
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.regex.Matcher;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -94,4 +96,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);
}
}