Copy on "get clipboard" if possible

Ctrl+c synchronizes the Android device clipboard to the computer
clipboard.

To make the copy more straightforward, if the device runs at least
Android 7, also send a COPY keycode before copying the clipboard.

<https://developer.android.com/reference/android/view/KeyEvent.html#KEYCODE_COPY>
This commit is contained in:
Romain Vimont
2020-05-28 10:11:05 +02:00
parent 0f6cdc56fa
commit 7a77f3bab4
9 changed files with 62 additions and 9 deletions

View File

@@ -18,6 +18,7 @@ public final class ControlMessage {
public static final int TYPE_ROTATE_DEVICE = 10;
public static final int FLAGS_PASTE = 1;
public static final int FLAGS_COPY = 2;
private int type;
private String text;
@@ -81,6 +82,15 @@ public final class ControlMessage {
return msg;
}
public static ControlMessage createGetClipboard(boolean copy) {
ControlMessage msg = new ControlMessage();
msg.type = TYPE_GET_CLIPBOARD;
if (copy) {
msg.flags = FLAGS_COPY;
}
return msg;
}
/**
* @param mode one of the {@code Device.SCREEN_POWER_MODE_*} constants
*/

View File

@@ -12,6 +12,7 @@ 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 GET_CLIPBOARD_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)
@@ -67,6 +68,9 @@ public class ControlMessageReader {
case ControlMessage.TYPE_INJECT_SCROLL_EVENT:
msg = parseInjectScrollEvent();
break;
case ControlMessage.TYPE_GET_CLIPBOARD:
msg = parseGetClipboard();
break;
case ControlMessage.TYPE_SET_CLIPBOARD:
msg = parseSetClipboard();
break;
@@ -76,7 +80,6 @@ public class ControlMessageReader {
case ControlMessage.TYPE_BACK_OR_SCREEN_ON:
case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL:
case ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL:
case ControlMessage.TYPE_GET_CLIPBOARD:
case ControlMessage.TYPE_ROTATE_DEVICE:
msg = ControlMessage.createEmpty(type);
break;
@@ -148,6 +151,14 @@ public class ControlMessageReader {
return ControlMessage.createInjectScrollEvent(position, hScroll, vScroll);
}
private ControlMessage parseGetClipboard() {
if (buffer.remaining() < GET_CLIPBOARD_PAYLOAD_LENGTH) {
return null;
}
boolean copy = buffer.get() != 0;
return ControlMessage.createGetClipboard(copy);
}
private ControlMessage parseSetClipboard() {
if (buffer.remaining() < SET_CLIPBOARD_FIXED_PAYLOAD_LENGTH) {
return null;

View File

@@ -104,10 +104,8 @@ public class Controller {
device.collapsePanels();
break;
case ControlMessage.TYPE_GET_CLIPBOARD:
String clipboardText = device.getClipboardText();
if (clipboardText != null) {
sender.pushClipboardText(clipboardText);
}
boolean copy = (msg.getFlags() & ControlMessage.FLAGS_COPY) != 0;
getClipboard(copy);
break;
case ControlMessage.TYPE_SET_CLIPBOARD:
boolean paste = (msg.getFlags() & ControlMessage.FLAGS_PASTE) != 0;
@@ -229,6 +227,19 @@ public class Controller {
return device.injectKeycode(keycode);
}
private void getClipboard(boolean copy) {
// On Android >= 7, also press the COPY key if requested
if (copy && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && device.supportsInputEvents()) {
// Must wait until the COPY has been executed
device.injectCopyKeycode();
}
String clipboardText = device.getClipboardText();
if (clipboardText != null) {
sender.pushClipboardText(clipboardText);
}
}
private boolean setClipboard(String text, boolean paste) {
boolean ok = device.setClipboardText(text);
if (ok) {

View File

@@ -186,6 +186,14 @@ public final class Device {
return injectKeycode(keyCode, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
public boolean injectCopyKeycode() {
isSettingClipboard.set(true);
// Must wait until the COPY has been executed
boolean ret = injectKeycode(KeyEvent.KEYCODE_COPY, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
isSettingClipboard.set(false);
return ret;
}
public boolean injectPasteKeycode() {
return injectKeycode(KeyEvent.KEYCODE_PASTE);
}

View File

@@ -200,6 +200,7 @@ public class ControlMessageReaderTest {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeByte(ControlMessage.TYPE_GET_CLIPBOARD);
dos.writeByte(1); // copy
byte[] packet = bos.toByteArray();
@@ -207,6 +208,7 @@ public class ControlMessageReaderTest {
ControlMessage event = reader.next();
Assert.assertEquals(ControlMessage.TYPE_GET_CLIPBOARD, event.getType());
Assert.assertEquals(1, (event.getFlags() & ControlMessage.FLAGS_COPY));
}
@Test