Skip to content

Commit

Permalink
Fix touch events HiDPI-scaling [TODO: rebase on dev]
Browse files Browse the repository at this point in the history
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 <#1536>
Refs #15 <#15>
Refs e40532a
  • Loading branch information
rom1v committed Jun 25, 2020
1 parent 42641d2 commit fb5e619
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 12 deletions.
19 changes: 10 additions & 9 deletions app/src/input_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand Down
11 changes: 9 additions & 2 deletions app/src/screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
9 changes: 8 additions & 1 deletion app/src/screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit fb5e619

Please sign in to comment.