diff --git a/README.md b/README.md index 7bf203ba..5daafb2e 100644 --- a/README.md +++ b/README.md @@ -294,6 +294,19 @@ _¹Double-click on black borders to remove them._ _²Right-click turns the screen on if it was off, presses BACK otherwise._ +## Custom paths + +To use a specific _adb_ binary, configure its path in the environment variable +`ADB`: + + ADB=/path/to/adb scrcpy + +To override the path of the `scrcpy-server.jar` file (it can be [useful] on +Windows), configure its path in `SCRCPY_SERVER_PATH`. + +[useful]: https://github.com/Genymobile/scrcpy/issues/278#issuecomment-429330345 + + ## Why _scrcpy_? A colleague challenged me to find a name as unpronounceable as [gnirehtet]. diff --git a/app/src/command.c b/app/src/command.c index 2e116ac8..2c6d45aa 100644 --- a/app/src/command.c +++ b/app/src/command.c @@ -1,5 +1,6 @@ #include "command.h" +#include #include #include #include @@ -20,15 +21,52 @@ get_adb_command(void) { return adb_command; } +// serialize argv to string "[arg1], [arg2], [arg3]" +static size_t +argv_to_string(const char *const *argv, char *buf, size_t bufsize) { + size_t idx = 0; + bool first = true; + while (*argv) { + const char *arg = *argv; + size_t len = strlen(arg); + // count space for "[], ...\0" + if (idx + len + 8 >= bufsize) { + // not enough space, truncate + assert(idx < bufsize - 4); + memcpy(&buf[idx], "...", 3); + idx += 3; + break; + } + if (first) { + first = false; + } else { + buf[idx++] = ','; + buf[idx++] = ' '; + } + buf[idx++] = '['; + memcpy(&buf[idx], arg, len); + idx += len; + buf[idx++] = ']'; + argv++; + } + assert(idx < bufsize); + buf[idx] = '\0'; + return idx; +} + static void -show_adb_err_msg(enum process_result err) { +show_adb_err_msg(enum process_result err, const char *const argv[]) { + char buf[512]; switch (err) { case PROCESS_ERROR_GENERIC: - LOGE("Failed to execute adb"); + argv_to_string(argv, buf, sizeof(buf)); + LOGE("Failed to execute: %s", buf); break; case PROCESS_ERROR_MISSING_BINARY: - LOGE("'adb' command not found (make it accessible from your PATH " - "or define its full path in the ADB environment variable)"); + argv_to_string(argv, buf, sizeof(buf)); + LOGE("Command not found: %s", buf); + LOGE("(make 'adb' accessible from your PATH or define its full" + "path in the ADB environment variable)"); break; case PROCESS_SUCCESS: /* do nothing */ @@ -37,7 +75,7 @@ show_adb_err_msg(enum process_result err) { } process_t -adb_execute(const char *serial, const char *const adb_cmd[], int len) { +adb_execute(const char *serial, const char *const adb_cmd[], size_t len) { const char *cmd[len + 4]; int i; process_t process; @@ -54,7 +92,7 @@ adb_execute(const char *serial, const char *const adb_cmd[], int len) { cmd[len + i] = NULL; enum process_result r = cmd_execute(cmd[0], cmd, &process); if (r != PROCESS_SUCCESS) { - show_adb_err_msg(r); + show_adb_err_msg(r, cmd); return PROCESS_NONE; } return process; diff --git a/app/src/command.h b/app/src/command.h index 6681f5ea..90eb7cb2 100644 --- a/app/src/command.h +++ b/app/src/command.h @@ -49,7 +49,7 @@ bool cmd_simple_wait(process_t pid, exit_code_t *exit_code); process_t -adb_execute(const char *serial, const char *const adb_cmd[], int len); +adb_execute(const char *serial, const char *const adb_cmd[], size_t len); process_t adb_forward(const char *serial, uint16_t local_port, diff --git a/app/src/compat.h b/app/src/compat.h index fd68d61a..de667bbf 100644 --- a/app/src/compat.h +++ b/app/src/compat.h @@ -43,4 +43,9 @@ # define SCRCPY_SDL_HAS_WINDOW_ALWAYS_ON_TOP #endif +#if SDL_VERSION_ATLEAST(2, 0, 8) +// +# define SCRCPY_SDL_HAS_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR +#endif + #endif diff --git a/app/src/convert.c b/app/src/convert.c index d20e255f..504befe0 100644 --- a/app/src/convert.c +++ b/app/src/convert.c @@ -81,9 +81,9 @@ convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod) { MAP(SDLK_ESCAPE, AKEYCODE_ESCAPE); MAP(SDLK_BACKSPACE, AKEYCODE_DEL); MAP(SDLK_TAB, AKEYCODE_TAB); - MAP(SDLK_HOME, AKEYCODE_HOME); MAP(SDLK_PAGEUP, AKEYCODE_PAGE_UP); MAP(SDLK_DELETE, AKEYCODE_FORWARD_DEL); + MAP(SDLK_HOME, AKEYCODE_MOVE_HOME); MAP(SDLK_END, AKEYCODE_MOVE_END); MAP(SDLK_PAGEDOWN, AKEYCODE_PAGE_DOWN); MAP(SDLK_RIGHT, AKEYCODE_DPAD_RIGHT); diff --git a/app/src/file_handler.c b/app/src/file_handler.c index d3dedcd2..c72b598d 100644 --- a/app/src/file_handler.c +++ b/app/src/file_handler.c @@ -10,11 +10,11 @@ struct request { file_handler_action_t action; - const char *file; + char *file; }; static struct request * -request_new(file_handler_action_t action, const char *file) { +request_new(file_handler_action_t action, char *file) { struct request *req = SDL_malloc(sizeof(*req)); if (!req) { return NULL; @@ -29,8 +29,8 @@ request_free(struct request *req) { if (!req) { return; } - SDL_free((void *) req->file); - SDL_free((void *) req); + SDL_free(req->file); + SDL_free(req); } static bool @@ -121,7 +121,7 @@ file_handler_destroy(struct file_handler *file_handler) { SDL_DestroyCond(file_handler->event_cond); SDL_DestroyMutex(file_handler->mutex); request_queue_destroy(&file_handler->queue); - SDL_free((void *) file_handler->serial); + SDL_free(file_handler->serial); } static process_t @@ -137,7 +137,7 @@ push_file(const char *serial, const char *file) { bool file_handler_request(struct file_handler *file_handler, file_handler_action_t action, - const char *file) { + char *file) { bool res; // start file_handler if it's used for the first time diff --git a/app/src/file_handler.h b/app/src/file_handler.h index 111161dc..382477d8 100644 --- a/app/src/file_handler.h +++ b/app/src/file_handler.h @@ -21,7 +21,7 @@ struct request_queue { }; struct file_handler { - const char *serial; + char *serial; SDL_Thread *thread; SDL_mutex *mutex; SDL_cond *event_cond; @@ -46,9 +46,10 @@ file_handler_stop(struct file_handler *file_handler); void file_handler_join(struct file_handler *file_handler); +// take ownership of file, and will SDL_free() it bool file_handler_request(struct file_handler *file_handler, file_handler_action_t action, - const char *file); + char *file); #endif diff --git a/app/src/main.c b/app/src/main.c index c61db725..fe93673f 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -105,7 +105,6 @@ static void usage(const char *arg0) { " resize window to remove black borders\n" "\n" " Ctrl+h\n" - " Home\n" " Middle-click\n" " click on HOME\n" "\n" diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 61b3f8d9..b777b770 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -9,6 +9,7 @@ #include "command.h" #include "common.h" +#include "compat.h" #include "controller.h" #include "decoder.h" #include "device.h" @@ -68,6 +69,13 @@ sdl_init_and_configure(bool display) { } #endif +#ifdef SCRCPY_SDL_HAS_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR + // Disable compositor bypassing on X11 + if (!SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0")) { + LOGW("Could not disable X11 compositor bypass"); + } +#endif + // Do not disable the screensaver when scrcpy is running SDL_EnableScreenSaver(); diff --git a/app/src/screen.c b/app/src/screen.c index 8476e94f..67b268c5 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -177,13 +177,12 @@ screen_init_rendering(struct screen *screen, const char *device_name, } SDL_Surface *icon = read_xpm(icon_xpm); - if (!icon) { - LOGE("Could not load icon: %s", SDL_GetError()); - screen_destroy(screen); - return false; + if (icon) { + SDL_SetWindowIcon(screen->window, icon); + SDL_FreeSurface(icon); + } else { + LOGW("Could not load icon"); } - SDL_SetWindowIcon(screen->window, icon); - SDL_FreeSurface(icon); LOGI("Initial texture: %" PRIu16 "x%" PRIu16, frame_size.width, frame_size.height); diff --git a/app/src/server.c b/app/src/server.c index 972fbbaa..c37e0070 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -210,7 +210,7 @@ server_start(struct server *server, const char *serial, close_socket(&server->server_socket); } disable_tunnel(server); - SDL_free((void *) server->serial); + SDL_free(server->serial); return false; } diff --git a/app/src/tiny_xpm.c b/app/src/tiny_xpm.c index 01fd280f..0fb410f3 100644 --- a/app/src/tiny_xpm.c +++ b/app/src/tiny_xpm.c @@ -105,6 +105,10 @@ read_xpm(char *xpm[]) { width, height, 32, 4 * width, rmask, gmask, bmask, amask); + if (!surface) { + LOGE("Could not create icon surface"); + return NULL; + } // make the surface own the raw pixels surface->flags &= ~SDL_PREALLOC; return surface;