2
0
mirror of https://github.com/Genymobile/scrcpy synced 2025-09-01 06:45:40 +00:00

Manually position and scale the content

Position and scale the content "manually" instead of relying on the
renderer "logical size".

This avoids possible rounding differences between the computed window
size and the content size, causing one row or column of black pixels on
the bottom or on the right.

This also avoids HiDPI scale issues, by computing the scaling manually.

This will also enable to draw items at their expected size on the screen
(unscaled).

Fixes #15 <https://github.com/Genymobile/scrcpy/issues/15>
This commit is contained in:
Romain Vimont
2020-04-17 18:44:24 +02:00
parent d860ad48e6
commit e40532a376
4 changed files with 125 additions and 77 deletions

View File

@@ -7,33 +7,6 @@
#include "util/lock.h"
#include "util/log.h"
// 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 y;
SDL_GetMouseState(&x, &y);
convert_to_renderer_coordinates(screen->renderer, &x, &y);
return (struct point) {
.x = x,
.y = y,
};
}
static const int ACTION_DOWN = 1;
static const int ACTION_UP = 1 << 1;
@@ -487,11 +460,17 @@ 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);
// SDL touch event coordinates are normalized in the range [0; 1]
float x = from->x * screen->content_size.width;
float y = from->y * screen->content_size.height;
int32_t x = from->x * ww;
int32_t y = from->y * wh;
to->inject_touch_event.position.point =
screen_convert_to_frame_coords(screen, x, y);
to->inject_touch_event.pressure = from->pressure;
to->inject_touch_event.buttons = 0;
return true;
@@ -508,13 +487,6 @@ input_manager_process_touch(struct input_manager *im,
}
}
static bool
is_outside_device_screen(struct input_manager *im, int x, int y)
{
return x < 0 || x >= im->screen->content_size.width ||
y < 0 || y >= im->screen->content_size.height;
}
static bool
convert_mouse_button(const SDL_MouseButtonEvent *from, struct screen *screen,
struct control_msg *to) {
@@ -552,10 +524,15 @@ input_manager_process_mouse_button(struct input_manager *im,
action_home(im->controller, ACTION_DOWN | ACTION_UP);
return;
}
// double-click on black borders resize to fit the device screen
if (event->button == SDL_BUTTON_LEFT && event->clicks == 2) {
bool outside =
is_outside_device_screen(im, event->x, event->y);
int32_t x = event->x;
int32_t y = event->y;
screen_hidpi_scale_coords(im->screen, &x, &y);
SDL_Rect *r = &im->screen->rect;
bool outside = x < r->x || x >= r->x + r->w
|| y < r->y || y >= r->y + r->h;
if (outside) {
screen_resize_to_fit(im->screen);
return;
@@ -579,9 +556,15 @@ input_manager_process_mouse_button(struct input_manager *im,
static bool
convert_mouse_wheel(const SDL_MouseWheelEvent *from, struct screen *screen,
struct control_msg *to) {
// mouse_x and mouse_y are expressed in pixels relative to the window
int mouse_x;
int mouse_y;
SDL_GetMouseState(&mouse_x, &mouse_y);
struct position position = {
.screen_size = screen->frame_size,
.point = get_mouse_point(screen),
.point = screen_convert_to_frame_coords(screen, mouse_x, mouse_y),
};
to->type = CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT;