Add option to disable 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 new option --no-clipboard-autosync disables this automatic
synchronization.

Fixes #2228 <https://github.com/Genymobile/scrcpy/issues/2228>
PR #2817 <https://github.com/Genymobile/scrcpy/pull/2817>
This commit is contained in:
Romain Vimont 2021-11-22 08:49:10 +01:00
parent 5d17bcf1bc
commit 6abff46c9f
13 changed files with 45 additions and 4 deletions

View file

@ -730,6 +730,9 @@ of <kbd>Ctrl</kbd>+<kbd>v</kbd> and <kbd>MOD</kbd>+<kbd>v</kbd> so that they
also inject the computer clipboard text as a sequence of key events (the same also inject the computer clipboard text as a sequence of key events (the same
way as <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>v</kbd>). way as <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>v</kbd>).
To disable automatic clipboard synchronization, use
`--no-clipboard-autosync`.
#### Pinch-to-zoom #### Pinch-to-zoom
To simulate "pinch-to-zoom": <kbd>Ctrl</kbd>+_click-and-move_. To simulate "pinch-to-zoom": <kbd>Ctrl</kbd>+_click-and-move_.

View file

@ -114,6 +114,12 @@ Limit both the width and height of the video to \fIvalue\fR. The other dimension
Default is 0 (unlimited). 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 .TP
.B \-n, \-\-no\-control .B \-n, \-\-no\-control
Disable device control (mirror the device in read\-only). Disable device control (mirror the device in read\-only).

View file

@ -49,6 +49,7 @@
#define OPT_V4L2_BUFFER 1029 #define OPT_V4L2_BUFFER 1029
#define OPT_TUNNEL_HOST 1030 #define OPT_TUNNEL_HOST 1030
#define OPT_TUNNEL_PORT 1031 #define OPT_TUNNEL_PORT 1031
#define OPT_NO_CLIPBOARD_AUTOSYNC 1032
struct sc_option { struct sc_option {
char shortopt; char shortopt;
@ -208,6 +209,15 @@ static const struct sc_option options[] = {
"is preserved.\n" "is preserved.\n"
"Default is 0 (unlimited).", "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', .shortopt = 'n',
.longopt = "no-control", .longopt = "no-control",
@ -1364,6 +1374,9 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
return false; return false;
} }
break; break;
case OPT_NO_CLIPBOARD_AUTOSYNC:
opts->clipboard_autosync = false;
break;
#ifdef HAVE_V4L2 #ifdef HAVE_V4L2
case OPT_V4L2_SINK: case OPT_V4L2_SINK:
opts->v4l2_device = optarg; opts->v4l2_device = optarg;

View file

@ -66,6 +66,7 @@ input_manager_init(struct input_manager *im, struct controller *controller,
im->control = options->control; im->control = options->control;
im->forward_all_clicks = options->forward_all_clicks; im->forward_all_clicks = options->forward_all_clicks;
im->legacy_paste = options->legacy_paste; im->legacy_paste = options->legacy_paste;
im->clipboard_autosync = options->clipboard_autosync;
const struct sc_shortcut_mods *shortcut_mods = &options->shortcut_mods; const struct sc_shortcut_mods *shortcut_mods = &options->shortcut_mods;
assert(shortcut_mods->count); assert(shortcut_mods->count);
@ -518,7 +519,7 @@ input_manager_process_key(struct input_manager *im,
uint64_t ack_to_wait = SC_SEQUENCE_INVALID; uint64_t ack_to_wait = SC_SEQUENCE_INVALID;
bool is_ctrl_v = ctrl && !shift && keycode == SDLK_v && down && !repeat; 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) { if (im->legacy_paste) {
// inject the text as input events // inject the text as input events
clipboard_paste(controller); clipboard_paste(controller);

View file

@ -24,6 +24,7 @@ struct input_manager {
bool control; bool control;
bool forward_all_clicks; bool forward_all_clicks;
bool legacy_paste; bool legacy_paste;
bool clipboard_autosync;
struct { struct {
unsigned data[SC_MAX_SHORTCUT_MODS]; unsigned data[SC_MAX_SHORTCUT_MODS];

View file

@ -53,4 +53,5 @@ const struct scrcpy_options scrcpy_options_default = {
.forward_all_clicks = false, .forward_all_clicks = false,
.legacy_paste = false, .legacy_paste = false,
.power_off_on_close = false, .power_off_on_close = false,
.clipboard_autosync = true,
}; };

View file

@ -108,6 +108,7 @@ struct scrcpy_options {
bool forward_all_clicks; bool forward_all_clicks;
bool legacy_paste; bool legacy_paste;
bool power_off_on_close; bool power_off_on_close;
bool clipboard_autosync;
}; };
extern const struct scrcpy_options scrcpy_options_default; extern const struct scrcpy_options scrcpy_options_default;

View file

@ -364,6 +364,7 @@ scrcpy(struct scrcpy_options *options) {
.encoder_name = options->encoder_name, .encoder_name = options->encoder_name,
.force_adb_forward = options->force_adb_forward, .force_adb_forward = options->force_adb_forward,
.power_off_on_close = options->power_off_on_close, .power_off_on_close = options->power_off_on_close,
.clipboard_autosync = options->clipboard_autosync,
}; };
static const struct sc_server_callbacks cbs = { static const struct sc_server_callbacks cbs = {

View file

@ -186,6 +186,7 @@ execute_server(struct sc_server *server,
params->codec_options ? params->codec_options : "-", params->codec_options ? params->codec_options : "-",
params->encoder_name ? params->encoder_name : "-", params->encoder_name ? params->encoder_name : "-",
params->power_off_on_close ? "true" : "false", params->power_off_on_close ? "true" : "false",
params->clipboard_autosync ? "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

@ -41,6 +41,7 @@ struct sc_server_params {
bool stay_awake; bool stay_awake;
bool force_adb_forward; bool force_adb_forward;
bool power_off_on_close; bool power_off_on_close;
bool clipboard_autosync;
}; };
struct sc_server { struct sc_server {

View file

@ -82,8 +82,8 @@ public final class Device {
} }
}, displayId); }, displayId);
if (options.getControl()) { if (options.getControl() && options.getClipboardAutosync()) {
// If control is enabled, synchronize Android clipboard to the computer automatically // If control and autosync are enabled, synchronize Android clipboard to the computer automatically
ClipboardManager clipboardManager = SERVICE_MANAGER.getClipboardManager(); ClipboardManager clipboardManager = SERVICE_MANAGER.getClipboardManager();
if (clipboardManager != null) { if (clipboardManager != null) {
clipboardManager.addPrimaryClipChangedListener(new IOnPrimaryClipChangedListener.Stub() { clipboardManager.addPrimaryClipChangedListener(new IOnPrimaryClipChangedListener.Stub() {

View file

@ -18,6 +18,7 @@ public class Options {
private String codecOptions; private String codecOptions;
private String encoderName; private String encoderName;
private boolean powerOffScreenOnClose; private boolean powerOffScreenOnClose;
private boolean clipboardAutosync;
public Ln.Level getLogLevel() { public Ln.Level getLogLevel() {
return logLevel; return logLevel;
@ -138,4 +139,12 @@ public class Options {
public boolean getPowerOffScreenOnClose() { public boolean getPowerOffScreenOnClose() {
return this.powerOffScreenOnClose; return this.powerOffScreenOnClose;
} }
public boolean getClipboardAutosync() {
return clipboardAutosync;
}
public void setClipboardAutosync(boolean clipboardAutosync) {
this.clipboardAutosync = clipboardAutosync;
}
} }

View file

@ -160,7 +160,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 = 16; final int expectedParameters = 17;
if (args.length != expectedParameters) { if (args.length != expectedParameters) {
throw new IllegalArgumentException("Expecting " + expectedParameters + " parameters"); throw new IllegalArgumentException("Expecting " + expectedParameters + " parameters");
} }
@ -213,6 +213,9 @@ public final class Server {
boolean powerOffScreenOnClose = Boolean.parseBoolean(args[15]); boolean powerOffScreenOnClose = Boolean.parseBoolean(args[15]);
options.setPowerOffScreenOnClose(powerOffScreenOnClose); options.setPowerOffScreenOnClose(powerOffScreenOnClose);
boolean clipboardAutosync = Boolean.parseBoolean(args[16]);
options.setClipboardAutosync(clipboardAutosync);
return options; return options;
} }