From 0afef0c6349e3c79ebcdc24d955f61fdc27c42f4 Mon Sep 17 00:00:00 2001 From: Simon Chan <1330321+yume-chan@users.noreply.github.com> Date: Sun, 29 Jan 2023 22:14:05 +0100 Subject: [PATCH] Forward action button to device On click event, only the whole buttons state was passed to the device. In addition, on ACTION_DOWN and ACTION_UP, pass the button associated to the action. Refs #3635 Co-authored-by: Romain Vimont Signed-off-by: Romain Vimont --- app/src/control_msg.c | 12 ++++++++---- app/src/control_msg.h | 1 + app/src/input_manager.c | 1 + app/src/mouse_inject.c | 1 + app/tests/test_control_msg_serialize.c | 6 ++++-- .../java/com/genymobile/scrcpy/ControlMessage.java | 9 ++++++++- .../com/genymobile/scrcpy/ControlMessageReader.java | 5 +++-- .../genymobile/scrcpy/ControlMessageReaderTest.java | 4 +++- 8 files changed, 29 insertions(+), 10 deletions(-) diff --git a/app/src/control_msg.c b/app/src/control_msg.c index 60bbd826..d4d6c62a 100644 --- a/app/src/control_msg.c +++ b/app/src/control_msg.c @@ -117,8 +117,9 @@ sc_control_msg_serialize(const struct sc_control_msg *msg, unsigned char *buf) { uint16_t pressure = sc_float_to_u16fp(msg->inject_touch_event.pressure); sc_write16be(&buf[22], pressure); - sc_write32be(&buf[24], msg->inject_touch_event.buttons); - return 28; + sc_write32be(&buf[24], msg->inject_touch_event.action_button); + sc_write32be(&buf[28], msg->inject_touch_event.buttons); + return 32; case SC_CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT: write_position(&buf[1], &msg->inject_scroll_event.position); int16_t hscroll = @@ -179,22 +180,25 @@ sc_control_msg_log(const struct sc_control_msg *msg) { if (pointer_name) { // string pointer id LOG_CMSG("touch [id=%s] %-4s position=%" PRIi32 ",%" PRIi32 - " pressure=%f buttons=%06lx", + " pressure=%f action_button=%06lx buttons=%06lx", pointer_name, MOTIONEVENT_ACTION_LABEL(action), msg->inject_touch_event.position.point.x, msg->inject_touch_event.position.point.y, msg->inject_touch_event.pressure, + (long) msg->inject_touch_event.action_button, (long) msg->inject_touch_event.buttons); } else { // numeric pointer id LOG_CMSG("touch [id=%" PRIu64_ "] %-4s position=%" PRIi32 ",%" - PRIi32 " pressure=%f buttons=%06lx", + PRIi32 " pressure=%f action_button=%06lx" + " buttons=%06lx", id, MOTIONEVENT_ACTION_LABEL(action), msg->inject_touch_event.position.point.x, msg->inject_touch_event.position.point.y, msg->inject_touch_event.pressure, + (long) msg->inject_touch_event.action_button, (long) msg->inject_touch_event.buttons); } break; diff --git a/app/src/control_msg.h b/app/src/control_msg.h index eb7e25b3..b90a00b3 100644 --- a/app/src/control_msg.h +++ b/app/src/control_msg.h @@ -65,6 +65,7 @@ struct sc_control_msg { } inject_text; struct { enum android_motionevent_action action; + enum android_motionevent_buttons action_button; enum android_motionevent_buttons buttons; uint64_t pointer_id; struct sc_position position; diff --git a/app/src/input_manager.c b/app/src/input_manager.c index ee95d00a..c8098ee7 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -339,6 +339,7 @@ simulate_virtual_finger(struct sc_input_manager *im, im->forward_all_clicks ? POINTER_ID_VIRTUAL_MOUSE : POINTER_ID_VIRTUAL_FINGER; msg.inject_touch_event.pressure = up ? 0.0f : 1.0f; + msg.inject_touch_event.action_button = 0; msg.inject_touch_event.buttons = 0; if (!sc_controller_push_msg(im->controller, &msg)) { diff --git a/app/src/mouse_inject.c b/app/src/mouse_inject.c index bca94637..71b7a64d 100644 --- a/app/src/mouse_inject.c +++ b/app/src/mouse_inject.c @@ -93,6 +93,7 @@ sc_mouse_processor_process_mouse_click(struct sc_mouse_processor *mp, .pointer_id = event->pointer_id, .position = event->position, .pressure = event->action == SC_ACTION_DOWN ? 1.f : 0.f, + .action_button = convert_mouse_buttons(event->button), .buttons = convert_mouse_buttons(event->buttons_state), }, }; diff --git a/app/tests/test_control_msg_serialize.c b/app/tests/test_control_msg_serialize.c index 87117e3a..b2eef49c 100644 --- a/app/tests/test_control_msg_serialize.c +++ b/app/tests/test_control_msg_serialize.c @@ -90,13 +90,14 @@ static void test_serialize_inject_touch_event(void) { }, }, .pressure = 1.0f, + .action_button = AMOTION_EVENT_BUTTON_PRIMARY, .buttons = AMOTION_EVENT_BUTTON_PRIMARY, }, }; unsigned char buf[SC_CONTROL_MSG_MAX_SIZE]; size_t size = sc_control_msg_serialize(&msg, buf); - assert(size == 28); + assert(size == 32); const unsigned char expected[] = { SC_CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT, @@ -105,7 +106,8 @@ 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 + 0x00, 0x00, 0x00, 0x01, // AMOTION_EVENT_BUTTON_PRIMARY (action button) + 0x00, 0x00, 0x00, 0x01, // AMOTION_EVENT_BUTTON_PRIMARY (buttons) }; assert(!memcmp(buf, expected, sizeof(expected))); } diff --git a/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java b/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java index 0b05b22a..e1800374 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java +++ b/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java @@ -29,6 +29,7 @@ public final class ControlMessage { private int metaState; // KeyEvent.META_* private int action; // KeyEvent.ACTION_* or MotionEvent.ACTION_* or POWER_MODE_* private int keycode; // KeyEvent.KEYCODE_* + private int actionButton; // MotionEvent.BUTTON_* private int buttons; // MotionEvent.BUTTON_* private long pointerId; private float pressure; @@ -60,13 +61,15 @@ public final class ControlMessage { return msg; } - public static ControlMessage createInjectTouchEvent(int action, long pointerId, Position position, float pressure, int buttons) { + public static ControlMessage createInjectTouchEvent(int action, long pointerId, Position position, float pressure, int actionButton, + 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.actionButton = actionButton; msg.buttons = buttons; return msg; } @@ -140,6 +143,10 @@ public final class ControlMessage { return keycode; } + public int getActionButton() { + return actionButton; + } + public int getButtons() { return buttons; } diff --git a/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java b/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java index a52fd134..d95c36d8 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java +++ b/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java @@ -9,7 +9,7 @@ import java.nio.charset.StandardCharsets; public class ControlMessageReader { static final int INJECT_KEYCODE_PAYLOAD_LENGTH = 13; - static final int INJECT_TOUCH_EVENT_PAYLOAD_LENGTH = 27; + static final int INJECT_TOUCH_EVENT_PAYLOAD_LENGTH = 31; static final int INJECT_SCROLL_EVENT_PAYLOAD_LENGTH = 20; static final int BACK_OR_SCREEN_ON_LENGTH = 1; static final int SET_SCREEN_POWER_MODE_PAYLOAD_LENGTH = 1; @@ -140,8 +140,9 @@ public class ControlMessageReader { long pointerId = buffer.getLong(); Position position = readPosition(buffer); float pressure = Binary.u16FixedPointToFloat(buffer.getShort()); + int actionButton = buffer.getInt(); int buttons = buffer.getInt(); - return ControlMessage.createInjectTouchEvent(action, pointerId, position, pressure, buttons); + return ControlMessage.createInjectTouchEvent(action, pointerId, position, pressure, actionButton, buttons); } private ControlMessage parseInjectScrollEvent() { diff --git a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java index 1fc009ce..8405905a 100644 --- a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java +++ b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java @@ -94,7 +94,8 @@ public class ControlMessageReaderTest { dos.writeShort(1080); dos.writeShort(1920); dos.writeShort(0xffff); // pressure - dos.writeInt(MotionEvent.BUTTON_PRIMARY); + dos.writeInt(MotionEvent.BUTTON_PRIMARY); // action button + dos.writeInt(MotionEvent.BUTTON_PRIMARY); // buttons byte[] packet = bos.toByteArray(); @@ -112,6 +113,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.getActionButton()); Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getButtons()); }