Compare commits

..

11 Commits

Author SHA1 Message Date
Romain Vimont
77998f543f Rename sc_display to sc_texture
The sc_display component now only handles a texture. Rendering has been
moved to sc_screen.

PR #6651 <https://github.com/Genymobile/scrcpy/pull/6651>
2026-02-09 18:33:57 +01:00
Romain Vimont
c43cc2ddc3 Set display texture from a frame
Add a function to set a texture from an AVFrame on a sc_display.

PR #6651 <https://github.com/Genymobile/scrcpy/pull/6651>
2026-02-09 18:33:52 +01:00
Romain Vimont
1617979549 Set display texture from a surface
Add a function to set a texture from a surface on a sc_display.

PR #6651 <https://github.com/Genymobile/scrcpy/pull/6651>
2026-02-09 18:33:48 +01:00
Romain Vimont
58818dc860 Use floating-point for content location
In SDL3, texture rendering uses SDL_FRect, unlike SDL2 which used
SDL_Rect.

Compute content location using floating-point coordinates from the
start.

PR #6651 <https://github.com/Genymobile/scrcpy/pull/6651>
2026-02-09 18:33:44 +01:00
Romain Vimont
3ef51e691e Factorize icon rendering
Replace SDL "logical rendering" with explicit computation of icon
location, and unify rendering of video frames and icons using the same
common code.

PR #6651 <https://github.com/Genymobile/scrcpy/pull/6651>
2026-02-09 18:33:41 +01:00
Romain Vimont
fb77f8556a Extract function to compute content location
PR #6651 <https://github.com/Genymobile/scrcpy/pull/6651>
2026-02-09 18:33:38 +01:00
Romain Vimont
e3f0c21f2a Use render output size to compute content location
The coordinates of the content to render depend on the render output
size, not the window size in pixels. In theory, the two could differ.

PR #6651 <https://github.com/Genymobile/scrcpy/pull/6651>
2026-02-09 18:33:35 +01:00
Romain Vimont
930169af4e Move rendering from sc_display to sc_screen
Three components are involved in displaying device content on screen:
 - a window
 - a renderer
 - a texture

Originally, all three were handled by sc_screen.

Commit 051b74c883 later extracted the
renderer and texture into a separate component, sc_display.

However, the split was a bit awkward because the window size and
rendering location were managed by separate components.

Move rendering back to sc_screen, keeping only texture management
separated.

PR #6651 <https://github.com/Genymobile/scrcpy/pull/6651>
2026-02-09 18:33:31 +01:00
Romain Vimont
3ce5feb5cb Move renderer from sc_display to sc_screen
Make sc_screen the owner of both the SDL window and the SDL renderer.
This is the first step toward limiting the role of sc_display to texture
management.

PR #6651 <https://github.com/Genymobile/scrcpy/pull/6651>
2026-02-09 18:33:29 +01:00
Romain Vimont
42e2264d67 Simplify texture failure handling
When the scrcpy window is minimized on Windows with D3D9, texture
creation and updates fail.

As a workaround, a mechanism was implemented to reattempt applying the
requested changes.

Since SDL3 defaults to the D3D11 backend, remove this workaround,
which adds a lot of complexity for a backend that should almost never
be used.

However, do not close scrcpy when texture creation or updates fail; only
that specific rendering should fail.

Refs SDL/#7651 <https://github.com/libsdl-org/SDL/issues/7651>
Refs #3947 <https://github.com/Genymobile/scrcpy/issues/3947>
Refs 6298ef095f
PR #6651 <https://github.com/Genymobile/scrcpy/pull/6651>
2026-02-09 18:33:18 +01:00
Romain Vimont
c497718a3e Report recording error on write error
The error flag was mistakenly set to false instead of true.
2026-02-05 18:27:05 +01:00
26 changed files with 91 additions and 407 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@@ -15,7 +15,6 @@ src = [
'src/delay_buffer.c',
'src/demuxer.c',
'src/device_msg.c',
'src/disconnect.c',
'src/events.c',
'src/icon.c',
'src/file_pusher.c',
@@ -191,7 +190,8 @@ executable('scrcpy', src,
datadir = get_option('datadir') # by default 'share'
install_man('scrcpy.1')
install_data('data/scrcpy.png',
install_data('data/icon.png',
rename: 'scrcpy.png',
install_dir: datadir / 'icons/hicolor/256x256/apps')
install_data('data/zsh-completion/_scrcpy',
install_dir: datadir / 'zsh/site-functions')
@@ -282,6 +282,6 @@ endif
if meson.version().version_compare('>= 0.58.0')
devenv = environment()
devenv.set('SCRCPY_ICON_DIR', meson.current_source_dir() / 'data')
devenv.set('SCRCPY_ICON_PATH', meson.current_source_dir() / 'data/icon.png')
meson.add_devenv(devenv)
endif

View File

@@ -851,8 +851,8 @@ Path to adb.
Device serial to use if no selector (\fB-s\fR, \fB-d\fR, \fB-e\fR or \fB\-\-tcpip=\fIaddr\fR) is specified.
.TP
.B SCRCPY_ICON_DIR
Path to the icon directory.
.B SCRCPY_ICON_PATH
Path to the program icon.
.TP
.B SCRCPY_SERVER_PATH

View File

@@ -1249,8 +1249,8 @@ static const struct sc_envvar envvars[] = {
"--tcpip=<addr>) is specified",
},
{
.name = "SCRCPY_ICON_DIR",
.text = "Path to the icon directory",
.name = "SCRCPY_ICON_PATH",
.text = "Path to the program icon",
},
{
.name = "SCRCPY_SERVER_PATH",

View File

@@ -1,89 +0,0 @@
#include "disconnect.h"
#include <assert.h>
#include "icon.h"
#include "util/log.h"
static int
run(void *userdata) {
struct sc_disconnect *d = userdata;
SDL_Surface *icon = sc_icon_load(SC_ICON_FILENAME_DISCONNECTED);
if (icon) {
d->cbs->on_icon_loaded(d, icon, d->cbs_userdata);
} else {
LOGE("Could not load disconnected icon");
}
if (d->deadline != SC_TICK_NONE) {
sc_mutex_lock(&d->mutex);
bool timed_out = false;
while (!d->interrupted && !timed_out) {
timed_out = !sc_cond_timedwait(&d->cond, &d->mutex, d->deadline);
}
sc_mutex_unlock(&d->mutex);
if (!d->interrupted) {
d->cbs->on_timeout(d, d->cbs_userdata);
}
}
return 0;
}
bool
sc_disconnect_start(struct sc_disconnect *d, sc_tick deadline,
const struct sc_disconnect_callbacks *cbs,
void *cbs_userdata) {
bool ok = sc_mutex_init(&d->mutex);
if (!ok) {
return false;
}
ok = sc_cond_init(&d->cond);
if (!ok) {
goto error_destroy_mutex;
}
ok = sc_thread_create(&d->thread, run, "scrcpy-dis", d);
if (!ok) {
goto error_destroy_cond;
}
d->deadline = deadline;
d->interrupted = false;
assert(cbs && cbs->on_icon_loaded && cbs->on_timeout);
d->cbs = cbs;
d->cbs_userdata = cbs_userdata;
return true;
error_destroy_mutex:
sc_mutex_destroy(&d->mutex);
error_destroy_cond:
sc_cond_destroy(&d->cond);
return false;
}
void
sc_disconnect_interrupt(struct sc_disconnect *d) {
sc_mutex_lock(&d->mutex);
d->interrupted = true;
sc_mutex_unlock(&d->mutex);
// wake up blocking wait
sc_cond_signal(&d->cond);
}
void
sc_disconnect_join(struct sc_disconnect *d) {
sc_thread_join(&d->thread, NULL);
}
void
sc_disconnect_destroy(struct sc_disconnect *d) {
sc_cond_destroy(&d->cond);
sc_mutex_destroy(&d->mutex);
}

View File

@@ -1,47 +0,0 @@
#ifndef SC_DISCONNECT
#define SC_DISCONNECT
#include "common.h"
#include "SDL3/SDL_surface.h"
#include "util/tick.h"
#include "util/thread.h"
// Tool to handle loading the icon and signal timeout when the device is
// unexpectedly disconnected
struct sc_disconnect {
sc_tick deadline;
struct sc_thread thread;
struct sc_mutex mutex;
struct sc_cond cond;
bool interrupted;
const struct sc_disconnect_callbacks *cbs;
void *cbs_userdata;
};
struct sc_disconnect_callbacks {
// Called when the disconnected icon is loaded
void (*on_icon_loaded)(struct sc_disconnect *d, SDL_Surface *icon,
void *userdata);
// Called when the timeout expired (the scrcpy window must be closed)
void (*on_timeout)(struct sc_disconnect *d, void *userdata);
};
bool
sc_disconnect_start(struct sc_disconnect *d, sc_tick deadline,
const struct sc_disconnect_callbacks *cbs,
void *cbs_userdata);
void
sc_disconnect_interrupt(struct sc_disconnect *d);
void
sc_disconnect_join(struct sc_disconnect *d);
void
sc_disconnect_destroy(struct sc_disconnect *d);
#endif

View File

@@ -6,13 +6,9 @@
#include "util/thread.h"
bool
sc_push_event_impl(uint32_t type, void* ptr, const char *name) {
SDL_Event event = {
.user = {
.type = type,
.data1 = ptr,
}
};
sc_push_event_impl(uint32_t type, const char *name) {
SDL_Event event;
event.type = type;
bool ok = SDL_PushEvent(&event);
if (!ok) {
LOGE("Could not post %s event: %s", name, SDL_GetError());

View File

@@ -13,20 +13,18 @@ enum {
SC_EVENT_DEVICE_DISCONNECTED,
SC_EVENT_SERVER_CONNECTION_FAILED,
SC_EVENT_SERVER_CONNECTED,
SC_EVENT_USB_DEVICE_DISCONNECTED,
SC_EVENT_DEMUXER_ERROR,
SC_EVENT_RECORDER_ERROR,
SC_EVENT_TIME_LIMIT_REACHED,
SC_EVENT_CONTROLLER_ERROR,
SC_EVENT_AOA_OPEN_ERROR,
SC_EVENT_DISCONNECTED_ICON_LOADED,
SC_EVENT_DISCONNECTED_TIMEOUT,
};
bool
sc_push_event_impl(uint32_t type, void* ptr, const char *name);
sc_push_event_impl(uint32_t type, const char *name);
#define sc_push_event(TYPE) sc_push_event_impl(TYPE, NULL, # TYPE)
#define sc_push_event_with_data(TYPE, PTR) sc_push_event_impl(TYPE, PTR, # TYPE)
#define sc_push_event(TYPE) sc_push_event_impl(TYPE, # TYPE)
typedef void (*sc_runnable_fn)(void *userdata);

View File

@@ -14,37 +14,33 @@
#include "config.h"
#include "util/env.h"
#include "util/file.h"
#ifdef PORTABLE
# include "util/file.h"
#endif
#include "util/log.h"
#define SCRCPY_DEFAULT_ICON_DIR PREFIX "/share/icons/hicolor/256x256/apps"
#define SCRCPY_PORTABLE_ICON_FILENAME "icon.png"
#define SCRCPY_DEFAULT_ICON_PATH \
PREFIX "/share/icons/hicolor/256x256/apps/scrcpy.png"
static char *
get_icon_path(const char *filename) {
char *icon_path;
char *icon_dir = sc_get_env("SCRCPY_ICON_DIR");
if (icon_dir) {
get_icon_path(void) {
char *icon_path = sc_get_env("SCRCPY_ICON_PATH");
if (icon_path) {
// if the envvar is set, use it
icon_path = sc_file_build_path(icon_dir, filename);
free(icon_dir);
if (!icon_path) {
LOG_OOM();
return NULL;
}
LOGD("Using icon from SCRCPY_ICON_DIR: %s", icon_path);
LOGD("Using SCRCPY_ICON_PATH: %s", icon_path);
return icon_path;
}
#ifndef PORTABLE
icon_path = sc_file_build_path(SCRCPY_DEFAULT_ICON_DIR, filename);
LOGD("Using icon: " SCRCPY_DEFAULT_ICON_PATH);
icon_path = strdup(SCRCPY_DEFAULT_ICON_PATH);
if (!icon_path) {
LOG_OOM();
return NULL;
}
LOGD("Using icon: %s", icon_path);
#else
icon_path = sc_file_get_local_path(filename);
icon_path = sc_file_get_local_path(SCRCPY_PORTABLE_ICON_FILENAME);
if (!icon_path) {
LOGE("Could not get icon path");
return NULL;
@@ -181,7 +177,7 @@ to_sdl_pixel_format(enum AVPixelFormat fmt) {
}
static SDL_Surface *
sc_icon_load_from_full_path(const char *path) {
load_from_path(const char *path) {
AVFrame *frame = decode_image(path);
if (!frame) {
return NULL;
@@ -278,19 +274,19 @@ error:
}
SDL_Surface *
sc_icon_load(const char *filename) {
char *icon_path = get_icon_path(filename);
scrcpy_icon_load(void) {
char *icon_path = get_icon_path();
if (!icon_path) {
return NULL;
}
SDL_Surface *icon = sc_icon_load_from_full_path(icon_path);
SDL_Surface *icon = load_from_path(icon_path);
free(icon_path);
return icon;
}
void
sc_icon_destroy(SDL_Surface *icon) {
scrcpy_icon_destroy(SDL_Surface *icon) {
SDL_PropertiesID props = SDL_GetSurfaceProperties(icon);
assert(props);
AVFrame *frame = SDL_GetPointerProperty(props, "sc_frame", NULL);

View File

@@ -5,13 +5,10 @@
#include <SDL3/SDL_surface.h>
#define SC_ICON_FILENAME_SCRCPY "scrcpy.png"
#define SC_ICON_FILENAME_DISCONNECTED "disconnected.png"
SDL_Surface *
sc_icon_load(const char *filename);
scrcpy_icon_load(void);
void
sc_icon_destroy(SDL_Surface *icon);
scrcpy_icon_destroy(SDL_Surface *icon);
#endif

View File

@@ -444,7 +444,7 @@ sc_recorder_process_packets(struct sc_recorder *recorder) {
int ret = av_write_trailer(recorder->ctx);
if (ret < 0) {
LOGE("Failed to write trailer to %s", recorder->filename);
error = false;
error = true;
}
end:

View File

@@ -167,41 +167,23 @@ sdl_configure(bool video_playback, bool disable_screensaver) {
}
static enum scrcpy_exit_code
event_loop(struct scrcpy *s, bool has_screen, bool disconnected) {
event_loop(struct scrcpy *s, bool has_screen) {
SDL_Event event;
while (SDL_WaitEvent(&event)) {
switch (event.type) {
case SC_EVENT_DEVICE_DISCONNECTED:
if (disconnected) {
break;
}
LOGW("Device disconnected");
if (has_screen && !sc_screen_handle_event(&s->screen, &event)) {
return SCRCPY_EXIT_FAILURE;
}
return SCRCPY_EXIT_DISCONNECTED;
case SC_EVENT_DEMUXER_ERROR:
if (disconnected) {
break;
}
LOGE("Demuxer error");
return SCRCPY_EXIT_FAILURE;
case SC_EVENT_CONTROLLER_ERROR:
if (disconnected) {
break;
}
LOGE("Controller error");
return SCRCPY_EXIT_FAILURE;
case SC_EVENT_RECORDER_ERROR:
if (disconnected) {
break;
}
LOGE("Recorder error");
return SCRCPY_EXIT_FAILURE;
case SC_EVENT_AOA_OPEN_ERROR:
if (disconnected) {
break;
}
LOGE("AOA open error");
return SCRCPY_EXIT_FAILURE;
case SC_EVENT_TIME_LIMIT_REACHED:
@@ -210,9 +192,6 @@ event_loop(struct scrcpy *s, bool has_screen, bool disconnected) {
case SDL_EVENT_QUIT:
LOGD("User requested to quit");
return SCRCPY_EXIT_SUCCESS;
case SC_EVENT_DISCONNECTED_TIMEOUT:
LOGD("Closing after device disconnection");
return SCRCPY_EXIT_DISCONNECTED;
case SC_EVENT_RUN_ON_MAIN_THREAD: {
sc_runnable_fn run = event.user.data1;
void *userdata = event.user.data2;
@@ -435,7 +414,6 @@ scrcpy(struct scrcpy_options *options) {
bool screen_initialized = false;
bool timeout_initialized = false;
bool timeout_started = false;
bool disconnected = false;
struct sc_acksync *acksync = NULL;
@@ -967,9 +945,16 @@ aoa_complete:
}
}
ret = event_loop(s, options->window, false);
ret = event_loop(s, options->window);
terminate_event_loop();
disconnected = ret == SCRCPY_EXIT_DISCONNECTED;
LOGD("quit...");
if (options->window) {
// Close the window immediately on closing, because screen_destroy()
// may only be called once the video demuxer thread is joined (it may
// take time)
sc_screen_hide_window(&s->screen);
}
end:
if (timeout_started) {
@@ -1014,25 +999,6 @@ end:
sc_server_stop(&s->server);
}
if (screen_initialized && ret != SCRCPY_EXIT_DISCONNECTED) {
assert(options->window);
// Close the window immediately, because sc_screen_destroy() may only be
// called once the video demuxer thread is joined (it may take time)
sc_screen_hide_window(&s->screen);
}
if (screen_initialized && options->window) {
if (disconnected) {
ret = event_loop(s, options->window, true);
sc_screen_interrupt_disconnect(&s->screen);
}
LOGD("Quit...");
// Close the window immediately, because sc_screen_destroy() may only be
// called once the video demuxer thread is joined (it may take time)
sc_screen_hide_window(&s->screen);
}
if (timeout_started) {
sc_timeout_join(&s->timeout);
}

View File

@@ -184,7 +184,7 @@ compute_content_rect(struct sc_size render_size, struct sc_size content_size,
static void
sc_screen_update_content_rect(struct sc_screen *screen) {
// Only upscale video frames, not icon
bool can_upscale = screen->video && !screen->disconnected;
bool can_upscale = screen->video;
struct sc_size render_size =
sc_sdl_get_render_output_size(screen->renderer);
@@ -210,9 +210,7 @@ sc_screen_render(struct sc_screen *screen, bool update_content_rect) {
bool ok = false;
SDL_Texture *texture = screen->tex.texture;
if (!texture) {
if (!screen->disconnected) {
LOGW("No texture to render");
}
LOGW("No texture to render");
goto end;
}
@@ -348,8 +346,6 @@ sc_screen_init(struct sc_screen *screen,
screen->paused = false;
screen->resume_frame = NULL;
screen->orientation = SC_ORIENTATION_0;
screen->disconnected = false;
screen->disconnect_started = false;
screen->video = params->video;
screen->camera = params->camera;
@@ -461,33 +457,35 @@ sc_screen_init(struct sc_screen *screen,
goto error_destroy_texture;
}
SDL_Surface *icon = sc_icon_load(SC_ICON_FILENAME_SCRCPY);
SDL_Surface *icon = scrcpy_icon_load();
if (icon) {
if (!SDL_SetWindowIcon(screen->window, icon)) {
LOGW("Could not set window icon: %s", SDL_GetError());
}
if (!params->video) {
screen->content_size.width = icon->w;
screen->content_size.height = icon->h;
ok = sc_texture_set_from_surface(&screen->tex, icon);
if (!ok) {
LOGE("Could not set icon: %s", SDL_GetError());
}
}
sc_icon_destroy(icon);
} else if (params->video) {
// just a warning
LOGW("Could not load icon");
} else {
// not fatal
// without video, the icon is used as window content, it must be present
LOGE("Could not load icon");
goto error_destroy_texture;
}
if (!params->video) {
// Make sure the content size is initialized
screen->content_size.width = 256;
screen->content_size.height = 256;
if (!params->video) {
assert(icon);
screen->content_size.width = icon->w;
screen->content_size.height = icon->h;
ok = sc_texture_set_from_surface(&screen->tex, icon);
if (!ok) {
scrcpy_icon_destroy(icon);
goto error_destroy_texture;
}
}
if (icon) {
scrcpy_icon_destroy(icon);
}
screen->frame = av_frame_alloc();
if (!screen->frame) {
LOG_OOM();
@@ -607,19 +605,9 @@ sc_screen_interrupt(struct sc_screen *screen) {
sc_fps_counter_interrupt(&screen->fps_counter);
}
void
sc_screen_interrupt_disconnect(struct sc_screen *screen) {
if (screen->disconnect_started) {
sc_disconnect_interrupt(&screen->disconnect);
}
}
void
sc_screen_join(struct sc_screen *screen) {
sc_fps_counter_join(&screen->fps_counter);
if (screen->disconnect_started) {
sc_disconnect_join(&screen->disconnect);
}
}
void
@@ -627,9 +615,6 @@ sc_screen_destroy(struct sc_screen *screen) {
#ifndef NDEBUG
assert(!screen->open);
#endif
if (screen->disconnect_started) {
sc_disconnect_destroy(&screen->disconnect);
}
sc_texture_destroy(&screen->tex);
av_frame_free(&screen->frame);
#ifdef SC_DISPLAY_FORCE_OPENGL_CORE_PROFILE
@@ -869,37 +854,12 @@ sc_screen_resize_to_pixel_perfect(struct sc_screen *screen) {
content_size.height);
}
static void
sc_disconnect_on_icon_loaded(struct sc_disconnect *d, SDL_Surface *icon,
void *userdata) {
(void) d;
(void) userdata;
bool ok = sc_push_event_with_data(SC_EVENT_DISCONNECTED_ICON_LOADED, icon);
if (!ok) {
sc_icon_destroy(icon);
}
}
static void
sc_disconnect_on_timeout(struct sc_disconnect *d, void *userdata) {
(void) d;
(void) userdata;
bool ok = sc_push_event(SC_EVENT_DISCONNECTED_TIMEOUT);
(void) ok; // ignore failure
}
bool
sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
// !video implies !has_video_window
assert(screen->video || !screen->has_video_window);
switch (event->type) {
case SC_EVENT_NEW_FRAME: {
if (screen->disconnected) {
// ignore
return true;
}
bool ok = sc_screen_update_frame(screen);
if (!ok) {
LOGE("Frame update failed\n");
@@ -934,44 +894,6 @@ sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
sc_screen_render(screen, true);
}
return true;
case SC_EVENT_DEVICE_DISCONNECTED:
if (screen->disconnected) {
return true;
}
screen->disconnected = true;
sc_texture_reset(&screen->tex);
sc_screen_render(screen, true);
sc_tick deadline = sc_tick_now() + SC_TICK_FROM_SEC(2);
static const struct sc_disconnect_callbacks cbs = {
.on_icon_loaded = sc_disconnect_on_icon_loaded,
.on_timeout = sc_disconnect_on_timeout,
};
bool ok =
sc_disconnect_start(&screen->disconnect, deadline, &cbs, NULL);
if (ok) {
screen->disconnect_started = true;
}
// else not fatal
return true;
case SC_EVENT_DISCONNECTED_ICON_LOADED: {
SDL_Surface *icon_disconnected = event->user.data1;
assert(icon_disconnected);
bool ok = sc_texture_set_from_surface(&screen->tex, icon_disconnected);
if (ok) {
screen->content_size.width = icon_disconnected->w;
screen->content_size.height = icon_disconnected->h;
sc_screen_render(screen, true);
} else {
// not fatal
LOGE("Could not set disconnected icon");
}
sc_icon_destroy(icon_disconnected);
return true;
}
}
if (sc_screen_is_relative_mode(screen)

View File

@@ -12,7 +12,6 @@
#include "controller.h"
#include "coords.h"
#include "disconnect.h"
#include "fps_counter.h"
#include "frame_buffer.h"
#include "input_manager.h"
@@ -78,10 +77,6 @@ struct sc_screen {
bool paused;
AVFrame *resume_frame;
bool disconnected;
bool disconnect_started;
struct sc_disconnect disconnect;
};
struct sc_screen_params {
@@ -121,15 +116,10 @@ bool
sc_screen_init(struct sc_screen *screen, const struct sc_screen_params *params);
// request to interrupt any inner thread
// must be called before sc_screen_join()
// must be called before screen_join()
void
sc_screen_interrupt(struct sc_screen *screen);
// request to interrupt the disconnected state (before closing the window)
// must be called before sc_screen_join();
void
sc_screen_interrupt_disconnect(struct sc_screen *screen);
// join any inner thread
void
sc_screen_join(struct sc_screen *screen);

View File

@@ -225,11 +225,3 @@ sc_texture_set_from_surface(struct sc_texture *tex, SDL_Surface *surface) {
return true;
}
void
sc_texture_reset(struct sc_texture *tex) {
if (tex->texture) {
SDL_DestroyTexture(tex->texture);
tex->texture = NULL;
}
}

View File

@@ -41,7 +41,4 @@ sc_texture_set_from_frame(struct sc_texture *tex, const AVFrame *frame);
bool
sc_texture_set_from_surface(struct sc_texture *tex, SDL_Surface *surface);
void
sc_texture_reset(struct sc_texture *tex);
#endif

View File

@@ -31,33 +31,23 @@ sc_usb_on_disconnected(struct sc_usb *usb, void *userdata) {
(void) usb;
(void) userdata;
sc_push_event(SC_EVENT_DEVICE_DISCONNECTED);
sc_push_event(SC_EVENT_USB_DEVICE_DISCONNECTED);
}
static enum scrcpy_exit_code
event_loop(struct scrcpy_otg *s, bool disconnected) {
event_loop(struct scrcpy_otg *s) {
SDL_Event event;
while (SDL_WaitEvent(&event)) {
switch (event.type) {
case SC_EVENT_DEVICE_DISCONNECTED:
if (disconnected) {
break;
}
case SC_EVENT_USB_DEVICE_DISCONNECTED:
LOGW("Device disconnected");
sc_screen_handle_event(&s->screen, &event);
return SCRCPY_EXIT_DISCONNECTED;
case SC_EVENT_AOA_OPEN_ERROR:
if (disconnected) {
break;
}
LOGE("AOA open error");
return SCRCPY_EXIT_FAILURE;
case SDL_EVENT_QUIT:
LOGD("User requested to quit");
return SCRCPY_EXIT_SUCCESS;
case SC_EVENT_DISCONNECTED_TIMEOUT:
LOGD("Closing after device disconnection");
return SCRCPY_EXIT_DISCONNECTED;
default:
sc_screen_handle_event(&s->screen, &event);
break;
@@ -106,7 +96,6 @@ scrcpy_otg(struct scrcpy_options *options) {
bool aoa_started = false;
bool aoa_initialized = false;
bool screen_initialized = false;
bool disconnected = false;
#ifdef _WIN32
// On Windows, only one process could open a USB device
@@ -231,8 +220,8 @@ scrcpy_otg(struct scrcpy_options *options) {
sc_usb_device_destroy(&usb_device);
usb_device_initialized = false;
ret = event_loop(s, false);
disconnected = ret == SCRCPY_EXIT_DISCONNECTED;
ret = event_loop(s);
LOGD("quit...");
end:
if (aoa_started) {
@@ -242,15 +231,6 @@ end:
if (screen_initialized) {
sc_screen_interrupt(&s->screen);
if (disconnected) {
ret = event_loop(s, true);
sc_screen_interrupt_disconnect(&s->screen);
}
LOGD("Quit...");
// Close the window immediately
sc_screen_hide_window(&s->screen);
}
if (mp) {

View File

@@ -5,25 +5,6 @@
#include "util/log.h"
char *
sc_file_build_path(const char *dir, const char *name) {
size_t dir_len = strlen(dir);
size_t name_len = strlen(name);
size_t len = dir_len + name_len + 2; // +2: '/' and '\0'
char *path = malloc(len);
if (!path) {
LOG_OOM();
return NULL;
}
memcpy(path, dir, dir_len);
path[dir_len] = SC_PATH_SEPARATOR;
// namelen + 1 to copy the final '\0'
memcpy(&path[dir_len + 1], name, name_len + 1);
return path;
}
char *
sc_file_get_local_path(const char *name) {
char *executable_path = sc_file_get_executable_path();
@@ -44,9 +25,24 @@ sc_file_get_local_path(const char *name) {
*p = '\0'; // modify executable_path in place
char *dir = executable_path;
char *file_path = sc_file_build_path(dir, name);
size_t dirlen = strlen(dir);
size_t namelen = strlen(name);
size_t len = dirlen + namelen + 2; // +2: '/' and '\0'
char *file_path = malloc(len);
if (!file_path) {
LOG_OOM();
free(executable_path);
return NULL;
}
memcpy(file_path, dir, dirlen);
file_path[dirlen] = SC_PATH_SEPARATOR;
// namelen + 1 to copy the final '\0'
memcpy(&file_path[dirlen + 1], name, namelen + 1);
free(executable_path);
return file_path;
}

View File

@@ -40,15 +40,6 @@ sc_file_get_executable_path(void);
char *
sc_file_get_local_path(const char *name);
/**
* Return the concatenation of dir, the path separator and the filename.
*
* The result must be freed by the caller using free(). It may return NULL on
* error.
*/
char *
sc_file_build_path(const char *dir, const char *filename);
/**
* Indicate if the file exists and is not a directory
*/

View File

@@ -6,7 +6,6 @@
#include <stdint.h>
typedef int64_t sc_tick;
#define SC_TICK_NONE INT64_MIN
#define PRItick PRIi64
#define SC_TICK_FREQ 1000000 // microsecond

View File

@@ -38,6 +38,6 @@ ninja -C "$LINUX_BUILD_DIR"
# Group intermediate outputs into a 'dist' directory
mkdir -p "$LINUX_BUILD_DIR/dist"
cp "$LINUX_BUILD_DIR"/app/scrcpy "$LINUX_BUILD_DIR/dist/"
cp app/data/scrcpy.png "$LINUX_BUILD_DIR/dist/"
cp app/data/icon.png "$LINUX_BUILD_DIR/dist/"
cp app/scrcpy.1 "$LINUX_BUILD_DIR/dist/"
cp -r "$ADB_INSTALL_DIR"/. "$LINUX_BUILD_DIR/dist/"

View File

@@ -38,6 +38,6 @@ ninja -C "$MACOS_BUILD_DIR"
# Group intermediate outputs into a 'dist' directory
mkdir -p "$MACOS_BUILD_DIR/dist"
cp "$MACOS_BUILD_DIR"/app/scrcpy "$MACOS_BUILD_DIR/dist/"
cp app/data/scrcpy.png "$MACOS_BUILD_DIR/dist/"
cp app/data/icon.png "$MACOS_BUILD_DIR/dist/"
cp app/scrcpy.1 "$MACOS_BUILD_DIR/dist/"
cp -r "$ADB_INSTALL_DIR"/. "$MACOS_BUILD_DIR/dist/"

View File

@@ -47,7 +47,7 @@ mkdir -p "$WINXX_BUILD_DIR/dist"
cp "$WINXX_BUILD_DIR"/app/scrcpy.exe "$WINXX_BUILD_DIR/dist/"
cp app/data/scrcpy-console.bat "$WINXX_BUILD_DIR/dist/"
cp app/data/scrcpy-noconsole.vbs "$WINXX_BUILD_DIR/dist/"
cp app/data/scrcpy.png "$WINXX_BUILD_DIR/dist/"
cp app/data/icon.png "$WINXX_BUILD_DIR/dist/"
cp app/data/open_a_terminal_here.bat "$WINXX_BUILD_DIR/dist/"
cp "$DEPS_INSTALL_DIR"/bin/*.dll "$WINXX_BUILD_DIR/dist/"
cp -r "$ADB_INSTALL_DIR"/. "$WINXX_BUILD_DIR/dist/"

2
run
View File

@@ -20,6 +20,6 @@ then
exit 1
fi
SCRCPY_ICON_DIR="app/data" \
SCRCPY_ICON_PATH="app/data/icon.png" \
SCRCPY_SERVER_PATH="$BUILDDIR/server/scrcpy-server" \
"$BUILDDIR/app/scrcpy" "$@"