Remove "paste on set clipboard" feature

Now that content is pasted on Ctrl+v, the hack to send the PASTE keycode
(for Android >= 7 only) is obsolete. Remove it.

The shortcut itself can still be useful though, when Ctrl+v does not
paste (in Termux for example, it generates ^V, but pasting is still
possible via the context menu).

This reverts fc1dec0270.
This commit is contained in:
Romain Vimont 2020-06-04 18:48:46 +02:00
commit 5882d23ee2
11 changed files with 19 additions and 54 deletions

View file

@ -582,7 +582,7 @@ device).
| Expand notification panel | `RCtrl`+`n` | Expand notification panel | `RCtrl`+`n`
| Collapse notification panel | `RCtrl`+`Shift`+`n` | Collapse notification panel | `RCtrl`+`Shift`+`n`
| Paste computer clipboard to device | `RCtrl`+`v` | Paste computer clipboard to device | `RCtrl`+`v`
| Copy computer clipboard to device and paste | `RCtrl`+`Shift`+`v` | Copy computer clipboard to device | `RCtrl`+`Shift`+`v`
| Enable/disable FPS counter (on stdout) | `RCtrl`+`i` | Enable/disable FPS counter (on stdout) | `RCtrl`+`i`
_¹Double-click on black borders to remove them._ _¹Double-click on black borders to remove them._

View file

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

View file

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

View file

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

View file

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

View file

@ -102,7 +102,7 @@ collapse_notification_panel(struct controller *controller) {
} }
static void static void
set_device_clipboard(struct controller *controller, bool paste) { set_device_clipboard(struct controller *controller) {
char *text = SDL_GetClipboardText(); char *text = SDL_GetClipboardText();
if (!text) { if (!text) {
LOGW("Could not get clipboard text: %s", SDL_GetError()); LOGW("Could not get clipboard text: %s", SDL_GetError());
@ -117,7 +117,6 @@ set_device_clipboard(struct controller *controller, bool paste) {
struct control_msg msg; struct control_msg msg;
msg.type = CONTROL_MSG_TYPE_SET_CLIPBOARD; msg.type = CONTROL_MSG_TYPE_SET_CLIPBOARD;
msg.set_clipboard.text = text; msg.set_clipboard.text = text;
msg.set_clipboard.paste = paste;
if (!controller_push_msg(controller, &msg)) { if (!controller_push_msg(controller, &msg)) {
SDL_free(text); SDL_free(text);
@ -334,8 +333,8 @@ input_manager_process_key(struct input_manager *im,
case SDLK_v: case SDLK_v:
if (control && !repeat && down) { if (control && !repeat && down) {
if (shift) { if (shift) {
// store the text in the device clipboard and paste // store the text in the device clipboard
set_device_clipboard(controller, true); set_device_clipboard(controller);
} else { } else {
// inject the text as input events // inject the text as input events
clipboard_paste(controller); clipboard_paste(controller);
@ -390,7 +389,7 @@ input_manager_process_key(struct input_manager *im,
if (lctrl && !shift && keycode == SDLK_v && down) { if (lctrl && !shift && keycode == SDLK_v && down) {
// Synchronize the computer clipboard to the device clipboard before // Synchronize the computer clipboard to the device clipboard before
// sending Ctrl+V, to allow seamless copy-paste. // sending Ctrl+V, to allow seamless copy-paste.
set_device_clipboard(controller, false); set_device_clipboard(controller);
} }
struct control_msg msg; struct control_msg msg;

View file

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

View file

@ -17,8 +17,6 @@ public final class ControlMessage {
public static final int TYPE_SET_SCREEN_POWER_MODE = 9; public static final int TYPE_SET_SCREEN_POWER_MODE = 9;
public static final int TYPE_ROTATE_DEVICE = 10; public static final int TYPE_ROTATE_DEVICE = 10;
public static final int FLAGS_PASTE = 1;
private int type; private int type;
private String text; private String text;
private int metaState; // KeyEvent.META_* private int metaState; // KeyEvent.META_*
@ -30,7 +28,6 @@ public final class ControlMessage {
private Position position; private Position position;
private int hScroll; private int hScroll;
private int vScroll; private int vScroll;
private int flags;
private ControlMessage() { private ControlMessage() {
} }
@ -71,13 +68,10 @@ public final class ControlMessage {
return msg; return msg;
} }
public static ControlMessage createSetClipboard(String text, boolean paste) { public static ControlMessage createSetClipboard(String text) {
ControlMessage msg = new ControlMessage(); ControlMessage msg = new ControlMessage();
msg.type = TYPE_SET_CLIPBOARD; msg.type = TYPE_SET_CLIPBOARD;
msg.text = text; msg.text = text;
if (paste) {
msg.flags = FLAGS_PASTE;
}
return msg; return msg;
} }
@ -140,8 +134,4 @@ public final class ControlMessage {
public int getVScroll() { public int getVScroll() {
return vScroll; return vScroll;
} }
public int getFlags() {
return flags;
}
} }

View file

@ -12,9 +12,8 @@ public class ControlMessageReader {
static final int INJECT_TOUCH_EVENT_PAYLOAD_LENGTH = 27; static final int INJECT_TOUCH_EVENT_PAYLOAD_LENGTH = 27;
static final int INJECT_SCROLL_EVENT_PAYLOAD_LENGTH = 20; static final int INJECT_SCROLL_EVENT_PAYLOAD_LENGTH = 20;
static final int SET_SCREEN_POWER_MODE_PAYLOAD_LENGTH = 1; static final int SET_SCREEN_POWER_MODE_PAYLOAD_LENGTH = 1;
static final int SET_CLIPBOARD_FIXED_PAYLOAD_LENGTH = 1;
public static final int CLIPBOARD_TEXT_MAX_LENGTH = 4092; // 4096 - 1 (type) - 1 (parse flag) - 2 (length) public static final int CLIPBOARD_TEXT_MAX_LENGTH = 4093; // 4096 - 1 (type) - 2 (length)
public static final int INJECT_TEXT_MAX_LENGTH = 300; public static final int INJECT_TEXT_MAX_LENGTH = 300;
private static final int RAW_BUFFER_SIZE = 4096; private static final int RAW_BUFFER_SIZE = 4096;
@ -149,15 +148,11 @@ public class ControlMessageReader {
} }
private ControlMessage parseSetClipboard() { private ControlMessage parseSetClipboard() {
if (buffer.remaining() < SET_CLIPBOARD_FIXED_PAYLOAD_LENGTH) {
return null;
}
boolean parse = buffer.get() != 0;
String text = parseString(); String text = parseString();
if (text == null) { if (text == null) {
return null; return null;
} }
return ControlMessage.createSetClipboard(text, parse); return ControlMessage.createSetClipboard(text);
} }
private ControlMessage parseSetScreenPowerMode() { private ControlMessage parseSetScreenPowerMode() {

View file

@ -1,6 +1,5 @@
package com.genymobile.scrcpy; package com.genymobile.scrcpy;
import android.os.Build;
import android.os.SystemClock; import android.os.SystemClock;
import android.view.InputDevice; import android.view.InputDevice;
import android.view.KeyCharacterMap; import android.view.KeyCharacterMap;
@ -110,8 +109,7 @@ public class Controller {
} }
break; break;
case ControlMessage.TYPE_SET_CLIPBOARD: case ControlMessage.TYPE_SET_CLIPBOARD:
boolean paste = (msg.getFlags() & ControlMessage.FLAGS_PASTE) != 0; setClipboard(msg.getText());
setClipboard(msg.getText(), paste);
break; break;
case ControlMessage.TYPE_SET_SCREEN_POWER_MODE: case ControlMessage.TYPE_SET_SCREEN_POWER_MODE:
if (device.supportsInputEvents()) { if (device.supportsInputEvents()) {
@ -229,17 +227,13 @@ public class Controller {
return device.injectKeycode(keycode); return device.injectKeycode(keycode);
} }
private boolean setClipboard(String text, boolean paste) { private boolean setClipboard(String text) {
boolean ok = device.setClipboardText(text); boolean ok = device.setClipboardText(text);
if (ok) { if (ok) {
Ln.i("Device clipboard set"); Ln.i("Device clipboard set");
return true;
} }
// On Android >= 7, also press the PASTE key if requested return false;
if (paste && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && device.supportsInputEvents()) {
device.injectKeycode(KeyEvent.KEYCODE_PASTE);
}
return ok;
} }
} }

View file

@ -216,7 +216,6 @@ public class ControlMessageReaderTest {
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos); DataOutputStream dos = new DataOutputStream(bos);
dos.writeByte(ControlMessage.TYPE_SET_CLIPBOARD); dos.writeByte(ControlMessage.TYPE_SET_CLIPBOARD);
dos.writeByte(1); // paste
byte[] text = "testé".getBytes(StandardCharsets.UTF_8); byte[] text = "testé".getBytes(StandardCharsets.UTF_8);
dos.writeShort(text.length); dos.writeShort(text.length);
dos.write(text); dos.write(text);
@ -228,9 +227,6 @@ public class ControlMessageReaderTest {
Assert.assertEquals(ControlMessage.TYPE_SET_CLIPBOARD, event.getType()); Assert.assertEquals(ControlMessage.TYPE_SET_CLIPBOARD, event.getType());
Assert.assertEquals("testé", event.getText()); Assert.assertEquals("testé", event.getText());
boolean parse = (event.getFlags() & ControlMessage.FLAGS_PASTE) != 0;
Assert.assertTrue(parse);
} }
@Test @Test
@ -242,7 +238,6 @@ public class ControlMessageReaderTest {
dos.writeByte(ControlMessage.TYPE_SET_CLIPBOARD); dos.writeByte(ControlMessage.TYPE_SET_CLIPBOARD);
byte[] rawText = new byte[ControlMessageReader.CLIPBOARD_TEXT_MAX_LENGTH]; byte[] rawText = new byte[ControlMessageReader.CLIPBOARD_TEXT_MAX_LENGTH];
dos.writeByte(1); // paste
Arrays.fill(rawText, (byte) 'a'); Arrays.fill(rawText, (byte) 'a');
String text = new String(rawText, 0, rawText.length); String text = new String(rawText, 0, rawText.length);
@ -256,9 +251,6 @@ public class ControlMessageReaderTest {
Assert.assertEquals(ControlMessage.TYPE_SET_CLIPBOARD, event.getType()); Assert.assertEquals(ControlMessage.TYPE_SET_CLIPBOARD, event.getType());
Assert.assertEquals(text, event.getText()); Assert.assertEquals(text, event.getText());
boolean parse = (event.getFlags() & ControlMessage.FLAGS_PASTE) != 0;
Assert.assertTrue(parse);
} }
@Test @Test