Fix scroll wheel mouse position

SDL_MouseWheelEvent does not provide the mouse location, so we used
SDL_GetMouseState() to retrieve it.

Unfortunately, SDL_GetMouseState() returns a position expressed in the
window coordinate system while the position filled in SDL events are
expressed in the renderer coordinate system. As a consequence, the
scroll was not applied at the right position on the device.

Therefore, convert the coordinate system.

See <https://stackoverflow.com/questions/49111054/how-to-get-mouse-position-on-mouse-wheel-event>.
This commit is contained in:
Romain Vimont 2018-03-05 14:54:12 +01:00
parent e6feb991db
commit db396f2138

View file

@ -4,10 +4,24 @@
#include "lockutil.h" #include "lockutil.h"
#include "log.h" #include "log.h"
static struct point get_mouse_point(void) { // Convert window coordinates (as provided by SDL_GetMouseState() to renderer coordinates (as provided in SDL mouse events)
//
// See my question:
// <https://stackoverflow.com/questions/49111054/how-to-get-mouse-position-on-mouse-wheel-event>
static void convert_to_renderer_coordinates(SDL_Renderer *renderer, int *x, int *y) {
SDL_Rect viewport;
float scale_x, scale_y;
SDL_RenderGetViewport(renderer, &viewport);
SDL_RenderGetScale(renderer, &scale_x, &scale_y);
*x = (int) (*x / scale_x) - viewport.x;
*y = (int) (*y / scale_y) - viewport.y;
}
static struct point get_mouse_point(struct screen *screen) {
int x; int x;
int y; int y;
SDL_GetMouseState(&x, &y); SDL_GetMouseState(&x, &y);
convert_to_renderer_coordinates(screen->renderer, &x, &y);
SDL_assert_release(x >= 0 && x < 0x10000 && y >= 0 && y < 0x10000); SDL_assert_release(x >= 0 && x < 0x10000 && y >= 0 && y < 0x10000);
return (struct point) { return (struct point) {
.x = (Uint16) x, .x = (Uint16) x,
@ -204,7 +218,7 @@ void input_manager_process_mouse_wheel(struct input_manager *input_manager,
const SDL_MouseWheelEvent *event) { const SDL_MouseWheelEvent *event) {
struct position position = { struct position position = {
.screen_size = input_manager->screen->frame_size, .screen_size = input_manager->screen->frame_size,
.point = get_mouse_point(), .point = get_mouse_point(input_manager->screen),
}; };
struct control_event control_event; struct control_event control_event;
if (mouse_wheel_from_sdl_to_android(event, position, &control_event)) { if (mouse_wheel_from_sdl_to_android(event, position, &control_event)) {