mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-07-18 06:51:44 +00:00
Sets the policy for how the display should show IME.
Possible values are "local", "fallback_display" and "hide".
This commit is contained in:
parent
c27d116a66
commit
b37aa747e2
15 changed files with 223 additions and 9 deletions
|
@ -23,6 +23,7 @@ _scrcpy() {
|
||||||
-d --select-usb
|
-d --select-usb
|
||||||
--disable-screensaver
|
--disable-screensaver
|
||||||
--display-id=
|
--display-id=
|
||||||
|
--display-ime-policy=
|
||||||
--display-orientation=
|
--display-orientation=
|
||||||
-e --select-tcpip
|
-e --select-tcpip
|
||||||
-f --fullscreen
|
-f --fullscreen
|
||||||
|
@ -148,6 +149,10 @@ _scrcpy() {
|
||||||
COMPREPLY=($(compgen -W '0 90 180 270 flip0 flip90 flip180 flip270' -- "$cur"))
|
COMPREPLY=($(compgen -W '0 90 180 270 flip0 flip90 flip180 flip270' -- "$cur"))
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
|
--display-ime-policy)
|
||||||
|
COMPREPLY=($(compgen -W 'local fallback_display hide' -- "$cur"))
|
||||||
|
return
|
||||||
|
;;
|
||||||
--record-orientation)
|
--record-orientation)
|
||||||
COMPREPLY=($(compgen -W '0 90 180 270' -- "$cur"))
|
COMPREPLY=($(compgen -W '0 90 180 270' -- "$cur"))
|
||||||
return
|
return
|
||||||
|
|
|
@ -30,6 +30,7 @@ arguments=(
|
||||||
{-d,--select-usb}'[Use USB device]'
|
{-d,--select-usb}'[Use USB device]'
|
||||||
'--disable-screensaver[Disable screensaver while scrcpy is running]'
|
'--disable-screensaver[Disable screensaver while scrcpy is running]'
|
||||||
'--display-id=[Specify the display id to mirror]'
|
'--display-id=[Specify the display id to mirror]'
|
||||||
|
'--display-ime-policy=[Sets the policy for how the display should show IME]'
|
||||||
'--display-orientation=[Set the initial display orientation]:orientation values:(0 90 180 270 flip0 flip90 flip180 flip270)'
|
'--display-orientation=[Set the initial display orientation]:orientation values:(0 90 180 270 flip0 flip90 flip180 flip270)'
|
||||||
{-e,--select-tcpip}'[Use TCP/IP device]'
|
{-e,--select-tcpip}'[Use TCP/IP device]'
|
||||||
{-f,--fullscreen}'[Start in fullscreen]'
|
{-f,--fullscreen}'[Start in fullscreen]'
|
||||||
|
|
10
app/scrcpy.1
10
app/scrcpy.1
|
@ -169,6 +169,16 @@ Possible values are 0, 90, 180, 270, flip0, flip90, flip180 and flip270. The num
|
||||||
|
|
||||||
Default is 0.
|
Default is 0.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "\-\-display\-ime-policy " value
|
||||||
|
Sets the policy for how the display should show IME.
|
||||||
|
|
||||||
|
Possible values are "local", "fallback_display" and "hide".
|
||||||
|
|
||||||
|
- The "local" policy means that the IME should appear on the local display.
|
||||||
|
- The "fallback_display" policy means that the IME should appear on a fallback display. The fallback display is always DEFAULT DISPLAY.
|
||||||
|
- The "hide" policy means that the IME should be hidden.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-e, \-\-select\-tcpip
|
.B \-e, \-\-select\-tcpip
|
||||||
Use TCP/IP device (if there is exactly one, like adb -e).
|
Use TCP/IP device (if there is exactly one, like adb -e).
|
||||||
|
|
|
@ -94,6 +94,7 @@ enum {
|
||||||
OPT_CAMERA_FPS,
|
OPT_CAMERA_FPS,
|
||||||
OPT_CAMERA_HIGH_SPEED,
|
OPT_CAMERA_HIGH_SPEED,
|
||||||
OPT_DISPLAY_ORIENTATION,
|
OPT_DISPLAY_ORIENTATION,
|
||||||
|
OPT_DISPLAY_IME_POLICY,
|
||||||
OPT_RECORD_ORIENTATION,
|
OPT_RECORD_ORIENTATION,
|
||||||
OPT_ORIENTATION,
|
OPT_ORIENTATION,
|
||||||
OPT_KEYBOARD,
|
OPT_KEYBOARD,
|
||||||
|
@ -366,6 +367,20 @@ static const struct sc_option options[] = {
|
||||||
" scrcpy --list-displays\n"
|
" scrcpy --list-displays\n"
|
||||||
"Default is 0.",
|
"Default is 0.",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.longopt_id = OPT_DISPLAY_IME_POLICY,
|
||||||
|
.longopt = "display-ime-policy",
|
||||||
|
.argdesc = "value",
|
||||||
|
.text = "Sets the policy for how the display should show IME.\n"
|
||||||
|
"Possible values are \"local\", \"fallback_display\" and "
|
||||||
|
"\"hide\".\n"
|
||||||
|
"The \"local\" policy means that the IME should appear on the "
|
||||||
|
"local display.\n"
|
||||||
|
"The \"fallback_display\" policy means that the IME should "
|
||||||
|
"appear on a fallback display. The fallback display is always "
|
||||||
|
"DEFAULT DISPLAY.\n"
|
||||||
|
"The \"hide\" policy means that the IME should be hidden.\n",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.longopt_id = OPT_DISPLAY_ORIENTATION,
|
.longopt_id = OPT_DISPLAY_ORIENTATION,
|
||||||
.longopt = "display-orientation",
|
.longopt = "display-orientation",
|
||||||
|
@ -1615,6 +1630,24 @@ parse_audio_output_buffer(const char *s, sc_tick *tick) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_display_ime_policy(const char *optarg, enum sc_display_ime_policy *policy) {
|
||||||
|
if (!strcmp(optarg, "local")) {
|
||||||
|
*policy = SC_DISPLAY_IME_POLICY_LOCAL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!strcmp(optarg, "fallback_display")) {
|
||||||
|
*policy = SC_DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!strcmp(optarg, "hide")) {
|
||||||
|
*policy = SC_DISPLAY_IME_POLICY_HIDE;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LOGE("Unsupported display IME policy: %s (expected local, fallback_display, hide)", optarg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
parse_orientation(const char *s, enum sc_orientation *orientation) {
|
parse_orientation(const char *s, enum sc_orientation *orientation) {
|
||||||
if (!strcmp(s, "0")) {
|
if (!strcmp(s, "0")) {
|
||||||
|
@ -2723,6 +2756,11 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||||
case OPT_NO_VD_SYSTEM_DECORATIONS:
|
case OPT_NO_VD_SYSTEM_DECORATIONS:
|
||||||
opts->vd_system_decorations = false;
|
opts->vd_system_decorations = false;
|
||||||
break;
|
break;
|
||||||
|
case OPT_DISPLAY_IME_POLICY:
|
||||||
|
if (!parse_display_ime_policy(optarg, &opts->display_ime_policy)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// getopt prints the error message on stderr
|
// getopt prints the error message on stderr
|
||||||
return false;
|
return false;
|
||||||
|
@ -2978,6 +3016,11 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts->display_ime_policy != SC_DISPLAY_IME_POLICY_UNDEFINDED) {
|
||||||
|
LOGE("--display-ime_policy is only available with --video-source=display");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (opts->camera_id && opts->camera_facing != SC_CAMERA_FACING_ANY) {
|
if (opts->camera_id && opts->camera_facing != SC_CAMERA_FACING_ANY) {
|
||||||
LOGE("Cannot specify both --camera-id and --camera-facing");
|
LOGE("Cannot specify both --camera-id and --camera-facing");
|
||||||
return false;
|
return false;
|
||||||
|
@ -3014,10 +3057,18 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts->display_id != 0 && opts->new_display) {
|
if (opts->display_id != 0) {
|
||||||
|
if (opts->new_display) {
|
||||||
LOGE("Cannot specify both --display-id and --new-display");
|
LOGE("Cannot specify both --display-id and --new-display");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!opts->new_display
|
||||||
|
&& opts->display_ime_policy != SC_DISPLAY_IME_POLICY_UNDEFINDED) {
|
||||||
|
LOGE("--display-ime-policy not supported if display_id == 0 and new_display == NULL");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (opts->audio && opts->audio_source == SC_AUDIO_SOURCE_AUTO) {
|
if (opts->audio && opts->audio_source == SC_AUDIO_SOURCE_AUTO) {
|
||||||
// Select the audio source according to the video source
|
// Select the audio source according to the video source
|
||||||
|
@ -3200,6 +3251,10 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||||
LOGE("OTG mode: could not select display");
|
LOGE("OTG mode: could not select display");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (opts->display_ime_policy != SC_DISPLAY_IME_POLICY_UNDEFINDED) {
|
||||||
|
LOGE("OTG mode: could not set the policy for how the display should show IME.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (v4l2) {
|
if (v4l2) {
|
||||||
LOGE("OTG mode: could not sink to V4L2 device");
|
LOGE("OTG mode: could not sink to V4L2 device");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -109,6 +109,7 @@ const struct scrcpy_options scrcpy_options_default = {
|
||||||
.audio_dup = false,
|
.audio_dup = false,
|
||||||
.new_display = NULL,
|
.new_display = NULL,
|
||||||
.start_app = NULL,
|
.start_app = NULL,
|
||||||
|
.display_ime_policy = SC_DISPLAY_IME_POLICY_UNDEFINDED,
|
||||||
.angle = NULL,
|
.angle = NULL,
|
||||||
.vd_destroy_content = true,
|
.vd_destroy_content = true,
|
||||||
.vd_system_decorations = true,
|
.vd_system_decorations = true,
|
||||||
|
|
|
@ -83,6 +83,13 @@ enum sc_orientation { // v v v
|
||||||
SC_ORIENTATION_FLIP_270, // 1 1 1
|
SC_ORIENTATION_FLIP_270, // 1 1 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum sc_display_ime_policy {
|
||||||
|
SC_DISPLAY_IME_POLICY_UNDEFINDED = -1,
|
||||||
|
SC_DISPLAY_IME_POLICY_LOCAL,
|
||||||
|
SC_DISPLAY_IME_POLICY_FALLBACK_DISPLAY,
|
||||||
|
SC_DISPLAY_IME_POLICY_HIDE,
|
||||||
|
};
|
||||||
|
|
||||||
enum sc_orientation_lock {
|
enum sc_orientation_lock {
|
||||||
SC_ORIENTATION_UNLOCKED,
|
SC_ORIENTATION_UNLOCKED,
|
||||||
SC_ORIENTATION_LOCKED_VALUE, // lock to specified orientation
|
SC_ORIENTATION_LOCKED_VALUE, // lock to specified orientation
|
||||||
|
@ -309,6 +316,7 @@ struct scrcpy_options {
|
||||||
bool audio_dup;
|
bool audio_dup;
|
||||||
const char *new_display; // [<width>x<height>][/<dpi>] parsed by the server
|
const char *new_display; // [<width>x<height>][/<dpi>] parsed by the server
|
||||||
const char *start_app;
|
const char *start_app;
|
||||||
|
enum sc_display_ime_policy display_ime_policy;
|
||||||
bool vd_destroy_content;
|
bool vd_destroy_content;
|
||||||
bool vd_system_decorations;
|
bool vd_system_decorations;
|
||||||
};
|
};
|
||||||
|
|
|
@ -436,6 +436,7 @@ scrcpy(struct scrcpy_options *options) {
|
||||||
.control = options->control,
|
.control = options->control,
|
||||||
.display_id = options->display_id,
|
.display_id = options->display_id,
|
||||||
.new_display = options->new_display,
|
.new_display = options->new_display,
|
||||||
|
.display_ime_policy = options->display_ime_policy,
|
||||||
.video = options->video,
|
.video = options->video,
|
||||||
.audio = options->audio,
|
.audio = options->audio,
|
||||||
.audio_dup = options->audio_dup,
|
.audio_dup = options->audio_dup,
|
||||||
|
|
|
@ -376,6 +376,10 @@ execute_server(struct sc_server *server,
|
||||||
VALIDATE_STRING(params->new_display);
|
VALIDATE_STRING(params->new_display);
|
||||||
ADD_PARAM("new_display=%s", params->new_display);
|
ADD_PARAM("new_display=%s", params->new_display);
|
||||||
}
|
}
|
||||||
|
if (params->display_ime_policy != SC_DISPLAY_IME_POLICY_UNDEFINDED) {
|
||||||
|
assert(params->display_ime_policy >= 0);
|
||||||
|
ADD_PARAM("display_ime_policy=%" PRIu32, params->display_ime_policy);
|
||||||
|
}
|
||||||
if (!params->vd_destroy_content) {
|
if (!params->vd_destroy_content) {
|
||||||
ADD_PARAM("vd_destroy_content=false");
|
ADD_PARAM("vd_destroy_content=false");
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ struct sc_server_params {
|
||||||
bool control;
|
bool control;
|
||||||
uint32_t display_id;
|
uint32_t display_id;
|
||||||
const char *new_display;
|
const char *new_display;
|
||||||
|
enum sc_display_ime_policy display_ime_policy;
|
||||||
bool video;
|
bool video;
|
||||||
bool audio;
|
bool audio;
|
||||||
bool audio_dup;
|
bool audio_dup;
|
||||||
|
|
|
@ -61,3 +61,14 @@ To move them to the main display instead, use:
|
||||||
```
|
```
|
||||||
scrcpy --new-display --no-vd-destroy-content
|
scrcpy --new-display --no-vd-destroy-content
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Display IME policy
|
||||||
|
|
||||||
|
By default, virtual display's IME appears on the DEFAULT display.
|
||||||
|
|
||||||
|
TO appears 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.Ln;
|
||||||
import com.genymobile.scrcpy.util.Settings;
|
import com.genymobile.scrcpy.util.Settings;
|
||||||
import com.genymobile.scrcpy.util.SettingsException;
|
import com.genymobile.scrcpy.util.SettingsException;
|
||||||
|
import com.genymobile.scrcpy.wrappers.ServiceManager;
|
||||||
|
|
||||||
import android.os.BatteryManager;
|
import android.os.BatteryManager;
|
||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
|
@ -100,15 +101,27 @@ public final class CleanUp {
|
||||||
boolean powerOffScreen = options.getPowerOffScreenOnClose();
|
boolean powerOffScreen = options.getPowerOffScreenOnClose();
|
||||||
int displayId = options.getDisplayId();
|
int displayId = options.getDisplayId();
|
||||||
|
|
||||||
|
int restoreDisplayImePolicy = -1;
|
||||||
|
if (displayId > 0) {
|
||||||
|
int displayImePolicy = options.getDisplayImePolicy();
|
||||||
|
if (displayImePolicy != -1) {
|
||||||
|
int currentValue = ServiceManager.getWindowManager().getDisplayImePolicy(displayId);
|
||||||
|
if (currentValue != displayImePolicy) {
|
||||||
|
ServiceManager.getWindowManager().setDisplayImePolicy(displayId, displayImePolicy);
|
||||||
|
restoreDisplayImePolicy = currentValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
run(displayId, restoreStayOn, disableShowTouches, powerOffScreen, restoreScreenOffTimeout);
|
run(displayId, restoreStayOn, disableShowTouches, powerOffScreen, restoreScreenOffTimeout, restoreDisplayImePolicy);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Ln.e("Clean up I/O exception", e);
|
Ln.e("Clean up I/O exception", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void run(int displayId, int restoreStayOn, boolean disableShowTouches, boolean powerOffScreen, int restoreScreenOffTimeout)
|
private void run(int displayId, int restoreStayOn, boolean disableShowTouches, boolean powerOffScreen, int restoreScreenOffTimeout,
|
||||||
throws IOException {
|
int restoreDisplayImePolicy) throws IOException {
|
||||||
String[] cmd = {
|
String[] cmd = {
|
||||||
"app_process",
|
"app_process",
|
||||||
"/",
|
"/",
|
||||||
|
@ -118,6 +131,7 @@ public final class CleanUp {
|
||||||
String.valueOf(disableShowTouches),
|
String.valueOf(disableShowTouches),
|
||||||
String.valueOf(powerOffScreen),
|
String.valueOf(powerOffScreen),
|
||||||
String.valueOf(restoreScreenOffTimeout),
|
String.valueOf(restoreScreenOffTimeout),
|
||||||
|
String.valueOf(restoreDisplayImePolicy),
|
||||||
};
|
};
|
||||||
|
|
||||||
ProcessBuilder builder = new ProcessBuilder(cmd);
|
ProcessBuilder builder = new ProcessBuilder(cmd);
|
||||||
|
@ -178,6 +192,7 @@ public final class CleanUp {
|
||||||
boolean disableShowTouches = Boolean.parseBoolean(args[2]);
|
boolean disableShowTouches = Boolean.parseBoolean(args[2]);
|
||||||
boolean powerOffScreen = Boolean.parseBoolean(args[3]);
|
boolean powerOffScreen = Boolean.parseBoolean(args[3]);
|
||||||
int restoreScreenOffTimeout = Integer.parseInt(args[4]);
|
int restoreScreenOffTimeout = Integer.parseInt(args[4]);
|
||||||
|
int restoreDisplayImePolicy = Integer.parseInt(args[5]);
|
||||||
|
|
||||||
// Dynamic option
|
// Dynamic option
|
||||||
boolean restoreDisplayPower = false;
|
boolean restoreDisplayPower = false;
|
||||||
|
@ -223,6 +238,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
|
// Change the power of the main display when mirroring a virtual display
|
||||||
int targetDisplayId = displayId != Device.DISPLAY_ID_NONE ? displayId : 0;
|
int targetDisplayId = displayId != Device.DISPLAY_ID_NONE ? displayId : 0;
|
||||||
if (Device.isScreenOn(targetDisplayId)) {
|
if (Device.isScreenOn(targetDisplayId)) {
|
||||||
|
|
|
@ -48,6 +48,7 @@ public class Options {
|
||||||
private boolean showTouches;
|
private boolean showTouches;
|
||||||
private boolean stayAwake;
|
private boolean stayAwake;
|
||||||
private int screenOffTimeout = -1;
|
private int screenOffTimeout = -1;
|
||||||
|
private int displayImePolicy = -1;
|
||||||
private List<CodecOption> videoCodecOptions;
|
private List<CodecOption> videoCodecOptions;
|
||||||
private List<CodecOption> audioCodecOptions;
|
private List<CodecOption> audioCodecOptions;
|
||||||
|
|
||||||
|
@ -194,6 +195,10 @@ public class Options {
|
||||||
return audioCodecOptions;
|
return audioCodecOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getDisplayImePolicy() {
|
||||||
|
return displayImePolicy;
|
||||||
|
}
|
||||||
|
|
||||||
public String getVideoEncoder() {
|
public String getVideoEncoder() {
|
||||||
return videoEncoder;
|
return videoEncoder;
|
||||||
}
|
}
|
||||||
|
@ -381,6 +386,14 @@ public class Options {
|
||||||
case "display_id":
|
case "display_id":
|
||||||
options.displayId = Integer.parseInt(value);
|
options.displayId = Integer.parseInt(value);
|
||||||
break;
|
break;
|
||||||
|
case "display_ime_policy":
|
||||||
|
if (!value.isEmpty()) {
|
||||||
|
options.displayImePolicy = Integer.parseInt(value);
|
||||||
|
if (options.displayImePolicy == -1) {
|
||||||
|
throw new IllegalArgumentException("Invalid display IME policy: " + options.displayImePolicy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "show_touches":
|
case "show_touches":
|
||||||
options.showTouches = Boolean.parseBoolean(value);
|
options.showTouches = Boolean.parseBoolean(value);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -80,10 +80,16 @@ public final class Server {
|
||||||
throw new ConfigurationException("Camera mirroring is not supported");
|
throw new ConfigurationException("Camera mirroring is not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < AndroidVersions.API_29_ANDROID_10 && options.getNewDisplay() != null) {
|
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");
|
Ln.e("New virtual display is not supported before Android 10");
|
||||||
throw new ConfigurationException("New virtual display is not supported");
|
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;
|
CleanUp cleanUp = null;
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ public class NewDisplayCapture extends SurfaceCapture {
|
||||||
private Size mainDisplaySize;
|
private Size mainDisplaySize;
|
||||||
private int mainDisplayDpi;
|
private int mainDisplayDpi;
|
||||||
private int maxSize;
|
private int maxSize;
|
||||||
|
private int displayImePolicy;
|
||||||
private final Rect crop;
|
private final Rect crop;
|
||||||
private final boolean captureOrientationLocked;
|
private final boolean captureOrientationLocked;
|
||||||
private final Orientation captureOrientation;
|
private final Orientation captureOrientation;
|
||||||
|
@ -68,6 +69,7 @@ public class NewDisplayCapture extends SurfaceCapture {
|
||||||
this.newDisplay = options.getNewDisplay();
|
this.newDisplay = options.getNewDisplay();
|
||||||
assert newDisplay != null;
|
assert newDisplay != null;
|
||||||
this.maxSize = options.getMaxSize();
|
this.maxSize = options.getMaxSize();
|
||||||
|
this.displayImePolicy = options.getDisplayImePolicy();
|
||||||
this.crop = options.getCrop();
|
this.crop = options.getCrop();
|
||||||
assert options.getCaptureOrientationLock() != null;
|
assert options.getCaptureOrientationLock() != null;
|
||||||
this.captureOrientationLocked = options.getCaptureOrientationLock() != Orientation.Lock.Unlocked;
|
this.captureOrientationLocked = options.getCaptureOrientationLock() != Orientation.Lock.Unlocked;
|
||||||
|
@ -191,6 +193,10 @@ public class NewDisplayCapture extends SurfaceCapture {
|
||||||
virtualDisplayId = virtualDisplay.getDisplay().getDisplayId();
|
virtualDisplayId = virtualDisplay.getDisplay().getDisplayId();
|
||||||
Ln.i("New display: " + displaySize.getWidth() + "x" + displaySize.getHeight() + "/" + dpi + " (id=" + virtualDisplayId + ")");
|
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);
|
displaySizeMonitor.start(virtualDisplayId, this::invalidate);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Ln.e("Could not create display", e);
|
Ln.e("Could not create display", e);
|
||||||
|
|
|
@ -10,6 +10,11 @@ import android.view.IDisplayWindowListener;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
public final class WindowManager {
|
public final class WindowManager {
|
||||||
|
// see https://android.googlesource.com/platform/frameworks/base.git/+/refs/heads/main/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 final IInterface manager;
|
||||||
private Method getRotationMethod;
|
private Method getRotationMethod;
|
||||||
|
|
||||||
|
@ -22,6 +27,13 @@ public final class WindowManager {
|
||||||
private Method thawDisplayRotationMethod;
|
private Method thawDisplayRotationMethod;
|
||||||
private int thawDisplayRotationMethodVersion;
|
private int thawDisplayRotationMethodVersion;
|
||||||
|
|
||||||
|
private Method getDisplayImePolicyMethod;
|
||||||
|
private boolean getDisplayImePolicyMethodNewVersion = true;
|
||||||
|
|
||||||
|
private Method setDisplayImePolicyMethod;
|
||||||
|
private boolean setDisplayImePolicyMethodNewVersion = true;
|
||||||
|
|
||||||
|
|
||||||
static WindowManager create() {
|
static WindowManager create() {
|
||||||
IInterface manager = ServiceManager.getService("window", "android.view.IWindowManager");
|
IInterface manager = ServiceManager.getService("window", "android.view.IWindowManager");
|
||||||
return new WindowManager(manager);
|
return new WindowManager(manager);
|
||||||
|
@ -198,4 +210,64 @@ public final class WindowManager {
|
||||||
Ln.e("Could not unregister display window listener", e);
|
Ln.e("Could not unregister display window listener", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TargetApi(AndroidVersions.API_29_ANDROID_10)
|
||||||
|
private Method getGetDisplayImePolicyMethod() throws NoSuchMethodException {
|
||||||
|
if (getDisplayImePolicyMethod == null) {
|
||||||
|
try {
|
||||||
|
getDisplayImePolicyMethod = manager.getClass().getMethod("getDisplayImePolicy", int.class);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
getDisplayImePolicyMethod = manager.getClass().getMethod("shouldShowIme", int.class);
|
||||||
|
getDisplayImePolicyMethodNewVersion = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getDisplayImePolicyMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(AndroidVersions.API_29_ANDROID_10)
|
||||||
|
public int getDisplayImePolicy(int displayId) {
|
||||||
|
try {
|
||||||
|
Method method = getGetDisplayImePolicyMethod();
|
||||||
|
if (getDisplayImePolicyMethodNewVersion) {
|
||||||
|
return (int) method.invoke(manager, displayId);
|
||||||
|
} else {
|
||||||
|
boolean shouldShow = (boolean) method.invoke(manager, displayId);
|
||||||
|
return shouldShow ? DISPLAY_IME_POLICY_LOCAL : DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
|
||||||
|
}
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
Ln.e("Could not invoke method", e);
|
||||||
|
return DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(AndroidVersions.API_29_ANDROID_10)
|
||||||
|
private Method getSetDisplayImePolicyMethod() throws NoSuchMethodException {
|
||||||
|
if (setDisplayImePolicyMethod == null) {
|
||||||
|
try {
|
||||||
|
setDisplayImePolicyMethod = manager.getClass().getMethod("setDisplayImePolicy", int.class, int.class);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
setDisplayImePolicyMethod = manager.getClass().getMethod("setShouldShowIme", int.class, boolean.class);
|
||||||
|
setDisplayImePolicyMethodNewVersion = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return setDisplayImePolicyMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(AndroidVersions.API_29_ANDROID_10)
|
||||||
|
public void setDisplayImePolicy(int displayId, int imePolicy) {
|
||||||
|
try {
|
||||||
|
Method method = getSetDisplayImePolicyMethod();
|
||||||
|
if (setDisplayImePolicyMethodNewVersion) {
|
||||||
|
method.invoke(manager, displayId, imePolicy);
|
||||||
|
} else {
|
||||||
|
if (imePolicy != DISPLAY_IME_POLICY_HIDE) {
|
||||||
|
method.invoke(manager, displayId, imePolicy == DISPLAY_IME_POLICY_LOCAL);
|
||||||
|
} else {
|
||||||
|
Ln.w("DISPLAY_IME_POLICY_HIDE not supported on this device");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
Ln.e("Could not invoke method", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue