diff --git a/README.md b/README.md index f355c7b6..fa4aff68 100644 --- a/README.md +++ b/README.md @@ -730,6 +730,9 @@ of Ctrl+v and MOD+v so that they also inject the computer clipboard text as a sequence of key events (the same way as MOD+Shift+v). +To disable automatic clipboard synchronization, use +`--no-clipboard-autosync`. + #### Pinch-to-zoom To simulate "pinch-to-zoom": Ctrl+_click-and-move_. diff --git a/app/scrcpy.1 b/app/scrcpy.1 index 7438118b..122af757 100644 --- a/app/scrcpy.1 +++ b/app/scrcpy.1 @@ -114,6 +114,12 @@ Limit both the width and height of the video to \fIvalue\fR. The other dimension Default is 0 (unlimited). +.TP +.B \-\-no\-clipboard\-autosync +By default, scrcpy automatically synchronizes the computer clipboard to the device clipboard before injecting Ctrl+v, and the device clipboard to the computer clipboard whenever it changes. + +This option disables this automatic synchronization. + .TP .B \-n, \-\-no\-control Disable device control (mirror the device in read\-only). diff --git a/app/src/cli.c b/app/src/cli.c index 5256d50e..29cb8932 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -49,6 +49,7 @@ #define OPT_V4L2_BUFFER 1029 #define OPT_TUNNEL_HOST 1030 #define OPT_TUNNEL_PORT 1031 +#define OPT_NO_CLIPBOARD_AUTOSYNC 1032 struct sc_option { char shortopt; @@ -208,6 +209,15 @@ static const struct sc_option options[] = { "is preserved.\n" "Default is 0 (unlimited).", }, + { + .longopt_id = OPT_NO_CLIPBOARD_AUTOSYNC, + .longopt = "no-clipboard-autosync", + .text = "By default, scrcpy automatically synchronizes the computer " + "clipboard to the device clipboard before injecting Ctrl+v, " + "and the device clipboard to the computer clipboard whenever " + "it changes.\n" + "This option disables this automatic synchronization." + }, { .shortopt = 'n', .longopt = "no-control", @@ -1364,6 +1374,9 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[], return false; } break; + case OPT_NO_CLIPBOARD_AUTOSYNC: + opts->clipboard_autosync = false; + break; #ifdef HAVE_V4L2 case OPT_V4L2_SINK: opts->v4l2_device = optarg; diff --git a/app/src/input_manager.c b/app/src/input_manager.c index f1715b79..31d6540f 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -66,6 +66,7 @@ input_manager_init(struct input_manager *im, struct controller *controller, im->control = options->control; im->forward_all_clicks = options->forward_all_clicks; im->legacy_paste = options->legacy_paste; + im->clipboard_autosync = options->clipboard_autosync; const struct sc_shortcut_mods *shortcut_mods = &options->shortcut_mods; assert(shortcut_mods->count); @@ -518,7 +519,7 @@ input_manager_process_key(struct input_manager *im, uint64_t ack_to_wait = SC_SEQUENCE_INVALID; bool is_ctrl_v = ctrl && !shift && keycode == SDLK_v && down && !repeat; - if (is_ctrl_v) { + if (im->clipboard_autosync && is_ctrl_v) { if (im->legacy_paste) { // inject the text as input events clipboard_paste(controller); diff --git a/app/src/input_manager.h b/app/src/input_manager.h index 22d77381..5e02b457 100644 --- a/app/src/input_manager.h +++ b/app/src/input_manager.h @@ -24,6 +24,7 @@ struct input_manager { bool control; bool forward_all_clicks; bool legacy_paste; + bool clipboard_autosync; struct { unsigned data[SC_MAX_SHORTCUT_MODS]; diff --git a/app/src/options.c b/app/src/options.c index 074bdf08..a99b09da 100644 --- a/app/src/options.c +++ b/app/src/options.c @@ -53,4 +53,5 @@ const struct scrcpy_options scrcpy_options_default = { .forward_all_clicks = false, .legacy_paste = false, .power_off_on_close = false, + .clipboard_autosync = true, }; diff --git a/app/src/options.h b/app/src/options.h index 82d094cd..d10b2e8a 100644 --- a/app/src/options.h +++ b/app/src/options.h @@ -108,6 +108,7 @@ struct scrcpy_options { bool forward_all_clicks; bool legacy_paste; bool power_off_on_close; + bool clipboard_autosync; }; extern const struct scrcpy_options scrcpy_options_default; diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 04239bf5..061a4e76 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -364,6 +364,7 @@ scrcpy(struct scrcpy_options *options) { .encoder_name = options->encoder_name, .force_adb_forward = options->force_adb_forward, .power_off_on_close = options->power_off_on_close, + .clipboard_autosync = options->clipboard_autosync, }; static const struct sc_server_callbacks cbs = { diff --git a/app/src/server.c b/app/src/server.c index 78127d2d..546216e9 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -186,6 +186,7 @@ execute_server(struct sc_server *server, params->codec_options ? params->codec_options : "-", params->encoder_name ? params->encoder_name : "-", params->power_off_on_close ? "true" : "false", + params->clipboard_autosync ? "true" : "false", }; #ifdef SERVER_DEBUGGER LOGI("Server debugger waiting for a client on device port " diff --git a/app/src/server.h b/app/src/server.h index cb1fadbb..5b25ff46 100644 --- a/app/src/server.h +++ b/app/src/server.h @@ -41,6 +41,7 @@ struct sc_server_params { bool stay_awake; bool force_adb_forward; bool power_off_on_close; + bool clipboard_autosync; }; struct sc_server { diff --git a/server/src/main/java/com/genymobile/scrcpy/Device.java b/server/src/main/java/com/genymobile/scrcpy/Device.java index 093646e2..03ae9b22 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Device.java +++ b/server/src/main/java/com/genymobile/scrcpy/Device.java @@ -82,8 +82,8 @@ public final class Device { } }, displayId); - if (options.getControl()) { - // If control is enabled, synchronize Android clipboard to the computer automatically + if (options.getControl() && options.getClipboardAutosync()) { + // If control and autosync are enabled, synchronize Android clipboard to the computer automatically ClipboardManager clipboardManager = SERVICE_MANAGER.getClipboardManager(); if (clipboardManager != null) { clipboardManager.addPrimaryClipChangedListener(new IOnPrimaryClipChangedListener.Stub() { diff --git a/server/src/main/java/com/genymobile/scrcpy/Options.java b/server/src/main/java/com/genymobile/scrcpy/Options.java index cf11df0f..74467c7c 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Options.java +++ b/server/src/main/java/com/genymobile/scrcpy/Options.java @@ -18,6 +18,7 @@ public class Options { private String codecOptions; private String encoderName; private boolean powerOffScreenOnClose; + private boolean clipboardAutosync; public Ln.Level getLogLevel() { return logLevel; @@ -138,4 +139,12 @@ public class Options { public boolean getPowerOffScreenOnClose() { return this.powerOffScreenOnClose; } + + public boolean getClipboardAutosync() { + return clipboardAutosync; + } + + public void setClipboardAutosync(boolean clipboardAutosync) { + this.clipboardAutosync = clipboardAutosync; + } } diff --git a/server/src/main/java/com/genymobile/scrcpy/Server.java b/server/src/main/java/com/genymobile/scrcpy/Server.java index 5a1f4619..188974ff 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Server.java +++ b/server/src/main/java/com/genymobile/scrcpy/Server.java @@ -160,7 +160,7 @@ public final class Server { "The server version (" + BuildConfig.VERSION_NAME + ") does not match the client " + "(" + clientVersion + ")"); } - final int expectedParameters = 16; + final int expectedParameters = 17; if (args.length != expectedParameters) { throw new IllegalArgumentException("Expecting " + expectedParameters + " parameters"); } @@ -213,6 +213,9 @@ public final class Server { boolean powerOffScreenOnClose = Boolean.parseBoolean(args[15]); options.setPowerOffScreenOnClose(powerOffScreenOnClose); + boolean clipboardAutosync = Boolean.parseBoolean(args[16]); + options.setClipboardAutosync(clipboardAutosync); + return options; }