Always synchronize clipboard on explicit COPY/CUT

If --no-clipboard-autosync is enabled, the automatic clipboard
synchronization performed whenever the device clipboard changes is
disabled.

But on explicit COPY and CUT scrcpy shortcuts (MOD+c and MOD+x), the
clipboard should still be synchronized, so that it remains possible to
copy-paste from the device to the computer.

This is consistent with the behavior of MOD+v, which pastes the computer
clipboard to the device.

Refs #2228 <https://github.com/Genymobile/scrcpy/issues/2228>
Refs #2817 <https://github.com/Genymobile/scrcpy/pull/2817>
PR #2834 <https://github.com/Genymobile/scrcpy/pull/2834>
This commit is contained in:
Romain Vimont
2021-11-29 09:30:57 +01:00
parent bfcb9d06c3
commit e2b3968c66
9 changed files with 102 additions and 26 deletions

View File

@@ -55,6 +55,12 @@ static const char *const screen_power_mode_labels[] = {
"suspend",
};
static const char *const copy_key_labels[] = {
"none",
"copy",
"cut",
};
static void
write_position(uint8_t *buf, const struct sc_position *position) {
buffer_write32be(&buf[0], position->point.x);
@@ -117,6 +123,9 @@ control_msg_serialize(const struct control_msg *msg, unsigned char *buf) {
case CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON:
buf[1] = msg->inject_keycode.action;
return 2;
case CONTROL_MSG_TYPE_GET_CLIPBOARD:
buf[1] = msg->get_clipboard.copy_key;
return 2;
case CONTROL_MSG_TYPE_SET_CLIPBOARD: {
buffer_write64be(&buf[1], msg->set_clipboard.sequence);
buf[9] = !!msg->set_clipboard.paste;
@@ -131,7 +140,6 @@ control_msg_serialize(const struct control_msg *msg, unsigned char *buf) {
case CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL:
case CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL:
case CONTROL_MSG_TYPE_COLLAPSE_PANELS:
case CONTROL_MSG_TYPE_GET_CLIPBOARD:
case CONTROL_MSG_TYPE_ROTATE_DEVICE:
// no additional data
return 1;
@@ -194,6 +202,10 @@ control_msg_log(const struct control_msg *msg) {
LOG_CMSG("back-or-screen-on %s",
KEYEVENT_ACTION_LABEL(msg->inject_keycode.action));
break;
case CONTROL_MSG_TYPE_GET_CLIPBOARD:
LOG_CMSG("get clipboard copy_key=%s",
copy_key_labels[msg->get_clipboard.copy_key]);
break;
case CONTROL_MSG_TYPE_SET_CLIPBOARD:
LOG_CMSG("clipboard %" PRIu64_ " %s \"%s\"",
msg->set_clipboard.sequence,
@@ -213,9 +225,6 @@ control_msg_log(const struct control_msg *msg) {
case CONTROL_MSG_TYPE_COLLAPSE_PANELS:
LOG_CMSG("collapse panels");
break;
case CONTROL_MSG_TYPE_GET_CLIPBOARD:
LOG_CMSG("get clipboard");
break;
case CONTROL_MSG_TYPE_ROTATE_DEVICE:
LOG_CMSG("rotate device");
break;

View File

@@ -41,6 +41,12 @@ enum screen_power_mode {
SCREEN_POWER_MODE_NORMAL = 2,
};
enum get_clipboard_copy_key {
GET_CLIPBOARD_COPY_KEY_NONE,
GET_CLIPBOARD_COPY_KEY_COPY,
GET_CLIPBOARD_COPY_KEY_CUT,
};
struct control_msg {
enum control_msg_type type;
union {
@@ -69,6 +75,9 @@ struct control_msg {
enum android_keyevent_action action; // action for the BACK key
// screen may only be turned on on ACTION_DOWN
} back_or_screen_on;
struct {
enum get_clipboard_copy_key copy_key;
} get_clipboard;
struct {
uint64_t sequence;
char *text; // owned, to be freed by free()

View File

@@ -148,16 +148,6 @@ action_menu(struct controller *controller, int actions) {
send_keycode(controller, AKEYCODE_MENU, actions, "MENU");
}
static inline void
action_copy(struct controller *controller, int actions) {
send_keycode(controller, AKEYCODE_COPY, actions, "COPY");
}
static inline void
action_cut(struct controller *controller, int actions) {
send_keycode(controller, AKEYCODE_CUT, actions, "CUT");
}
// turn the screen on if it was off, press BACK otherwise
// If the screen is off, it is turned on only on ACTION_DOWN
static void
@@ -211,6 +201,21 @@ collapse_panels(struct controller *controller) {
}
}
static bool
get_device_clipboard(struct controller *controller,
enum get_clipboard_copy_key copy_key) {
struct control_msg msg;
msg.type = CONTROL_MSG_TYPE_GET_CLIPBOARD;
msg.get_clipboard.copy_key = copy_key;
if (!controller_push_msg(controller, &msg)) {
LOGW("Could not request 'get device clipboard'");
return false;
}
return true;
}
static bool
set_device_clipboard(struct controller *controller, bool paste,
uint64_t sequence) {
@@ -450,13 +455,15 @@ input_manager_process_key(struct input_manager *im,
}
return;
case SDLK_c:
if (control && !shift && !repeat) {
action_copy(controller, action);
if (control && !shift && !repeat && down) {
get_device_clipboard(controller,
GET_CLIPBOARD_COPY_KEY_COPY);
}
return;
case SDLK_x:
if (control && !shift && !repeat) {
action_cut(controller, action);
if (control && !shift && !repeat && down) {
get_device_clipboard(controller,
GET_CLIPBOARD_COPY_KEY_CUT);
}
return;
case SDLK_v:

View File

@@ -210,14 +210,18 @@ static void test_serialize_collapse_panels(void) {
static void test_serialize_get_clipboard(void) {
struct control_msg msg = {
.type = CONTROL_MSG_TYPE_GET_CLIPBOARD,
.get_clipboard = {
.copy_key = GET_CLIPBOARD_COPY_KEY_COPY,
},
};
unsigned char buf[CONTROL_MSG_MAX_SIZE];
size_t size = control_msg_serialize(&msg, buf);
assert(size == 1);
assert(size == 2);
const unsigned char expected[] = {
CONTROL_MSG_TYPE_GET_CLIPBOARD,
GET_CLIPBOARD_COPY_KEY_COPY,
};
assert(!memcmp(buf, expected, sizeof(expected)));
}