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

Adding new option for falling back to clipboard pasting on character injection failures. #1805

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
11 changes: 11 additions & 0 deletions app/src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ scrcpy_print_usage(const char *arg0) {
" Unit suffixes are supported: 'K' (x1000) and 'M' (x1000000).\n"
" Default is %d.\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"
" Set a list of comma-separated key:type=value options for the\n"
" device encoder.\n"
Expand Down Expand Up @@ -651,12 +656,15 @@ guess_record_format(const char *filename) {
#define OPT_DISABLE_SCREENSAVER 1020
#define OPT_SHORTCUT_MOD 1021
#define OPT_NO_KEY_REPEAT 1022
#define OPT_CHAR_INJECT_FALLBACK 1023

bool
scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
static const struct option long_options[] = {
{"always-on-top", no_argument, NULL, OPT_ALWAYS_ON_TOP},
{"bit-rate", required_argument, NULL, 'b'},
{"char-inject-fallback", no_argument, NULL,
OPT_CHAR_INJECT_FALLBACK},
{"codec-options", required_argument, NULL, OPT_CODEC_OPTIONS},
{"crop", required_argument, NULL, OPT_CROP},
{"disable-screensaver", no_argument, NULL,
Expand Down Expand Up @@ -719,6 +727,9 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
case OPT_CROP:
opts->crop = optarg;
break;
case OPT_CHAR_INJECT_FALLBACK:
opts->char_inject_fallback = true;
break;
case OPT_DISPLAY_ID:
if (!parse_display_id(optarg, &opts->display_id)) {
return false;
Expand Down
1 change: 1 addition & 0 deletions app/src/scrcpy.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ scrcpy(const struct scrcpy_options *options) {
.bit_rate = options->bit_rate,
.max_fps = options->max_fps,
.lock_video_orientation = options->lock_video_orientation,
.char_inject_fallback = options->char_inject_fallback,
.control = options->control,
.display_id = options->display_id,
.show_touches = options->show_touches,
Expand Down
2 changes: 2 additions & 0 deletions app/src/scrcpy.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ struct scrcpy_options {
bool fullscreen;
bool always_on_top;
bool control;
bool char_inject_fallback;
bool display;
bool turn_screen_off;
bool render_expired_frames;
Expand Down Expand Up @@ -112,6 +113,7 @@ struct scrcpy_options {
.show_touches = false, \
.fullscreen = false, \
.always_on_top = false, \
.char_inject_fallback = false, \
.control = true, \
.display = true, \
.turn_screen_off = false, \
Expand Down
1 change: 1 addition & 0 deletions app/src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ execute_server(struct server *server, const struct server_params *params) {
params->show_touches ? "true" : "false",
params->stay_awake ? "true" : "false",
params->codec_options ? params->codec_options : "-",
params->char_inject_fallback ? "true" : "false",
};
#ifdef SERVER_DEBUGGER
LOGI("Server debugger waiting for a client on device port "
Expand Down
1 change: 1 addition & 0 deletions app/src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ struct server_params {
uint32_t bit_rate;
uint16_t max_fps;
int8_t lock_video_orientation;
bool char_inject_fallback;
bool control;
uint16_t display_id;
bool show_touches;
Expand Down
19 changes: 16 additions & 3 deletions server/src/main/java/com/genymobile/scrcpy/Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class Controller {
private final Device device;
private final DesktopConnection connection;
private final DeviceMessageSender sender;
private final boolean charInjectFallback;

private final KeyCharacterMap charMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);

Expand All @@ -31,9 +32,10 @@ public class Controller {

private boolean keepPowerModeOff;

public Controller(Device device, DesktopConnection connection) {
public Controller(Device device, DesktopConnection connection, boolean charInjectFallback) {
this.device = device;
this.connection = connection;
this.charInjectFallback = charInjectFallback;
initPointers();
sender = new DeviceMessageSender(connection);
}
Expand Down Expand Up @@ -163,8 +165,19 @@ private int injectText(String text) {
int successCount = 0;
for (char c : text.toCharArray()) {
if (!injectChar(c)) {
Ln.w("Could not inject char u+" + String.format("%04x", (int) c));
continue;
if (this.charInjectFallback) {
// 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++;
}
Expand Down
9 changes: 9 additions & 0 deletions server/src/main/java/com/genymobile/scrcpy/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class Options {
private boolean showTouches;
private boolean stayAwake;
private String codecOptions;
private boolean charInjectFallback;

public Ln.Level getLogLevel() {
return logLevel;
Expand Down Expand Up @@ -120,4 +121,12 @@ public String getCodecOptions() {
public void setCodecOptions(String codecOptions) {
this.codecOptions = codecOptions;
}

public boolean getCharInjectFallback() {
return charInjectFallback;
}

public void setCharInjectFallback(boolean charInjectFallback) {
this.charInjectFallback = charInjectFallback;
}
}
7 changes: 5 additions & 2 deletions server/src/main/java/com/genymobile/scrcpy/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ private static void scrcpy(Options options) throws IOException {
ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate(), options.getMaxFps(), codecOptions);

if (options.getControl()) {
final Controller controller = new Controller(device, connection);
final Controller controller = new Controller(device, connection, options.getCharInjectFallback());

// asynchronous
startController(controller);
Expand Down Expand Up @@ -120,7 +120,7 @@ private static Options createOptions(String... args) {
"The server version (" + BuildConfig.VERSION_NAME + ") does not match the client " + "(" + clientVersion + ")");
}

final int expectedParameters = 14;
final int expectedParameters = 15;
if (args.length != expectedParameters) {
throw new IllegalArgumentException("Expecting " + expectedParameters + " parameters");
}
Expand Down Expand Up @@ -167,6 +167,9 @@ private static Options createOptions(String... args) {
String codecOptions = args[13];
options.setCodecOptions(codecOptions);

boolean charInjectFallback = Boolean.parseBoolean(args[14]);
options.setCharInjectFallback(charInjectFallback);

return options;
}

Expand Down