mirror of
https://github.com/Genymobile/scrcpy
synced 2025-02-23 16:06:50 +00: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:
parent
986328ff9e
commit
fd8bef68b7
@ -23,6 +23,7 @@ _scrcpy() {
|
||||
-d --select-usb
|
||||
--disable-screensaver
|
||||
--display-id=
|
||||
--display-ime-policy=
|
||||
--display-orientation=
|
||||
-e --select-tcpip
|
||||
-f --fullscreen
|
||||
@ -148,6 +149,10 @@ _scrcpy() {
|
||||
COMPREPLY=($(compgen -W '0 90 180 270 flip0 flip90 flip180 flip270' -- "$cur"))
|
||||
return
|
||||
;;
|
||||
--display-ime-policy)
|
||||
COMPREPLY=($(compgen -W 'local fallback hide' -- "$cur"))
|
||||
return
|
||||
;;
|
||||
--record-orientation)
|
||||
COMPREPLY=($(compgen -W '0 90 180 270' -- "$cur"))
|
||||
return
|
||||
|
@ -30,6 +30,7 @@ arguments=(
|
||||
{-d,--select-usb}'[Use USB device]'
|
||||
'--disable-screensaver[Disable screensaver while scrcpy is running]'
|
||||
'--display-id=[Specify the display id to mirror]'
|
||||
'--display-ime-policy[Set the policy for selecting where the IME should be displayed]'
|
||||
'--display-orientation=[Set the initial display orientation]:orientation values:(0 90 180 270 flip0 flip90 flip180 flip270)'
|
||||
{-e,--select-tcpip}'[Use TCP/IP device]'
|
||||
{-f,--fullscreen}'[Start in fullscreen]'
|
||||
|
13
app/scrcpy.1
13
app/scrcpy.1
@ -161,6 +161,19 @@ The available display ids can be listed by \fB\-\-list\-displays\fR.
|
||||
|
||||
Default is 0.
|
||||
|
||||
.TP
|
||||
.BI "\-\-display\-ime\-policy " value
|
||||
Set the policy for selecting where the IME should be displayed.
|
||||
|
||||
Possible values are "local", "fallback" and "hide":
|
||||
|
||||
- "local" means that the IME should appear on the local display.
|
||||
- "fallback" means that the IME should appear on a fallback display (the default display).
|
||||
- "hide" means that the IME should be hidden.
|
||||
|
||||
By default, the IME policy is left unchanged.
|
||||
|
||||
|
||||
.TP
|
||||
.BI "\-\-display\-orientation " value
|
||||
Set the initial display orientation.
|
||||
|
@ -113,6 +113,7 @@ enum {
|
||||
OPT_ANGLE,
|
||||
OPT_NO_VD_SYSTEM_DECORATIONS,
|
||||
OPT_NO_VD_DESTROY_CONTENT,
|
||||
OPT_DISPLAY_IME_POLICY,
|
||||
};
|
||||
|
||||
struct sc_option {
|
||||
@ -366,6 +367,19 @@ static const struct sc_option options[] = {
|
||||
" scrcpy --list-displays\n"
|
||||
"Default is 0.",
|
||||
},
|
||||
{
|
||||
.longopt_id = OPT_DISPLAY_IME_POLICY,
|
||||
.longopt = "display-ime-policy",
|
||||
.argdesc = "value",
|
||||
.text = "Set the policy for selecting where the IME should be "
|
||||
"displayed.\n"
|
||||
"Possible values are \"local\", \"fallback\" and \"hide\".\n"
|
||||
"\"local\" means that the IME should appear on the local "
|
||||
"display.\n"
|
||||
"\"fallback\" means that the IME should appear on a fallback "
|
||||
"display (the default display).\n"
|
||||
"\"hide\" means that the IME should be hidden.",
|
||||
},
|
||||
{
|
||||
.longopt_id = OPT_DISPLAY_ORIENTATION,
|
||||
.longopt = "display-orientation",
|
||||
@ -1614,6 +1628,25 @@ parse_audio_output_buffer(const char *s, sc_tick *tick) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_display_ime_policy(const char *s, enum sc_display_ime_policy *policy) {
|
||||
if (!strcmp(s, "local")) {
|
||||
*policy = SC_DISPLAY_IME_POLICY_LOCAL;
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(s, "fallback")) {
|
||||
*policy = SC_DISPLAY_IME_POLICY_FALLBACK;
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(s, "hide")) {
|
||||
*policy = SC_DISPLAY_IME_POLICY_HIDE;
|
||||
return true;
|
||||
}
|
||||
LOGE("Unsupported display IME policy: %s (expected local, fallback or "
|
||||
"hide)", s);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_orientation(const char *s, enum sc_orientation *orientation) {
|
||||
if (!strcmp(s, "0")) {
|
||||
@ -2722,6 +2755,12 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||
case OPT_NO_VD_SYSTEM_DECORATIONS:
|
||||
opts->vd_system_decorations = false;
|
||||
break;
|
||||
case OPT_DISPLAY_IME_POLICY:
|
||||
if (!parse_display_ime_policy(optarg,
|
||||
&opts->display_ime_policy)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// getopt prints the error message on stderr
|
||||
return false;
|
||||
@ -2978,6 +3017,12 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||
return false;
|
||||
}
|
||||
|
||||
if (opts->display_ime_policy != SC_DISPLAY_IME_POLICY_UNDEFINED) {
|
||||
LOGE("--display-ime-policy is only available with "
|
||||
"--video-source=display");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (opts->camera_id && opts->camera_facing != SC_CAMERA_FACING_ANY) {
|
||||
LOGE("Cannot specify both --camera-id and --camera-facing");
|
||||
return false;
|
||||
@ -3019,6 +3064,12 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||
return false;
|
||||
}
|
||||
|
||||
if (opts->display_ime_policy != SC_DISPLAY_IME_POLICY_UNDEFINED
|
||||
&& opts->display_id == 0 && !opts->new_display) {
|
||||
LOGE("--display-ime-policy is only supported on a secondary display");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (opts->audio && opts->audio_source == SC_AUDIO_SOURCE_AUTO) {
|
||||
// Select the audio source according to the video source
|
||||
if (opts->video_source == SC_VIDEO_SOURCE_DISPLAY) {
|
||||
|
@ -56,6 +56,7 @@ const struct scrcpy_options scrcpy_options_default = {
|
||||
.capture_orientation_lock = SC_ORIENTATION_UNLOCKED,
|
||||
.display_orientation = SC_ORIENTATION_0,
|
||||
.record_orientation = SC_ORIENTATION_0,
|
||||
.display_ime_policy = SC_DISPLAY_IME_POLICY_UNDEFINED,
|
||||
.window_x = SC_WINDOW_POSITION_UNDEFINED,
|
||||
.window_y = SC_WINDOW_POSITION_UNDEFINED,
|
||||
.window_width = 0,
|
||||
|
@ -89,6 +89,13 @@ enum sc_orientation_lock {
|
||||
SC_ORIENTATION_LOCKED_INITIAL, // lock to initial device orientation
|
||||
};
|
||||
|
||||
enum sc_display_ime_policy {
|
||||
SC_DISPLAY_IME_POLICY_UNDEFINED,
|
||||
SC_DISPLAY_IME_POLICY_LOCAL,
|
||||
SC_DISPLAY_IME_POLICY_FALLBACK,
|
||||
SC_DISPLAY_IME_POLICY_HIDE,
|
||||
};
|
||||
|
||||
static inline bool
|
||||
sc_orientation_is_mirror(enum sc_orientation orientation) {
|
||||
assert(!(orientation & ~7));
|
||||
@ -251,6 +258,7 @@ struct scrcpy_options {
|
||||
enum sc_orientation_lock capture_orientation_lock;
|
||||
enum sc_orientation display_orientation;
|
||||
enum sc_orientation record_orientation;
|
||||
enum sc_display_ime_policy display_ime_policy;
|
||||
int16_t window_x; // SC_WINDOW_POSITION_UNDEFINED for "auto"
|
||||
int16_t window_y; // SC_WINDOW_POSITION_UNDEFINED for "auto"
|
||||
uint16_t window_width;
|
||||
|
@ -436,6 +436,7 @@ scrcpy(struct scrcpy_options *options) {
|
||||
.control = options->control,
|
||||
.display_id = options->display_id,
|
||||
.new_display = options->new_display,
|
||||
.display_ime_policy = options->display_ime_policy,
|
||||
.video = options->video,
|
||||
.audio = options->audio,
|
||||
.audio_dup = options->audio_dup,
|
||||
|
@ -155,6 +155,21 @@ sc_server_get_audio_source_name(enum sc_audio_source audio_source) {
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
sc_server_get_display_ime_policy_name(enum sc_display_ime_policy policy) {
|
||||
switch (policy) {
|
||||
case SC_DISPLAY_IME_POLICY_LOCAL:
|
||||
return "local";
|
||||
case SC_DISPLAY_IME_POLICY_FALLBACK:
|
||||
return "fallback";
|
||||
case SC_DISPLAY_IME_POLICY_HIDE:
|
||||
return "hide";
|
||||
default:
|
||||
assert(!"unexpected display IME policy");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_string(const char *s) {
|
||||
// The parameters values are passed as command line arguments to adb, so
|
||||
@ -376,6 +391,10 @@ execute_server(struct sc_server *server,
|
||||
VALIDATE_STRING(params->new_display);
|
||||
ADD_PARAM("new_display=%s", params->new_display);
|
||||
}
|
||||
if (params->display_ime_policy != SC_DISPLAY_IME_POLICY_UNDEFINED) {
|
||||
ADD_PARAM("display_ime_policy=%s",
|
||||
sc_server_get_display_ime_policy_name(params->display_ime_policy));
|
||||
}
|
||||
if (!params->vd_destroy_content) {
|
||||
ADD_PARAM("vd_destroy_content=false");
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ struct sc_server_params {
|
||||
bool control;
|
||||
uint32_t display_id;
|
||||
const char *new_display;
|
||||
enum sc_display_ime_policy display_ime_policy;
|
||||
bool video;
|
||||
bool audio;
|
||||
bool audio_dup;
|
||||
|
@ -61,3 +61,15 @@ To move them to the main display instead, use:
|
||||
```
|
||||
scrcpy --new-display --no-vd-destroy-content
|
||||
```
|
||||
|
||||
|
||||
## Display IME policy
|
||||
|
||||
By default, the virtual display IME appears on the default display.
|
||||
|
||||
To make it appear on the local display, use `--display-ime-policy=local`:
|
||||
|
||||
```bash
|
||||
scrcpy --display-id=1 --display-ime-policy=local
|
||||
scrcpy --new-display --display-ime-policy=local
|
||||
```
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user