|
|
|
@ -205,6 +205,8 @@ sc_screen_toggle_mouse_capture(struct sc_screen *screen) {
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
sc_screen_update_content_rect(struct sc_screen *screen) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
int dw;
|
|
|
|
|
int dh;
|
|
|
|
|
SDL_GL_GetDrawableSize(screen->window, &dw, &dh);
|
|
|
|
@ -246,6 +248,8 @@ sc_screen_update_content_rect(struct sc_screen *screen) {
|
|
|
|
|
// changed, so that the content rectangle is recomputed
|
|
|
|
|
static void
|
|
|
|
|
sc_screen_render(struct sc_screen *screen, bool update_content_rect) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
if (update_content_rect) {
|
|
|
|
|
sc_screen_update_content_rect(screen);
|
|
|
|
|
}
|
|
|
|
@ -255,6 +259,13 @@ sc_screen_render(struct sc_screen *screen, bool update_content_rect) {
|
|
|
|
|
(void) res; // any error already logged
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
sc_screen_render_novideo(struct sc_screen *screen) {
|
|
|
|
|
enum sc_display_result res =
|
|
|
|
|
sc_display_render(&screen->display, NULL, SC_ORIENTATION_0);
|
|
|
|
|
(void) res; // any error already logged
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(__APPLE__) || defined(__WINDOWS__)
|
|
|
|
|
# define CONTINUOUS_RESIZING_WORKAROUND
|
|
|
|
|
#endif
|
|
|
|
@ -268,6 +279,8 @@ sc_screen_render(struct sc_screen *screen, bool update_content_rect) {
|
|
|
|
|
static int
|
|
|
|
|
event_watcher(void *data, SDL_Event *event) {
|
|
|
|
|
struct sc_screen *screen = data;
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
if (event->type == SDL_WINDOWEVENT
|
|
|
|
|
&& event->window.event == SDL_WINDOWEVENT_RESIZED) {
|
|
|
|
|
// In practice, it seems to always be called from the same thread in
|
|
|
|
@ -326,6 +339,7 @@ sc_screen_frame_sink_close(struct sc_frame_sink *sink) {
|
|
|
|
|
static bool
|
|
|
|
|
sc_screen_frame_sink_push(struct sc_frame_sink *sink, const AVFrame *frame) {
|
|
|
|
|
struct sc_screen *screen = DOWNCAST(sink);
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
bool previous_skipped;
|
|
|
|
|
bool ok = sc_frame_buffer_push(&screen->fb, frame, &previous_skipped);
|
|
|
|
@ -364,6 +378,9 @@ sc_screen_init(struct sc_screen *screen,
|
|
|
|
|
screen->mouse_capture_key_pressed = 0;
|
|
|
|
|
screen->paused = false;
|
|
|
|
|
screen->resume_frame = NULL;
|
|
|
|
|
screen->orientation = SC_ORIENTATION_0;
|
|
|
|
|
|
|
|
|
|
screen->video = params->video;
|
|
|
|
|
|
|
|
|
|
screen->req.x = params->window_x;
|
|
|
|
|
screen->req.y = params->window_y;
|
|
|
|
@ -381,41 +398,75 @@ sc_screen_init(struct sc_screen *screen,
|
|
|
|
|
goto error_destroy_frame_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (screen->video) {
|
|
|
|
|
screen->orientation = params->orientation;
|
|
|
|
|
if (screen->orientation != SC_ORIENTATION_0) {
|
|
|
|
|
LOGI("Initial display orientation set to %s",
|
|
|
|
|
sc_orientation_get_name(screen->orientation));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t window_flags = SDL_WINDOW_HIDDEN
|
|
|
|
|
| SDL_WINDOW_RESIZABLE
|
|
|
|
|
| SDL_WINDOW_ALLOW_HIGHDPI;
|
|
|
|
|
uint32_t window_flags = SDL_WINDOW_ALLOW_HIGHDPI;
|
|
|
|
|
if (params->always_on_top) {
|
|
|
|
|
window_flags |= SDL_WINDOW_ALWAYS_ON_TOP;
|
|
|
|
|
}
|
|
|
|
|
if (params->window_borderless) {
|
|
|
|
|
window_flags |= SDL_WINDOW_BORDERLESS;
|
|
|
|
|
}
|
|
|
|
|
if (params->video) {
|
|
|
|
|
// The window will be shown on first frame
|
|
|
|
|
window_flags |= SDL_WINDOW_HIDDEN
|
|
|
|
|
| SDL_WINDOW_RESIZABLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *title = params->window_title;
|
|
|
|
|
assert(title);
|
|
|
|
|
|
|
|
|
|
int x = SDL_WINDOWPOS_UNDEFINED;
|
|
|
|
|
int y = SDL_WINDOWPOS_UNDEFINED;
|
|
|
|
|
int width = 256;
|
|
|
|
|
int height = 256;
|
|
|
|
|
if (params->window_x != SC_WINDOW_POSITION_UNDEFINED) {
|
|
|
|
|
x = params->window_x;
|
|
|
|
|
}
|
|
|
|
|
if (params->window_y != SC_WINDOW_POSITION_UNDEFINED) {
|
|
|
|
|
y = params->window_y;
|
|
|
|
|
}
|
|
|
|
|
if (params->window_width) {
|
|
|
|
|
width = params->window_width;
|
|
|
|
|
}
|
|
|
|
|
if (params->window_height) {
|
|
|
|
|
height = params->window_height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The window will be positioned and sized on first video frame
|
|
|
|
|
screen->window =
|
|
|
|
|
SDL_CreateWindow(params->window_title, 0, 0, 0, 0, window_flags);
|
|
|
|
|
screen->window = SDL_CreateWindow(title, x, y, width, height, window_flags);
|
|
|
|
|
if (!screen->window) {
|
|
|
|
|
LOGE("Could not create window: %s", SDL_GetError());
|
|
|
|
|
goto error_destroy_fps_counter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ok = sc_display_init(&screen->display, screen->window, params->mipmaps);
|
|
|
|
|
if (!ok) {
|
|
|
|
|
goto error_destroy_window;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SDL_Surface *icon = scrcpy_icon_load();
|
|
|
|
|
if (icon) {
|
|
|
|
|
SDL_SetWindowIcon(screen->window, icon);
|
|
|
|
|
scrcpy_icon_destroy(icon);
|
|
|
|
|
} else {
|
|
|
|
|
} else if (params->video) {
|
|
|
|
|
// just a warning
|
|
|
|
|
LOGW("Could not load icon");
|
|
|
|
|
} else {
|
|
|
|
|
// without video, the icon is used as window content, it must be present
|
|
|
|
|
LOGE("Could not load icon");
|
|
|
|
|
goto error_destroy_fps_counter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SDL_Surface *icon_novideo = params->video ? NULL : icon;
|
|
|
|
|
bool mipmaps = params->video && params->mipmaps;
|
|
|
|
|
ok = sc_display_init(&screen->display, screen->window, icon_novideo,
|
|
|
|
|
mipmaps);
|
|
|
|
|
if (icon) {
|
|
|
|
|
scrcpy_icon_destroy(icon);
|
|
|
|
|
}
|
|
|
|
|
if (!ok) {
|
|
|
|
|
goto error_destroy_window;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
screen->frame = av_frame_alloc();
|
|
|
|
@ -439,7 +490,9 @@ sc_screen_init(struct sc_screen *screen,
|
|
|
|
|
sc_input_manager_init(&screen->im, &im_params);
|
|
|
|
|
|
|
|
|
|
#ifdef CONTINUOUS_RESIZING_WORKAROUND
|
|
|
|
|
if (screen->video) {
|
|
|
|
|
SDL_AddEventWatch(event_watcher, screen);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static const struct sc_frame_sink_ops ops = {
|
|
|
|
@ -454,6 +507,11 @@ sc_screen_init(struct sc_screen *screen,
|
|
|
|
|
screen->open = false;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (!screen->video && sc_screen_is_relative_mode(screen)) {
|
|
|
|
|
// Capture mouse immediately if video mirroring is disabled
|
|
|
|
|
sc_screen_set_mouse_capture(screen, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
error_destroy_display:
|
|
|
|
@ -524,6 +582,8 @@ sc_screen_destroy(struct sc_screen *screen) {
|
|
|
|
|
static void
|
|
|
|
|
resize_for_content(struct sc_screen *screen, struct sc_size old_content_size,
|
|
|
|
|
struct sc_size new_content_size) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
struct sc_size window_size = get_window_size(screen);
|
|
|
|
|
struct sc_size target_size = {
|
|
|
|
|
.width = (uint32_t) window_size.width * new_content_size.width
|
|
|
|
@ -537,6 +597,8 @@ resize_for_content(struct sc_screen *screen, struct sc_size old_content_size,
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
set_content_size(struct sc_screen *screen, struct sc_size new_content_size) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
if (!screen->fullscreen && !screen->maximized && !screen->minimized) {
|
|
|
|
|
resize_for_content(screen, screen->content_size, new_content_size);
|
|
|
|
|
} else if (!screen->resize_pending) {
|
|
|
|
@ -551,6 +613,8 @@ set_content_size(struct sc_screen *screen, struct sc_size new_content_size) {
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
apply_pending_resize(struct sc_screen *screen) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
assert(!screen->fullscreen);
|
|
|
|
|
assert(!screen->maximized);
|
|
|
|
|
assert(!screen->minimized);
|
|
|
|
@ -564,6 +628,8 @@ apply_pending_resize(struct sc_screen *screen) {
|
|
|
|
|
void
|
|
|
|
|
sc_screen_set_orientation(struct sc_screen *screen,
|
|
|
|
|
enum sc_orientation orientation) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
if (orientation == screen->orientation) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -598,6 +664,8 @@ sc_screen_init_size(struct sc_screen *screen) {
|
|
|
|
|
// recreate the texture and resize the window if the frame size has changed
|
|
|
|
|
static enum sc_display_result
|
|
|
|
|
prepare_for_frame(struct sc_screen *screen, struct sc_size new_frame_size) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
if (screen->frame_size.width == new_frame_size.width
|
|
|
|
|
&& screen->frame_size.height == new_frame_size.height) {
|
|
|
|
|
return SC_DISPLAY_RESULT_OK;
|
|
|
|
@ -617,6 +685,8 @@ prepare_for_frame(struct sc_screen *screen, struct sc_size new_frame_size) {
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
sc_screen_apply_frame(struct sc_screen *screen) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
sc_fps_counter_add_rendered_frame(&screen->fps_counter);
|
|
|
|
|
|
|
|
|
|
AVFrame *frame = screen->frame;
|
|
|
|
@ -656,6 +726,8 @@ sc_screen_apply_frame(struct sc_screen *screen) {
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
sc_screen_update_frame(struct sc_screen *screen) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
if (screen->paused) {
|
|
|
|
|
if (!screen->resume_frame) {
|
|
|
|
|
screen->resume_frame = av_frame_alloc();
|
|
|
|
@ -677,6 +749,8 @@ sc_screen_update_frame(struct sc_screen *screen) {
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
sc_screen_set_paused(struct sc_screen *screen, bool paused) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
if (!paused && !screen->paused) {
|
|
|
|
|
// nothing to do
|
|
|
|
|
return;
|
|
|
|
@ -704,6 +778,8 @@ sc_screen_set_paused(struct sc_screen *screen, bool paused) {
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
sc_screen_switch_fullscreen(struct sc_screen *screen) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
uint32_t new_mode = screen->fullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP;
|
|
|
|
|
if (SDL_SetWindowFullscreen(screen->window, new_mode)) {
|
|
|
|
|
LOGW("Could not switch fullscreen mode: %s", SDL_GetError());
|
|
|
|
@ -721,6 +797,8 @@ sc_screen_switch_fullscreen(struct sc_screen *screen) {
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
sc_screen_resize_to_fit(struct sc_screen *screen) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
if (screen->fullscreen || screen->maximized || screen->minimized) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -745,6 +823,8 @@ sc_screen_resize_to_fit(struct sc_screen *screen) {
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
sc_screen_resize_to_pixel_perfect(struct sc_screen *screen) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
if (screen->fullscreen || screen->minimized) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -788,6 +868,13 @@ sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
case SDL_WINDOWEVENT:
|
|
|
|
|
if (!screen->video
|
|
|
|
|
&& event->window.event == SDL_WINDOWEVENT_EXPOSED) {
|
|
|
|
|
sc_screen_render_novideo(screen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// !video implies !has_frame
|
|
|
|
|
assert(screen->video || !screen->has_frame);
|
|
|
|
|
if (!screen->has_frame) {
|
|
|
|
|
// Do nothing
|
|
|
|
|
return true;
|
|
|
|
@ -891,6 +978,8 @@ sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
|
|
|
|
|
struct sc_point
|
|
|
|
|
sc_screen_convert_drawable_to_frame_coords(struct sc_screen *screen,
|
|
|
|
|
int32_t x, int32_t y) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
|
|
|
|
|
enum sc_orientation orientation = screen->orientation;
|
|
|
|
|
|
|
|
|
|
int32_t w = screen->content_size.width;
|
|
|
|
|