mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-08-08 09:09:08 +00:00
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:
parent
274b591d18
commit
fc1dec0270
11 changed files with 84 additions and 41 deletions
|
@ -17,6 +17,8 @@ public final class ControlMessage {
|
|||
public static final int TYPE_SET_SCREEN_POWER_MODE = 9;
|
||||
public static final int TYPE_ROTATE_DEVICE = 10;
|
||||
|
||||
public static final int FLAGS_PASTE = 1;
|
||||
|
||||
private int type;
|
||||
private String text;
|
||||
private int metaState; // KeyEvent.META_*
|
||||
|
@ -28,6 +30,7 @@ public final class ControlMessage {
|
|||
private Position position;
|
||||
private int hScroll;
|
||||
private int vScroll;
|
||||
private int flags;
|
||||
|
||||
private ControlMessage() {
|
||||
}
|
||||
|
@ -68,10 +71,13 @@ public final class ControlMessage {
|
|||
return msg;
|
||||
}
|
||||
|
||||
public static ControlMessage createSetClipboard(String text) {
|
||||
public static ControlMessage createSetClipboard(String text, boolean paste) {
|
||||
ControlMessage msg = new ControlMessage();
|
||||
msg.type = TYPE_SET_CLIPBOARD;
|
||||
msg.text = text;
|
||||
if (paste) {
|
||||
msg.flags = FLAGS_PASTE;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
@ -134,4 +140,8 @@ public final class ControlMessage {
|
|||
public int getVScroll() {
|
||||
return vScroll;
|
||||
}
|
||||
|
||||
public int getFlags() {
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,9 @@ public class ControlMessageReader {
|
|||
static final int INJECT_TOUCH_EVENT_PAYLOAD_LENGTH = 27;
|
||||
static final int INJECT_SCROLL_EVENT_PAYLOAD_LENGTH = 20;
|
||||
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 = 4093;
|
||||
public static final int CLIPBOARD_TEXT_MAX_LENGTH = 4092; // 4096 - 1 (type) - 1 (parse flag) - 2 (length)
|
||||
public static final int INJECT_TEXT_MAX_LENGTH = 300;
|
||||
|
||||
private static final int RAW_BUFFER_SIZE = 4096;
|
||||
|
@ -148,11 +149,15 @@ public class ControlMessageReader {
|
|||
}
|
||||
|
||||
private ControlMessage parseSetClipboard() {
|
||||
if (buffer.remaining() < SET_CLIPBOARD_FIXED_PAYLOAD_LENGTH) {
|
||||
return null;
|
||||
}
|
||||
boolean parse = buffer.get() != 0;
|
||||
String text = parseString();
|
||||
if (text == null) {
|
||||
return null;
|
||||
}
|
||||
return ControlMessage.createSetClipboard(text);
|
||||
return ControlMessage.createSetClipboard(text, parse);
|
||||
}
|
||||
|
||||
private ControlMessage parseSetScreenPowerMode() {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.genymobile.scrcpy;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyCharacterMap;
|
||||
|
@ -107,10 +108,8 @@ public class Controller {
|
|||
sender.pushClipboardText(clipboardText);
|
||||
break;
|
||||
case ControlMessage.TYPE_SET_CLIPBOARD:
|
||||
boolean setClipboardOk = device.setClipboardText(msg.getText());
|
||||
if (setClipboardOk) {
|
||||
Ln.i("Device clipboard set");
|
||||
}
|
||||
boolean paste = (msg.getFlags() & ControlMessage.FLAGS_PASTE) != 0;
|
||||
setClipboard(msg.getText(), paste);
|
||||
break;
|
||||
case ControlMessage.TYPE_SET_SCREEN_POWER_MODE:
|
||||
if (device.supportsInputEvents()) {
|
||||
|
@ -227,4 +226,18 @@ public class Controller {
|
|||
int keycode = device.isScreenOn() ? KeyEvent.KEYCODE_BACK : KeyEvent.KEYCODE_POWER;
|
||||
return device.injectKeycode(keycode);
|
||||
}
|
||||
|
||||
private boolean setClipboard(String text, boolean paste) {
|
||||
boolean ok = device.setClipboardText(text);
|
||||
if (ok) {
|
||||
Ln.i("Device clipboard set");
|
||||
}
|
||||
|
||||
// On Android >= 7, also press the PASTE key if requested
|
||||
if (paste && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && device.supportsInputEvents()) {
|
||||
device.injectKeycode(KeyEvent.KEYCODE_PASTE);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -216,6 +216,7 @@ public class ControlMessageReaderTest {
|
|||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
DataOutputStream dos = new DataOutputStream(bos);
|
||||
dos.writeByte(ControlMessage.TYPE_SET_CLIPBOARD);
|
||||
dos.writeByte(1); // paste
|
||||
byte[] text = "testé".getBytes(StandardCharsets.UTF_8);
|
||||
dos.writeShort(text.length);
|
||||
dos.write(text);
|
||||
|
@ -227,6 +228,9 @@ public class ControlMessageReaderTest {
|
|||
|
||||
Assert.assertEquals(ControlMessage.TYPE_SET_CLIPBOARD, event.getType());
|
||||
Assert.assertEquals("testé", event.getText());
|
||||
|
||||
boolean parse = (event.getFlags() & ControlMessage.FLAGS_PASTE) != 0;
|
||||
Assert.assertTrue(parse);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -238,6 +242,7 @@ public class ControlMessageReaderTest {
|
|||
dos.writeByte(ControlMessage.TYPE_SET_CLIPBOARD);
|
||||
|
||||
byte[] rawText = new byte[ControlMessageReader.CLIPBOARD_TEXT_MAX_LENGTH];
|
||||
dos.writeByte(1); // paste
|
||||
Arrays.fill(rawText, (byte) 'a');
|
||||
String text = new String(rawText, 0, rawText.length);
|
||||
|
||||
|
@ -251,6 +256,9 @@ public class ControlMessageReaderTest {
|
|||
|
||||
Assert.assertEquals(ControlMessage.TYPE_SET_CLIPBOARD, event.getType());
|
||||
Assert.assertEquals(text, event.getText());
|
||||
|
||||
boolean parse = (event.getFlags() & ControlMessage.FLAGS_PASTE) != 0;
|
||||
Assert.assertTrue(parse);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue