Merge branch 'master' into dev
This commit is contained in:
commit
b75f0e9427
12 changed files with 91 additions and 24 deletions
13
README.md
13
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._
|
_²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_?
|
## Why _scrcpy_?
|
||||||
|
|
||||||
A colleague challenged me to find a name as unpronounceable as [gnirehtet].
|
A colleague challenged me to find a name as unpronounceable as [gnirehtet].
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -20,15 +21,52 @@ get_adb_command(void) {
|
||||||
return adb_command;
|
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
|
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) {
|
switch (err) {
|
||||||
case PROCESS_ERROR_GENERIC:
|
case PROCESS_ERROR_GENERIC:
|
||||||
LOGE("Failed to execute adb");
|
argv_to_string(argv, buf, sizeof(buf));
|
||||||
|
LOGE("Failed to execute: %s", buf);
|
||||||
break;
|
break;
|
||||||
case PROCESS_ERROR_MISSING_BINARY:
|
case PROCESS_ERROR_MISSING_BINARY:
|
||||||
LOGE("'adb' command not found (make it accessible from your PATH "
|
argv_to_string(argv, buf, sizeof(buf));
|
||||||
"or define its full path in the ADB environment variable)");
|
LOGE("Command not found: %s", buf);
|
||||||
|
LOGE("(make 'adb' accessible from your PATH or define its full"
|
||||||
|
"path in the ADB environment variable)");
|
||||||
break;
|
break;
|
||||||
case PROCESS_SUCCESS:
|
case PROCESS_SUCCESS:
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
|
@ -37,7 +75,7 @@ show_adb_err_msg(enum process_result err) {
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t
|
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];
|
const char *cmd[len + 4];
|
||||||
int i;
|
int i;
|
||||||
process_t process;
|
process_t process;
|
||||||
|
@ -54,7 +92,7 @@ adb_execute(const char *serial, const char *const adb_cmd[], int len) {
|
||||||
cmd[len + i] = NULL;
|
cmd[len + i] = NULL;
|
||||||
enum process_result r = cmd_execute(cmd[0], cmd, &process);
|
enum process_result r = cmd_execute(cmd[0], cmd, &process);
|
||||||
if (r != PROCESS_SUCCESS) {
|
if (r != PROCESS_SUCCESS) {
|
||||||
show_adb_err_msg(r);
|
show_adb_err_msg(r, cmd);
|
||||||
return PROCESS_NONE;
|
return PROCESS_NONE;
|
||||||
}
|
}
|
||||||
return process;
|
return process;
|
||||||
|
|
|
@ -49,7 +49,7 @@ bool
|
||||||
cmd_simple_wait(process_t pid, exit_code_t *exit_code);
|
cmd_simple_wait(process_t pid, exit_code_t *exit_code);
|
||||||
|
|
||||||
process_t
|
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
|
process_t
|
||||||
adb_forward(const char *serial, uint16_t local_port,
|
adb_forward(const char *serial, uint16_t local_port,
|
||||||
|
|
|
@ -43,4 +43,9 @@
|
||||||
# define SCRCPY_SDL_HAS_WINDOW_ALWAYS_ON_TOP
|
# define SCRCPY_SDL_HAS_WINDOW_ALWAYS_ON_TOP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 8)
|
||||||
|
// <https://hg.libsdl.org/SDL/rev/dfde5d3f9781>
|
||||||
|
# define SCRCPY_SDL_HAS_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -81,9 +81,9 @@ convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod) {
|
||||||
MAP(SDLK_ESCAPE, AKEYCODE_ESCAPE);
|
MAP(SDLK_ESCAPE, AKEYCODE_ESCAPE);
|
||||||
MAP(SDLK_BACKSPACE, AKEYCODE_DEL);
|
MAP(SDLK_BACKSPACE, AKEYCODE_DEL);
|
||||||
MAP(SDLK_TAB, AKEYCODE_TAB);
|
MAP(SDLK_TAB, AKEYCODE_TAB);
|
||||||
MAP(SDLK_HOME, AKEYCODE_HOME);
|
|
||||||
MAP(SDLK_PAGEUP, AKEYCODE_PAGE_UP);
|
MAP(SDLK_PAGEUP, AKEYCODE_PAGE_UP);
|
||||||
MAP(SDLK_DELETE, AKEYCODE_FORWARD_DEL);
|
MAP(SDLK_DELETE, AKEYCODE_FORWARD_DEL);
|
||||||
|
MAP(SDLK_HOME, AKEYCODE_MOVE_HOME);
|
||||||
MAP(SDLK_END, AKEYCODE_MOVE_END);
|
MAP(SDLK_END, AKEYCODE_MOVE_END);
|
||||||
MAP(SDLK_PAGEDOWN, AKEYCODE_PAGE_DOWN);
|
MAP(SDLK_PAGEDOWN, AKEYCODE_PAGE_DOWN);
|
||||||
MAP(SDLK_RIGHT, AKEYCODE_DPAD_RIGHT);
|
MAP(SDLK_RIGHT, AKEYCODE_DPAD_RIGHT);
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
|
|
||||||
struct request {
|
struct request {
|
||||||
file_handler_action_t action;
|
file_handler_action_t action;
|
||||||
const char *file;
|
char *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct request *
|
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));
|
struct request *req = SDL_malloc(sizeof(*req));
|
||||||
if (!req) {
|
if (!req) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -29,8 +29,8 @@ request_free(struct request *req) {
|
||||||
if (!req) {
|
if (!req) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SDL_free((void *) req->file);
|
SDL_free(req->file);
|
||||||
SDL_free((void *) req);
|
SDL_free(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -121,7 +121,7 @@ file_handler_destroy(struct file_handler *file_handler) {
|
||||||
SDL_DestroyCond(file_handler->event_cond);
|
SDL_DestroyCond(file_handler->event_cond);
|
||||||
SDL_DestroyMutex(file_handler->mutex);
|
SDL_DestroyMutex(file_handler->mutex);
|
||||||
request_queue_destroy(&file_handler->queue);
|
request_queue_destroy(&file_handler->queue);
|
||||||
SDL_free((void *) file_handler->serial);
|
SDL_free(file_handler->serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static process_t
|
static process_t
|
||||||
|
@ -137,7 +137,7 @@ push_file(const char *serial, const char *file) {
|
||||||
bool
|
bool
|
||||||
file_handler_request(struct file_handler *file_handler,
|
file_handler_request(struct file_handler *file_handler,
|
||||||
file_handler_action_t action,
|
file_handler_action_t action,
|
||||||
const char *file) {
|
char *file) {
|
||||||
bool res;
|
bool res;
|
||||||
|
|
||||||
// start file_handler if it's used for the first time
|
// start file_handler if it's used for the first time
|
||||||
|
|
|
@ -21,7 +21,7 @@ struct request_queue {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct file_handler {
|
struct file_handler {
|
||||||
const char *serial;
|
char *serial;
|
||||||
SDL_Thread *thread;
|
SDL_Thread *thread;
|
||||||
SDL_mutex *mutex;
|
SDL_mutex *mutex;
|
||||||
SDL_cond *event_cond;
|
SDL_cond *event_cond;
|
||||||
|
@ -46,9 +46,10 @@ file_handler_stop(struct file_handler *file_handler);
|
||||||
void
|
void
|
||||||
file_handler_join(struct file_handler *file_handler);
|
file_handler_join(struct file_handler *file_handler);
|
||||||
|
|
||||||
|
// take ownership of file, and will SDL_free() it
|
||||||
bool
|
bool
|
||||||
file_handler_request(struct file_handler *file_handler,
|
file_handler_request(struct file_handler *file_handler,
|
||||||
file_handler_action_t action,
|
file_handler_action_t action,
|
||||||
const char *file);
|
char *file);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -105,7 +105,6 @@ static void usage(const char *arg0) {
|
||||||
" resize window to remove black borders\n"
|
" resize window to remove black borders\n"
|
||||||
"\n"
|
"\n"
|
||||||
" Ctrl+h\n"
|
" Ctrl+h\n"
|
||||||
" Home\n"
|
|
||||||
" Middle-click\n"
|
" Middle-click\n"
|
||||||
" click on HOME\n"
|
" click on HOME\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "compat.h"
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "decoder.h"
|
#include "decoder.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
@ -68,6 +69,13 @@ sdl_init_and_configure(bool display) {
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
// Do not disable the screensaver when scrcpy is running
|
||||||
SDL_EnableScreenSaver();
|
SDL_EnableScreenSaver();
|
||||||
|
|
||||||
|
|
|
@ -177,13 +177,12 @@ screen_init_rendering(struct screen *screen, const char *device_name,
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Surface *icon = read_xpm(icon_xpm);
|
SDL_Surface *icon = read_xpm(icon_xpm);
|
||||||
if (!icon) {
|
if (icon) {
|
||||||
LOGE("Could not load icon: %s", SDL_GetError());
|
|
||||||
screen_destroy(screen);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
SDL_SetWindowIcon(screen->window, icon);
|
SDL_SetWindowIcon(screen->window, icon);
|
||||||
SDL_FreeSurface(icon);
|
SDL_FreeSurface(icon);
|
||||||
|
} else {
|
||||||
|
LOGW("Could not load icon");
|
||||||
|
}
|
||||||
|
|
||||||
LOGI("Initial texture: %" PRIu16 "x%" PRIu16, frame_size.width,
|
LOGI("Initial texture: %" PRIu16 "x%" PRIu16, frame_size.width,
|
||||||
frame_size.height);
|
frame_size.height);
|
||||||
|
|
|
@ -210,7 +210,7 @@ server_start(struct server *server, const char *serial,
|
||||||
close_socket(&server->server_socket);
|
close_socket(&server->server_socket);
|
||||||
}
|
}
|
||||||
disable_tunnel(server);
|
disable_tunnel(server);
|
||||||
SDL_free((void *) server->serial);
|
SDL_free(server->serial);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,10 @@ read_xpm(char *xpm[]) {
|
||||||
width, height,
|
width, height,
|
||||||
32, 4 * width,
|
32, 4 * width,
|
||||||
rmask, gmask, bmask, amask);
|
rmask, gmask, bmask, amask);
|
||||||
|
if (!surface) {
|
||||||
|
LOGE("Could not create icon surface");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
// make the surface own the raw pixels
|
// make the surface own the raw pixels
|
||||||
surface->flags &= ~SDL_PREALLOC;
|
surface->flags &= ~SDL_PREALLOC;
|
||||||
return surface;
|
return surface;
|
||||||
|
|
Loading…
Reference in a new issue