mirror of
https://github.com/Genymobile/scrcpy.git
synced 2026-03-20 11:04:28 +01:00
Compare commits
14 Commits
disconnect
...
disconnect
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0589acfb78 | ||
|
|
a124a8756e | ||
|
|
9a50c02bf4 | ||
|
|
28ba0912d2 | ||
|
|
2145f6ddbd | ||
|
|
7f5fd43e4e | ||
|
|
8f51e23645 | ||
|
|
c4aefde96f | ||
|
|
bad2183087 | ||
|
|
e17a885f32 | ||
|
|
691a63761c | ||
|
|
57af6b9209 | ||
|
|
0597c5eb8d | ||
|
|
10e0c3226c |
@@ -1729,7 +1729,7 @@ parse_orientation(const char *s, enum sc_orientation *orientation) {
|
||||
return true;
|
||||
}
|
||||
LOGE("Unsupported orientation: %s (expected 0, 90, 180, 270, flip0, "
|
||||
"flip90, flip180 or flip270)", optarg);
|
||||
"flip90, flip180 or flip270)", s);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,17 +16,16 @@ run(void *userdata) {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
bool interrupted = d->interrupted;
|
||||
sc_mutex_unlock(&d->mutex);
|
||||
|
||||
if (!d->interrupted) {
|
||||
d->cbs->on_timeout(d, d->cbs_userdata);
|
||||
}
|
||||
if (!interrupted) {
|
||||
d->cbs->on_timeout(d, d->cbs_userdata);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -46,11 +45,6 @@ sc_disconnect_start(struct sc_disconnect *d, sc_tick deadline,
|
||||
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;
|
||||
|
||||
@@ -58,12 +52,17 @@ sc_disconnect_start(struct sc_disconnect *d, sc_tick deadline,
|
||||
d->cbs = cbs;
|
||||
d->cbs_userdata = cbs_userdata;
|
||||
|
||||
ok = sc_thread_create(&d->thread, run, "scrcpy-dis", d);
|
||||
if (!ok) {
|
||||
goto error_destroy_cond;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error_destroy_mutex:
|
||||
sc_mutex_destroy(&d->mutex);
|
||||
error_destroy_cond:
|
||||
sc_cond_destroy(&d->cond);
|
||||
error_destroy_mutex:
|
||||
sc_mutex_destroy(&d->mutex);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
enum {
|
||||
SC_EVENT_NEW_FRAME = SDL_EVENT_USER,
|
||||
SC_EVENT_OPEN_WINDOW,
|
||||
SC_EVENT_RUN_ON_MAIN_THREAD,
|
||||
SC_EVENT_DEVICE_DISCONNECTED,
|
||||
SC_EVENT_SERVER_CONNECTION_FAILED,
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "android/input.h"
|
||||
#include "android/keycodes.h"
|
||||
#include "events.h"
|
||||
#include "input_events.h"
|
||||
#include "screen.h"
|
||||
#include "shortcut_mod.h"
|
||||
@@ -46,6 +47,8 @@ sc_input_manager_init(struct sc_input_manager *im,
|
||||
im->key_repeat = 0;
|
||||
|
||||
im->next_sequence = 1; // 0 is reserved for SC_SEQUENCE_INVALID
|
||||
|
||||
im->disconnected = false;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -349,7 +352,7 @@ apply_orientation_transform(struct sc_input_manager *im,
|
||||
static void
|
||||
sc_input_manager_process_text_input(struct sc_input_manager *im,
|
||||
const SDL_TextInputEvent *event) {
|
||||
if (im->camera || !im->kp || im->screen->paused) {
|
||||
if (im->camera || !im->kp || im->screen->paused || im->disconnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -417,6 +420,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
||||
bool control = im->controller;
|
||||
bool paused = im->screen->paused;
|
||||
bool video = im->screen->video;
|
||||
bool disconnected = im->disconnected;
|
||||
|
||||
SDL_Keycode sdl_keycode = event->key;
|
||||
uint16_t mod = event->mod;
|
||||
@@ -433,7 +437,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
||||
bool is_shortcut = sc_shortcut_mods_is_shortcut_mod(mods, mod)
|
||||
|| sc_shortcut_mods_is_shortcut_key(mods, sdl_keycode);
|
||||
|
||||
if (down && !repeat) {
|
||||
if (down && !repeat && !disconnected) {
|
||||
if (sdl_keycode == im->last_keycode && mod == im->last_mod) {
|
||||
++im->key_repeat;
|
||||
} else {
|
||||
@@ -510,6 +514,12 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
||||
return;
|
||||
}
|
||||
|
||||
if (disconnected) {
|
||||
// Only handle shortcuts that do not interact with the device (since
|
||||
// it is disconnected)
|
||||
return;
|
||||
}
|
||||
|
||||
// Flatten conditions to avoid additional indentation levels
|
||||
if (control) {
|
||||
// Controls for all sources
|
||||
@@ -718,7 +728,7 @@ sc_input_manager_get_position(struct sc_input_manager *im, int32_t x,
|
||||
static void
|
||||
sc_input_manager_process_mouse_motion(struct sc_input_manager *im,
|
||||
const SDL_MouseMotionEvent *event) {
|
||||
if (im->camera || !im->mp || im->screen->paused) {
|
||||
if (im->camera || !im->mp || im->screen->paused || im->disconnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -757,7 +767,7 @@ sc_input_manager_process_mouse_motion(struct sc_input_manager *im,
|
||||
static void
|
||||
sc_input_manager_process_touch(struct sc_input_manager *im,
|
||||
const SDL_TouchFingerEvent *event) {
|
||||
if (im->camera || !im->mp || im->screen->paused) {
|
||||
if (im->camera || !im->mp || im->screen->paused || im->disconnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -812,7 +822,7 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
||||
// some mouse events do not interact with the device, so process the event
|
||||
// even if control is disabled
|
||||
|
||||
if (im->camera) {
|
||||
if (im->camera || im->disconnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -983,7 +993,7 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
||||
static void
|
||||
sc_input_manager_process_mouse_wheel(struct sc_input_manager *im,
|
||||
const SDL_MouseWheelEvent *event) {
|
||||
if (im->camera || !im->kp || im->screen->paused) {
|
||||
if (im->camera || !im->kp || im->screen->paused || im->disconnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1013,7 +1023,7 @@ sc_input_manager_process_gamepad_device(struct sc_input_manager *im,
|
||||
const SDL_GamepadDeviceEvent *event) {
|
||||
// Handle device added or removed even if paused
|
||||
|
||||
if (im->camera || !im->gp) {
|
||||
if (im->camera || !im->gp || im->disconnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1058,7 +1068,7 @@ sc_input_manager_process_gamepad_device(struct sc_input_manager *im,
|
||||
static void
|
||||
sc_input_manager_process_gamepad_axis(struct sc_input_manager *im,
|
||||
const SDL_GamepadAxisEvent *event) {
|
||||
if (im->camera || !im->gp || im->screen->paused) {
|
||||
if (im->camera || !im->gp || im->screen->paused || im->disconnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1078,7 +1088,7 @@ sc_input_manager_process_gamepad_axis(struct sc_input_manager *im,
|
||||
static void
|
||||
sc_input_manager_process_gamepad_button(struct sc_input_manager *im,
|
||||
const SDL_GamepadButtonEvent *event) {
|
||||
if (im->camera || !im->gp || im->screen->paused) {
|
||||
if (im->camera || !im->gp || im->screen->paused || im->disconnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1104,7 +1114,7 @@ is_apk(const char *file) {
|
||||
static void
|
||||
sc_input_manager_process_file(struct sc_input_manager *im,
|
||||
const SDL_DropEvent *event) {
|
||||
if (im->camera || !im->controller) {
|
||||
if (im->camera || !im->controller || im->disconnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1127,6 +1137,16 @@ sc_input_manager_process_file(struct sc_input_manager *im,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sc_input_manager_on_device_disconnected(struct sc_input_manager *im) {
|
||||
im->disconnected = true;
|
||||
|
||||
struct sc_fps_counter *fps_counter = &im->screen->fps_counter;
|
||||
if (sc_fps_counter_is_started(fps_counter)) {
|
||||
sc_fps_counter_stop(fps_counter);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sc_input_manager_handle_event(struct sc_input_manager *im,
|
||||
const SDL_Event *event) {
|
||||
@@ -1167,5 +1187,8 @@ sc_input_manager_handle_event(struct sc_input_manager *im,
|
||||
case SDL_EVENT_DROP_FILE:
|
||||
sc_input_manager_process_file(im, &event->drop);
|
||||
break;
|
||||
case SC_EVENT_DEVICE_DISCONNECTED:
|
||||
sc_input_manager_on_device_disconnected(im);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ struct sc_input_manager {
|
||||
uint16_t last_mod;
|
||||
|
||||
uint64_t next_sequence; // used for request acknowledgements
|
||||
|
||||
bool disconnected;
|
||||
};
|
||||
|
||||
struct sc_input_manager_params {
|
||||
|
||||
@@ -212,17 +212,18 @@ event_loop(struct scrcpy *s, bool has_screen) {
|
||||
}
|
||||
|
||||
static void
|
||||
terminate_event_loop(void) {
|
||||
terminate_runnables_on_event_loop(void) {
|
||||
sc_reject_new_runnables();
|
||||
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SC_EVENT_RUN_ON_MAIN_THREAD) {
|
||||
// Make sure all posted runnables are run, to avoid memory leaks
|
||||
sc_runnable_fn run = event.user.data1;
|
||||
void *userdata = event.user.data2;
|
||||
run(userdata);
|
||||
}
|
||||
while (SDL_PeepEvents(&event, 1, SDL_GETEVENT,
|
||||
SC_EVENT_RUN_ON_MAIN_THREAD,
|
||||
SC_EVENT_RUN_ON_MAIN_THREAD) == 1) {
|
||||
assert(event.type == SC_EVENT_RUN_ON_MAIN_THREAD);
|
||||
// Make sure all posted runnables are run, to avoid memory leaks
|
||||
sc_runnable_fn run = event.user.data1;
|
||||
void *userdata = event.user.data2;
|
||||
run(userdata);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -950,7 +951,7 @@ aoa_complete:
|
||||
}
|
||||
|
||||
ret = event_loop(s, options->window);
|
||||
terminate_event_loop();
|
||||
terminate_runnables_on_event_loop();
|
||||
disconnected = ret == SCRCPY_EXIT_DISCONNECTED;
|
||||
|
||||
end:
|
||||
|
||||
125
app/src/screen.c
125
app/src/screen.c
@@ -198,21 +198,30 @@ 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 || screen->has_video_window);
|
||||
assert(screen->window_shown);
|
||||
|
||||
if (update_content_rect) {
|
||||
sc_screen_update_content_rect(screen);
|
||||
}
|
||||
|
||||
SDL_Renderer *renderer = screen->renderer;
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
|
||||
sc_sdl_render_clear(renderer);
|
||||
|
||||
bool ok = false;
|
||||
SDL_Texture *texture = screen->tex.texture;
|
||||
if (!texture) {
|
||||
if (!screen->disconnected) {
|
||||
LOGW("No texture to render");
|
||||
}
|
||||
// Draw a dark 10x10 square in the top-right corner to distinguish a
|
||||
// black frame from the absence of a frame
|
||||
struct sc_size render_size = sc_sdl_get_render_output_size(renderer);
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0x33, 0xff);
|
||||
SDL_FRect rect = {
|
||||
.x = render_size.width - 20,
|
||||
.y = 10,
|
||||
.w = 10,
|
||||
.h = 10,
|
||||
};
|
||||
SDL_RenderFillRect(renderer, &rect);
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -282,11 +291,8 @@ sc_screen_frame_sink_open(struct sc_frame_sink *sink,
|
||||
const AVCodecContext *ctx,
|
||||
const struct sc_stream_session *session) {
|
||||
assert(ctx->pix_fmt == AV_PIX_FMT_YUV420P);
|
||||
(void) ctx;
|
||||
(void) session;
|
||||
|
||||
struct sc_screen *screen = DOWNCAST(sink);
|
||||
(void) screen;
|
||||
|
||||
if (ctx->width <= 0 || ctx->width > 0xFFFF
|
||||
|| ctx->height <= 0 || ctx->height > 0xFFFF) {
|
||||
@@ -294,6 +300,19 @@ sc_screen_frame_sink_open(struct sc_frame_sink *sink,
|
||||
return false;
|
||||
}
|
||||
|
||||
// content_size can be written from this thread, because it is never read
|
||||
// from the main thread before handling SC_EVENT_OPEN_WINDOW (which acts as
|
||||
// a synchronization point) when video is enabled
|
||||
screen->frame_size.width = session->video.width;
|
||||
screen->frame_size.height = session->video.height;
|
||||
screen->content_size = get_oriented_size(screen->frame_size,
|
||||
screen->orientation);
|
||||
|
||||
bool ok = sc_push_event(SC_EVENT_OPEN_WINDOW);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
screen->open = true;
|
||||
#endif
|
||||
@@ -343,9 +362,7 @@ bool
|
||||
sc_screen_init(struct sc_screen *screen,
|
||||
const struct sc_screen_params *params) {
|
||||
screen->resize_pending = false;
|
||||
screen->has_frame = false;
|
||||
screen->has_video_window = false;
|
||||
screen->window_shown = true;
|
||||
screen->window_shown = false;
|
||||
screen->paused = false;
|
||||
screen->resume_frame = NULL;
|
||||
screen->orientation = SC_ORIENTATION_0;
|
||||
@@ -538,8 +555,8 @@ sc_screen_init(struct sc_screen *screen,
|
||||
|
||||
if (!screen->video) {
|
||||
// Show the window immediately
|
||||
sc_sdl_show_window(screen->window);
|
||||
screen->window_shown = true;
|
||||
sc_sdl_show_window(screen->window);
|
||||
|
||||
if (sc_screen_is_relative_mode(screen)) {
|
||||
// Capture mouse immediately if video mirroring is disabled
|
||||
@@ -595,15 +612,15 @@ sc_screen_show_initial_window(struct sc_screen *screen) {
|
||||
sc_fps_counter_start(&screen->fps_counter);
|
||||
}
|
||||
|
||||
sc_sdl_show_window(screen->window);
|
||||
screen->window_shown = true;
|
||||
sc_sdl_show_window(screen->window);
|
||||
sc_screen_update_content_rect(screen);
|
||||
}
|
||||
|
||||
void
|
||||
sc_screen_hide_window(struct sc_screen *screen) {
|
||||
screen->window_shown = false;
|
||||
sc_sdl_hide_window(screen->window);
|
||||
screen->window_shown = false;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -643,6 +660,17 @@ sc_screen_destroy(struct sc_screen *screen) {
|
||||
SDL_DestroyWindow(screen->window);
|
||||
sc_fps_counter_destroy(&screen->fps_counter);
|
||||
sc_frame_buffer_destroy(&screen->fb);
|
||||
|
||||
SDL_Event event;
|
||||
int nevents = SDL_PeepEvents(&event, 1, SDL_GETEVENT,
|
||||
SC_EVENT_DISCONNECTED_ICON_LOADED,
|
||||
SC_EVENT_DISCONNECTED_ICON_LOADED);
|
||||
if (nevents == 1) {
|
||||
assert(event.type == SC_EVENT_DISCONNECTED_ICON_LOADED);
|
||||
// The event was posted, but not handled, the icon must be freed
|
||||
SDL_Surface *dangling_icon = event.user.data1;
|
||||
sc_icon_destroy(dangling_icon);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -713,14 +741,14 @@ sc_screen_set_orientation(struct sc_screen *screen,
|
||||
static bool
|
||||
sc_screen_apply_frame(struct sc_screen *screen) {
|
||||
assert(screen->video);
|
||||
assert(screen->window_shown);
|
||||
|
||||
sc_fps_counter_add_rendered_frame(&screen->fps_counter);
|
||||
|
||||
AVFrame *frame = screen->frame;
|
||||
struct sc_size new_frame_size = {frame->width, frame->height};
|
||||
|
||||
if (!screen->has_frame
|
||||
|| screen->frame_size.width != new_frame_size.width
|
||||
if (screen->frame_size.width != new_frame_size.width
|
||||
|| screen->frame_size.height != new_frame_size.height) {
|
||||
|
||||
// frame dimension changed
|
||||
@@ -728,14 +756,8 @@ sc_screen_apply_frame(struct sc_screen *screen) {
|
||||
|
||||
struct sc_size new_content_size =
|
||||
get_oriented_size(new_frame_size, screen->orientation);
|
||||
if (screen->has_frame) {
|
||||
set_content_size(screen, new_content_size);
|
||||
sc_screen_update_content_rect(screen);
|
||||
} else {
|
||||
// This is the first frame
|
||||
screen->has_frame = true;
|
||||
screen->content_size = new_content_size;
|
||||
}
|
||||
set_content_size(screen, new_content_size);
|
||||
sc_screen_update_content_rect(screen);
|
||||
}
|
||||
|
||||
bool ok = sc_texture_set_from_frame(&screen->tex, frame);
|
||||
@@ -743,18 +765,6 @@ sc_screen_apply_frame(struct sc_screen *screen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(screen->has_frame);
|
||||
if (!screen->has_video_window) {
|
||||
screen->has_video_window = true;
|
||||
// this is the very first frame, show the window
|
||||
sc_screen_show_initial_window(screen);
|
||||
|
||||
if (sc_screen_is_relative_mode(screen)) {
|
||||
// Capture mouse on start
|
||||
sc_mouse_capture_set_active(&screen->mc, true);
|
||||
}
|
||||
}
|
||||
|
||||
sc_screen_render(screen, false);
|
||||
return true;
|
||||
}
|
||||
@@ -896,9 +906,17 @@ sc_disconnect_on_timeout(struct sc_disconnect *d, void *userdata) {
|
||||
|
||||
void
|
||||
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_OPEN_WINDOW:
|
||||
sc_screen_show_initial_window(screen);
|
||||
|
||||
if (sc_screen_is_relative_mode(screen)) {
|
||||
// Capture mouse on start
|
||||
sc_mouse_capture_set_active(&screen->mc, true);
|
||||
}
|
||||
|
||||
sc_screen_render(screen, false);
|
||||
return;
|
||||
case SC_EVENT_NEW_FRAME: {
|
||||
bool ok = sc_screen_update_frame(screen);
|
||||
if (!ok) {
|
||||
@@ -907,28 +925,27 @@ sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
|
||||
return;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_EXPOSED:
|
||||
if (!screen->video || screen->has_video_window) {
|
||||
sc_screen_render(screen, true);
|
||||
}
|
||||
sc_screen_render(screen, true);
|
||||
return;
|
||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
||||
if (screen->has_video_window) {
|
||||
// This event can be triggered before the window is shown
|
||||
if (screen->window_shown) {
|
||||
sc_screen_render(screen, true);
|
||||
}
|
||||
return;
|
||||
case SDL_EVENT_WINDOW_RESTORED:
|
||||
if (screen->has_video_window && is_windowed(screen)) {
|
||||
if (screen->video && is_windowed(screen)) {
|
||||
apply_pending_resize(screen);
|
||||
sc_screen_render(screen, true);
|
||||
}
|
||||
return;
|
||||
case SDL_EVENT_WINDOW_ENTER_FULLSCREEN:
|
||||
LOGD("Switched to fullscreen mode");
|
||||
assert(screen->has_video_window);
|
||||
assert(screen->video);
|
||||
return;
|
||||
case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
|
||||
LOGD("Switched to windowed mode");
|
||||
assert(screen->has_video_window);
|
||||
assert(screen->video);
|
||||
if (is_windowed(screen)) {
|
||||
apply_pending_resize(screen);
|
||||
sc_screen_render(screen, true);
|
||||
@@ -942,6 +959,8 @@ sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
|
||||
return;
|
||||
}
|
||||
|
||||
sc_input_manager_handle_event(&screen->im, event);
|
||||
|
||||
sc_texture_reset(&screen->tex);
|
||||
sc_screen_render(screen, true);
|
||||
|
||||
@@ -975,6 +994,11 @@ sc_screen_handle_disconnection(struct sc_screen *screen) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!screen->disconnect_started) {
|
||||
// If sc_disconnect_start() failed, quit immediately
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Event event;
|
||||
while (SDL_WaitEvent(&event)) {
|
||||
switch (event.type) {
|
||||
@@ -995,17 +1019,20 @@ sc_screen_handle_disconnection(struct sc_screen *screen) {
|
||||
sc_icon_destroy(icon_disconnected);
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_EXPOSED:
|
||||
sc_screen_render(screen, true);
|
||||
break;
|
||||
case SC_EVENT_DISCONNECTED_TIMEOUT:
|
||||
LOGD("Closing after device disconnection");
|
||||
goto end;
|
||||
return;
|
||||
case SDL_EVENT_QUIT:
|
||||
LOGD("User requested to quit");
|
||||
goto end;
|
||||
sc_screen_interrupt_disconnect(screen);
|
||||
return;
|
||||
default:
|
||||
sc_input_manager_handle_event(&screen->im, &event);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
sc_screen_interrupt_disconnect(screen);
|
||||
}
|
||||
|
||||
struct sc_point
|
||||
|
||||
@@ -71,8 +71,6 @@ struct sc_screen {
|
||||
enum sc_orientation orientation;
|
||||
// rectangle of the content (excluding black borders)
|
||||
struct SDL_FRect rect;
|
||||
bool has_frame;
|
||||
bool has_video_window;
|
||||
bool window_shown;
|
||||
|
||||
AVFrame *frame;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -93,4 +93,4 @@ Then just double-click on that file to run it.
|
||||
|
||||
To start scrcpy without opening a terminal, double-click `scrcpy-noconsole.vbs`
|
||||
(note that errors won't be shown). To pass arguments, edit (a copy of)
|
||||
`scrcpy-noconsole.vbs` add and the desired arguments.
|
||||
`scrcpy-noconsole.vbs` and add the desired arguments.
|
||||
|
||||
Reference in New Issue
Block a user