Implement computer-to-device clipboard copy
It was already possible to _paste_ (with Ctrl+v) the content of the computer clipboard on the device. Technically, it injects a sequence of events to generate the text. Add a new feature (Ctrl+Shift+v) to copy to the device clipboard instead, without injecting the content. Contrary to events injection, this preserves the UTF-8 content exactly, so the text is not broken by special characters. <https://github.com/Genymobile/scrcpy/issues/413>
This commit is contained in:
@@ -47,6 +47,12 @@ control_event_serialize(const struct control_event *event, unsigned char *buf) {
|
||||
buffer_write32be(&buf[13], (uint32_t) event->scroll_event.hscroll);
|
||||
buffer_write32be(&buf[17], (uint32_t) event->scroll_event.vscroll);
|
||||
return 21;
|
||||
case CONTROL_EVENT_TYPE_SET_CLIPBOARD: {
|
||||
size_t len = write_string(event->text_event.text,
|
||||
CONTROL_EVENT_CLIPBOARD_TEXT_MAX_LENGTH,
|
||||
&buf[1]);
|
||||
return 1 + len;
|
||||
}
|
||||
case CONTROL_EVENT_TYPE_BACK_OR_SCREEN_ON:
|
||||
case CONTROL_EVENT_TYPE_EXPAND_NOTIFICATION_PANEL:
|
||||
case CONTROL_EVENT_TYPE_COLLAPSE_NOTIFICATION_PANEL:
|
||||
@@ -61,7 +67,15 @@ control_event_serialize(const struct control_event *event, unsigned char *buf) {
|
||||
|
||||
void
|
||||
control_event_destroy(struct control_event *event) {
|
||||
if (event->type == CONTROL_EVENT_TYPE_TEXT) {
|
||||
SDL_free(event->text_event.text);
|
||||
switch (event->type) {
|
||||
case CONTROL_EVENT_TYPE_TEXT:
|
||||
SDL_free(event->text_event.text);
|
||||
break;
|
||||
case CONTROL_EVENT_TYPE_SET_CLIPBOARD:
|
||||
SDL_free(event->set_clipboard_event.text);
|
||||
break;
|
||||
default:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#include "common.h"
|
||||
|
||||
#define CONTROL_EVENT_TEXT_MAX_LENGTH 300
|
||||
#define CONTROL_EVENT_SERIALIZED_MAX_SIZE (3 + CONTROL_EVENT_TEXT_MAX_LENGTH)
|
||||
#define CONTROL_EVENT_CLIPBOARD_TEXT_MAX_LENGTH 4093
|
||||
#define CONTROL_EVENT_SERIALIZED_MAX_SIZE \
|
||||
(3 + CONTROL_EVENT_CLIPBOARD_TEXT_MAX_LENGTH)
|
||||
|
||||
enum control_event_type {
|
||||
CONTROL_EVENT_TYPE_KEYCODE,
|
||||
@@ -21,6 +23,7 @@ enum control_event_type {
|
||||
CONTROL_EVENT_TYPE_EXPAND_NOTIFICATION_PANEL,
|
||||
CONTROL_EVENT_TYPE_COLLAPSE_NOTIFICATION_PANEL,
|
||||
CONTROL_EVENT_TYPE_GET_CLIPBOARD,
|
||||
CONTROL_EVENT_TYPE_SET_CLIPBOARD,
|
||||
};
|
||||
|
||||
struct control_event {
|
||||
@@ -44,6 +47,9 @@ struct control_event {
|
||||
int32_t hscroll;
|
||||
int32_t vscroll;
|
||||
} scroll_event;
|
||||
struct {
|
||||
char *text; // owned, to be freed by SDL_free()
|
||||
} set_clipboard_event;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -136,6 +136,29 @@ request_device_clipboard(struct controller *controller) {
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_device_clipboard(struct controller *controller) {
|
||||
char *text = SDL_GetClipboardText();
|
||||
if (!text) {
|
||||
LOGW("Cannot get clipboard text: %s", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
if (!*text) {
|
||||
// empty text
|
||||
SDL_free(text);
|
||||
return;
|
||||
}
|
||||
|
||||
struct control_event control_event;
|
||||
control_event.type = CONTROL_EVENT_TYPE_SET_CLIPBOARD;
|
||||
control_event.set_clipboard_event.text = text;
|
||||
|
||||
if (!controller_push_event(controller, &control_event)) {
|
||||
SDL_free(text);
|
||||
LOGW("Cannot send clipboard paste event");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
switch_fps_counter_state(struct video_buffer *vb) {
|
||||
mutex_lock(vb->mutex);
|
||||
@@ -267,9 +290,15 @@ input_manager_process_key(struct input_manager *input_manager,
|
||||
}
|
||||
return;
|
||||
case SDLK_v:
|
||||
if (control && ctrl && !meta && !shift && !repeat
|
||||
if (control && ctrl && !meta && !repeat
|
||||
&& event->type == SDL_KEYDOWN) {
|
||||
clipboard_paste(input_manager->controller);
|
||||
if (shift) {
|
||||
// store the text in the device clipboard
|
||||
set_device_clipboard(input_manager->controller);
|
||||
} else {
|
||||
// inject the text as input events
|
||||
clipboard_paste(input_manager->controller);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case SDLK_f:
|
||||
|
||||
@@ -143,6 +143,9 @@ static void usage(const char *arg0) {
|
||||
" Ctrl+v\n"
|
||||
" paste computer clipboard to device\n"
|
||||
"\n"
|
||||
" Ctrl+Shift+v\n"
|
||||
" copy computer clipboard to device\n"
|
||||
"\n"
|
||||
" Ctrl+i\n"
|
||||
" enable/disable FPS counter (print frames/second in logs)\n"
|
||||
"\n"
|
||||
|
||||
Reference in New Issue
Block a user