mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-12-17 05:24:19 +01:00
Add --display-ime-policy option
Add an option to select where the IME should be displayed. Possible values are "local", "fallback" and "hide". PR #5703 <https://github.com/Genymobile/scrcpy/pull/5703> Signed-off-by: Romain Vimont <rom@rom1v.com>
This commit is contained in:
committed by
Romain Vimont
parent
986328ff9e
commit
fd8bef68b7
@@ -4,6 +4,7 @@ import com.genymobile.scrcpy.device.Device;
|
||||
import com.genymobile.scrcpy.util.Ln;
|
||||
import com.genymobile.scrcpy.util.Settings;
|
||||
import com.genymobile.scrcpy.util.SettingsException;
|
||||
import com.genymobile.scrcpy.wrappers.ServiceManager;
|
||||
|
||||
import android.os.BatteryManager;
|
||||
import android.system.ErrnoException;
|
||||
@@ -97,18 +98,31 @@ public final class CleanUp {
|
||||
}
|
||||
}
|
||||
|
||||
boolean powerOffScreen = options.getPowerOffScreenOnClose();
|
||||
int displayId = options.getDisplayId();
|
||||
|
||||
int restoreDisplayImePolicy = -1;
|
||||
if (displayId > 0) {
|
||||
int displayImePolicy = options.getDisplayImePolicy();
|
||||
if (displayImePolicy != -1) {
|
||||
int currentDisplayImePolicy = ServiceManager.getWindowManager().getDisplayImePolicy(displayId);
|
||||
if (currentDisplayImePolicy != displayImePolicy) {
|
||||
ServiceManager.getWindowManager().setDisplayImePolicy(displayId, displayImePolicy);
|
||||
restoreDisplayImePolicy = currentDisplayImePolicy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean powerOffScreen = options.getPowerOffScreenOnClose();
|
||||
|
||||
try {
|
||||
run(displayId, restoreStayOn, disableShowTouches, powerOffScreen, restoreScreenOffTimeout);
|
||||
run(displayId, restoreStayOn, disableShowTouches, powerOffScreen, restoreScreenOffTimeout, restoreDisplayImePolicy);
|
||||
} catch (IOException e) {
|
||||
Ln.e("Clean up I/O exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void run(int displayId, int restoreStayOn, boolean disableShowTouches, boolean powerOffScreen, int restoreScreenOffTimeout)
|
||||
throws IOException {
|
||||
private void run(int displayId, int restoreStayOn, boolean disableShowTouches, boolean powerOffScreen, int restoreScreenOffTimeout,
|
||||
int restoreDisplayImePolicy) throws IOException {
|
||||
String[] cmd = {
|
||||
"app_process",
|
||||
"/",
|
||||
@@ -118,6 +132,7 @@ public final class CleanUp {
|
||||
String.valueOf(disableShowTouches),
|
||||
String.valueOf(powerOffScreen),
|
||||
String.valueOf(restoreScreenOffTimeout),
|
||||
String.valueOf(restoreDisplayImePolicy),
|
||||
};
|
||||
|
||||
ProcessBuilder builder = new ProcessBuilder(cmd);
|
||||
@@ -178,6 +193,7 @@ public final class CleanUp {
|
||||
boolean disableShowTouches = Boolean.parseBoolean(args[2]);
|
||||
boolean powerOffScreen = Boolean.parseBoolean(args[3]);
|
||||
int restoreScreenOffTimeout = Integer.parseInt(args[4]);
|
||||
int restoreDisplayImePolicy = Integer.parseInt(args[5]);
|
||||
|
||||
// Dynamic option
|
||||
boolean restoreDisplayPower = false;
|
||||
@@ -223,6 +239,11 @@ public final class CleanUp {
|
||||
}
|
||||
}
|
||||
|
||||
if (restoreDisplayImePolicy != -1) {
|
||||
Ln.i("Restoring \"display IME policy\"");
|
||||
ServiceManager.getWindowManager().setDisplayImePolicy(displayId, restoreDisplayImePolicy);
|
||||
}
|
||||
|
||||
// Change the power of the main display when mirroring a virtual display
|
||||
int targetDisplayId = displayId != Device.DISPLAY_ID_NONE ? displayId : 0;
|
||||
if (Device.isScreenOn(targetDisplayId)) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.genymobile.scrcpy.video.CameraAspectRatio;
|
||||
import com.genymobile.scrcpy.video.CameraFacing;
|
||||
import com.genymobile.scrcpy.video.VideoCodec;
|
||||
import com.genymobile.scrcpy.video.VideoSource;
|
||||
import com.genymobile.scrcpy.wrappers.WindowManager;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.util.Pair;
|
||||
@@ -48,6 +49,7 @@ public class Options {
|
||||
private boolean showTouches;
|
||||
private boolean stayAwake;
|
||||
private int screenOffTimeout = -1;
|
||||
private int displayImePolicy = -1;
|
||||
private List<CodecOption> videoCodecOptions;
|
||||
private List<CodecOption> audioCodecOptions;
|
||||
|
||||
@@ -186,6 +188,10 @@ public class Options {
|
||||
return screenOffTimeout;
|
||||
}
|
||||
|
||||
public int getDisplayImePolicy() {
|
||||
return displayImePolicy;
|
||||
}
|
||||
|
||||
public List<CodecOption> getVideoCodecOptions() {
|
||||
return videoCodecOptions;
|
||||
}
|
||||
@@ -482,6 +488,9 @@ public class Options {
|
||||
options.captureOrientationLock = pair.first;
|
||||
options.captureOrientation = pair.second;
|
||||
break;
|
||||
case "display_ime_policy":
|
||||
options.displayImePolicy = parseDisplayImePolicy(value);
|
||||
break;
|
||||
case "send_device_meta":
|
||||
options.sendDeviceMeta = Boolean.parseBoolean(value);
|
||||
break;
|
||||
@@ -626,4 +635,17 @@ public class Options {
|
||||
|
||||
return Pair.create(lock, Orientation.getByName(value));
|
||||
}
|
||||
|
||||
private static int parseDisplayImePolicy(String value) {
|
||||
switch (value) {
|
||||
case "local":
|
||||
return WindowManager.DISPLAY_IME_POLICY_LOCAL;
|
||||
case "fallback":
|
||||
return WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
|
||||
case "hide":
|
||||
return WindowManager.DISPLAY_IME_POLICY_HIDE;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid display IME policy: " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,9 +80,15 @@ public final class Server {
|
||||
throw new ConfigurationException("Camera mirroring is not supported");
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < AndroidVersions.API_29_ANDROID_10 && options.getNewDisplay() != null) {
|
||||
Ln.e("New virtual display is not supported before Android 10");
|
||||
throw new ConfigurationException("New virtual display is not supported");
|
||||
if (Build.VERSION.SDK_INT < AndroidVersions.API_29_ANDROID_10) {
|
||||
if (options.getNewDisplay() != null) {
|
||||
Ln.e("New virtual display is not supported before Android 10");
|
||||
throw new ConfigurationException("New virtual display is not supported");
|
||||
}
|
||||
if (options.getDisplayImePolicy() != -1) {
|
||||
Ln.e("Display IME policy is not supported before Android 10");
|
||||
throw new ConfigurationException("Display IME policy is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
CleanUp cleanUp = null;
|
||||
|
||||
@@ -49,6 +49,7 @@ public class NewDisplayCapture extends SurfaceCapture {
|
||||
private Size mainDisplaySize;
|
||||
private int mainDisplayDpi;
|
||||
private int maxSize;
|
||||
private int displayImePolicy;
|
||||
private final Rect crop;
|
||||
private final boolean captureOrientationLocked;
|
||||
private final Orientation captureOrientation;
|
||||
@@ -68,6 +69,7 @@ public class NewDisplayCapture extends SurfaceCapture {
|
||||
this.newDisplay = options.getNewDisplay();
|
||||
assert newDisplay != null;
|
||||
this.maxSize = options.getMaxSize();
|
||||
this.displayImePolicy = options.getDisplayImePolicy();
|
||||
this.crop = options.getCrop();
|
||||
assert options.getCaptureOrientationLock() != null;
|
||||
this.captureOrientationLocked = options.getCaptureOrientationLock() != Orientation.Lock.Unlocked;
|
||||
@@ -191,6 +193,10 @@ public class NewDisplayCapture extends SurfaceCapture {
|
||||
virtualDisplayId = virtualDisplay.getDisplay().getDisplayId();
|
||||
Ln.i("New display: " + displaySize.getWidth() + "x" + displaySize.getHeight() + "/" + dpi + " (id=" + virtualDisplayId + ")");
|
||||
|
||||
if (displayImePolicy != -1) {
|
||||
ServiceManager.getWindowManager().setDisplayImePolicy(virtualDisplayId, displayImePolicy);
|
||||
}
|
||||
|
||||
displaySizeMonitor.start(virtualDisplayId, this::invalidate);
|
||||
} catch (Exception e) {
|
||||
Ln.e("Could not create display", e);
|
||||
|
||||
@@ -4,12 +4,19 @@ import com.genymobile.scrcpy.AndroidVersions;
|
||||
import com.genymobile.scrcpy.util.Ln;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
import android.os.IInterface;
|
||||
import android.view.IDisplayWindowListener;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public final class WindowManager {
|
||||
|
||||
// <https://android.googlesource.com/platform/frameworks/base.git/+/2103ff441c66772c80c8560e322dcd9a45be7dcd/core/java/android/view/WindowManager.java#692>
|
||||
public static final int DISPLAY_IME_POLICY_LOCAL = 0;
|
||||
public static final int DISPLAY_IME_POLICY_FALLBACK_DISPLAY = 1;
|
||||
public static final int DISPLAY_IME_POLICY_HIDE = 2;
|
||||
|
||||
private final IInterface manager;
|
||||
private Method getRotationMethod;
|
||||
|
||||
@@ -22,6 +29,9 @@ public final class WindowManager {
|
||||
private Method thawDisplayRotationMethod;
|
||||
private int thawDisplayRotationMethodVersion;
|
||||
|
||||
private Method getDisplayImePolicyMethod;
|
||||
private Method setDisplayImePolicyMethod;
|
||||
|
||||
static WindowManager create() {
|
||||
IInterface manager = ServiceManager.getService("window", "android.view.IWindowManager");
|
||||
return new WindowManager(manager);
|
||||
@@ -198,4 +208,59 @@ public final class WindowManager {
|
||||
Ln.e("Could not unregister display window listener", e);
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(AndroidVersions.API_29_ANDROID_10)
|
||||
private Method getGetDisplayImePolicyMethod() throws NoSuchMethodException {
|
||||
if (getDisplayImePolicyMethod == null) {
|
||||
if (Build.VERSION.SDK_INT >= AndroidVersions.API_31_ANDROID_12) {
|
||||
getDisplayImePolicyMethod = manager.getClass().getMethod("getDisplayImePolicy", int.class);
|
||||
} else {
|
||||
getDisplayImePolicyMethod = manager.getClass().getMethod("shouldShowIme", int.class);
|
||||
}
|
||||
}
|
||||
return getDisplayImePolicyMethod;
|
||||
}
|
||||
|
||||
@TargetApi(AndroidVersions.API_29_ANDROID_10)
|
||||
public int getDisplayImePolicy(int displayId) {
|
||||
try {
|
||||
Method method = getGetDisplayImePolicyMethod();
|
||||
if (Build.VERSION.SDK_INT >= AndroidVersions.API_31_ANDROID_12) {
|
||||
return (int) method.invoke(manager, displayId);
|
||||
}
|
||||
boolean shouldShowIme = (boolean) method.invoke(manager, displayId);
|
||||
return shouldShowIme ? DISPLAY_IME_POLICY_LOCAL : DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
|
||||
} catch (ReflectiveOperationException e) {
|
||||
Ln.e("Could not invoke method", e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(AndroidVersions.API_29_ANDROID_10)
|
||||
private Method getSetDisplayImePolicyMethod() throws NoSuchMethodException {
|
||||
if (setDisplayImePolicyMethod == null) {
|
||||
if (Build.VERSION.SDK_INT >= AndroidVersions.API_31_ANDROID_12) {
|
||||
setDisplayImePolicyMethod = manager.getClass().getMethod("setDisplayImePolicy", int.class, int.class);
|
||||
} else {
|
||||
setDisplayImePolicyMethod = manager.getClass().getMethod("setShouldShowIme", int.class, boolean.class);
|
||||
}
|
||||
}
|
||||
return setDisplayImePolicyMethod;
|
||||
}
|
||||
|
||||
@TargetApi(AndroidVersions.API_29_ANDROID_10)
|
||||
public void setDisplayImePolicy(int displayId, int displayImePolicy) {
|
||||
try {
|
||||
Method method = getSetDisplayImePolicyMethod();
|
||||
if (Build.VERSION.SDK_INT >= AndroidVersions.API_31_ANDROID_12) {
|
||||
method.invoke(manager, displayId, displayImePolicy);
|
||||
} else if (displayImePolicy != DISPLAY_IME_POLICY_HIDE) {
|
||||
method.invoke(manager, displayId, displayImePolicy == DISPLAY_IME_POLICY_LOCAL);
|
||||
} else {
|
||||
Ln.w("DISPLAY_IME_POLICY_HIDE is not supported before Android 12");
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
Ln.e("Could not invoke method", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user