diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 8c549d6779e22c91a78a9b4deb54414c60e23670..38429ece33aa2c0dfef7ea6ebdeedef6df3ee749 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -35,6 +35,21 @@ static struct input_manager input_manager = { .screen = &screen, }; +static void hidpi_fix_coordinates(Sint32 *x, Sint32 *y) { + struct screen_sizes sizes = screen_get_sizes(&screen); + Uint16 ww = sizes.window_size.width; + Uint16 wh = sizes.window_size.height; + Uint16 dw = sizes.drawable_size.width; + Uint16 dh = sizes.drawable_size.height; + printf("window=%dx%d; drawable=%dx%d\n", (int) ww, (int) wh, (int) dw, (int) dh); + if (dw && dw != ww) { + *x = ((Sint64) *x) * ww / dw; + } + if (dh && dh != wh) { + *y = ((Sint64) *y) * wh / dh; + } +} + static void event_loop(void) { SDL_Event event; while (SDL_WaitEvent(&event)) { @@ -72,14 +87,17 @@ static void event_loop(void) { input_manager_process_key(&input_manager, &event.key); break; case SDL_MOUSEMOTION: + hidpi_fix_coordinates(&event.motion.x, &event.motion.y); input_manager_process_mouse_motion(&input_manager, &event.motion); break; case SDL_MOUSEWHEEL: { + hidpi_fix_coordinates(&event.wheel.x, &event.wheel.y); input_manager_process_mouse_wheel(&input_manager, &event.wheel); break; } case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: { + hidpi_fix_coordinates(&event.button.y, &event.button.y); input_manager_process_mouse_button(&input_manager, &event.button); break; } diff --git a/app/src/screen.c b/app/src/screen.c index 9c82773825bf8ede2a6148545d47169ef40e3b5e..61f311aa0b15d307f967a10e6ec24762a2a09711 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -45,6 +45,27 @@ static struct size get_native_window_size(SDL_Window *window) { return size; } +// get the size of the window underlying drawable in pixels +// may differ from get_native_window_size() if hi-dpi is enabled +static struct size get_native_drawable_size(SDL_Window *window) { + int width; + int height; + SDL_GL_GetDrawableSize(window, &width, &height); + + struct size size; + size.width = width; + size.height = height; + return size; +} + +// return both the native window size and native drawable size +struct screen_sizes screen_get_sizes(const struct screen *screen) { + struct screen_sizes sizes; + sizes.window_size = get_native_window_size(screen->window); + sizes.drawable_size = get_native_drawable_size(screen->window); + return sizes; +} + // get the windowed window size static struct size get_window_size(const struct screen *screen) { if (screen->fullscreen) { @@ -141,7 +162,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; diff --git a/app/src/screen.h b/app/src/screen.h index 13103eaa6f6005e92ad7109a7099b4b0eae91c8d..9da1cb85a6b7e8eba6e6178796dee61ae4da718c 100644 --- a/app/src/screen.h +++ b/app/src/screen.h @@ -34,6 +34,15 @@ struct screen { .fullscreen = SDL_FALSE, \ } +// the window and drawable size may differ if hi-dpi is enabled +struct screen_sizes { + // the size of the window client area, as reported by SDL_GetWindowSize() + struct size window_size; + // the size of the window underlying drawable, as reported by + // SDL_GL_GetDrawableSize() + struct size drawable_size; +}; + // init SDL and set appropriate hints SDL_bool sdl_init_and_configure(void); @@ -66,4 +75,6 @@ void screen_resize_to_fit(struct screen *screen); // resize window to 1:1 (pixel-perfect) void screen_resize_to_pixel_perfect(struct screen *screen); +struct screen_sizes screen_get_sizes(const struct screen *screen); + #endif