From c2d0dcd002de3aa002cf4a8fc24badb567bf98a7 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 6 Oct 2019 22:27:53 +0200 Subject: [PATCH] Add multitouch simulation While the Ctrl key is held, the first left-click adds an immobile "virtual finger" at this position. Moving the mouse moves another cursor. The left click may be released and pressed as necessary to control the second finger. Releasing Ctrl releases the virtual finger. --- app/src/control_msg.h | 1 + app/src/input_manager.c | 56 ++++++++++++++++++++++++++++++++++++----- app/src/input_manager.h | 7 ++++++ 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/app/src/control_msg.h b/app/src/control_msg.h index 2f319d9d..2d57c573 100644 --- a/app/src/control_msg.h +++ b/app/src/control_msg.h @@ -16,6 +16,7 @@ (3 + CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH) #define POINTER_ID_MOUSE UINT64_C(-1); +#define POINTER_ID_VIRTUAL_FINGER UINT64_C(-2); enum control_msg_type { CONTROL_MSG_TYPE_INJECT_KEYCODE, diff --git a/app/src/input_manager.c b/app/src/input_manager.c index 2e591320..9457cc30 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -15,6 +15,9 @@ input_manager_init(struct input_manager *input_manager, input_manager->controller = controller; input_manager->video_buffer = video_buffer; input_manager->screen = screen; + + input_manager->ctrl_down = false; + input_manager->vfinger.down = false; } // Convert window coordinates (as provided by SDL_GetMouseState() to renderer @@ -221,6 +224,26 @@ clipboard_paste(struct controller *controller) { } } +static void +simulate_virtual_finger(struct input_manager *input_manager, bool down, + struct position *position) { + SDL_assert(input_manager->vfinger.down != down); + input_manager->vfinger.down = down; + + struct control_msg msg; + msg.type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT; + msg.inject_touch_event.action = down ? AMOTION_EVENT_ACTION_DOWN + : AMOTION_EVENT_ACTION_UP; + msg.inject_touch_event.pointer_id = POINTER_ID_VIRTUAL_FINGER; + msg.inject_touch_event.position = *position; + msg.inject_touch_event.pressure = 1.f; + msg.inject_touch_event.buttons = 0; + + if (!controller_push_msg(input_manager->controller, &msg)) { + LOGW("Could not request 'inject virtual finger event'"); + } +} + void input_manager_process_text_input(struct input_manager *input_manager, const SDL_TextInputEvent *event) { @@ -254,6 +277,14 @@ input_manager_process_key(struct input_manager *input_manager, bool alt = event->keysym.mod & (KMOD_LALT | KMOD_RALT); bool meta = event->keysym.mod & (KMOD_LGUI | KMOD_RGUI); + // store the Ctrl state to modify mouse events + input_manager->ctrl_down = ctrl; + + if (input_manager->vfinger.down && !ctrl) { + simulate_virtual_finger(input_manager, false, + &input_manager->vfinger.position); + } + // use Cmd on macOS, Ctrl on other platforms #ifdef __APPLE__ bool cmd = !ctrl && meta; @@ -437,6 +468,7 @@ input_manager_process_mouse_button(struct input_manager *input_manager, // simulated from touch events, so it's a duplicate return; } + if (event->type == SDL_MOUSEBUTTONDOWN) { if (control && event->button == SDL_BUTTON_RIGHT) { press_back_or_turn_screen_on(input_manager->controller); @@ -447,12 +479,24 @@ input_manager_process_mouse_button(struct input_manager *input_manager, return; } // double-click on black borders resize to fit the device screen - if (event->button == SDL_BUTTON_LEFT && event->clicks == 2) { - bool outside = - is_outside_device_screen(input_manager, event->x, event->y); - if (outside) { - screen_resize_to_fit(input_manager->screen); - return; + if (event->button == SDL_BUTTON_LEFT) { + if (event->clicks >= 2) { + bool outside = + is_outside_device_screen(input_manager, event->x, event->y); + if (outside) { + screen_resize_to_fit(input_manager->screen); + return; + } + } + + struct virtual_finger *vfinger = &input_manager->vfinger; + if (input_manager->ctrl_down && !vfinger->down) { + vfinger->position.point.x = event->x; + vfinger->position.point.y = event->y; + vfinger->position.screen_size = + input_manager->screen->frame_size, + simulate_virtual_finger(input_manager, true, + &vfinger->position); } } // otherwise, send the click event to the device diff --git a/app/src/input_manager.h b/app/src/input_manager.h index 94915d7a..3be93142 100644 --- a/app/src/input_manager.h +++ b/app/src/input_manager.h @@ -14,6 +14,13 @@ struct input_manager { struct controller *controller; struct video_buffer *video_buffer; struct screen *screen; + + bool ctrl_down; + + struct virtual_finger { + bool down; + struct position position; + } vfinger; }; void