From 1f17564334e5d462df6ce80df562d918c05e723e Mon Sep 17 00:00:00 2001 From: Tinura Dinith Date: Mon, 9 Mar 2026 00:45:31 +0530 Subject: [PATCH] Removed recreate fallback | removed sc_screen_maybe_send_vd_resize duplication | dpi value arg added | Avoid relaunching on successful resizes --- app/src/cli.c | 37 ++++++++++++++++++- app/src/options.c | 1 + app/src/options.h | 1 + app/src/scrcpy.c | 1 + app/src/screen.c | 12 +++--- app/src/screen.h | 2 + .../genymobile/scrcpy/control/Controller.java | 13 ------- .../scrcpy/video/NewDisplayCapture.java | 5 +-- 8 files changed, 49 insertions(+), 23 deletions(-) diff --git a/app/src/cli.c b/app/src/cli.c index 8a33691a..430d870e 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -641,7 +641,8 @@ static const struct sc_option options[] = { .optional_arg = true, .text = "Create a new display that adapts to the scrcpy window size.\n" "When the window is resized, the virtual display is resized " - "accordingly and its density is updated.", + "accordingly and its density is updated.\n" + "If / is provided, use that fixed density.", }, { .longopt_id = OPT_ADAPTIVE_SCALE, @@ -1822,6 +1823,29 @@ parse_display_id(const char *s, uint32_t *display_id) { return true; } +static bool +parse_display_dpi(const char *s, uint16_t *dpi_out, bool *has_dpi_out) { + *has_dpi_out = false; + if (!s) { + return true; + } + const char *slash = strrchr(s, '/'); + if (!slash) { + return true; + } + const char *dpi_str = slash + 1; + if (*dpi_str == '\0') { + return false; + } + long value = 0; + if (!sc_str_parse_integer(dpi_str, &value) || value <= 0 || value > 65535) { + return false; + } + *dpi_out = (uint16_t) value; + *has_dpi_out = true; + return true; +} + static bool parse_log_level(const char *s, enum sc_log_level *log_level) { if (!strcmp(s, "verbose")) { @@ -2818,6 +2842,17 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[], case OPT_ADAPTIVE_NEW_DISPLAY: opts->adaptive_new_display = true; opts->new_display = optarg ? optarg : ""; + if (optarg) { + uint16_t dpi = 0; + bool has_dpi = false; + if (!parse_display_dpi(optarg, &dpi, &has_dpi)) { + LOGE("Invalid adaptive-new-display DPI: %s", optarg); + return false; + } + if (has_dpi) { + opts->adaptive_dpi = dpi; + } + } break; case OPT_ADAPTIVE_SCALE: { char *endptr = NULL; diff --git a/app/src/options.c b/app/src/options.c index dcf920b1..9d71c447 100644 --- a/app/src/options.c +++ b/app/src/options.c @@ -111,6 +111,7 @@ const struct scrcpy_options scrcpy_options_default = { .new_display = NULL, .adaptive_new_display = false, .adaptive_scale = 0.0, + .adaptive_dpi = 0, .start_app = NULL, .angle = NULL, .vd_destroy_content = true, diff --git a/app/src/options.h b/app/src/options.h index 542a0a49..1a6f77d7 100644 --- a/app/src/options.h +++ b/app/src/options.h @@ -326,6 +326,7 @@ struct scrcpy_options { const char *new_display; // [x][/] parsed by the server bool adaptive_new_display; double adaptive_scale; + uint16_t adaptive_dpi; // if non-zero, use as fixed dpi for adaptive mode const char *start_app; bool vd_destroy_content; bool vd_system_decorations; diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 2506b258..0e277406 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -827,6 +827,7 @@ aoa_complete: .new_display = options->new_display != NULL, .adaptive_new_display = options->adaptive_new_display, .adaptive_scale = options->adaptive_scale, + .adaptive_dpi = options->adaptive_dpi, }; if (!sc_screen_init(&s->screen, &screen_params)) { diff --git a/app/src/screen.c b/app/src/screen.c index cf9b732b..f1543bf2 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -11,6 +11,7 @@ #include "util/log.h" #define DISPLAY_MARGINS 96 +#define SC_VD_RESIZE_DEBOUNCE_MS 250 #define DOWNCAST(SINK) container_of(SINK, struct sc_screen, frame_sink) @@ -29,6 +30,9 @@ get_oriented_size(struct sc_size size, enum sc_orientation orientation) { static uint16_t get_window_dpi(const struct sc_screen *screen) { + if (screen->vd_fixed_dpi) { + return screen->vd_fixed_dpi; + } if (screen->adaptive_new_display) { double scale = screen->vd_scale > 0.0 ? screen->vd_scale : 1.0; uint32_t dpi = (uint32_t) (scale * 160.0 + 0.5); @@ -85,15 +89,13 @@ sc_screen_schedule_vd_resize(struct sc_screen *screen) { return; } struct sc_size size = get_window_size(screen); - if (size.width == 0 || size.height == 0) { - return; - } if (size.width < 64 || size.height < 64) { return; } screen->vd_resize_size = size; screen->vd_resize_pending = true; - screen->vd_resize_deadline_ms = SDL_GetTicks() + 250; + screen->vd_resize_deadline_ms = SDL_GetTicks() + + SC_VD_RESIZE_DEBOUNCE_MS; } static void @@ -427,6 +429,7 @@ sc_screen_init(struct sc_screen *screen, screen->vd_initial_resize_sent = false; screen->vd_last_sent_valid = false; screen->vd_last_sent_dpi = 0; + screen->vd_fixed_dpi = params->adaptive_dpi; screen->vd_resize_deadline_ms = 0; screen->vd_scale = params->adaptive_scale; @@ -922,7 +925,6 @@ sc_screen_resize_to_pixel_perfect(struct sc_screen *screen) { bool sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) { - sc_screen_maybe_send_vd_resize(screen); switch (event->type) { case SC_EVENT_SCREEN_INIT_SIZE: { // The initial size is passed via screen->frame_size diff --git a/app/src/screen.h b/app/src/screen.h index d5c3be3d..50c35499 100644 --- a/app/src/screen.h +++ b/app/src/screen.h @@ -79,6 +79,7 @@ struct sc_screen { struct sc_size vd_last_sent_size; bool vd_last_sent_valid; uint16_t vd_last_sent_dpi; + uint16_t vd_fixed_dpi; uint32_t vd_resize_deadline_ms; double vd_scale; }; @@ -115,6 +116,7 @@ struct sc_screen_params { bool new_display; bool adaptive_new_display; double adaptive_scale; + uint16_t adaptive_dpi; }; // initialize screen, create window, renderer and texture (window is hidden) diff --git a/server/src/main/java/com/genymobile/scrcpy/control/Controller.java b/server/src/main/java/com/genymobile/scrcpy/control/Controller.java index d0cdfc54..11f5e1e0 100644 --- a/server/src/main/java/com/genymobile/scrcpy/control/Controller.java +++ b/server/src/main/java/com/genymobile/scrcpy/control/Controller.java @@ -96,9 +96,6 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener { private final MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[PointersState.MAX_POINTERS]; private boolean keepDisplayPowerOff; - private String lastStartedAppPackage; - private boolean lastStartedAppForceStop; - private boolean pendingRelaunchOnResize; // Used for resetting video encoding on RESET_VIDEO message private SurfaceCapture surfaceCapture; @@ -149,11 +146,6 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener { displayDataAvailable.notify(); } } - if (pendingRelaunchOnResize && lastStartedAppPackage != null) { - pendingRelaunchOnResize = false; - Ln.i("Relaunching app \"" + lastStartedAppPackage + "\" on resized display " + virtualDisplayId + "..."); - Device.startApp(lastStartedAppPackage, virtualDisplayId, lastStartedAppForceStop); - } } public void setSurfaceCapture(SurfaceCapture surfaceCapture) { @@ -702,8 +694,6 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener { Ln.i("Starting app \"" + app.getName() + "\" [" + app.getPackageName() + "] on display " + startAppDisplayId + "..."); Device.startApp(app.getPackageName(), startAppDisplayId, forceStopBeforeStart); - lastStartedAppPackage = app.getPackageName(); - lastStartedAppForceStop = forceStopBeforeStart; } private int getStartAppDisplayId() { @@ -773,9 +763,6 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener { com.genymobile.scrcpy.video.NewDisplayCapture nd = (com.genymobile.scrcpy.video.NewDisplayCapture) surfaceCapture; Ln.i("Resize virtual display to " + width + "x" + height + "/" + dpi); - if (lastStartedAppPackage != null) { - pendingRelaunchOnResize = true; - } nd.setDisplaySize(width, height, dpi); } else { Ln.w("Display resize ignored: not a virtual display capture"); diff --git a/server/src/main/java/com/genymobile/scrcpy/video/NewDisplayCapture.java b/server/src/main/java/com/genymobile/scrcpy/video/NewDisplayCapture.java index 738f59fb..69b31c23 100644 --- a/server/src/main/java/com/genymobile/scrcpy/video/NewDisplayCapture.java +++ b/server/src/main/java/com/genymobile/scrcpy/video/NewDisplayCapture.java @@ -298,10 +298,7 @@ public class NewDisplayCapture extends SurfaceCapture { displaySizeMonitor.setSessionDisplaySize(requestedDisplaySize); Ln.i("Virtual display resized in-place to " + width + "x" + height + "/" + newDpi); } catch (Exception e) { - Ln.w("Virtual display resize failed, fallback to recreate", e); - displaySizeMonitor.stopAndRelease(); - virtualDisplay.release(); - virtualDisplay = null; + Ln.w("Virtual display resize failed, keeping existing display", e); } }