Paste on "set clipboard" if possible

Ctrl+Shift+v synchronizes the computer clipboard to the Android device
clipboard. This feature had been added to provide a way to copy UTF-8
text from the computer to the device.

To make such a paste more straightforward, if the device runs at least
Android 7, also send a PASTE keycode to paste immediately.

<https://developer.android.com/reference/android/view/KeyEvent.html#KEYCODE_PASTE>

Fixes #786 <https://github.com/Genymobile/scrcpy/issues/786>
This commit is contained in:
Romain Vimont
2020-05-25 20:58:24 +02:00
parent 274b591d18
commit fc1dec0270
11 changed files with 84 additions and 41 deletions

View File

@@ -280,7 +280,7 @@ Paste computer clipboard to device
.TP
.B Ctrl+Shift+v
Copy computer clipboard to device
Copy computer clipboard to device (and paste if the device runs Android >= 7)
.TP
.B Ctrl+i

View File

@@ -247,7 +247,8 @@ scrcpy_print_usage(const char *arg0) {
" Paste computer clipboard to device\n"
"\n"
" " CTRL_OR_CMD "+Shift+v\n"
" Copy computer clipboard to device\n"
" Copy computer clipboard to device (and paste if the device\n"
" runs Android >= 7)\n"
"\n"
" " CTRL_OR_CMD "+i\n"
" Enable/disable FPS counter (print frames/second in logs)\n"

View File

@@ -67,10 +67,11 @@ control_msg_serialize(const struct control_msg *msg, unsigned char *buf) {
(uint32_t) msg->inject_scroll_event.vscroll);
return 21;
case CONTROL_MSG_TYPE_SET_CLIPBOARD: {
buf[1] = !!msg->set_clipboard.paste;
size_t len = write_string(msg->set_clipboard.text,
CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH,
&buf[1]);
return 1 + len;
&buf[2]);
return 2 + len;
}
case CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE:
buf[1] = msg->set_screen_power_mode.mode;

View File

@@ -11,9 +11,9 @@
#include "common.h"
#define CONTROL_MSG_INJECT_TEXT_MAX_LENGTH 300
#define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH 4093
#define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH 4092
#define CONTROL_MSG_SERIALIZED_MAX_SIZE \
(3 + CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH)
(4 + CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH)
#define POINTER_ID_MOUSE UINT64_C(-1);
@@ -62,6 +62,7 @@ struct control_msg {
} inject_scroll_event;
struct {
char *text; // owned, to be freed by SDL_free()
bool paste;
} set_clipboard;
struct {
enum screen_power_mode mode;

View File

@@ -112,7 +112,7 @@ request_device_clipboard(struct controller *controller) {
}
static void
set_device_clipboard(struct controller *controller) {
set_device_clipboard(struct controller *controller, bool paste) {
char *text = SDL_GetClipboardText();
if (!text) {
LOGW("Could not get clipboard text: %s", SDL_GetError());
@@ -127,6 +127,7 @@ set_device_clipboard(struct controller *controller) {
struct control_msg msg;
msg.type = CONTROL_MSG_TYPE_SET_CLIPBOARD;
msg.set_clipboard.text = text;
msg.set_clipboard.paste = paste;
if (!controller_push_msg(controller, &msg)) {
SDL_free(text);
@@ -354,8 +355,8 @@ input_manager_process_key(struct input_manager *im,
case SDLK_v:
if (control && cmd && !repeat && down) {
if (shift) {
// store the text in the device clipboard
set_device_clipboard(controller);
// store the text in the device clipboard and paste
set_device_clipboard(controller, true);
} else {
// inject the text as input events
clipboard_paste(controller);

View File

@@ -201,16 +201,18 @@ static void test_serialize_set_clipboard(void) {
struct control_msg msg = {
.type = CONTROL_MSG_TYPE_SET_CLIPBOARD,
.set_clipboard = {
.paste = true,
.text = "hello, world!",
},
};
unsigned char buf[CONTROL_MSG_SERIALIZED_MAX_SIZE];
int size = control_msg_serialize(&msg, buf);
assert(size == 16);
assert(size == 17);
const unsigned char expected[] = {
CONTROL_MSG_TYPE_SET_CLIPBOARD,
1, // paste
0x00, 0x0d, // text length
'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', // text
};