diff --git a/app/src/events.c b/app/src/events.c index 4e256be2..e60dc3e5 100644 --- a/app/src/events.c +++ b/app/src/events.c @@ -17,3 +17,24 @@ sc_push_event_impl(uint32_t type, const char *name) { return true; } + +bool +sc_post_to_main_thread(sc_runnable_fn run, void *userdata) { + SDL_Event event = { + .user = { + .type = SC_EVENT_RUN_ON_MAIN_THREAD, + .data1 = run, + .data2 = userdata, + }, + }; + int ret = SDL_PushEvent(&event); + // ret < 0: error (queue full) + // ret == 0: event was filtered + // ret == 1: success + if (ret != 1) { + LOGW("Coud not post to main thread: %s", SDL_GetError()); + return false; + } + + return true; +} diff --git a/app/src/events.h b/app/src/events.h index 639fa97e..4d6165c8 100644 --- a/app/src/events.h +++ b/app/src/events.h @@ -9,6 +9,7 @@ enum { SC_EVENT_NEW_FRAME = SDL_USEREVENT, + SC_EVENT_RUN_ON_MAIN_THREAD, SC_EVENT_DEVICE_DISCONNECTED, SC_EVENT_SERVER_CONNECTION_FAILED, SC_EVENT_SERVER_CONNECTED, @@ -25,4 +26,9 @@ sc_push_event_impl(uint32_t type, const char *name); #define sc_push_event(TYPE) sc_push_event_impl(TYPE, # TYPE) +typedef void (*sc_runnable_fn)(void *userdata); + +bool +sc_post_to_main_thread(sc_runnable_fn run, void *userdata); + #endif diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 5dfc425d..001df42c 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -174,6 +174,11 @@ event_loop(struct scrcpy *s) { case SDL_QUIT: LOGD("User requested to quit"); return SCRCPY_EXIT_SUCCESS; + case SC_EVENT_RUN_ON_MAIN_THREAD: + sc_runnable_fn run = event.user.data1; + void *userdata = event.user.data2; + run(userdata); + break; default: if (!sc_screen_handle_event(&s->screen, &event)) { return SCRCPY_EXIT_FAILURE; diff --git a/app/src/usb/scrcpy_otg.c b/app/src/usb/scrcpy_otg.c index 5ace01ed..bf288752 100644 --- a/app/src/usb/scrcpy_otg.c +++ b/app/src/usb/scrcpy_otg.c @@ -38,6 +38,11 @@ event_loop(struct scrcpy_otg *s) { case SDL_QUIT: LOGD("User requested to quit"); return SCRCPY_EXIT_SUCCESS; + case SC_EVENT_RUN_ON_MAIN_THREAD: + sc_runnable_fn run = event.user.data1; + void *userdata = event.user.data2; + run(userdata); + break; default: sc_screen_otg_handle_event(&s->screen_otg, &event); break;