From 3ef31a1f587f4ccf1819a337e54c277402b0f098 Mon Sep 17 00:00:00 2001 From: Reynaldo San Juan Date: Sat, 13 Sep 2025 19:16:10 +0200 Subject: [PATCH] feat: enhance resizable virtual display handling and improve resize quality --- app/src/input_manager.c | 5 ++ app/src/screen.c | 62 ++++++------------- .../genymobile/scrcpy/control/Controller.java | 1 + .../scrcpy/video/NewDisplayCapture.java | 13 ++-- 4 files changed, 34 insertions(+), 47 deletions(-) diff --git a/app/src/input_manager.c b/app/src/input_manager.c index 3e4dd0f3..d6ab31ac 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -541,6 +541,11 @@ sc_input_manager_process_key(struct sc_input_manager *im, if (shift) { reset_video(im); } else { + // Disable MOD+R rotation in resizable virtual display mode + if (im->screen->resizable_new_display) { + LOGI("MOD+R rotation disabled in resizable virtual display mode"); + return; + } rotate_device(im); } } diff --git a/app/src/screen.c b/app/src/screen.c index 006cbc3c..520dc325 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -251,45 +251,8 @@ event_watcher(void *data, SDL_Event *event) { assert(screen->video); if (event->type == SDL_WINDOWEVENT && event->window.event == SDL_WINDOWEVENT_RESIZED) { - int width = event->window.data1; - int height = event->window.data2; - if (screen->resizable_new_display) { - if ((!sizes_are_close(width, screen->last_window_width, 2) || !sizes_are_close(height, screen->last_window_height, 2)) && - !screen->initial_setup && !screen->content_driven_resize) { - screen->last_window_width = width; - screen->last_window_height = height; - // --- Resize diferido --- - screen->pending_resize_width = width; - screen->pending_resize_height = height; - if (screen->resize_timer) { - SDL_RemoveTimer(screen->resize_timer); - } - screen->resize_timer = SDL_AddTimer(RESIZE_FINISHED_DELAY, resize_timer_callback, screen); - // --- Fin resize diferido --- - sc_screen_render(screen, true); - } else if (screen->initial_setup) { - LOGD("[RESIZED] Initial setup resize ignored: %dx%d", width, height); - sc_screen_render(screen, true); - } else if (screen->content_driven_resize) { - LOGD("[RESIZED] Content-driven resize ignored: %dx%d", width, height); - sc_screen_render(screen, true); - } - } else { - // Modo normal - if (screen->content_driven_resize) { - LOGD("[RESIZED] Content-driven resize, solo render"); - sc_screen_render(screen, true); - return 0; - } - if (screen->initial_setup) { - LOGD("[RESIZED] Initial setup, solo render"); - sc_screen_render(screen, true); - return 0; - } - LOGD("[RESIZED] User resize detected: %dx%d", width, height); - sc_screen_render(screen, true); - sc_screen_send_resize_display(screen, width, height); - } + // Only handle rendering for the workaround, resize logic should be handled elsewhere + sc_screen_render(screen, true); } return 0; } @@ -924,8 +887,18 @@ sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) { screen->last_window_width = w; screen->last_window_height = h; // --- Resize diferido --- - screen->pending_resize_width = w; - screen->pending_resize_height = h; + // Round to multiple of 8 to match server-side rounding and avoid quality degradation + int rounded_w = (w + 4) & ~7; // Round to nearest multiple of 8 + int rounded_h = (h + 4) & ~7; // Round to nearest multiple of 8 + + // Resize window to rounded dimensions to maintain quality + if (rounded_w != w || rounded_h != h) { + SDL_SetWindowSize(screen->window, rounded_w, rounded_h); + LOGD("Window resized to rounded dimensions: %dx%d (from %dx%d)", rounded_w, rounded_h, w, h); + } + + screen->pending_resize_width = rounded_w; + screen->pending_resize_height = rounded_h; if (screen->resize_timer) { SDL_RemoveTimer(screen->resize_timer); } @@ -1084,7 +1057,10 @@ static Uint32 resize_timer_callback(Uint32 interval, void *param) { LOGD("Ignoring invalid resize: %dx%d", width, height); return 0; } - LOGD("[RESIZE_FINISHED] Notifying display resize: %dx%d", width, height); - sc_screen_send_resize_display(screen, width, height); + // Round to multiple of 8 to match server-side rounding and avoid quality degradation + int rounded_w = (width + 4) & ~7; // Round to nearest multiple of 8 + int rounded_h = (height + 4) & ~7; // Round to nearest multiple of 8 + LOGD("[RESIZE_FINISHED] Notifying display resize: %dx%d (rounded from %dx%d)", rounded_w, rounded_h, width, height); + sc_screen_send_resize_display(screen, rounded_w, rounded_h); return 0; } 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 d86220ed..b7da5b42 100644 --- a/server/src/main/java/com/genymobile/scrcpy/control/Controller.java +++ b/server/src/main/java/com/genymobile/scrcpy/control/Controller.java @@ -313,6 +313,7 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener { break; case ControlMessage.TYPE_ROTATE_DEVICE: Device.rotateDevice(getActionDisplayId()); + // The virtual display resize will be handled by the main display monitor break; case ControlMessage.TYPE_UHID_CREATE: getUhidManager().open(msg.getId(), msg.getVendorId(), msg.getProductId(), msg.getText(), msg.getData()); 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 f3fa93d4..c20fcf04 100644 --- a/server/src/main/java/com/genymobile/scrcpy/video/NewDisplayCapture.java +++ b/server/src/main/java/com/genymobile/scrcpy/video/NewDisplayCapture.java @@ -295,14 +295,19 @@ public class NewDisplayCapture extends SurfaceCapture { // Ensure DPI is within valid range (Android requires DPI >= 1) newDpi = Math.max(1, newDpi); - // Resize the virtual display - virtualDisplay.resize(newWidth, newHeight, newDpi); + // Round to multiple of 8 to avoid quality degradation from encoding constraints + Size roundedSize = new Size(newWidth, newHeight).round8(); + int roundedWidth = roundedSize.getWidth(); + int roundedHeight = roundedSize.getHeight(); + + // Resize the virtual display with rounded dimensions + virtualDisplay.resize(roundedWidth, roundedHeight, newDpi); // Update our internal state - displaySize = new Size(newWidth, newHeight); + displaySize = new Size(roundedWidth, roundedHeight); dpi = newDpi; - Ln.i("Resized display to: " + newWidth + "x" + newHeight + "/" + newDpi); + Ln.i("Resized display to: " + roundedWidth + "x" + roundedHeight + "/" + newDpi + " (rounded from " + newWidth + "x" + newHeight + ")"); // Trigger a reconfiguration invalidate();