mirror of
https://github.com/Genymobile/scrcpy.git
synced 2026-04-21 01:33:36 +00:00
Added adaptive virtual display that adjusts to window size
This commit is contained in:
parent
3fcc177da5
commit
52709d60ba
12 changed files with 308 additions and 8 deletions
|
|
@ -106,6 +106,8 @@ enum {
|
|||
OPT_AUDIO_DUP,
|
||||
OPT_GAMEPAD,
|
||||
OPT_NEW_DISPLAY,
|
||||
OPT_ADAPTIVE_NEW_DISPLAY,
|
||||
OPT_ADAPTIVE_SCALE,
|
||||
OPT_LIST_APPS,
|
||||
OPT_START_APP,
|
||||
OPT_SCREEN_OFF_TIMEOUT,
|
||||
|
|
@ -632,6 +634,22 @@ static const struct sc_option options[] = {
|
|||
" --new-display # main display size and density\n"
|
||||
" --new-display=/240 # main display size and 240 dpi",
|
||||
},
|
||||
{
|
||||
.longopt_id = OPT_ADAPTIVE_NEW_DISPLAY,
|
||||
.longopt = "adaptive-new-display",
|
||||
.argdesc = "[<width>x<height>][/<dpi>]",
|
||||
.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.",
|
||||
},
|
||||
{
|
||||
.longopt_id = OPT_ADAPTIVE_SCALE,
|
||||
.longopt = "adaptive-scale",
|
||||
.argdesc = "<scale>",
|
||||
.text = "Set adaptive scale factor (dpi = scale * 160). "
|
||||
"Default is 1.0 (dpi=160).",
|
||||
},
|
||||
{
|
||||
.longopt_id = OPT_NO_AUDIO,
|
||||
.longopt = "no-audio",
|
||||
|
|
@ -2797,6 +2815,20 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
|||
case OPT_NEW_DISPLAY:
|
||||
opts->new_display = optarg ? optarg : "";
|
||||
break;
|
||||
case OPT_ADAPTIVE_NEW_DISPLAY:
|
||||
opts->adaptive_new_display = true;
|
||||
opts->new_display = optarg ? optarg : "";
|
||||
break;
|
||||
case OPT_ADAPTIVE_SCALE: {
|
||||
char *endptr = NULL;
|
||||
double value = strtod(optarg, &endptr);
|
||||
if (!endptr || *endptr != '\0' || value <= 0.0) {
|
||||
LOGE("Invalid adaptive scale: %s", optarg);
|
||||
return false;
|
||||
}
|
||||
opts->adaptive_scale = value;
|
||||
break;
|
||||
}
|
||||
case OPT_START_APP:
|
||||
opts->start_app = optarg;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -182,6 +182,11 @@ sc_control_msg_serialize(const struct sc_control_msg *msg, uint8_t *buf) {
|
|||
size_t len = write_string_tiny(&buf[1], msg->start_app.name, 255);
|
||||
return 1 + len;
|
||||
}
|
||||
case SC_CONTROL_MSG_TYPE_SET_DISPLAY_SIZE:
|
||||
sc_write16be(&buf[1], msg->set_display_size.width);
|
||||
sc_write16be(&buf[3], msg->set_display_size.height);
|
||||
sc_write16be(&buf[5], msg->set_display_size.dpi);
|
||||
return 7;
|
||||
case SC_CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL:
|
||||
case SC_CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL:
|
||||
case SC_CONTROL_MSG_TYPE_COLLAPSE_PANELS:
|
||||
|
|
@ -315,6 +320,12 @@ sc_control_msg_log(const struct sc_control_msg *msg) {
|
|||
case SC_CONTROL_MSG_TYPE_START_APP:
|
||||
LOG_CMSG("start app \"%s\"", msg->start_app.name);
|
||||
break;
|
||||
case SC_CONTROL_MSG_TYPE_SET_DISPLAY_SIZE:
|
||||
LOG_CMSG("set display size %ux%u/%u",
|
||||
msg->set_display_size.width,
|
||||
msg->set_display_size.height,
|
||||
msg->set_display_size.dpi);
|
||||
break;
|
||||
case SC_CONTROL_MSG_TYPE_RESET_VIDEO:
|
||||
LOG_CMSG("reset video");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ enum sc_control_msg_type {
|
|||
SC_CONTROL_MSG_TYPE_OPEN_HARD_KEYBOARD_SETTINGS,
|
||||
SC_CONTROL_MSG_TYPE_START_APP,
|
||||
SC_CONTROL_MSG_TYPE_RESET_VIDEO,
|
||||
SC_CONTROL_MSG_TYPE_SET_DISPLAY_SIZE,
|
||||
};
|
||||
|
||||
enum sc_copy_key {
|
||||
|
|
@ -111,6 +112,11 @@ struct sc_control_msg {
|
|||
struct {
|
||||
char *name;
|
||||
} start_app;
|
||||
struct {
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint16_t dpi;
|
||||
} set_display_size;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ const struct scrcpy_options scrcpy_options_default = {
|
|||
.mouse_hover = true,
|
||||
.audio_dup = false,
|
||||
.new_display = NULL,
|
||||
.adaptive_new_display = false,
|
||||
.adaptive_scale = 0.0,
|
||||
.start_app = NULL,
|
||||
.angle = NULL,
|
||||
.vd_destroy_content = true,
|
||||
|
|
|
|||
|
|
@ -324,6 +324,8 @@ struct scrcpy_options {
|
|||
bool mouse_hover;
|
||||
bool audio_dup;
|
||||
const char *new_display; // [<width>x<height>][/<dpi>] parsed by the server
|
||||
bool adaptive_new_display;
|
||||
double adaptive_scale;
|
||||
const char *start_app;
|
||||
bool vd_destroy_content;
|
||||
bool vd_system_decorations;
|
||||
|
|
|
|||
|
|
@ -824,6 +824,9 @@ aoa_complete:
|
|||
.mipmaps = options->mipmaps,
|
||||
.fullscreen = options->fullscreen,
|
||||
.start_fps_counter = options->start_fps_counter,
|
||||
.new_display = options->new_display != NULL,
|
||||
.adaptive_new_display = options->adaptive_new_display,
|
||||
.adaptive_scale = options->adaptive_scale,
|
||||
};
|
||||
|
||||
if (!sc_screen_init(&s->screen, &screen_params)) {
|
||||
|
|
|
|||
133
app/src/screen.c
133
app/src/screen.c
|
|
@ -4,6 +4,7 @@
|
|||
#include <string.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "control_msg.h"
|
||||
#include "events.h"
|
||||
#include "icon.h"
|
||||
#include "options.h"
|
||||
|
|
@ -26,6 +27,38 @@ get_oriented_size(struct sc_size size, enum sc_orientation orientation) {
|
|||
return oriented_size;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
get_window_dpi(const struct sc_screen *screen) {
|
||||
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);
|
||||
if (dpi == 0) {
|
||||
dpi = 1;
|
||||
} else if (dpi > 65535) {
|
||||
dpi = 65535;
|
||||
}
|
||||
return (uint16_t) dpi;
|
||||
}
|
||||
|
||||
int display_index = SDL_GetWindowDisplayIndex(screen->window);
|
||||
if (display_index < 0) {
|
||||
return 0;
|
||||
}
|
||||
float ddpi = 0.f;
|
||||
float hdpi = 0.f;
|
||||
float vdpi = 0.f;
|
||||
if (SDL_GetDisplayDPI(display_index, &ddpi, &hdpi, &vdpi) != 0) {
|
||||
return 0;
|
||||
}
|
||||
if (ddpi <= 0.f) {
|
||||
return 0;
|
||||
}
|
||||
if (ddpi > 65535.f) {
|
||||
ddpi = 65535.f;
|
||||
}
|
||||
return (uint16_t) (ddpi + 0.5f);
|
||||
}
|
||||
|
||||
// get the window size in a struct sc_size
|
||||
static struct sc_size
|
||||
get_window_size(const struct sc_screen *screen) {
|
||||
|
|
@ -39,6 +72,60 @@ get_window_size(const struct sc_screen *screen) {
|
|||
return size;
|
||||
}
|
||||
|
||||
static void
|
||||
sc_screen_schedule_vd_resize(struct sc_screen *screen) {
|
||||
if (!screen->adaptive_new_display) {
|
||||
return;
|
||||
}
|
||||
if (!screen->vd_resize_enabled) {
|
||||
return;
|
||||
}
|
||||
// screen->im.controller may be NULL if --no-control
|
||||
if (!screen->im.controller) {
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
sc_screen_maybe_send_vd_resize(struct sc_screen *screen) {
|
||||
if (!screen->vd_resize_pending) {
|
||||
return;
|
||||
}
|
||||
uint32_t now = SDL_GetTicks();
|
||||
if (now < screen->vd_resize_deadline_ms) {
|
||||
return;
|
||||
}
|
||||
if (screen->vd_last_sent_valid
|
||||
&& screen->vd_last_sent_size.width == screen->vd_resize_size.width
|
||||
&& screen->vd_last_sent_size.height == screen->vd_resize_size.height) {
|
||||
screen->vd_resize_pending = false;
|
||||
return;
|
||||
}
|
||||
uint16_t dpi = get_window_dpi(screen);
|
||||
struct sc_control_msg msg = {
|
||||
.type = SC_CONTROL_MSG_TYPE_SET_DISPLAY_SIZE,
|
||||
};
|
||||
msg.set_display_size.width = (uint16_t) screen->vd_resize_size.width;
|
||||
msg.set_display_size.height = (uint16_t) screen->vd_resize_size.height;
|
||||
msg.set_display_size.dpi = dpi;
|
||||
if (sc_controller_push_msg(screen->im.controller, &msg)) {
|
||||
screen->vd_last_sent_size = screen->vd_resize_size;
|
||||
screen->vd_last_sent_valid = true;
|
||||
screen->vd_last_sent_dpi = dpi;
|
||||
}
|
||||
screen->vd_resize_pending = false;
|
||||
}
|
||||
|
||||
static struct sc_point
|
||||
get_window_position(const struct sc_screen *screen) {
|
||||
int x;
|
||||
|
|
@ -333,6 +420,15 @@ sc_screen_init(struct sc_screen *screen,
|
|||
screen->paused = false;
|
||||
screen->resume_frame = NULL;
|
||||
screen->orientation = SC_ORIENTATION_0;
|
||||
screen->new_display = params->new_display;
|
||||
screen->adaptive_new_display = params->adaptive_new_display;
|
||||
screen->vd_resize_pending = false;
|
||||
screen->vd_resize_enabled = false;
|
||||
screen->vd_initial_resize_sent = false;
|
||||
screen->vd_last_sent_valid = false;
|
||||
screen->vd_last_sent_dpi = 0;
|
||||
screen->vd_resize_deadline_ms = 0;
|
||||
screen->vd_scale = params->adaptive_scale;
|
||||
|
||||
screen->video = params->video;
|
||||
|
||||
|
|
@ -491,9 +587,22 @@ sc_screen_show_initial_window(struct sc_screen *screen) {
|
|||
int y = screen->req.y != SC_WINDOW_POSITION_UNDEFINED
|
||||
? screen->req.y : (int) SDL_WINDOWPOS_CENTERED;
|
||||
|
||||
struct sc_size window_size =
|
||||
get_initial_optimal_size(screen->content_size, screen->req.width,
|
||||
screen->req.height);
|
||||
struct sc_size window_size;
|
||||
if (screen->adaptive_new_display
|
||||
&& !screen->req.width && !screen->req.height) {
|
||||
struct sc_size bounds;
|
||||
if (get_preferred_display_bounds(&bounds)) {
|
||||
window_size = get_optimal_size(bounds, screen->content_size, true);
|
||||
} else {
|
||||
window_size = get_initial_optimal_size(screen->content_size,
|
||||
screen->req.width,
|
||||
screen->req.height);
|
||||
}
|
||||
} else {
|
||||
window_size = get_initial_optimal_size(screen->content_size,
|
||||
screen->req.width,
|
||||
screen->req.height);
|
||||
}
|
||||
|
||||
set_window_size(screen, window_size);
|
||||
SDL_SetWindowPosition(screen->window, x, y);
|
||||
|
|
@ -557,6 +666,14 @@ static void
|
|||
set_content_size(struct sc_screen *screen, struct sc_size new_content_size) {
|
||||
assert(screen->video);
|
||||
|
||||
if (screen->new_display) {
|
||||
// For new-display, keep the window size controlled by the user.
|
||||
// Do not auto-resize the window to the content size to avoid
|
||||
// feedback loops with virtual display resizing.
|
||||
screen->content_size = new_content_size;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!screen->fullscreen && !screen->maximized && !screen->minimized) {
|
||||
resize_for_content(screen, screen->content_size, new_content_size);
|
||||
} else if (!screen->resize_pending) {
|
||||
|
|
@ -671,6 +788,11 @@ sc_screen_apply_frame(struct sc_screen *screen) {
|
|||
screen->has_frame = true;
|
||||
// this is the very first frame, show the window
|
||||
sc_screen_show_initial_window(screen);
|
||||
screen->vd_resize_enabled = true;
|
||||
if (screen->adaptive_new_display && !screen->vd_initial_resize_sent) {
|
||||
sc_screen_schedule_vd_resize(screen);
|
||||
screen->vd_initial_resize_sent = true;
|
||||
}
|
||||
|
||||
if (sc_screen_is_relative_mode(screen)) {
|
||||
// Capture mouse on start
|
||||
|
|
@ -800,6 +922,7 @@ 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
|
||||
|
|
@ -811,6 +934,7 @@ sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
|
|||
return true;
|
||||
}
|
||||
case SC_EVENT_NEW_FRAME: {
|
||||
sc_screen_maybe_send_vd_resize(screen);
|
||||
bool ok = sc_screen_update_frame(screen);
|
||||
if (!ok) {
|
||||
LOGE("Frame update failed\n");
|
||||
|
|
@ -837,6 +961,9 @@ sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
|
|||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
sc_screen_render(screen, true);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
sc_screen_schedule_vd_resize(screen);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_MAXIMIZED:
|
||||
screen->maximized = true;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -69,6 +69,18 @@ struct sc_screen {
|
|||
|
||||
bool paused;
|
||||
AVFrame *resume_frame;
|
||||
|
||||
bool new_display;
|
||||
bool adaptive_new_display;
|
||||
bool vd_resize_pending;
|
||||
bool vd_resize_enabled;
|
||||
bool vd_initial_resize_sent;
|
||||
struct sc_size vd_resize_size;
|
||||
struct sc_size vd_last_sent_size;
|
||||
bool vd_last_sent_valid;
|
||||
uint16_t vd_last_sent_dpi;
|
||||
uint32_t vd_resize_deadline_ms;
|
||||
double vd_scale;
|
||||
};
|
||||
|
||||
struct sc_screen_params {
|
||||
|
|
@ -100,6 +112,9 @@ struct sc_screen_params {
|
|||
|
||||
bool fullscreen;
|
||||
bool start_fps_counter;
|
||||
bool new_display;
|
||||
bool adaptive_new_display;
|
||||
double adaptive_scale;
|
||||
};
|
||||
|
||||
// initialize screen, create window, renderer and texture (window is hidden)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ public final class ControlMessage {
|
|||
public static final int TYPE_OPEN_HARD_KEYBOARD_SETTINGS = 15;
|
||||
public static final int TYPE_START_APP = 16;
|
||||
public static final int TYPE_RESET_VIDEO = 17;
|
||||
public static final int TYPE_SET_DISPLAY_SIZE = 18;
|
||||
|
||||
public static final long SEQUENCE_INVALID = 0;
|
||||
|
||||
|
|
@ -53,6 +54,9 @@ public final class ControlMessage {
|
|||
private boolean on;
|
||||
private int vendorId;
|
||||
private int productId;
|
||||
private int displayWidth;
|
||||
private int displayHeight;
|
||||
private int displayDpi;
|
||||
|
||||
private ControlMessage() {
|
||||
}
|
||||
|
|
@ -166,6 +170,15 @@ public final class ControlMessage {
|
|||
return msg;
|
||||
}
|
||||
|
||||
public static ControlMessage createSetDisplaySize(int width, int height, int dpi) {
|
||||
ControlMessage msg = new ControlMessage();
|
||||
msg.type = TYPE_SET_DISPLAY_SIZE;
|
||||
msg.displayWidth = width;
|
||||
msg.displayHeight = height;
|
||||
msg.displayDpi = dpi;
|
||||
return msg;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
|
@ -249,4 +262,16 @@ public final class ControlMessage {
|
|||
public int getProductId() {
|
||||
return productId;
|
||||
}
|
||||
|
||||
public int getDisplayWidth() {
|
||||
return displayWidth;
|
||||
}
|
||||
|
||||
public int getDisplayHeight() {
|
||||
return displayHeight;
|
||||
}
|
||||
|
||||
public int getDisplayDpi() {
|
||||
return displayDpi;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ public class ControlMessageReader {
|
|||
case ControlMessage.TYPE_OPEN_HARD_KEYBOARD_SETTINGS:
|
||||
case ControlMessage.TYPE_RESET_VIDEO:
|
||||
return ControlMessage.createEmpty(type);
|
||||
case ControlMessage.TYPE_SET_DISPLAY_SIZE:
|
||||
return parseSetDisplaySize();
|
||||
case ControlMessage.TYPE_UHID_CREATE:
|
||||
return parseUhidCreate();
|
||||
case ControlMessage.TYPE_UHID_INPUT:
|
||||
|
|
@ -141,6 +143,13 @@ public class ControlMessageReader {
|
|||
return ControlMessage.createSetDisplayPower(on);
|
||||
}
|
||||
|
||||
private ControlMessage parseSetDisplaySize() throws IOException {
|
||||
int width = dis.readUnsignedShort();
|
||||
int height = dis.readUnsignedShort();
|
||||
int dpi = dis.readUnsignedShort();
|
||||
return ControlMessage.createSetDisplaySize(width, height, dpi);
|
||||
}
|
||||
|
||||
private ControlMessage parseUhidCreate() throws IOException {
|
||||
int id = dis.readUnsignedShort();
|
||||
int vendorId = dis.readUnsignedShort();
|
||||
|
|
|
|||
|
|
@ -96,6 +96,9 @@ 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;
|
||||
|
|
@ -146,6 +149,11 @@ 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) {
|
||||
|
|
@ -331,6 +339,9 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener {
|
|||
case ControlMessage.TYPE_RESET_VIDEO:
|
||||
resetVideo();
|
||||
break;
|
||||
case ControlMessage.TYPE_SET_DISPLAY_SIZE:
|
||||
setDisplaySize(msg.getDisplayWidth(), msg.getDisplayHeight(), msg.getDisplayDpi());
|
||||
break;
|
||||
default:
|
||||
// do nothing
|
||||
}
|
||||
|
|
@ -691,6 +702,8 @@ 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() {
|
||||
|
|
@ -754,4 +767,18 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener {
|
|||
surfaceCapture.requestInvalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private void setDisplaySize(int width, int height, int dpi) {
|
||||
if (surfaceCapture instanceof com.genymobile.scrcpy.video.NewDisplayCapture) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ public class NewDisplayCapture extends SurfaceCapture {
|
|||
private Size physicalSize; // the physical size of the display (without rotation)
|
||||
|
||||
private int dpi;
|
||||
private Size requestedDisplaySize;
|
||||
private int requestedDpi;
|
||||
private boolean hasRequestedSize;
|
||||
|
||||
public NewDisplayCapture(VirtualDisplayListener vdListener, Options options) {
|
||||
this.vdListener = vdListener;
|
||||
|
|
@ -105,11 +108,20 @@ public class NewDisplayCapture extends SurfaceCapture {
|
|||
public void prepare() {
|
||||
int displayRotation;
|
||||
if (virtualDisplay == null) {
|
||||
if (!newDisplay.hasExplicitSize()) {
|
||||
displaySize = mainDisplaySize;
|
||||
}
|
||||
if (!newDisplay.hasExplicitDpi()) {
|
||||
dpi = scaleDpi(mainDisplaySize, mainDisplayDpi, displaySize);
|
||||
if (hasRequestedSize && requestedDisplaySize != null) {
|
||||
displaySize = requestedDisplaySize;
|
||||
if (requestedDpi != 0) {
|
||||
dpi = requestedDpi;
|
||||
} else {
|
||||
dpi = scaleDpi(mainDisplaySize, mainDisplayDpi, displaySize);
|
||||
}
|
||||
} else {
|
||||
if (!newDisplay.hasExplicitSize()) {
|
||||
displaySize = mainDisplaySize;
|
||||
}
|
||||
if (!newDisplay.hasExplicitDpi()) {
|
||||
dpi = scaleDpi(mainDisplaySize, mainDisplayDpi, displaySize);
|
||||
}
|
||||
}
|
||||
|
||||
videoSize = displaySize;
|
||||
|
|
@ -266,4 +278,33 @@ public class NewDisplayCapture extends SurfaceCapture {
|
|||
public void requestInvalidate() {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public synchronized void setDisplaySize(int width, int height, int dpi) {
|
||||
if (width <= 0 || height <= 0) {
|
||||
return;
|
||||
}
|
||||
requestedDisplaySize = new Size(width, height);
|
||||
requestedDpi = dpi;
|
||||
hasRequestedSize = true;
|
||||
|
||||
if (virtualDisplay != null) {
|
||||
int newDpi = dpi;
|
||||
if (newDpi == 0) {
|
||||
newDpi = scaleDpi(mainDisplaySize, mainDisplayDpi, requestedDisplaySize);
|
||||
}
|
||||
|
||||
try {
|
||||
virtualDisplay.resize(width, height, newDpi);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue