Compare commits

..

20 Commits

Author SHA1 Message Date
Romain Vimont
2594354bce notouch 2021-12-30 15:10:16 +01:00
Romain Vimont
fe229a8c5f vscroll 2021-12-30 15:09:28 +01:00
Romain Vimont
0c03b53ad4 wip 2021-12-30 15:09:28 +01:00
Romain Vimont
71fbbf6484 wip 2021-12-30 15:09:28 +01:00
Romain Vimont
3345be133a Add relative mouse motion in event
This will allow the mouse processor to handle relative motion easily.
2021-12-30 15:09:28 +01:00
Romain Vimont
a88a7f6325 relative-mouse-mode 2021-12-30 15:09:28 +01:00
Romain Vimont
52349740ef hid_mouse 2021-12-30 15:09:28 +01:00
Romain Vimont
dec9e436c2 Add CLAMP() macro 2021-12-30 15:09:28 +01:00
Romain Vimont
a0d1c23d8d Make some mouse processors ops optional
Do not force all mouse processors implementations to implement scroll
events or touch events.
2021-12-30 15:08:42 +01:00
Romain Vimont
05474b0cd6 Make process_text() optional
Not all key processors support text injection (HID keyboard does not
support it).

Instead of providing a dummy op function, set it to NULL and check on
the caller side before calling it.
2021-12-30 15:05:55 +01:00
Romain Vimont
b07cd47248 Apply buttons mask if not --forward-all-clicks
If --forward-all-clicks is not set, then only left clicks are forwarded.
For consistency, also mask the buttons state in other events.
2021-12-30 11:52:44 +01:00
Romain Vimont
bf5366f7ef Reorder mouse processor ops
Group the mouse events callbacks before the touch event callback.
2021-12-30 11:52:44 +01:00
Romain Vimont
2dd3466210 Simplify mouse injection implementation
The static functions are now so simple they become unnecessary: the
control message may be initialized directly instead.
2021-12-30 11:52:44 +01:00
Romain Vimont
5768ecdb48 Make some event conversions infallible
When the implementation handles all possible input values, it may never
fail.
2021-12-30 11:52:38 +01:00
Romain Vimont
8fcc5e9e4e Use scrcpy input events for mouse processors
Pass scrcpy input events instead of SDL input events to mouse
processors.

These events represent exactly what mouse processors need, abstracted
from any visual orientation and scaling applied on the SDL window.

This makes the mouse processors independent of the "screen" instance,
and the implementation source code independent of the SDL API.
2021-12-29 16:56:11 +01:00
Romain Vimont
c0cb944c94 Use scrcpy input events for key processors
Pass scrcpy input events instead of SDL input events to key processors.

This makes the source code of key processors independent of the SDL API.
2021-12-29 16:14:34 +01:00
Romain Vimont
57905a0e6d Use common sc_action in input manager
Now that the scrcpy input events API exposes a sc_action enum, use the
same from the input manager.
2021-12-29 15:56:59 +01:00
Romain Vimont
04b2b1d58f Add intermediate input events layer
This aims to make the key/mouse processors independent of the "screen",
instead of processing SDL events themselves.

In particular, these scrcpy events are not impacted by any UI window
scaling or rotation (contrary to SDL events).
2021-12-29 15:55:43 +01:00
Romain Vimont
ccfb4d3cfd Rename SC_MOD_* to SC_SHORTCUT_MOD_*
This will avoid conflicts with new SC_MOD_* constants.
2021-12-29 01:39:55 +01:00
Romain Vimont
49a788841d Remove actions bitset
The input manager exposed functions taking an "actions" parameter,
containing a bitmask-OR of ACTION_UP and ACTION_DOWN.

But they are never called with both actions simultaneously anymore, so
simplify.

Refs 964b6d2243
Refs d0739911a3
2021-12-29 01:34:54 +01:00
13 changed files with 25 additions and 65 deletions

View File

@@ -119,8 +119,7 @@ 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);
buffer_write32be(&buf[21], msg->inject_scroll_event.buttons);
return 25;
return 21;
case CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON:
buf[1] = msg->inject_keycode.action;
return 2;
@@ -193,12 +192,11 @@ 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 " buttons=%06lx",
" vscroll=%" PRIi32,
msg->inject_scroll_event.position.point.x,
msg->inject_scroll_event.position.point.y,
msg->inject_scroll_event.hscroll,
msg->inject_scroll_event.vscroll,
(long) msg->inject_scroll_event.buttons);
msg->inject_scroll_event.vscroll);
break;
case CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON:
LOG_CMSG("back-or-screen-on %s",

View File

@@ -70,7 +70,6 @@ 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

View File

@@ -43,24 +43,24 @@ static const unsigned char mouse_report_desc[] = {
// Usage Minimum (1)
0x19, 0x01,
// Usage Maximum (5)
0x29, 0x05,
// Usage Maximum (3)
0x29, 0x03,
// Logical Minimum (0)
0x15, 0x00,
// Logical Maximum (1)
0x25, 0x01,
// Report Count (5)
0x95, 0x05,
// Report Count (3)
0x95, 0x03,
// Report Size (1)
0x75, 0x01,
// Input (Data, Variable, Absolute): 5 buttons bits
// Input (Data, Variable, Absolute): 3 buttons bits
0x81, 0x02,
// Report Count (1)
0x95, 0x01,
// Report Size (3)
0x75, 0x03,
// Input (Constant): 3 bits padding
// Report Size (5)
0x75, 0x05,
// Input (Constant): 5 bits padding
0x81, 0x01,
// Usage Page (Generic Desktop)
@@ -98,14 +98,12 @@ static const unsigned char mouse_report_desc[] = {
*
* 7 6 5 4 3 2 1 0
* +---------------+
* byte 0: |0 0 0 . . . . .| buttons state
* byte 0: |0 0 0 0 0 . . .| buttons state
* +---------------+
* ^ ^ ^ ^ ^
* | | | | `- left button
* | | | `--- right button
* | | `----- middle button
* | `------- button 4
* `--------- button 5
* ^ ^ ^
* | | `- left button
* | `--- right button
* `----- middle button
*
* +---------------+
* byte 1: |. . . . . . . .| relative x motion
@@ -154,12 +152,7 @@ buttons_state_to_hid_buttons(uint8_t buttons_state) {
if (buttons_state & SC_MOUSE_BUTTON_MIDDLE) {
c |= 1 << 2;
}
if (buttons_state & SC_MOUSE_BUTTON_X1) {
c |= 1 << 3;
}
if (buttons_state & SC_MOUSE_BUTTON_X2) {
c |= 1 << 4;
}
// TODO buttons 4 and 5?
return c;
}

View File

@@ -361,7 +361,6 @@ 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 {

View File

@@ -777,12 +777,6 @@ input_manager_process_mouse_button(struct input_manager *im,
assert(im->mp->ops->process_mouse_click);
im->mp->ops->process_mouse_click(im->mp, &evt);
if (im->mp->relative_mode) {
assert(!im->vfinger_down); // vfinger must not be used in relative mode
// No pinch-to-zoom simulation
return;
}
// Pinch-to-zoom simulation.
//
// If Ctrl is hold when the left-click button is pressed, then
@@ -820,7 +814,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;
uint32_t buttons = SDL_GetMouseState(&mouse_x, &mouse_y);
SDL_GetMouseState(&mouse_x, &mouse_y);
struct sc_mouse_scroll_event evt = {
.position = {
@@ -830,8 +824,6 @@ 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);

View File

@@ -108,7 +108,6 @@ 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),
},
};
@@ -151,6 +150,4 @@ sc_mouse_inject_init(struct sc_mouse_inject *mi,
};
mi->mouse_processor.ops = &ops;
mi->mouse_processor.relative_mode = false;
}

View File

@@ -16,13 +16,6 @@
*/
struct sc_mouse_processor {
const struct sc_mouse_processor_ops *ops;
/**
* If set, the mouse processor works in relative mode (the absolute
* position is irrelevant). In particular, it indicates that the mouse
* pointer must be "captured" by the UI.
*/
bool relative_mode;
};
struct sc_mouse_processor_ops {

View File

@@ -11,7 +11,6 @@ static void test_get_ip_single_line() {
char *ip = sc_adb_parse_device_ip_from_output(ip_route, sizeof(ip_route));
assert(ip);
assert(!strcmp(ip, "192.168.12.34"));
free(ip);
}
static void test_get_ip_single_line_without_eol() {
@@ -21,7 +20,6 @@ static void test_get_ip_single_line_without_eol() {
char *ip = sc_adb_parse_device_ip_from_output(ip_route, sizeof(ip_route));
assert(ip);
assert(!strcmp(ip, "192.168.12.34"));
free(ip);
}
static void test_get_ip_single_line_with_trailing_space() {
@@ -31,7 +29,6 @@ static void test_get_ip_single_line_with_trailing_space() {
char *ip = sc_adb_parse_device_ip_from_output(ip_route, sizeof(ip_route));
assert(ip);
assert(!strcmp(ip, "192.168.12.34"));
free(ip);
}
static void test_get_ip_multiline_first_ok() {
@@ -43,7 +40,6 @@ static void test_get_ip_multiline_first_ok() {
char *ip = sc_adb_parse_device_ip_from_output(ip_route, sizeof(ip_route));
assert(ip);
assert(!strcmp(ip, "192.168.1.2"));
free(ip);
}
static void test_get_ip_multiline_second_ok() {
@@ -55,7 +51,6 @@ static void test_get_ip_multiline_second_ok() {
char *ip = sc_adb_parse_device_ip_from_output(ip_route, sizeof(ip_route));
assert(ip);
assert(!strcmp(ip, "192.168.1.3"));
free(ip);
}
static void test_get_ip_no_wlan() {

View File

@@ -126,13 +126,12 @@ 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 == 25);
assert(size == 21);
const unsigned char expected[] = {
CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT,
@@ -140,7 +139,6 @@ 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)));
}

View File

@@ -71,13 +71,12 @@ public final class ControlMessage {
return msg;
}
public static ControlMessage createInjectScrollEvent(Position position, int hScroll, int vScroll, int buttons) {
public static ControlMessage createInjectScrollEvent(Position position, int hScroll, int vScroll) {
ControlMessage msg = new ControlMessage();
msg.type = TYPE_INJECT_SCROLL_EVENT;
msg.position = position;
msg.hScroll = hScroll;
msg.vScroll = vScroll;
msg.buttons = buttons;
return msg;
}

View File

@@ -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 = 24;
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;
static final int GET_CLIPBOARD_LENGTH = 1;
@@ -154,8 +154,7 @@ public class ControlMessageReader {
Position position = readPosition(buffer);
int hScroll = buffer.getInt();
int vScroll = buffer.getInt();
int buttons = buffer.getInt();
return ControlMessage.createInjectScrollEvent(position, hScroll, vScroll, buttons);
return ControlMessage.createInjectScrollEvent(position, hScroll, vScroll);
}
private ControlMessage parseBackOrScreenOnEvent() {

View File

@@ -98,7 +98,7 @@ public class Controller {
break;
case ControlMessage.TYPE_INJECT_SCROLL_EVENT:
if (device.supportsInputEvents()) {
injectScroll(msg.getPosition(), msg.getHScroll(), msg.getVScroll(), msg.getButtons());
injectScroll(msg.getPosition(), msg.getHScroll(), msg.getVScroll());
}
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, int buttons) {
private boolean injectScroll(Position position, int hScroll, int vScroll) {
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, buttons, 1f, 1f, DEFAULT_DEVICE_ID, 0,
.obtain(lastTouchDown, now, MotionEvent.ACTION_SCROLL, 1, pointerProperties, pointerCoords, 0, 0, 1f, 1f, DEFAULT_DEVICE_ID, 0,
InputDevice.SOURCE_MOUSE, 0);
return device.injectEvent(event, Device.INJECT_MODE_ASYNC);
}

View File

@@ -128,7 +128,6 @@ public class ControlMessageReaderTest {
dos.writeShort(1920);
dos.writeInt(1);
dos.writeInt(-1);
dos.writeInt(1);
byte[] packet = bos.toByteArray();
@@ -145,7 +144,6 @@ 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