From 6220456def65e00696a268ac654756a8b22a96a7 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Thu, 3 Oct 2019 20:14:12 +0200 Subject: [PATCH] Merge mouse and touch events Both are handled the very same way on the device. --- app/src/control_msg.c | 8 +--- app/src/control_msg.h | 7 +-- app/src/event_converter.c | 47 ++++++++++--------- app/tests/test_control_msg_serialize.c | 38 ++------------- .../com/genymobile/scrcpy/ControlMessage.java | 30 +++++------- .../scrcpy/ControlMessageReader.java | 16 +------ .../com/genymobile/scrcpy/Controller.java | 3 -- .../com/genymobile/scrcpy/PointersState.java | 1 - .../scrcpy/ControlMessageReaderTest.java | 31 +----------- 9 files changed, 48 insertions(+), 133 deletions(-) diff --git a/app/src/control_msg.c b/app/src/control_msg.c index 11e87e40..e042dc5a 100644 --- a/app/src/control_msg.c +++ b/app/src/control_msg.c @@ -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], diff --git a/app/src/control_msg.h b/app/src/control_msg.h index 546564cf..2f319d9d 100644 --- a/app/src/control_msg.h +++ b/app/src/control_msg.h @@ -15,10 +15,11 @@ #define CONTROL_MSG_SERIALIZED_MAX_SIZE \ (3 + CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH) +#define POINTER_ID_MOUSE UINT64_C(-1); + 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 +50,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; diff --git a/app/src/event_converter.c b/app/src/event_converter.c index e9fbe13b..13abfab2 100644 --- a/app/src/event_converter.c +++ b/app/src/event_converter.c @@ -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; } diff --git a/app/tests/test_control_msg_serialize.c b/app/tests/test_control_msg_serialize.c index ea06211a..83ab011f 100644 --- a/app/tests/test_control_msg_serialize.c +++ b/app/tests/test_control_msg_serialize.c @@ -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))); -} - 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(); diff --git a/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java b/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java index 34da7741..30c05a3b 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java +++ b/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java @@ -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; } diff --git a/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java b/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java index e6a6c905..2f8b5177 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java +++ b/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java @@ -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() { diff --git a/server/src/main/java/com/genymobile/scrcpy/Controller.java b/server/src/main/java/com/genymobile/scrcpy/Controller.java index 8c5e645a..19bf9d94 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Controller.java +++ b/server/src/main/java/com/genymobile/scrcpy/Controller.java @@ -81,9 +81,6 @@ public class Controller { case ControlMessage.TYPE_INJECT_TEXT: injectText(msg.getText()); break; - case ControlMessage.TYPE_INJECT_MOUSE_EVENT: - injectTouch(msg.getAction(), PointersState.POINTER_ID_MOUSE, msg.getPosition(), 1, msg.getButtons()); - break; case ControlMessage.TYPE_INJECT_TOUCH_EVENT: injectTouch(msg.getAction(), msg.getPointerId(), msg.getPosition(), msg.getPressure(), 0); break; diff --git a/server/src/main/java/com/genymobile/scrcpy/PointersState.java b/server/src/main/java/com/genymobile/scrcpy/PointersState.java index eab258b1..d8daaff2 100644 --- a/server/src/main/java/com/genymobile/scrcpy/PointersState.java +++ b/server/src/main/java/com/genymobile/scrcpy/PointersState.java @@ -8,7 +8,6 @@ import java.util.List; public class PointersState { public static final int MAX_POINTERS = 10; - public static final long POINTER_ID_MOUSE = -1; private final List pointers = new ArrayList<>(); diff --git a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java index 33380295..ede759dc 100644 --- a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java +++ b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java @@ -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