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.
This commit is contained in:
Romain Vimont 2019-10-06 22:27:53 +02:00
parent 9448eae8a4
commit c2d0dcd002
3 changed files with 58 additions and 6 deletions

View File

@ -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,

View File

@ -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

View File

@ -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