mirror of https://github.com/Genymobile/scrcpy
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.8 KiB
Java
114 lines
3.8 KiB
Java
7 years ago
|
package com.genymobile.scrcpy;
|
||
|
|
||
|
import java.io.IOException;
|
||
|
import java.io.InputStream;
|
||
|
import java.nio.ByteBuffer;
|
||
|
import java.nio.charset.StandardCharsets;
|
||
|
|
||
|
public class ControlEventReader {
|
||
|
|
||
|
private static final int KEYCODE_PAYLOAD_LENGTH = 9;
|
||
|
private static final int MOUSE_PAYLOAD_LENGTH = 13;
|
||
|
private static final int SCROLL_PAYLOAD_LENGTH = 16;
|
||
|
|
||
|
private final byte[] rawBuffer = new byte[128];
|
||
|
private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer);
|
||
|
private final byte[] textBuffer = new byte[32];
|
||
|
|
||
|
public ControlEventReader() {
|
||
|
// invariant: the buffer is always in "get" mode
|
||
|
buffer.limit(0);
|
||
|
}
|
||
|
|
||
|
public boolean isFull() {
|
||
|
return buffer.remaining() == rawBuffer.length;
|
||
|
}
|
||
|
|
||
|
public boolean readFrom(InputStream input) throws IOException {
|
||
|
if (isFull()) {
|
||
|
throw new IllegalStateException("Buffer full, call next() to consume");
|
||
|
}
|
||
|
buffer.compact();
|
||
|
int head = buffer.position();
|
||
|
int r = input.read(rawBuffer, head, rawBuffer.length - head);
|
||
|
if (r == -1) {
|
||
|
return false;
|
||
|
}
|
||
|
buffer.position(head + r);
|
||
|
buffer.flip();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public ControlEvent next() {
|
||
|
if (!buffer.hasRemaining()) {
|
||
|
return null;
|
||
|
}
|
||
|
int savedPosition = buffer.position();
|
||
|
|
||
|
int type = buffer.get();
|
||
|
switch (type) {
|
||
|
case ControlEvent.TYPE_KEYCODE: {
|
||
|
if (buffer.remaining() < KEYCODE_PAYLOAD_LENGTH) {
|
||
|
break;
|
||
|
}
|
||
6 years ago
|
int action = toUnsigned(buffer.get());
|
||
7 years ago
|
int keycode = buffer.getInt();
|
||
|
int metaState = buffer.getInt();
|
||
|
return ControlEvent.createKeycodeControlEvent(action, keycode, metaState);
|
||
|
}
|
||
|
case ControlEvent.TYPE_TEXT: {
|
||
|
if (buffer.remaining() < 1) {
|
||
|
break;
|
||
|
}
|
||
6 years ago
|
int len = toUnsigned(buffer.get());
|
||
7 years ago
|
if (buffer.remaining() < len) {
|
||
|
break;
|
||
|
}
|
||
|
buffer.get(textBuffer, 0, len);
|
||
|
String text = new String(textBuffer, 0, len, StandardCharsets.UTF_8);
|
||
|
return ControlEvent.createTextControlEvent(text);
|
||
|
}
|
||
|
case ControlEvent.TYPE_MOUSE: {
|
||
|
if (buffer.remaining() < MOUSE_PAYLOAD_LENGTH) {
|
||
|
break;
|
||
|
}
|
||
6 years ago
|
int action = toUnsigned(buffer.get());
|
||
7 years ago
|
int buttons = buffer.getInt();
|
||
6 years ago
|
Position position = readPosition(buffer);
|
||
|
return ControlEvent.createMotionControlEvent(action, buttons, position);
|
||
7 years ago
|
}
|
||
|
case ControlEvent.TYPE_SCROLL: {
|
||
|
if (buffer.remaining() < SCROLL_PAYLOAD_LENGTH) {
|
||
|
break;
|
||
|
}
|
||
6 years ago
|
Position position = readPosition(buffer);
|
||
|
int hScroll = buffer.getInt();
|
||
|
int vScroll = buffer.getInt();
|
||
|
return ControlEvent.createScrollControlEvent(position, hScroll, vScroll);
|
||
7 years ago
|
}
|
||
|
default:
|
||
|
Ln.w("Unknown event type: " + type);
|
||
|
}
|
||
|
|
||
|
// failure, reset savedPosition
|
||
|
buffer.position(savedPosition);
|
||
|
return null;
|
||
|
}
|
||
6 years ago
|
|
||
6 years ago
|
private static Position readPosition(ByteBuffer buffer) {
|
||
6 years ago
|
int x = toUnsigned(buffer.getShort());
|
||
|
int y = toUnsigned(buffer.getShort());
|
||
|
int screenWidth = toUnsigned(buffer.getShort());
|
||
|
int screenHeight = toUnsigned(buffer.getShort());
|
||
6 years ago
|
return new Position(x, y, screenWidth, screenHeight);
|
||
6 years ago
|
}
|
||
|
|
||
|
private static int toUnsigned(short value) {
|
||
|
return value & 0xffff;
|
||
|
}
|
||
|
|
||
|
private static int toUnsigned(byte value) {
|
||
|
return value & 0xff;
|
||
|
}
|
||
7 years ago
|
}
|