diff --git a/app/src/control_msg.c b/app/src/control_msg.c index 6ccdc054..75c74628 100644 --- a/app/src/control_msg.c +++ b/app/src/control_msg.c @@ -119,7 +119,8 @@ control_msg_serialize(const struct control_msg *msg, unsigned char *buf) { (uint32_t) msg->inject_scroll_event.hscroll); buffer_write32be(&buf[17], (uint32_t) msg->inject_scroll_event.vscroll); - return 21; + buffer_write32be(&buf[21], msg->inject_scroll_event.buttons); + return 25; case CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON: buf[1] = msg->inject_keycode.action; return 2; @@ -192,11 +193,12 @@ control_msg_log(const struct control_msg *msg) { } case CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT: LOG_CMSG("scroll position=%" PRIi32 ",%" PRIi32 " hscroll=%" PRIi32 - " vscroll=%" PRIi32, + " vscroll=%" PRIi32 " buttons=%06lx", msg->inject_scroll_event.position.point.x, msg->inject_scroll_event.position.point.y, msg->inject_scroll_event.hscroll, - msg->inject_scroll_event.vscroll); + msg->inject_scroll_event.vscroll, + (long) msg->inject_scroll_event.buttons); break; case CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON: LOG_CMSG("back-or-screen-on %s", diff --git a/app/src/control_msg.h b/app/src/control_msg.h index 7f3235d7..0eadd4f2 100644 --- a/app/src/control_msg.h +++ b/app/src/control_msg.h @@ -70,6 +70,7 @@ struct control_msg { struct sc_position position; int32_t hscroll; int32_t vscroll; + enum android_motionevent_buttons buttons; } inject_scroll_event; struct { enum android_keyevent_action action; // action for the BACK key diff --git a/app/src/input_events.h b/app/src/input_events.h index 48c51ee7..c27a7a47 100644 --- a/app/src/input_events.h +++ b/app/src/input_events.h @@ -360,6 +360,7 @@ struct sc_mouse_scroll_event { struct sc_position position; int32_t hscroll; int32_t vscroll; + uint8_t buttons_state; // bitwise-OR of sc_mouse_button values }; struct sc_mouse_motion_event { diff --git a/app/src/input_manager.c b/app/src/input_manager.c index ec91787a..64922f28 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -810,7 +810,7 @@ input_manager_process_mouse_wheel(struct input_manager *im, // mouse_x and mouse_y are expressed in pixels relative to the window int mouse_x; int mouse_y; - SDL_GetMouseState(&mouse_x, &mouse_y); + uint32_t buttons = SDL_GetMouseState(&mouse_x, &mouse_y); struct sc_mouse_scroll_event evt = { .position = { @@ -820,6 +820,8 @@ input_manager_process_mouse_wheel(struct input_manager *im, }, .hscroll = event->x, .vscroll = event->y, + .buttons_state = + sc_mouse_buttons_state_from_sdl(buttons, im->forward_all_clicks), }; im->mp->ops->process_mouse_scroll(im->mp, &evt); diff --git a/app/src/mouse_inject.c b/app/src/mouse_inject.c index 1d14509d..38bfa404 100644 --- a/app/src/mouse_inject.c +++ b/app/src/mouse_inject.c @@ -108,6 +108,7 @@ sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp, .position = event->position, .hscroll = event->hscroll, .vscroll = event->vscroll, + .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 42b72b59..d1f0f161 100644 --- a/app/tests/test_control_msg_serialize.c +++ b/app/tests/test_control_msg_serialize.c @@ -126,12 +126,13 @@ static void test_serialize_inject_scroll_event(void) { }, .hscroll = 1, .vscroll = -1, + .buttons = 1, }, }; unsigned char buf[CONTROL_MSG_MAX_SIZE]; size_t size = control_msg_serialize(&msg, buf); - assert(size == 21); + assert(size == 25); const unsigned char expected[] = { CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT, @@ -139,6 +140,7 @@ static void test_serialize_inject_scroll_event(void) { 0x04, 0x38, 0x07, 0x80, // 1080 1920 0x00, 0x00, 0x00, 0x01, // 1 0xFF, 0xFF, 0xFF, 0xFF, // -1 + 0x00, 0x00, 0x00, 0x01, // 1 }; 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 63ba0fa3..99eb805f 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java +++ b/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java @@ -71,12 +71,13 @@ public final class ControlMessage { return msg; } - public static ControlMessage createInjectScrollEvent(Position position, int hScroll, int vScroll) { + public static ControlMessage createInjectScrollEvent(Position position, int hScroll, int vScroll, int buttons) { ControlMessage msg = new ControlMessage(); msg.type = TYPE_INJECT_SCROLL_EVENT; msg.position = position; msg.hScroll = hScroll; msg.vScroll = vScroll; + 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 f09ed26f..24dc5e50 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java +++ b/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java @@ -10,7 +10,7 @@ public class ControlMessageReader { static final int INJECT_KEYCODE_PAYLOAD_LENGTH = 13; static final int INJECT_TOUCH_EVENT_PAYLOAD_LENGTH = 27; - static final int INJECT_SCROLL_EVENT_PAYLOAD_LENGTH = 20; + static final int INJECT_SCROLL_EVENT_PAYLOAD_LENGTH = 24; static final int BACK_OR_SCREEN_ON_LENGTH = 1; static final int SET_SCREEN_POWER_MODE_PAYLOAD_LENGTH = 1; static final int GET_CLIPBOARD_LENGTH = 1; @@ -154,7 +154,8 @@ public class ControlMessageReader { Position position = readPosition(buffer); int hScroll = buffer.getInt(); int vScroll = buffer.getInt(); - return ControlMessage.createInjectScrollEvent(position, hScroll, vScroll); + int buttons = buffer.getInt(); + return ControlMessage.createInjectScrollEvent(position, hScroll, vScroll, buttons); } private ControlMessage parseBackOrScreenOnEvent() { diff --git a/server/src/main/java/com/genymobile/scrcpy/Controller.java b/server/src/main/java/com/genymobile/scrcpy/Controller.java index 9246004a..481c512f 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Controller.java +++ b/server/src/main/java/com/genymobile/scrcpy/Controller.java @@ -98,7 +98,7 @@ public class Controller { break; case ControlMessage.TYPE_INJECT_SCROLL_EVENT: if (device.supportsInputEvents()) { - injectScroll(msg.getPosition(), msg.getHScroll(), msg.getVScroll()); + injectScroll(msg.getPosition(), msg.getHScroll(), msg.getVScroll(), msg.getButtons()); } break; case ControlMessage.TYPE_BACK_OR_SCREEN_ON: @@ -221,7 +221,7 @@ public class Controller { return device.injectEvent(event, Device.INJECT_MODE_ASYNC); } - private boolean injectScroll(Position position, int hScroll, int vScroll) { + private boolean injectScroll(Position position, int hScroll, int vScroll, int buttons) { long now = SystemClock.uptimeMillis(); Point point = device.getPhysicalPoint(position); if (point == null) { @@ -239,7 +239,7 @@ public class Controller { coords.setAxisValue(MotionEvent.AXIS_VSCROLL, vScroll); MotionEvent event = MotionEvent - .obtain(lastTouchDown, now, MotionEvent.ACTION_SCROLL, 1, pointerProperties, pointerCoords, 0, 0, 1f, 1f, DEFAULT_DEVICE_ID, 0, + .obtain(lastTouchDown, now, MotionEvent.ACTION_SCROLL, 1, pointerProperties, pointerCoords, 0, buttons, 1f, 1f, DEFAULT_DEVICE_ID, 0, InputDevice.SOURCE_MOUSE, 0); return device.injectEvent(event, Device.INJECT_MODE_ASYNC); } diff --git a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java index 5e79d4f0..2a4ffe75 100644 --- a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java +++ b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java @@ -128,6 +128,7 @@ public class ControlMessageReaderTest { dos.writeShort(1920); dos.writeInt(1); dos.writeInt(-1); + dos.writeInt(1); byte[] packet = bos.toByteArray(); @@ -144,6 +145,7 @@ public class ControlMessageReaderTest { Assert.assertEquals(1920, event.getPosition().getScreenSize().getHeight()); Assert.assertEquals(1, event.getHScroll()); Assert.assertEquals(-1, event.getVScroll()); + Assert.assertEquals(1, event.getButtons()); } @Test