Removed recreate fallback | removed sc_screen_maybe_send_vd_resize duplication | dpi value arg added | Avoid relaunching on successful resizes

This commit is contained in:
Tinura Dinith 2026-03-09 00:45:31 +05:30
parent 52709d60ba
commit 1f17564334
8 changed files with 49 additions and 23 deletions

View file

@ -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 /<dpi> 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;

View file

@ -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,

View file

@ -326,6 +326,7 @@ struct scrcpy_options {
const char *new_display; // [<width>x<height>][/<dpi>] 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;

View file

@ -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)) {

View file

@ -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

View file

@ -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)

View file

@ -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");

View file

@ -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);
}
}