diff --git a/app/meson.build b/app/meson.build index e62a60f7..04cc2fbe 100644 --- a/app/meson.build +++ b/app/meson.build @@ -8,6 +8,7 @@ src = [ 'src/device.c', 'src/fpscounter.c', 'src/frames.c', + 'src/hidpi.c', 'src/inputmanager.c', 'src/lockutil.c', 'src/net.c', diff --git a/app/src/convert.c b/app/src/convert.c index ec6f1de0..b93755d7 100644 --- a/app/src/convert.c +++ b/app/src/convert.c @@ -136,6 +136,7 @@ SDL_bool input_key_from_sdl_to_android(const SDL_KeyboardEvent *from, SDL_bool mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from, struct size screen_size, + struct hidpi_scale *hidpi_scale, struct control_event *to) { to->type = CONTROL_EVENT_TYPE_MOUSE; @@ -145,21 +146,30 @@ SDL_bool mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from, to->mouse_event.buttons = convert_mouse_buttons(SDL_BUTTON(from->button)); to->mouse_event.position.screen_size = screen_size; - to->mouse_event.position.point.x = (Uint16) from->x; - to->mouse_event.position.point.y = (Uint16) from->y; + + Sint32 x = from->x; + Sint32 y = from->y; + hidpi_unscale_coordinates(hidpi_scale, &x, &y); + to->mouse_event.position.point.x = (Uint16) x; + to->mouse_event.position.point.y = (Uint16) y; return SDL_TRUE; } SDL_bool mouse_motion_from_sdl_to_android(const SDL_MouseMotionEvent *from, struct size screen_size, + struct hidpi_scale *hidpi_scale, struct control_event *to) { to->type = CONTROL_EVENT_TYPE_MOUSE; to->mouse_event.action = AMOTION_EVENT_ACTION_MOVE; to->mouse_event.buttons = convert_mouse_buttons(from->state); to->mouse_event.position.screen_size = screen_size; - to->mouse_event.position.point.x = from->x; - to->mouse_event.position.point.y = from->y; + + Sint32 x = from->x; + Sint32 y = from->y; + hidpi_unscale_coordinates(hidpi_scale, &x, &y); + to->mouse_event.position.point.x = (Uint16) x; + to->mouse_event.position.point.y = (Uint16) y; return SDL_TRUE; } diff --git a/app/src/convert.h b/app/src/convert.h index 5a535a37..e6e22952 100644 --- a/app/src/convert.h +++ b/app/src/convert.h @@ -3,7 +3,10 @@ #include #include + +#include "common.h" #include "controlevent.h" +#include "hidpi.h" struct complete_mouse_motion_event { SDL_MouseMotionEvent *mouse_motion_event; @@ -19,12 +22,14 @@ SDL_bool input_key_from_sdl_to_android(const SDL_KeyboardEvent *from, struct control_event *to); SDL_bool mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from, struct size screen_size, + struct hidpi_scale *hidpi_scale, struct control_event *to); // the video size may be different from the real device size, so we need the size // to which the absolute position apply, to scale it accordingly SDL_bool mouse_motion_from_sdl_to_android(const SDL_MouseMotionEvent *from, struct size screen_size, + struct hidpi_scale *hidpi_scale, struct control_event *to); // on Android, a scroll event requires the current mouse position diff --git a/app/src/hidpi.c b/app/src/hidpi.c new file mode 100644 index 00000000..738889a6 --- /dev/null +++ b/app/src/hidpi.c @@ -0,0 +1,16 @@ +#include "hidpi.h" + +void hidpi_get_scale(struct screen *screen, struct hidpi_scale *scale) { + SDL_GL_GetDrawableSize(screen->window, &scale->horizontal.num, &scale->vertical.num); + SDL_GetWindowSize(screen->window, &scale->horizontal.div, &scale->vertical.div); +} + +void hidpi_unscale_coordinates(struct hidpi_scale *scale, Sint32 *x, Sint32 *y) { + // to unscale, we devide by the ratio (so num and div are reversed) + if (scale->horizontal.num) { + *x = ((Sint64) *x) * scale->horizontal.div / scale->horizontal.num; + } + if (scale->vertical.num) { + *y = ((Sint64) *y) * scale->vertical.div / scale->vertical.num; + } +} diff --git a/app/src/hidpi.h b/app/src/hidpi.h new file mode 100644 index 00000000..dcbf093f --- /dev/null +++ b/app/src/hidpi.h @@ -0,0 +1,24 @@ +#ifndef HIDPI_H +#define HIDPI_H + +#include "common.h" +#include "screen.h" + +// rational number p/q +struct rational { + int num; + int div; +}; + +struct hidpi_scale { + struct rational horizontal; // drawable.width / window.width + struct rational vertical; // drawable.height / window.height +}; + +void hidpi_get_scale(struct screen *screen, struct hidpi_scale *hidpi_scale); + +// mouse location need to be "unscaled" if hidpi is enabled +// +void hidpi_unscale_coordinates(struct hidpi_scale *hidpi_scale, Sint32 *x, Sint32 *y); + +#endif diff --git a/app/src/inputmanager.c b/app/src/inputmanager.c index c5d15924..416cfef4 100644 --- a/app/src/inputmanager.c +++ b/app/src/inputmanager.c @@ -1,6 +1,7 @@ #include "inputmanager.h" #include "convert.h" +#include "hidpi.h" #include "lockutil.h" #include "log.h" @@ -18,10 +19,19 @@ static void convert_to_renderer_coordinates(SDL_Renderer *renderer, int *x, int } static struct point get_mouse_point(struct screen *screen) { - int x; - int y; - SDL_GetMouseState(&x, &y); - convert_to_renderer_coordinates(screen->renderer, &x, &y); + int mx; + int my; + SDL_GetMouseState(&mx, &my); + convert_to_renderer_coordinates(screen->renderer, &mx, &my); + + struct hidpi_scale hidpi_scale; + hidpi_get_scale(screen, &hidpi_scale); + + // SDL sometimes uses "int", sometimes "Sint32" + Sint32 x = mx; + Sint32 y = my; + hidpi_unscale_coordinates(&hidpi_scale, &x, &y); + SDL_assert_release(x >= 0 && x < 0x10000 && y >= 0 && y < 0x10000); return (struct point) { .x = (Uint16) x, @@ -192,8 +202,12 @@ void input_manager_process_mouse_motion(struct input_manager *input_manager, // do not send motion events when no button is pressed return; } + + struct hidpi_scale hidpi_scale; + hidpi_get_scale(input_manager->screen, &hidpi_scale); + struct control_event control_event; - if (mouse_motion_from_sdl_to_android(event, input_manager->screen->frame_size, &control_event)) { + if (mouse_motion_from_sdl_to_android(event, input_manager->screen->frame_size, &hidpi_scale, &control_event)) { if (!controller_push_event(input_manager->controller, &control_event)) { LOGW("Cannot send mouse motion event"); } @@ -206,8 +220,12 @@ void input_manager_process_mouse_button(struct input_manager *input_manager, turn_screen_on(input_manager->controller); return; }; + + struct hidpi_scale hidpi_scale; + hidpi_get_scale(input_manager->screen, &hidpi_scale); + struct control_event control_event; - if (mouse_button_from_sdl_to_android(event, input_manager->screen->frame_size, &control_event)) { + if (mouse_button_from_sdl_to_android(event, input_manager->screen->frame_size, &hidpi_scale, &control_event)) { if (!controller_push_event(input_manager->controller, &control_event)) { LOGW("Cannot send mouse button event"); } diff --git a/app/src/screen.c b/app/src/screen.c index 9c827738..6186d67f 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -141,7 +141,8 @@ SDL_bool screen_init_rendering(struct screen *screen, const char *device_name, s struct size window_size = get_initial_optimal_size(frame_size); screen->window = SDL_CreateWindow(device_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - window_size.width, window_size.height, SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE); + window_size.width, window_size.height, + SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); if (!screen->window) { LOGC("Could not create window: %s", SDL_GetError()); return SDL_FALSE;