From fb5e619636299af06e8f71df8a71fe620cadca7f Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Thu, 25 Jun 2020 08:54:40 +0200 Subject: [PATCH] Fix touch events HiDPI-scaling [TODO: rebase on dev] Touch events were HiDPI-scaled twice: - once because the position (provided as floats between 0 and 1) were converted in pixels using the drawable size (not the window size) - once due to screen_convert_to_frame_coords() One possible fix could be to compute the position in pixels from the window size instead, but this would unnecessarily round the event position to the nearest window coordinates (instead of drawable coordinates). Instead, expose two separate functions to convert to frame coordinates from either window or drawable coordinates. Fixes #1536 Refs #15 Refs e40532a3761da8b3aef484f1d435ef5f50d94574 --- app/src/input_manager.c | 19 ++++++++++--------- app/src/screen.c | 11 +++++++++-- app/src/screen.h | 9 ++++++++- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/app/src/input_manager.c b/app/src/input_manager.c index e8ba9f79..5da2c5a4 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -427,7 +427,7 @@ convert_mouse_motion(const SDL_MouseMotionEvent *from, struct screen *screen, 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_to_frame_coords(screen, from->x, from->y); + 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); @@ -465,15 +465,15 @@ convert_touch(const SDL_TouchFingerEvent *from, struct screen *screen, to->inject_touch_event.pointer_id = from->fingerId; to->inject_touch_event.position.screen_size = screen->frame_size; - int ww; - int wh; - SDL_GL_GetDrawableSize(screen->window, &ww, &wh); + 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 * ww; - int32_t y = from->y * wh; + int32_t x = from->x * dw; + int32_t y = from->y * dh; to->inject_touch_event.position.point = - screen_convert_to_frame_coords(screen, x, y); + screen_convert_drawable_to_frame_coords(screen, x, y); to->inject_touch_event.pressure = from->pressure; to->inject_touch_event.buttons = 0; @@ -503,7 +503,7 @@ convert_mouse_button(const SDL_MouseButtonEvent *from, struct screen *screen, 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_to_frame_coords(screen, from->x, from->y); + 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(SDL_BUTTON(from->button)); @@ -568,7 +568,8 @@ convert_mouse_wheel(const SDL_MouseWheelEvent *from, struct screen *screen, struct position position = { .screen_size = screen->frame_size, - .point = screen_convert_to_frame_coords(screen, mouse_x, mouse_y), + .point = screen_convert_window_to_frame_coords(screen, + mouse_x, mouse_y), }; to->type = CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT; diff --git a/app/src/screen.c b/app/src/screen.c index 66a1163b..ef9bb5de 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -579,14 +579,14 @@ screen_handle_window_event(struct screen *screen, } struct point -screen_convert_to_frame_coords(struct screen *screen, int32_t x, int32_t y) { +screen_convert_drawable_to_frame_coords(struct screen *screen, + int32_t x, int32_t y) { unsigned rotation = screen->rotation; assert(rotation < 4); int32_t w = screen->content_size.width; int32_t h = screen->content_size.height; - screen_hidpi_scale_coords(screen, &x, &y); x = (int64_t) (x - screen->rect.x) * w / screen->rect.w; y = (int64_t) (y - screen->rect.y) * h / screen->rect.h; @@ -615,6 +615,13 @@ screen_convert_to_frame_coords(struct screen *screen, int32_t x, int32_t y) { return result; } +struct point +screen_convert_window_to_frame_coords(struct screen *screen, + int32_t x, int32_t y) { + screen_hidpi_scale_coords(screen, &x, &y); + return screen_convert_drawable_to_frame_coords(screen, x, y); +} + void screen_hidpi_scale_coords(struct screen *screen, int32_t *x, int32_t *y) { // take the HiDPI scaling (dw/ww and dh/wh) into account diff --git a/app/src/screen.h b/app/src/screen.h index aa6218f7..3ce6f1c1 100644 --- a/app/src/screen.h +++ b/app/src/screen.h @@ -126,7 +126,14 @@ screen_handle_window_event(struct screen *screen, const SDL_WindowEvent *event); // convert point from window coordinates to frame coordinates // x and y are expressed in pixels struct point -screen_convert_to_frame_coords(struct screen *screen, int32_t x, int32_t y); +screen_convert_window_to_frame_coords(struct screen *screen, + int32_t x, int32_t y); + +// convert point from drawable coordinates to frame coordinates +// x and y are expressed in pixels +struct point +screen_convert_drawable_to_frame_coords(struct screen *screen, + int32_t x, int32_t y); // Convert coordinates from window to drawable. // Events are expressed in window coordinates, but content is expressed in