Skip to content

Commit

Permalink
Add pinch-to-zoom simulation
Browse files Browse the repository at this point in the history
If Ctrl is hold when the left-click button is pressed, enable
pinch-to-zoom to scale and rotate relative to the center of the screen.

Fixes #24 <#24>
  • Loading branch information
rom1v committed Aug 9, 2020
1 parent a59a157 commit eff5036
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 7 deletions.
1 change: 1 addition & 0 deletions app/src/control_msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH (CONTROL_MSG_MAX_SIZE - 6)

#define POINTER_ID_MOUSE UINT64_C(-1);
#define POINTER_ID_VIRTUAL_FINGER UINT64_C(-2);

enum control_msg_type {
CONTROL_MSG_TYPE_INJECT_KEYCODE,
Expand Down
84 changes: 77 additions & 7 deletions app/src/input_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ input_manager_init(struct input_manager *im,
im->sdl_shortcut_mods.data[i] = sdl_mod;
}
im->sdl_shortcut_mods.count = shortcut_mods->count;

im->vfinger_down = false;
}

static void
Expand Down Expand Up @@ -299,6 +301,36 @@ input_manager_process_text_input(struct input_manager *im,
}
}

static bool
simulate_virtual_finger(struct input_manager *im,
enum android_motionevent_action action,
struct point point) {
bool up = action == AMOTION_EVENT_ACTION_UP;

struct control_msg msg;
msg.type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT;
msg.inject_touch_event.action = action;
msg.inject_touch_event.position.screen_size = im->screen->frame_size;
msg.inject_touch_event.position.point = point;
msg.inject_touch_event.pointer_id = POINTER_ID_VIRTUAL_FINGER;
msg.inject_touch_event.pressure = up ? 0.0f : 1.0f;
msg.inject_touch_event.buttons = 0;

if (!controller_push_msg(im->controller, &msg)) {
LOGW("Could not request 'inject virtual finger event'");
return false;
}

return true;
}

static struct point
inverse_point(struct point point, struct size size) {
point.x = size.width - point.x;
point.y = size.height - point.y;
return point;
}

static bool
convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to,
bool prefer_text, uint32_t repeat) {
Expand Down Expand Up @@ -512,9 +544,19 @@ input_manager_process_mouse_motion(struct input_manager *im,
return;
}
struct control_msg msg;
if (convert_mouse_motion(event, im->screen, &msg)) {
if (!controller_push_msg(im->controller, &msg)) {
LOGW("Could not request 'inject mouse motion event'");
if (!convert_mouse_motion(event, im->screen, &msg)) {
return;
}

if (!controller_push_msg(im->controller, &msg)) {
LOGW("Could not request 'inject mouse motion event'");
}

if (im->vfinger_down) {
struct point mouse = msg.inject_touch_event.position.point;
struct point vfinger = inverse_point(mouse, im->screen->frame_size);
if (!simulate_virtual_finger(im, AMOTION_EVENT_ACTION_MOVE, vfinger)) {
return;
}
}
}
Expand Down Expand Up @@ -587,7 +629,9 @@ input_manager_process_mouse_button(struct input_manager *im,
// simulated from touch events, so it's a duplicate
return;
}
if (event->type == SDL_MOUSEBUTTONDOWN) {

bool down = event->type == SDL_MOUSEBUTTONDOWN;
if (down) {
if (control && event->button == SDL_BUTTON_RIGHT) {
press_back_or_turn_screen_on(im->controller);
return;
Expand Down Expand Up @@ -618,10 +662,36 @@ input_manager_process_mouse_button(struct input_manager *im,
}

struct control_msg msg;
if (convert_mouse_button(event, im->screen, &msg)) {
if (!controller_push_msg(im->controller, &msg)) {
LOGW("Could not request 'inject mouse button event'");
if (!convert_mouse_button(event, im->screen, &msg)) {
return;
}

if (!controller_push_msg(im->controller, &msg)) {
LOGW("Could not request 'inject mouse button event'");
return;
}

// Pinch-to-zoom simulation.
//
// If Ctrl is hold when the left-click button is pressed, then
// pinch-to-zoom mode is enabled: on every mouse event until the left-click
// button is released, an additional "virtual finger" event is generated,
// having a position inversed with respect to the center of the screen.
//
// In other words, the center of the rotation/scaling is the center of the
// screen.
#define CTRL_PRESSED (SDL_GetModState() & (KMOD_LCTRL | KMOD_RCTRL))
if ((down && !im->vfinger_down && CTRL_PRESSED)
|| (!down && im->vfinger_down)) {
struct point mouse = msg.inject_touch_event.position.point;
struct point vfinger = inverse_point(mouse, im->screen->frame_size);
enum android_motionevent_action action = down
? AMOTION_EVENT_ACTION_DOWN
: AMOTION_EVENT_ACTION_UP;
if (!simulate_virtual_finger(im, action, vfinger)) {
return;
}
im->vfinger_down = down;
}
}

Expand Down
2 changes: 2 additions & 0 deletions app/src/input_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ struct input_manager {
unsigned data[SC_MAX_SHORTCUT_MODS];
unsigned count;
} sdl_shortcut_mods;

bool vfinger_down;
};

void
Expand Down

0 comments on commit eff5036

Please sign in to comment.