diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index cbf3a40ed0..cb4cfb36d9 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -146,8 +146,10 @@ handle_event(SDL_Event *event, bool control) { switch (event->window.event) { case SDL_WINDOWEVENT_SIZE_CHANGED: #ifdef HIDPI_SUPPORT - LOGD("Reinitializing renderer"); - screen_init_renderer_and_texture(&screen); + if (!screen_test_correct_hidpi_ratio(&screen)) { + LOGW("Reinitializing renderer due to incorrect hidpi ratio"); + screen_init_renderer_and_texture(&screen); + } #endif // fall-through no break case SDL_WINDOWEVENT_EXPOSED: diff --git a/app/src/screen.c b/app/src/screen.c index 52035a8084..8ec4fc9e35 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -47,7 +47,10 @@ set_window_size(struct screen *screen, struct size new_size) { } else { SDL_SetWindowSize(screen->window, new_size.width, new_size.height); #ifdef HIDPI_SUPPORT - screen_init_renderer_and_texture(screen); + if (!screen_test_correct_hidpi_ratio(screen)) { + LOGW("Reinitializing renderer due to incorrect hidpi ratio"); + screen_init_renderer_and_texture(screen); + } #endif } } @@ -164,6 +167,14 @@ screen_init_renderer_and_texture(struct screen *screen) { return false; } +#ifdef HIDPI_SUPPORT + int window_w, window_h, renderer_w, renderer_h; + SDL_GetWindowSize(screen->window, &window_w, &window_h); + SDL_GetRendererOutputSize(screen->renderer, &renderer_w, &renderer_h); + screen->expected_hidpi_w_factor = renderer_w * 1000 / window_w; + screen->expected_hidpi_h_factor = renderer_h * 1000 / window_h; +#endif + screen->texture = create_texture(screen->renderer, screen->frame_size); if (!screen->texture) { LOGC("Could not create texture: %s", SDL_GetError()); @@ -214,6 +225,19 @@ screen_init_rendering(struct screen *screen, const char *window_title, return screen_init_renderer_and_texture(screen); } +#ifdef HIDPI_SUPPORT +bool +screen_test_correct_hidpi_ratio(struct screen *screen) { + int window_w, window_h, renderer_w, renderer_h; + SDL_GetWindowSize(screen->window, &window_w, &window_h); + SDL_GetRendererOutputSize(screen->renderer, &renderer_w, &renderer_h); + int current_hidpi_w_factor = renderer_w * 1000 / window_w; + int current_hidpi_h_factor = renderer_h * 1000 / window_h; + return current_hidpi_w_factor == screen->expected_hidpi_w_factor && + current_hidpi_h_factor == screen->expected_hidpi_h_factor; +} +#endif + void screen_show_window(struct screen *screen) { SDL_ShowWindow(screen->window); diff --git a/app/src/screen.h b/app/src/screen.h index 6f002d13d7..f337903d24 100644 --- a/app/src/screen.h +++ b/app/src/screen.h @@ -20,6 +20,15 @@ struct screen { bool has_frame; bool fullscreen; bool no_window; +#ifdef HIDPI_SUPPORT + // these values store the ratio between renderer pixel size and window size + // in most configurations these ratios would be 1.0 (1000), but on MacOS with + // a Retina/HIDPI monitor connected they are 2.0 (2000) because that's how + // Apple chose to maintain compatibility with legacy apps, by pretending that + // that the screen has half of its real resolution. + int expected_hidpi_w_factor; // multiplied by 1000 to avoid float + int expected_hidpi_h_factor; // multiplied by 1000 to avoid float +#endif }; #define SCREEN_INITIALIZER { \ @@ -48,6 +57,15 @@ bool screen_init_rendering(struct screen *screen, const char *window_title, struct size frame_size, bool always_on_top); +#ifdef HIDPI_SUPPORT +// test if the expected renderer to window ratio is correct +// used to work around SDL bugs +// returns true if correct. +// If it returns false the renderer state needs to be fixed +bool +screen_test_correct_hidpi_ratio(struct screen *screen); +#endif + // reinitialize the renderer (only used in some configurations // if necessary to workaround SDL bugs) bool