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:
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user