Compare commits

..

11 Commits

Author SHA1 Message Date
Romain Vimont
c2d0dcd002 Add multitouch simulation
While the Ctrl key is held, the first left-click adds an immobile
"virtual finger" at this position.

Moving the mouse moves another cursor. The left click may be released
and pressed as necessary to control the second finger.

Releasing Ctrl releases the virtual finger.
2019-10-10 21:45:22 +02:00
Romain Vimont
9448eae8a4 Initialize input manager dynamically
To simulate multitouch, we will need more fields in input_manager, which
will be initialized dynamically.
2019-10-06 21:36:06 +02:00
Romain Vimont
6220456def Merge mouse and touch events
Both are handled the very same way on the device.
2019-10-03 20:37:49 +02:00
Romain Vimont
7e1d52c119 Rename "touch pointer" to "pointer"
There are only touch pointers now, mouse pointers have been removed.
2019-10-03 20:27:28 +02:00
Romain Vimont
280d5b718c Use common pointers for mouse and touch
The mouse is a pointer like any other.
2019-10-03 20:05:29 +02:00
Romain Vimont
30168f0428 Ignore duplicate mouse events
In SDL, a touch event may simulate an identical mouse event. Since we
already handle touch event, ignore these duplicates.
2019-10-03 20:05:29 +02:00
Romain Vimont
b5a2d99bc2 Send touch events from the client
On SDL touch events, send control messages to the server.
2019-10-03 20:05:29 +02:00
Romain Vimont
f765aae352 Inject touch events on the server
On receiving an "inject touch" control message, update the local
pointers state and inject touches.
2019-10-03 20:05:29 +02:00
Romain Vimont
77f876e29c Add "inject touch" control message
Add a control message type in the protocol to forward touch events to
the device.
2019-10-03 20:05:27 +02:00
Romain Vimont
d90549d1e6 Rename "pointer" to "mouse pointer"
This will help to distinguish them from "touch pointers".
2019-10-02 21:40:26 +02:00
Romain Vimont
810ff80ba7 Add buffer_write64be()
Add a function to write 64 bits in big-endian from a uint64_t.
2019-10-02 21:40:26 +02:00
11 changed files with 148 additions and 203 deletions

View File

@@ -49,11 +49,6 @@ control_msg_serialize(const struct control_msg *msg, unsigned char *buf) {
CONTROL_MSG_TEXT_MAX_LENGTH, &buf[1]);
return 1 + len;
}
case CONTROL_MSG_TYPE_INJECT_MOUSE_EVENT:
buf[1] = msg->inject_mouse_event.action;
buffer_write32be(&buf[2], msg->inject_mouse_event.buttons);
write_position(&buf[6], &msg->inject_mouse_event.position);
return 18;
case CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT:
buf[1] = msg->inject_touch_event.action;
buffer_write64be(&buf[2], msg->inject_touch_event.pointer_id);
@@ -61,7 +56,8 @@ control_msg_serialize(const struct control_msg *msg, unsigned char *buf) {
uint16_t pressure =
to_fixed_point_16(msg->inject_touch_event.pressure);
buffer_write16be(&buf[22], pressure);
return 24;
buffer_write32be(&buf[24], msg->inject_touch_event.buttons);
return 28;
case CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT:
write_position(&buf[1], &msg->inject_scroll_event.position);
buffer_write32be(&buf[13],

View File

@@ -15,10 +15,12 @@
#define CONTROL_MSG_SERIALIZED_MAX_SIZE \
(3 + CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH)
#define POINTER_ID_MOUSE UINT64_C(-1);
#define POINTER_ID_VIRTUAL_FINGER UINT64_C(-2);
enum control_msg_type {
CONTROL_MSG_TYPE_INJECT_KEYCODE,
CONTROL_MSG_TYPE_INJECT_TEXT,
CONTROL_MSG_TYPE_INJECT_MOUSE_EVENT,
CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT,
CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT,
CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON,
@@ -49,10 +51,6 @@ struct control_msg {
struct {
enum android_motionevent_action action;
enum android_motionevent_buttons buttons;
struct position position;
} inject_mouse_event;
struct {
enum android_motionevent_action action;
uint64_t pointer_id;
struct position position;
float pressure;

View File

@@ -128,15 +128,6 @@ convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod) {
}
}
static bool
convert_mouse_action(SDL_EventType from, enum android_motionevent_action *to) {
switch (from) {
MAP(SDL_MOUSEBUTTONDOWN, AMOTION_EVENT_ACTION_DOWN);
MAP(SDL_MOUSEBUTTONUP, AMOTION_EVENT_ACTION_UP);
FAIL;
}
}
static enum android_motionevent_buttons
convert_mouse_buttons(uint32_t state) {
enum android_motionevent_buttons buttons = 0;
@@ -176,20 +167,31 @@ convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to) {
return true;
}
static bool
convert_mouse_action(SDL_EventType from, enum android_motionevent_action *to) {
switch (from) {
MAP(SDL_MOUSEBUTTONDOWN, AMOTION_EVENT_ACTION_DOWN);
MAP(SDL_MOUSEBUTTONUP, AMOTION_EVENT_ACTION_UP);
FAIL;
}
}
bool
convert_mouse_button(const SDL_MouseButtonEvent *from, struct size screen_size,
struct control_msg *to) {
to->type = CONTROL_MSG_TYPE_INJECT_MOUSE_EVENT;
to->type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT;
if (!convert_mouse_action(from->type, &to->inject_mouse_event.action)) {
if (!convert_mouse_action(from->type, &to->inject_touch_event.action)) {
return false;
}
to->inject_mouse_event.buttons =
to->inject_touch_event.pointer_id = POINTER_ID_MOUSE;
to->inject_touch_event.position.screen_size = screen_size;
to->inject_touch_event.position.point.x = from->x;
to->inject_touch_event.position.point.y = from->y;
to->inject_touch_event.pressure = 1.f;
to->inject_touch_event.buttons =
convert_mouse_buttons(SDL_BUTTON(from->button));
to->inject_mouse_event.position.screen_size = screen_size;
to->inject_mouse_event.position.point.x = from->x;
to->inject_mouse_event.position.point.y = from->y;
return true;
}
@@ -197,12 +199,14 @@ convert_mouse_button(const SDL_MouseButtonEvent *from, struct size screen_size,
bool
convert_mouse_motion(const SDL_MouseMotionEvent *from, struct size screen_size,
struct control_msg *to) {
to->type = CONTROL_MSG_TYPE_INJECT_MOUSE_EVENT;
to->inject_mouse_event.action = AMOTION_EVENT_ACTION_MOVE;
to->inject_mouse_event.buttons = convert_mouse_buttons(from->state);
to->inject_mouse_event.position.screen_size = screen_size;
to->inject_mouse_event.position.point.x = from->x;
to->inject_mouse_event.position.point.y = from->y;
to->type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT;
to->inject_touch_event.action = AMOTION_EVENT_ACTION_MOVE;
to->inject_touch_event.pointer_id = POINTER_ID_MOUSE;
to->inject_touch_event.position.screen_size = screen_size;
to->inject_touch_event.position.point.x = from->x;
to->inject_touch_event.position.point.y = from->y;
to->inject_touch_event.pressure = 1.f;
to->inject_touch_event.buttons = convert_mouse_buttons(from->state);
return true;
}
@@ -232,6 +236,7 @@ convert_touch(const SDL_TouchFingerEvent *from, struct size screen_size,
to->inject_touch_event.position.point.x = from->x * screen_size.width;
to->inject_touch_event.position.point.y = from->y * screen_size.height;
to->inject_touch_event.pressure = from->pressure;
to->inject_touch_event.buttons = 0;
return true;
}

View File

@@ -7,6 +7,19 @@
#include "lock_util.h"
#include "log.h"
void
input_manager_init(struct input_manager *input_manager,
struct controller *controller,
struct video_buffer *video_buffer,
struct screen *screen) {
input_manager->controller = controller;
input_manager->video_buffer = video_buffer;
input_manager->screen = screen;
input_manager->ctrl_down = false;
input_manager->vfinger.down = false;
}
// Convert window coordinates (as provided by SDL_GetMouseState() to renderer
// coordinates (as provided in SDL mouse events)
//
@@ -211,6 +224,26 @@ clipboard_paste(struct controller *controller) {
}
}
static void
simulate_virtual_finger(struct input_manager *input_manager, bool down,
struct position *position) {
SDL_assert(input_manager->vfinger.down != down);
input_manager->vfinger.down = down;
struct control_msg msg;
msg.type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT;
msg.inject_touch_event.action = down ? AMOTION_EVENT_ACTION_DOWN
: AMOTION_EVENT_ACTION_UP;
msg.inject_touch_event.pointer_id = POINTER_ID_VIRTUAL_FINGER;
msg.inject_touch_event.position = *position;
msg.inject_touch_event.pressure = 1.f;
msg.inject_touch_event.buttons = 0;
if (!controller_push_msg(input_manager->controller, &msg)) {
LOGW("Could not request 'inject virtual finger event'");
}
}
void
input_manager_process_text_input(struct input_manager *input_manager,
const SDL_TextInputEvent *event) {
@@ -244,6 +277,14 @@ input_manager_process_key(struct input_manager *input_manager,
bool alt = event->keysym.mod & (KMOD_LALT | KMOD_RALT);
bool meta = event->keysym.mod & (KMOD_LGUI | KMOD_RGUI);
// store the Ctrl state to modify mouse events
input_manager->ctrl_down = ctrl;
if (input_manager->vfinger.down && !ctrl) {
simulate_virtual_finger(input_manager, false,
&input_manager->vfinger.position);
}
// use Cmd on macOS, Ctrl on other platforms
#ifdef __APPLE__
bool cmd = !ctrl && meta;
@@ -427,6 +468,7 @@ input_manager_process_mouse_button(struct input_manager *input_manager,
// simulated from touch events, so it's a duplicate
return;
}
if (event->type == SDL_MOUSEBUTTONDOWN) {
if (control && event->button == SDL_BUTTON_RIGHT) {
press_back_or_turn_screen_on(input_manager->controller);
@@ -437,12 +479,24 @@ input_manager_process_mouse_button(struct input_manager *input_manager,
return;
}
// double-click on black borders resize to fit the device screen
if (event->button == SDL_BUTTON_LEFT && event->clicks == 2) {
bool outside =
is_outside_device_screen(input_manager, event->x, event->y);
if (outside) {
screen_resize_to_fit(input_manager->screen);
return;
if (event->button == SDL_BUTTON_LEFT) {
if (event->clicks >= 2) {
bool outside =
is_outside_device_screen(input_manager, event->x, event->y);
if (outside) {
screen_resize_to_fit(input_manager->screen);
return;
}
}
struct virtual_finger *vfinger = &input_manager->vfinger;
if (input_manager->ctrl_down && !vfinger->down) {
vfinger->position.point.x = event->x;
vfinger->position.point.y = event->y;
vfinger->position.screen_size =
input_manager->screen->frame_size,
simulate_virtual_finger(input_manager, true,
&vfinger->position);
}
}
// otherwise, send the click event to the device

View File

@@ -14,8 +14,21 @@ struct input_manager {
struct controller *controller;
struct video_buffer *video_buffer;
struct screen *screen;
bool ctrl_down;
struct virtual_finger {
bool down;
struct position position;
} vfinger;
};
void
input_manager_init(struct input_manager *input_manager,
struct controller *controller,
struct video_buffer *video_buffer,
struct screen *screen);
void
input_manager_process_text_input(struct input_manager *input_manager,
const SDL_TextInputEvent *event);

View File

@@ -37,12 +37,7 @@ static struct decoder decoder;
static struct recorder recorder;
static struct controller controller;
static struct file_handler file_handler;
static struct input_manager input_manager = {
.controller = &controller,
.video_buffer = &video_buffer,
.screen = &screen,
};
static struct input_manager input_manager;
// init SDL and set appropriate hints
static bool
@@ -311,6 +306,8 @@ scrcpy(const struct scrcpy_options *options) {
goto end;
}
input_manager_init(&input_manager, &controller, &video_buffer, &screen);
if (!server_connect_to(&server)) {
goto end;
}

View File

@@ -67,39 +67,6 @@ static void test_serialize_inject_text_long(void) {
assert(!memcmp(buf, expected, sizeof(expected)));
}
static void test_serialize_inject_mouse_event(void) {
struct control_msg msg = {
.type = CONTROL_MSG_TYPE_INJECT_MOUSE_EVENT,
.inject_mouse_event = {
.action = AMOTION_EVENT_ACTION_DOWN,
.buttons = AMOTION_EVENT_BUTTON_PRIMARY,
.position = {
.point = {
.x = 260,
.y = 1026,
},
.screen_size = {
.width = 1080,
.height = 1920,
},
},
},
};
unsigned char buf[CONTROL_MSG_SERIALIZED_MAX_SIZE];
int size = control_msg_serialize(&msg, buf);
assert(size == 18);
const unsigned char expected[] = {
CONTROL_MSG_TYPE_INJECT_MOUSE_EVENT,
0x00, // AKEY_EVENT_ACTION_DOWN
0x00, 0x00, 0x00, 0x01, // AMOTION_EVENT_BUTTON_PRIMARY
0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x04, 0x02, // 260 1026
0x04, 0x38, 0x07, 0x80, // 1080 1920
};
assert(!memcmp(buf, expected, sizeof(expected)));
}
#include <stdio.h>
static void test_serialize_inject_touch_event(void) {
struct control_msg msg = {
.type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT,
@@ -117,12 +84,13 @@ static void test_serialize_inject_touch_event(void) {
},
},
.pressure = 1.0f,
.buttons = AMOTION_EVENT_BUTTON_PRIMARY,
},
};
unsigned char buf[CONTROL_MSG_SERIALIZED_MAX_SIZE];
int size = control_msg_serialize(&msg, buf);
assert(size == 24);
assert(size == 28);
const unsigned char expected[] = {
CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT,
@@ -131,6 +99,7 @@ static void test_serialize_inject_touch_event(void) {
0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0xc8, // 100 200
0x04, 0x38, 0x07, 0x80, // 1080 1920
0xff, 0xff, // pressure
0x00, 0x00, 0x00, 0x01 // AMOTION_EVENT_BUTTON_PRIMARY
};
assert(!memcmp(buf, expected, sizeof(expected)));
}
@@ -271,7 +240,6 @@ int main(void) {
test_serialize_inject_keycode();
test_serialize_inject_text();
test_serialize_inject_text_long();
test_serialize_inject_mouse_event();
test_serialize_inject_touch_event();
test_serialize_inject_scroll_event();
test_serialize_back_or_screen_on();

View File

@@ -7,15 +7,14 @@ public final class ControlMessage {
public static final int TYPE_INJECT_KEYCODE = 0;
public static final int TYPE_INJECT_TEXT = 1;
public static final int TYPE_INJECT_MOUSE_EVENT = 2;
public static final int TYPE_INJECT_TOUCH_EVENT = 3;
public static final int TYPE_INJECT_SCROLL_EVENT = 4;
public static final int TYPE_BACK_OR_SCREEN_ON = 5;
public static final int TYPE_EXPAND_NOTIFICATION_PANEL = 6;
public static final int TYPE_COLLAPSE_NOTIFICATION_PANEL = 7;
public static final int TYPE_GET_CLIPBOARD = 8;
public static final int TYPE_SET_CLIPBOARD = 9;
public static final int TYPE_SET_SCREEN_POWER_MODE = 10;
public static final int TYPE_INJECT_TOUCH_EVENT = 2;
public static final int TYPE_INJECT_SCROLL_EVENT = 3;
public static final int TYPE_BACK_OR_SCREEN_ON = 4;
public static final int TYPE_EXPAND_NOTIFICATION_PANEL = 5;
public static final int TYPE_COLLAPSE_NOTIFICATION_PANEL = 6;
public static final int TYPE_GET_CLIPBOARD = 7;
public static final int TYPE_SET_CLIPBOARD = 8;
public static final int TYPE_SET_SCREEN_POWER_MODE = 9;
private int type;
private String text;
@@ -48,22 +47,15 @@ public final class ControlMessage {
return msg;
}
public static ControlMessage createInjectMouseEvent(int action, int buttons, Position position) {
ControlMessage msg = new ControlMessage();
msg.type = TYPE_INJECT_MOUSE_EVENT;
msg.action = action;
msg.buttons = buttons;
msg.position = position;
return msg;
}
public static ControlMessage createInjectTouchEvent(int action, long pointerId, Position position, float pressure) {
public static ControlMessage createInjectTouchEvent(int action, long pointerId, Position position, float pressure,
int buttons) {
ControlMessage msg = new ControlMessage();
msg.type = TYPE_INJECT_TOUCH_EVENT;
msg.action = action;
msg.pointerId = pointerId;
msg.pressure = pressure;
msg.position = position;
msg.buttons = buttons;
return msg;
}

View File

@@ -60,9 +60,6 @@ public class ControlMessageReader {
case ControlMessage.TYPE_INJECT_TEXT:
msg = parseInjectText();
break;
case ControlMessage.TYPE_INJECT_MOUSE_EVENT:
msg = parseInjectMouseEvent();
break;
case ControlMessage.TYPE_INJECT_TOUCH_EVENT:
msg = parseInjectTouchEvent();
break;
@@ -124,16 +121,6 @@ public class ControlMessageReader {
return ControlMessage.createInjectText(text);
}
private ControlMessage parseInjectMouseEvent() {
if (buffer.remaining() < INJECT_MOUSE_EVENT_PAYLOAD_LENGTH) {
return null;
}
int action = toUnsigned(buffer.get());
int buttons = buffer.getInt();
Position position = readPosition(buffer);
return ControlMessage.createInjectMouseEvent(action, buttons, position);
}
@SuppressWarnings("checkstyle:MagicNumber")
private ControlMessage parseInjectTouchEvent() {
if (buffer.remaining() < INJECT_TOUCH_EVENT_PAYLOAD_LENGTH) {
@@ -146,7 +133,8 @@ public class ControlMessageReader {
int pressureInt = toUnsigned(buffer.getShort());
// convert it to a float between 0 and 1 (0x1p16f is 2^16 as float)
float pressure = pressureInt == 0xffff ? 1f : (pressureInt / 0x1p16f);
return ControlMessage.createInjectTouchEvent(action, pointerId, position, pressure);
int buttons = buffer.getInt();
return ControlMessage.createInjectTouchEvent(action, pointerId, position, pressure, buttons);
}
private ControlMessage parseInjectScrollEvent() {

View File

@@ -19,37 +19,21 @@ public class Controller {
private final KeyCharacterMap charMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
private long lastMouseDown;
private final MotionEvent.PointerProperties[] mousePointerProperties = {new MotionEvent.PointerProperties()};
private final MotionEvent.PointerCoords[] mousePointerCoords = {new MotionEvent.PointerCoords()};
private long lastTouchDown;
private final PointersState pointersState = new PointersState();
private final MotionEvent.PointerProperties[] touchPointerProperties =
private final MotionEvent.PointerProperties[] pointerProperties =
new MotionEvent.PointerProperties[PointersState.MAX_POINTERS];
private final MotionEvent.PointerCoords[] touchPointerCoords =
private final MotionEvent.PointerCoords[] pointerCoords =
new MotionEvent.PointerCoords[PointersState.MAX_POINTERS];
public Controller(Device device, DesktopConnection connection) {
this.device = device;
this.connection = connection;
initMousePointer();
initTouchPointers();
initPointers();
sender = new DeviceMessageSender(connection);
}
private void initMousePointer() {
MotionEvent.PointerProperties props = mousePointerProperties[0];
props.id = 0;
props.toolType = MotionEvent.TOOL_TYPE_FINGER;
MotionEvent.PointerCoords coords = mousePointerCoords[0];
coords.orientation = 0;
coords.pressure = 1;
coords.size = 1;
}
private void initTouchPointers() {
private void initPointers() {
for (int i = 0; i < PointersState.MAX_POINTERS; ++i) {
MotionEvent.PointerProperties props = new MotionEvent.PointerProperties();
props.toolType = MotionEvent.TOOL_TYPE_FINGER;
@@ -58,23 +42,11 @@ public class Controller {
coords.orientation = 0;
coords.size = 1;
touchPointerProperties[i] = props;
touchPointerCoords[i] = coords;
pointerProperties[i] = props;
pointerCoords[i] = coords;
}
}
private void setMousePointerCoords(Point point) {
MotionEvent.PointerCoords coords = mousePointerCoords[0];
coords.x = point.getX();
coords.y = point.getY();
}
private void setScroll(int hScroll, int vScroll) {
MotionEvent.PointerCoords coords = mousePointerCoords[0];
coords.setAxisValue(MotionEvent.AXIS_HSCROLL, hScroll);
coords.setAxisValue(MotionEvent.AXIS_VSCROLL, vScroll);
}
@SuppressWarnings("checkstyle:MagicNumber")
public void control() throws IOException {
// on start, power on the device
@@ -109,11 +81,8 @@ public class Controller {
case ControlMessage.TYPE_INJECT_TEXT:
injectText(msg.getText());
break;
case ControlMessage.TYPE_INJECT_MOUSE_EVENT:
injectMouse(msg.getAction(), msg.getButtons(), msg.getPosition());
break;
case ControlMessage.TYPE_INJECT_TOUCH_EVENT:
injectTouch(msg.getAction(), msg.getPointerId(), msg.getPosition(), msg.getPressure());
injectTouch(msg.getAction(), msg.getPointerId(), msg.getPosition(), msg.getPressure(), 0);
break;
case ControlMessage.TYPE_INJECT_SCROLL_EVENT:
injectScroll(msg.getPosition(), msg.getHScroll(), msg.getVScroll());
@@ -173,23 +142,7 @@ public class Controller {
return successCount;
}
private boolean injectMouse(int action, int buttons, Position position) {
long now = SystemClock.uptimeMillis();
if (action == MotionEvent.ACTION_DOWN) {
lastMouseDown = now;
}
Point point = device.getPhysicalPoint(position);
if (point == null) {
// ignore event
return false;
}
setMousePointerCoords(point);
MotionEvent event = MotionEvent.obtain(lastMouseDown, now, action, 1, mousePointerProperties,
mousePointerCoords, 0, buttons, 1f, 1f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
return injectEvent(event);
}
private boolean injectTouch(int action, long pointerId, Position position, float pressure) {
private boolean injectTouch(int action, long pointerId, Position position, float pressure, int buttons) {
long now = SystemClock.uptimeMillis();
Point point = device.getPhysicalPoint(position);
@@ -208,7 +161,7 @@ public class Controller {
pointer.setPressure(pressure);
pointer.setUp(action == MotionEvent.ACTION_UP);
int pointerCount = pointersState.update(touchPointerProperties, touchPointerCoords);
int pointerCount = pointersState.update(pointerProperties, pointerCoords);
if (pointerCount == 1) {
if (action == MotionEvent.ACTION_DOWN) {
@@ -223,8 +176,8 @@ public class Controller {
}
}
MotionEvent event = MotionEvent.obtain(lastTouchDown, now, action, pointerCount, touchPointerProperties,
touchPointerCoords, 0, 0, 1f, 1f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
MotionEvent event = MotionEvent.obtain(lastTouchDown, now, action, pointerCount, pointerProperties,
pointerCoords, 0, 0, 1f, 1f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
return injectEvent(event);
}
@@ -235,10 +188,18 @@ public class Controller {
// ignore event
return false;
}
setMousePointerCoords(point);
setScroll(hScroll, vScroll);
MotionEvent event = MotionEvent.obtain(lastMouseDown, now, MotionEvent.ACTION_SCROLL, 1,
mousePointerProperties, mousePointerCoords, 0, 0, 1f, 1f, 0, 0, InputDevice.SOURCE_MOUSE, 0);
MotionEvent.PointerProperties props = pointerProperties[0];
props.id = 0;
MotionEvent.PointerCoords coords = pointerCoords[0];
coords.x = point.getX();
coords.y = point.getY();
coords.setAxisValue(MotionEvent.AXIS_HSCROLL, hScroll);
coords.setAxisValue(MotionEvent.AXIS_VSCROLL, vScroll);
MotionEvent event = MotionEvent.obtain(lastTouchDown, now, MotionEvent.ACTION_SCROLL, 1, pointerProperties,
pointerCoords, 0, 0, 1f, 1f, 0, 0, InputDevice.SOURCE_MOUSE, 0);
return injectEvent(event);
}

View File

@@ -76,35 +76,6 @@ public class ControlMessageReaderTest {
Assert.assertEquals(new String(text, StandardCharsets.US_ASCII), event.getText());
}
@Test
@SuppressWarnings("checkstyle:MagicNumber")
public void testParseMouseEvent() throws IOException {
ControlMessageReader reader = new ControlMessageReader();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeByte(ControlMessage.TYPE_INJECT_MOUSE_EVENT);
dos.writeByte(MotionEvent.ACTION_DOWN);
dos.writeInt(MotionEvent.BUTTON_PRIMARY);
dos.writeInt(100);
dos.writeInt(200);
dos.writeShort(1080);
dos.writeShort(1920);
byte[] packet = bos.toByteArray();
reader.readFrom(new ByteArrayInputStream(packet));
ControlMessage event = reader.next();
Assert.assertEquals(ControlMessage.TYPE_INJECT_MOUSE_EVENT, event.getType());
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getButtons());
Assert.assertEquals(100, event.getPosition().getPoint().getX());
Assert.assertEquals(200, event.getPosition().getPoint().getY());
Assert.assertEquals(1080, event.getPosition().getScreenSize().getWidth());
Assert.assertEquals(1920, event.getPosition().getScreenSize().getHeight());
}
@Test
@SuppressWarnings("checkstyle:MagicNumber")
public void testParseTouchEvent() throws IOException {
@@ -120,6 +91,7 @@ public class ControlMessageReaderTest {
dos.writeShort(1080);
dos.writeShort(1920);
dos.writeShort(0xffff); // pressure
dos.writeInt(MotionEvent.BUTTON_PRIMARY);
byte[] packet = bos.toByteArray();
@@ -134,6 +106,7 @@ public class ControlMessageReaderTest {
Assert.assertEquals(1080, event.getPosition().getScreenSize().getWidth());
Assert.assertEquals(1920, event.getPosition().getScreenSize().getHeight());
Assert.assertEquals(1f, event.getPressure(), 0f); // must be exact
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getButtons());
}
@Test