This commit is contained in:
P. Chen 2020-10-05 23:05:49 +02:00 committed by GitHub
commit 91cc10176b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 46 additions and 5 deletions

View file

@ -26,6 +26,11 @@ scrcpy_print_usage(const char *arg0) {
" Unit suffixes are supported: 'K' (x1000) and 'M' (x1000000).\n" " Unit suffixes are supported: 'K' (x1000) and 'M' (x1000000).\n"
" Default is %d.\n" " Default is %d.\n"
"\n" "\n"
" --char-inject-fallback\n"
" Fallback to the clipboard (copy and paste) when non-supported\n"
" non-ASCII characters are typed.\n"
" Would override the device clipboard content when it happens.\n"
"\n"
" --codec-options key[:type]=value[,...]\n" " --codec-options key[:type]=value[,...]\n"
" Set a list of comma-separated key:type=value options for the\n" " Set a list of comma-separated key:type=value options for the\n"
" device encoder.\n" " device encoder.\n"
@ -651,12 +656,15 @@ guess_record_format(const char *filename) {
#define OPT_DISABLE_SCREENSAVER 1020 #define OPT_DISABLE_SCREENSAVER 1020
#define OPT_SHORTCUT_MOD 1021 #define OPT_SHORTCUT_MOD 1021
#define OPT_NO_KEY_REPEAT 1022 #define OPT_NO_KEY_REPEAT 1022
#define OPT_CHAR_INJECT_FALLBACK 1023
bool bool
scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) { scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
static const struct option long_options[] = { static const struct option long_options[] = {
{"always-on-top", no_argument, NULL, OPT_ALWAYS_ON_TOP}, {"always-on-top", no_argument, NULL, OPT_ALWAYS_ON_TOP},
{"bit-rate", required_argument, NULL, 'b'}, {"bit-rate", required_argument, NULL, 'b'},
{"char-inject-fallback", no_argument, NULL,
OPT_CHAR_INJECT_FALLBACK},
{"codec-options", required_argument, NULL, OPT_CODEC_OPTIONS}, {"codec-options", required_argument, NULL, OPT_CODEC_OPTIONS},
{"crop", required_argument, NULL, OPT_CROP}, {"crop", required_argument, NULL, OPT_CROP},
{"disable-screensaver", no_argument, NULL, {"disable-screensaver", no_argument, NULL,
@ -719,6 +727,9 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
case OPT_CROP: case OPT_CROP:
opts->crop = optarg; opts->crop = optarg;
break; break;
case OPT_CHAR_INJECT_FALLBACK:
opts->char_inject_fallback = true;
break;
case OPT_DISPLAY_ID: case OPT_DISPLAY_ID:
if (!parse_display_id(optarg, &opts->display_id)) { if (!parse_display_id(optarg, &opts->display_id)) {
return false; return false;

View file

@ -313,6 +313,7 @@ scrcpy(const struct scrcpy_options *options) {
.bit_rate = options->bit_rate, .bit_rate = options->bit_rate,
.max_fps = options->max_fps, .max_fps = options->max_fps,
.lock_video_orientation = options->lock_video_orientation, .lock_video_orientation = options->lock_video_orientation,
.char_inject_fallback = options->char_inject_fallback,
.control = options->control, .control = options->control,
.display_id = options->display_id, .display_id = options->display_id,
.show_touches = options->show_touches, .show_touches = options->show_touches,

View file

@ -69,6 +69,7 @@ struct scrcpy_options {
bool fullscreen; bool fullscreen;
bool always_on_top; bool always_on_top;
bool control; bool control;
bool char_inject_fallback;
bool display; bool display;
bool turn_screen_off; bool turn_screen_off;
bool render_expired_frames; bool render_expired_frames;
@ -112,6 +113,7 @@ struct scrcpy_options {
.show_touches = false, \ .show_touches = false, \
.fullscreen = false, \ .fullscreen = false, \
.always_on_top = false, \ .always_on_top = false, \
.char_inject_fallback = false, \
.control = true, \ .control = true, \
.display = true, \ .display = true, \
.turn_screen_off = false, \ .turn_screen_off = false, \

View file

@ -294,6 +294,7 @@ execute_server(struct server *server, const struct server_params *params) {
params->show_touches ? "true" : "false", params->show_touches ? "true" : "false",
params->stay_awake ? "true" : "false", params->stay_awake ? "true" : "false",
params->codec_options ? params->codec_options : "-", params->codec_options ? params->codec_options : "-",
params->char_inject_fallback ? "true" : "false",
}; };
#ifdef SERVER_DEBUGGER #ifdef SERVER_DEBUGGER
LOGI("Server debugger waiting for a client on device port " LOGI("Server debugger waiting for a client on device port "

View file

@ -53,6 +53,7 @@ struct server_params {
uint32_t bit_rate; uint32_t bit_rate;
uint16_t max_fps; uint16_t max_fps;
int8_t lock_video_orientation; int8_t lock_video_orientation;
bool char_inject_fallback;
bool control; bool control;
uint16_t display_id; uint16_t display_id;
bool show_touches; bool show_touches;

View file

@ -21,6 +21,7 @@ public class Controller {
private final Device device; private final Device device;
private final DesktopConnection connection; private final DesktopConnection connection;
private final DeviceMessageSender sender; private final DeviceMessageSender sender;
private final boolean charInjectFallback;
private final KeyCharacterMap charMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); private final KeyCharacterMap charMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
@ -31,9 +32,10 @@ public class Controller {
private boolean keepPowerModeOff; private boolean keepPowerModeOff;
public Controller(Device device, DesktopConnection connection) { public Controller(Device device, DesktopConnection connection, boolean charInjectFallback) {
this.device = device; this.device = device;
this.connection = connection; this.connection = connection;
this.charInjectFallback = charInjectFallback;
initPointers(); initPointers();
sender = new DeviceMessageSender(connection); sender = new DeviceMessageSender(connection);
} }
@ -163,8 +165,19 @@ public class Controller {
int successCount = 0; int successCount = 0;
for (char c : text.toCharArray()) { for (char c : text.toCharArray()) {
if (!injectChar(c)) { if (!injectChar(c)) {
Ln.w("Could not inject char u+" + String.format("%04x", (int) c)); if (this.charInjectFallback) {
continue; // Needs to handle the full remaining substring than only the failed character,
// since the events may happen too fast. E.g. if we are to do it per character,
// the expected input "ABCD" may lead to the actual value of "DDDD".
String remaining = text.substring(successCount);
setClipboard(remaining, true);
successCount = text.length();
break;
}
else {
Ln.w("Could not inject char u+" + String.format("%04x", (int) c));
continue;
}
} }
successCount++; successCount++;
} }

View file

@ -16,6 +16,7 @@ public class Options {
private boolean showTouches; private boolean showTouches;
private boolean stayAwake; private boolean stayAwake;
private String codecOptions; private String codecOptions;
private boolean charInjectFallback;
public Ln.Level getLogLevel() { public Ln.Level getLogLevel() {
return logLevel; return logLevel;
@ -120,4 +121,12 @@ public class Options {
public void setCodecOptions(String codecOptions) { public void setCodecOptions(String codecOptions) {
this.codecOptions = codecOptions; this.codecOptions = codecOptions;
} }
public boolean getCharInjectFallback() {
return charInjectFallback;
}
public void setCharInjectFallback(boolean charInjectFallback) {
this.charInjectFallback = charInjectFallback;
}
} }

View file

@ -57,7 +57,7 @@ public final class Server {
ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate(), options.getMaxFps(), codecOptions); ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate(), options.getMaxFps(), codecOptions);
if (options.getControl()) { if (options.getControl()) {
final Controller controller = new Controller(device, connection); final Controller controller = new Controller(device, connection, options.getCharInjectFallback());
// asynchronous // asynchronous
startController(controller); startController(controller);
@ -120,7 +120,7 @@ public final class Server {
"The server version (" + BuildConfig.VERSION_NAME + ") does not match the client " + "(" + clientVersion + ")"); "The server version (" + BuildConfig.VERSION_NAME + ") does not match the client " + "(" + clientVersion + ")");
} }
final int expectedParameters = 14; final int expectedParameters = 15;
if (args.length != expectedParameters) { if (args.length != expectedParameters) {
throw new IllegalArgumentException("Expecting " + expectedParameters + " parameters"); throw new IllegalArgumentException("Expecting " + expectedParameters + " parameters");
} }
@ -167,6 +167,9 @@ public final class Server {
String codecOptions = args[13]; String codecOptions = args[13];
options.setCodecOptions(codecOptions); options.setCodecOptions(codecOptions);
boolean charInjectFallback = Boolean.parseBoolean(args[14]);
options.setCharInjectFallback(charInjectFallback);
return options; return options;
} }