From 9460bdd87ba76f03ff27e98973073a6acd8ed306 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Wed, 29 Dec 2021 16:24:20 +0100 Subject: [PATCH] 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. --- app/src/input_manager.c | 101 ++++++++++++++++++++- app/src/mouse_inject.c | 152 +++++++++++++------------------- app/src/mouse_inject.h | 4 +- app/src/scrcpy.c | 2 +- app/src/trait/mouse_processor.h | 14 +-- 5 files changed, 169 insertions(+), 104 deletions(-) diff --git a/app/src/input_manager.c b/app/src/input_manager.c index 03d19b0e..ba6a4e2a 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -30,6 +30,44 @@ sc_action_from_sdl_keyboard_type(uint32_t type) { return SC_ACTION_UP; } +static inline enum sc_action +sc_action_from_sdl_mousebutton_type(uint32_t type) { + assert(type == SDL_MOUSEBUTTONDOWN || type == SDL_MOUSEBUTTONUP); + if (type == SDL_MOUSEBUTTONDOWN) { + return SC_ACTION_DOWN; + } + return SC_ACTION_UP; +} + +static inline enum sc_touch_action +sc_touch_action_from_sdl(uint32_t type) { + assert(type == SDL_FINGERMOTION || type == SDL_FINGERDOWN || + type == SDL_FINGERUP); + if (type == SDL_FINGERMOTION) { + return SC_TOUCH_ACTION_MOVE; + } + if (type == SDL_FINGERDOWN) { + return SC_TOUCH_ACTION_DOWN; + } + return SC_TOUCH_ACTION_UP; +} + +static inline enum sc_mouse_button +sc_mouse_button_from_sdl(uint8_t button) { + if (button >= SDL_BUTTON_LEFT && button <= SDL_BUTTON_X2) { + // SC_MOUSE_BUTTON_* constants are initialized from SDL_BUTTON(index) + return SDL_BUTTON(button); + } + + return SC_MOUSE_BUTTON_UNKNOWN; +} + +static inline uint8_t +sc_mouse_buttons_state_from_sdl(uint32_t buttons_state) { + assert(buttons_state < 0x100); // fits in uint8_t + return buttons_state; +} + #define SC_SDL_SHORTCUT_MODS_MASK (KMOD_CTRL | KMOD_ALT | KMOD_GUI) static inline uint16_t @@ -591,7 +629,16 @@ input_manager_process_mouse_motion(struct input_manager *im, return; } - im->mp->ops->process_mouse_motion(im->mp, event); + struct sc_mouse_motion_event evt = { + .position = { + .screen_size = im->screen->frame_size, + .point = screen_convert_window_to_frame_coords(im->screen, + event->x, event->y), + }, + .buttons_state = sc_mouse_buttons_state_from_sdl(event->state), + }; + + im->mp->ops->process_mouse_motion(im->mp, &evt); if (im->vfinger_down) { struct sc_point mouse = @@ -605,7 +652,25 @@ input_manager_process_mouse_motion(struct input_manager *im, static void input_manager_process_touch(struct input_manager *im, const SDL_TouchFingerEvent *event) { - im->mp->ops->process_touch(im->mp, event); + int dw; + int dh; + SDL_GL_GetDrawableSize(im->screen->window, &dw, &dh); + + // SDL touch event coordinates are normalized in the range [0; 1] + int32_t x = event->x * dw; + int32_t y = event->y * dh; + + struct sc_touch_event evt = { + .position = { + .screen_size = im->screen->frame_size, + .point = screen_convert_drawable_to_frame_coords(im->screen, x, y), + }, + .action = sc_touch_action_from_sdl(event->type), + .pointer_id = event->fingerId, + .pressure = event->pressure, + }; + + im->mp->ops->process_touch(im->mp, &evt); } static void @@ -665,7 +730,20 @@ input_manager_process_mouse_button(struct input_manager *im, return; } - im->mp->ops->process_mouse_button(im->mp, event); + uint32_t sdl_buttons_state = SDL_GetMouseState(NULL, NULL); + + struct sc_mouse_click_event evt = { + .position = { + .screen_size = im->screen->frame_size, + .point = screen_convert_window_to_frame_coords(im->screen, event->x, + event->y), + }, + .action = sc_action_from_sdl_mousebutton_type(event->type), + .button = sc_mouse_button_from_sdl(event->button), + .buttons_state = sc_mouse_buttons_state_from_sdl(sdl_buttons_state), + }; + + im->mp->ops->process_mouse_click(im->mp, &evt); // Pinch-to-zoom simulation. // @@ -696,7 +774,22 @@ input_manager_process_mouse_button(struct input_manager *im, static void input_manager_process_mouse_wheel(struct input_manager *im, const SDL_MouseWheelEvent *event) { - im->mp->ops->process_mouse_wheel(im->mp, event); + // 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); + + struct sc_mouse_scroll_event evt = { + .position = { + .screen_size = im->screen->frame_size, + .point = screen_convert_window_to_frame_coords(im->screen, + mouse_x, mouse_y), + }, + .hscroll = event->x, + .vscroll = event->y, + }; + + im->mp->ops->process_mouse_scroll(im->mp, &evt); } bool diff --git a/app/src/mouse_inject.c b/app/src/mouse_inject.c index 8f7e363d..a4d2e1a7 100644 --- a/app/src/mouse_inject.c +++ b/app/src/mouse_inject.c @@ -1,11 +1,11 @@ #include "mouse_inject.h" #include -#include #include "android/input.h" #include "control_msg.h" #include "controller.h" +#include "input_events.h" #include "util/intmap.h" #include "util/log.h" @@ -15,29 +15,29 @@ static enum android_motionevent_buttons convert_mouse_buttons(uint32_t state) { enum android_motionevent_buttons buttons = 0; - if (state & SDL_BUTTON_LMASK) { + if (state & SC_MOUSE_BUTTON_LEFT) { buttons |= AMOTION_EVENT_BUTTON_PRIMARY; } - if (state & SDL_BUTTON_RMASK) { + if (state & SC_MOUSE_BUTTON_RIGHT) { buttons |= AMOTION_EVENT_BUTTON_SECONDARY; } - if (state & SDL_BUTTON_MMASK) { + if (state & SC_MOUSE_BUTTON_MIDDLE) { buttons |= AMOTION_EVENT_BUTTON_TERTIARY; } - if (state & SDL_BUTTON_X1MASK) { + if (state & SC_MOUSE_BUTTON_X1) { buttons |= AMOTION_EVENT_BUTTON_BACK; } - if (state & SDL_BUTTON_X2MASK) { + if (state & SC_MOUSE_BUTTON_X2) { buttons |= AMOTION_EVENT_BUTTON_FORWARD; } return buttons; } static bool -convert_mouse_action(SDL_EventType from, enum android_motionevent_action *to) { +convert_mouse_action(enum sc_action from, enum android_motionevent_action *to) { static const struct sc_intmap_entry actions[] = { - {SDL_MOUSEBUTTONDOWN, AMOTION_EVENT_ACTION_DOWN}, - {SDL_MOUSEBUTTONUP, AMOTION_EVENT_ACTION_UP}, + {SC_ACTION_DOWN, AMOTION_EVENT_ACTION_DOWN}, + {SC_ACTION_UP, AMOTION_EVENT_ACTION_UP}, }; const struct sc_intmap_entry *entry = SC_INTMAP_FIND_ENTRY(actions, from); @@ -50,11 +50,12 @@ convert_mouse_action(SDL_EventType from, enum android_motionevent_action *to) { } static bool -convert_touch_action(SDL_EventType from, enum android_motionevent_action *to) { +convert_touch_action(enum sc_touch_action from, + enum android_motionevent_action *to) { static const struct sc_intmap_entry actions[] = { - {SDL_FINGERMOTION, AMOTION_EVENT_ACTION_MOVE}, - {SDL_FINGERDOWN, AMOTION_EVENT_ACTION_DOWN}, - {SDL_FINGERUP, AMOTION_EVENT_ACTION_UP}, + {SC_TOUCH_ACTION_MOVE, AMOTION_EVENT_ACTION_MOVE}, + {SC_TOUCH_ACTION_DOWN, AMOTION_EVENT_ACTION_DOWN}, + {SC_TOUCH_ACTION_UP, AMOTION_EVENT_ACTION_UP}, }; const struct sc_intmap_entry *entry = SC_INTMAP_FIND_ENTRY(actions, from); @@ -67,99 +68,73 @@ convert_touch_action(SDL_EventType from, enum android_motionevent_action *to) { } static bool -convert_mouse_motion(const SDL_MouseMotionEvent *from, struct screen *screen, - struct control_msg *to) { - 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->frame_size; - to->inject_touch_event.position.point = - screen_convert_window_to_frame_coords(screen, from->x, from->y); - to->inject_touch_event.pressure = 1.f; - to->inject_touch_event.buttons = convert_mouse_buttons(from->state); +convert_mouse_motion(const struct sc_mouse_motion_event *event, + struct control_msg *msg) { + msg->type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT; + msg->inject_touch_event.action = AMOTION_EVENT_ACTION_MOVE; + msg->inject_touch_event.pointer_id = POINTER_ID_MOUSE; + msg->inject_touch_event.position = event->position; + msg->inject_touch_event.pressure = 1.f; + msg->inject_touch_event.buttons = + convert_mouse_buttons(event->buttons_state); return true; } static bool -convert_touch(const SDL_TouchFingerEvent *from, struct screen *screen, - struct control_msg *to) { - to->type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT; +convert_touch(const struct sc_touch_event *event, + struct control_msg *msg) { + msg->type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT; - if (!convert_touch_action(from->type, &to->inject_touch_event.action)) { + if (!convert_touch_action(event->action, &msg->inject_touch_event.action)) { return false; } - to->inject_touch_event.pointer_id = from->fingerId; - to->inject_touch_event.position.screen_size = screen->frame_size; + msg->inject_touch_event.pointer_id = event->pointer_id; + msg->inject_touch_event.position = event->position; + msg->inject_touch_event.pressure = event->pressure; + msg->inject_touch_event.buttons = 0; - int dw; - int dh; - SDL_GL_GetDrawableSize(screen->window, &dw, &dh); - - // SDL touch event coordinates are normalized in the range [0; 1] - int32_t x = from->x * dw; - int32_t y = from->y * dh; - to->inject_touch_event.position.point = - screen_convert_drawable_to_frame_coords(screen, x, y); - - to->inject_touch_event.pressure = from->pressure; - to->inject_touch_event.buttons = 0; return true; } static bool -convert_mouse_button(const SDL_MouseButtonEvent *from, struct screen *screen, - struct control_msg *to) { - to->type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT; +convert_mouse_click(const struct sc_mouse_click_event *event, + struct control_msg *msg) { + msg->type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT; - if (!convert_mouse_action(from->type, &to->inject_touch_event.action)) { + if (!convert_mouse_action(event->action, &msg->inject_touch_event.action)) { return false; } - to->inject_touch_event.pointer_id = POINTER_ID_MOUSE; - to->inject_touch_event.position.screen_size = screen->frame_size; - to->inject_touch_event.position.point = - screen_convert_window_to_frame_coords(screen, from->x, from->y); - to->inject_touch_event.pressure = - from->type == SDL_MOUSEBUTTONDOWN ? 1.f : 0.f; - to->inject_touch_event.buttons = - convert_mouse_buttons(SDL_BUTTON(from->button)); + msg->inject_touch_event.pointer_id = POINTER_ID_MOUSE; + msg->inject_touch_event.position = event->position; + msg->inject_touch_event.pressure = event->action == SC_ACTION_DOWN + ? 1.f : 0.f; + msg->inject_touch_event.buttons = + convert_mouse_buttons(event->buttons_state); return true; } static bool -convert_mouse_wheel(const SDL_MouseWheelEvent *from, struct screen *screen, - struct control_msg *to) { - - // 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); - - struct sc_position position = { - .screen_size = screen->frame_size, - .point = screen_convert_window_to_frame_coords(screen, - mouse_x, mouse_y), - }; - - to->type = CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT; - - to->inject_scroll_event.position = position; - to->inject_scroll_event.hscroll = from->x; - to->inject_scroll_event.vscroll = from->y; +convert_mouse_scroll(const struct sc_mouse_scroll_event *event, + struct control_msg *msg) { + msg->type = CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT; + msg->inject_scroll_event.position = event->position; + msg->inject_scroll_event.hscroll = event->hscroll; + msg->inject_scroll_event.vscroll = event->vscroll; return true; } static void sc_mouse_processor_process_mouse_motion(struct sc_mouse_processor *mp, - const SDL_MouseMotionEvent *event) { + const struct sc_mouse_motion_event *event) { struct sc_mouse_inject *mi = DOWNCAST(mp); struct control_msg msg; - if (!convert_mouse_motion(event, mi->screen, &msg)) { + if (!convert_mouse_motion(event, &msg)) { return; } @@ -170,11 +145,11 @@ sc_mouse_processor_process_mouse_motion(struct sc_mouse_processor *mp, static void sc_mouse_processor_process_touch(struct sc_mouse_processor *mp, - const SDL_TouchFingerEvent *event) { + const struct sc_touch_event *event) { struct sc_mouse_inject *mi = DOWNCAST(mp); struct control_msg msg; - if (convert_touch(event, mi->screen, &msg)) { + if (convert_touch(event, &msg)) { if (!controller_push_msg(mi->controller, &msg)) { LOGW("Could not request 'inject touch event'"); } @@ -182,42 +157,41 @@ sc_mouse_processor_process_touch(struct sc_mouse_processor *mp, } static void -sc_mouse_processor_process_mouse_button(struct sc_mouse_processor *mp, - const SDL_MouseButtonEvent *event) { +sc_mouse_processor_process_mouse_click(struct sc_mouse_processor *mp, + const struct sc_mouse_click_event *event) { struct sc_mouse_inject *mi = DOWNCAST(mp); struct control_msg msg; - if (convert_mouse_button(event, mi->screen, &msg)) { + if (convert_mouse_click(event, &msg)) { if (!controller_push_msg(mi->controller, &msg)) { - LOGW("Could not request 'inject mouse button event'"); + LOGW("Could not request 'inject mouse click event'"); } } } static void -sc_mouse_processor_process_mouse_wheel(struct sc_mouse_processor *mp, - const SDL_MouseWheelEvent *event) { +sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp, + const struct sc_mouse_scroll_event *event) { struct sc_mouse_inject *mi = DOWNCAST(mp); struct control_msg msg; - if (convert_mouse_wheel(event, mi->screen, &msg)) { + if (convert_mouse_scroll(event, &msg)) { if (!controller_push_msg(mi->controller, &msg)) { - LOGW("Could not request 'inject mouse wheel event'"); + LOGW("Could not request 'inject mouse scroll event'"); } } } void -sc_mouse_inject_init(struct sc_mouse_inject *mi, struct controller *controller, - struct screen *screen) { +sc_mouse_inject_init(struct sc_mouse_inject *mi, + struct controller *controller) { mi->controller = controller; - mi->screen = screen; static const struct sc_mouse_processor_ops ops = { .process_mouse_motion = sc_mouse_processor_process_mouse_motion, .process_touch = sc_mouse_processor_process_touch, - .process_mouse_button = sc_mouse_processor_process_mouse_button, - .process_mouse_wheel = sc_mouse_processor_process_mouse_wheel, + .process_mouse_click = sc_mouse_processor_process_mouse_click, + .process_mouse_scroll = sc_mouse_processor_process_mouse_scroll, }; mi->mouse_processor.ops = &ops; diff --git a/app/src/mouse_inject.h b/app/src/mouse_inject.h index 7dcf7e83..50591e2b 100644 --- a/app/src/mouse_inject.h +++ b/app/src/mouse_inject.h @@ -13,11 +13,9 @@ struct sc_mouse_inject { struct sc_mouse_processor mouse_processor; // mouse processor trait struct controller *controller; - struct screen *screen; }; void -sc_mouse_inject_init(struct sc_mouse_inject *mi, struct controller *controller, - struct screen *screen); +sc_mouse_inject_init(struct sc_mouse_inject *mi, struct controller *controller); #endif diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 3a271ee5..51eb19fb 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -578,7 +578,7 @@ aoa_hid_end: kp = &s->keyboard_inject.key_processor; } - sc_mouse_inject_init(&s->mouse_inject, &s->controller, &s->screen); + sc_mouse_inject_init(&s->mouse_inject, &s->controller); mp = &s->mouse_inject.mouse_processor; } diff --git a/app/src/trait/mouse_processor.h b/app/src/trait/mouse_processor.h index f3548574..e06545bf 100644 --- a/app/src/trait/mouse_processor.h +++ b/app/src/trait/mouse_processor.h @@ -6,7 +6,7 @@ #include #include -#include +#include "input_events.h" /** * Mouse processor trait. @@ -21,19 +21,19 @@ struct sc_mouse_processor { struct sc_mouse_processor_ops { void (*process_mouse_motion)(struct sc_mouse_processor *mp, - const SDL_MouseMotionEvent *event); + const struct sc_mouse_motion_event *event); void (*process_touch)(struct sc_mouse_processor *mp, - const SDL_TouchFingerEvent *event); + const struct sc_touch_event *event); void - (*process_mouse_button)(struct sc_mouse_processor *mp, - const SDL_MouseButtonEvent *event); + (*process_mouse_click)(struct sc_mouse_processor *mp, + const struct sc_mouse_click_event *event); void - (*process_mouse_wheel)(struct sc_mouse_processor *mp, - const SDL_MouseWheelEvent *event); + (*process_mouse_scroll)(struct sc_mouse_processor *mp, + const struct sc_mouse_scroll_event *event); }; #endif