Compare commits

..

18 Commits

Author SHA1 Message Date
854a56e588 Enable linear filtering in OTG mode
This improves the icon quality with non-standard window size.

PR #3219 <https://github.com/Genymobile/scrcpy/pull/3219>
2022-04-28 19:18:16 +02:00
436b368f9d Make OTG window resizable
PR #3219 <https://github.com/Genymobile/scrcpy/pull/3219>
2022-04-28 19:18:12 +02:00
fc8942aa03 Apply requested window size in OTG mode
Fixes #3099 <https://github.com/Genymobile/scrcpy/issues/3099>
PR #3219 <https://github.com/Genymobile/scrcpy/pull/3219>
2022-04-28 19:18:09 +02:00
c6d9711109 Create OTG window with HIGHDPI flag
This will avoid poor quality with HiDPI displays.

PR #3219 <https://github.com/Genymobile/scrcpy/pull/3219>
2022-04-28 19:17:49 +02:00
0fca2ad830 Add option to not power on on start
By default, on start, the device is powered on. To prevent this
behavior, add a new option --no-power-on.

Fixes #3148 <https://github.com/Genymobile/scrcpy/issues/3148>
PR #3210 <https://github.com/Genymobile/scrcpy/pull/3210>
2022-04-28 19:12:52 +02:00
326897a0d4 Add missing mouse shortcuts in --help
Document 4th-click and 5th-click shortcuts.

Fixes #3122 <https://github.com/Genymobile/scrcpy/issues/3122>
2022-04-25 18:35:06 +02:00
4db97531e8 Upgrade libusb (1.0.26) for Windows
Upgrade and enable libusb support for Windows 32-bit builds.

Refs #3011 <https://github.com/Genymobile/scrcpy/pull/3011>
Fixes #3204 <https://github.com/Genymobile/scrcpy/issues/3204>
PR #3206 <https://github.com/Genymobile/scrcpy/pull/3206>
2022-04-22 13:34:58 +02:00
b8d78743f7 Upgrade platform-tools (33.0.1) for Windows
PR #3206 <https://github.com/Genymobile/scrcpy/pull/3206>
2022-04-22 13:34:11 +02:00
6a4a4a283d Remove obsolete alternative injection method
The previous commit replaced the IInterface instance (the "input"
service) by the InputManager instance (retrieved by
InputManager.getInstance()).

Both define an "injectInputEvent" method, but the alternate version
(probably) does not concern the InputManager.

This reverts commit b7a06278fe.

PR #3190 <https://github.com/Genymobile/scrcpy/pull/3190>
2022-04-22 09:52:41 +02:00
7d8b72d4a6 Adapt event injection to Android 13
Using the "input" service results in a permission error in Android 13.

Use the InputManager instance (retrieved by InputManager.getInstance())
instead.

Fixes #3186 <https://github.com/Genymobile/scrcpy/issues/3186>
PR #3190 <https://github.com/Genymobile/scrcpy/pull/3190>
2022-04-22 09:52:41 +02:00
fa5b2a29e9 Add missing SC_ prefix to header guards 2022-04-12 23:59:01 +02:00
0c94887075 Add missing include
Refs c3d45c8397
2022-04-12 23:51:05 +02:00
88543cb545 Fix icon path in ./run
The data/ directory has been moved to app/data/.

Refs 36c75e15b8
2022-03-30 14:00:05 +02:00
aaf3869a54 Fix OpenGL ES prefix skip 2022-03-30 12:01:01 +02:00
c3d45c8397 Consider emulators as TCP/IP devices
Emulators were wrongly considered as USB devices, so they were selected
using -d instead of -e (which was inconsistent with the adb behavior).

Refs #3005 <https://github.com/Genymobile/scrcpy/issues/3005>
Refs #3137 <https://github.com/Genymobile/scrcpy/issues/3137>
2022-03-22 21:08:08 +01:00
e56f2ac7a9 Log an error on unexpected device state
Refs #3129 <https://github.com/Genymobile/scrcpy/issues/3129>
2022-03-20 14:56:52 +01:00
4ce7af42c6 Use $ANDROID_SERIAL if no selector is specified
Like adb, read the ANDROID_SERIAL environment variable to select a
device by serial if no explicit selection (-s, -d, -e or --tcpip=<addr>)
is provided via the command line.

Fixes #3111 <https://github.com/Genymobile/scrcpy/issues/3111>
PR #3113 <https://github.com/Genymobile/scrcpy/pull/3113>
2022-03-15 08:32:34 +01:00
b1dbc30072 Document exit status in --help
Refs #3085 <https://github.com/Genymobile/scrcpy/pull/3085>
2022-03-10 09:13:21 +01:00
41 changed files with 236 additions and 88 deletions

View File

@ -448,6 +448,9 @@ scrcpy --serial 0123456789abcdef
scrcpy -s 0123456789abcdef # short version
```
The serial may also be provided via the environment variable `ANDROID_SERIAL`
(also used by `adb`).
If the device is connected over TCP/IP:
```bash
@ -718,6 +721,16 @@ To turn the device screen off when closing scrcpy:
scrcpy --power-off-on-close
```
#### Power on on start
By default, on start, the device is powered on.
To prevent this behavior:
```bash
scrcpy --no-power-on
```
#### Show touches

View File

@ -29,6 +29,7 @@ _scrcpy() {
-N --no-display
--no-key-repeat
--no-mipmaps
--no-power-on
--otg
-p --port=
--power-off-on-close

View File

@ -35,6 +35,7 @@ arguments=(
{-N,--no-display}'[Do not display device \(during screen recording or when V4L2 sink is enabled\)]'
'--no-key-repeat[Do not forward repeated key events when a key is held down]'
'--no-mipmaps[Disable the generation of mipmaps]'
'--no-power-on[Do not power on the device on start]'
'--otg[Run in OTG mode \(simulating physical keyboard and mouse\)]'
{-p,--port=}'[\[port\[\:port\]\] Set the TCP port \(range\) used by the client to listen]'
'--power-off-on-close[Turn the device screen off when closing scrcpy]'

View File

@ -143,12 +143,12 @@ else
prebuilt_libusb = meson.get_cross_property('prebuilt_libusb')
prebuilt_libusb_root = meson.get_cross_property('prebuilt_libusb_root')
libusb_bin_dir = meson.current_source_dir() + '/prebuilt-deps/data/' + prebuilt_libusb + '/dll'
libusb_bin_dir = meson.current_source_dir() + '/prebuilt-deps/data/' + prebuilt_libusb
libusb_include_dir = 'prebuilt-deps/data/' + prebuilt_libusb_root + '/include'
libusb = declare_dependency(
dependencies: [
cc.find_library('libusb-1.0', dirs: libusb_bin_dir),
cc.find_library('msys-usb-1.0', dirs: libusb_bin_dir),
],
include_directories: include_directories(libusb_include_dir)
)

View File

@ -6,10 +6,10 @@ cd "$DIR"
mkdir -p "$PREBUILT_DATA_DIR"
cd "$PREBUILT_DATA_DIR"
DEP_DIR=platform-tools-31.0.3
DEP_DIR=platform-tools-33.0.1
FILENAME=platform-tools_r31.0.3-windows.zip
SHA256SUM=0f4b8fdd26af2c3733539d6eebb3c2ed499ea1d4bb1f4e0ecc2d6016961a6e24
FILENAME=platform-tools_r33.0.1-windows.zip
SHA256SUM=c1f02d42ea24ef4ff2a405ae7370e764ef4546f9b3e4520f5571a00ed5012c42
if [[ -d "$DEP_DIR" ]]
then

View File

@ -6,10 +6,10 @@ cd "$DIR"
mkdir -p "$PREBUILT_DATA_DIR"
cd "$PREBUILT_DATA_DIR"
DEP_DIR=libusb-1.0.25
DEP_DIR=libusb-1.0.26
FILENAME=libusb-1.0.25.7z
SHA256SUM=3d1c98416f454026034b2b5d67f8a294053898cb70a8b489874e75b136c6674d
FILENAME=libusb-1.0.26-binaries.7z
SHA256SUM=9c242696342dbde9cdc47239391f71833939bf9f7aa2bbb28cdaabe890465ec5
if [[ -d "$DEP_DIR" ]]
then
@ -17,12 +17,18 @@ then
exit 0
fi
get_file "https://github.com/libusb/libusb/releases/download/v1.0.25/$FILENAME" "$FILENAME" "$SHA256SUM"
get_file "https://github.com/libusb/libusb/releases/download/v1.0.26/$FILENAME" "$FILENAME" "$SHA256SUM"
mkdir "$DEP_DIR"
cd "$DEP_DIR"
# include/ is the same in all folders of the archive
7z x "../$FILENAME" \
MinGW32/dll/libusb-1.0.dll \
MinGW64/dll/libusb-1.0.dll \
include /
libusb-1.0.26-binaries/libusb-MinGW-Win32/bin/msys-usb-1.0.dll \
libusb-1.0.26-binaries/libusb-MinGW-x64/bin/msys-usb-1.0.dll \
libusb-1.0.26-binaries/libusb-MinGW-x64/include/
mv libusb-1.0.26-binaries/libusb-MinGW-Win32/bin MinGW-Win32
mv libusb-1.0.26-binaries/libusb-MinGW-x64/bin MinGW-x64
mv libusb-1.0.26-binaries/libusb-MinGW-x64/include .
rm -rf libusb-1.0.26-binaries

View File

@ -180,6 +180,10 @@ Do not forward repeated key events when a key is held down.
.B \-\-no\-mipmaps
If the renderer is OpenGL 3.0+ or OpenGL ES 2.0+, then mipmaps are automatically generated to improve downscaling quality. This option disables the generation of mipmaps.
.TP
.B \-\-no\-power\-on
Do not power on the device on start.
.TP
.B \-\-otg
Run in OTG mode: simulate physical keyboard and mouse, as if the computer keyboard and mouse were plugged directly to the device via an OTG cable.
@ -477,6 +481,10 @@ Push file to device (see \fB\-\-push\-target\fR)
.B ADB
Path to adb.
.TP
.B ANDROID_SERIAL
Device serial to use if no selector (-s, -d, -e or --tcpip=<addr>) is specified.
.TP
.B SCRCPY_ICON_PATH
Path to the program icon.

View File

@ -473,9 +473,12 @@ sc_adb_accept_device(const struct sc_adb_device *device,
}
return !strcmp(selector->serial, device->serial);
case SC_ADB_DEVICE_SELECT_USB:
return !sc_adb_is_serial_tcpip(device->serial);
return sc_adb_device_get_type(device->serial) ==
SC_ADB_DEVICE_TYPE_USB;
case SC_ADB_DEVICE_SELECT_TCPIP:
return sc_adb_is_serial_tcpip(device->serial);
// Both emulators and TCP/IP devices are selected via -e
return sc_adb_device_get_type(device->serial) !=
SC_ADB_DEVICE_TYPE_USB;
default:
assert(!"Missing SC_ADB_DEVICE_SELECT_* handling");
break;
@ -509,8 +512,10 @@ sc_adb_devices_log(enum sc_log_level level, struct sc_adb_device *devices,
for (size_t i = 0; i < count; ++i) {
struct sc_adb_device *d = &devices[i];
const char *selection = d->selected ? "-->" : " ";
const char *type = sc_adb_is_serial_tcpip(d->serial) ? "(tcpip)"
: " (usb)";
bool is_usb =
sc_adb_device_get_type(d->serial) == SC_ADB_DEVICE_TYPE_USB;
const char *type = is_usb ? " (usb)"
: "(tcpip)";
LOG(level, " %s %s %-20s %16s %s",
selection, type, d->serial, d->state, d->model ? d->model : "");
}
@ -531,6 +536,8 @@ sc_adb_device_check_state(struct sc_adb_device *device,
LOGE("A popup should open on the device to request authorization.");
LOGE("Check the FAQ: "
"<https://github.com/Genymobile/scrcpy/blob/master/FAQ.md>");
} else {
LOGE("Device could not be connected (state=%s)", state);
}
return false;
@ -705,8 +712,3 @@ sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags) {
return sc_adb_parse_device_ip_from_output(buf);
}
bool
sc_adb_is_serial_tcpip(const char *serial) {
return strchr(serial, ':');
}

View File

@ -114,13 +114,4 @@ sc_adb_getprop(struct sc_intr *intr, const char *serial, const char *prop,
char *
sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags);
/**
* Indicate if the serial represents an IP address
*
* In practice, it just returns true if and only if it contains a ':', which is
* sufficient to distinguish an ip:port from a real USB serial.
*/
bool
sc_adb_is_serial_tcpip(const char *serial);
#endif

View File

@ -1,6 +1,7 @@
#include "adb_device.h"
#include <stdlib.h>
#include <string.h>
void
sc_adb_device_destroy(struct sc_adb_device *device) {
@ -25,3 +26,18 @@ sc_adb_devices_destroy(struct sc_vec_adb_devices *devices) {
sc_vector_destroy(devices);
}
enum sc_adb_device_type
sc_adb_device_get_type(const char *serial) {
// Starts with "emulator-"
if (!strncmp(serial, "emulator-", sizeof("emulator-") - 1)) {
return SC_ADB_DEVICE_TYPE_EMULATOR;
}
// If the serial contains a ':', then it is a TCP/IP device (it is
// sufficient to distinguish an ip:port from a real USB serial)
if (strchr(serial, ':')) {
return SC_ADB_DEVICE_TYPE_TCPIP;
}
return SC_ADB_DEVICE_TYPE_USB;
}

View File

@ -15,6 +15,12 @@ struct sc_adb_device {
bool selected;
};
enum sc_adb_device_type {
SC_ADB_DEVICE_TYPE_USB,
SC_ADB_DEVICE_TYPE_TCPIP,
SC_ADB_DEVICE_TYPE_EMULATOR,
};
struct sc_vec_adb_devices SC_VECTOR(struct sc_adb_device);
void
@ -35,4 +41,10 @@ sc_adb_device_move(struct sc_adb_device *dst, struct sc_adb_device *src);
void
sc_adb_devices_destroy(struct sc_vec_adb_devices *devices);
/**
* Deduce the device type from the serial
*/
enum sc_adb_device_type
sc_adb_device_get_type(const char *serial);
#endif

View File

@ -56,6 +56,7 @@
#define OPT_OTG 1036
#define OPT_NO_CLEANUP 1037
#define OPT_PRINT_FPS 1038
#define OPT_NO_POWER_ON 1039
struct sc_option {
char shortopt;
@ -80,6 +81,11 @@ struct sc_envvar {
const char *text;
};
struct sc_exit_status {
unsigned value;
const char *text;
};
struct sc_getopt_adapter {
char *optstring;
struct option *longopts;
@ -297,6 +303,11 @@ static const struct sc_option options[] = {
"mipmaps are automatically generated to improve downscaling "
"quality. This option disables the generation of mipmaps.",
},
{
.longopt_id = OPT_NO_POWER_ON,
.longopt = "no-power-on",
.text = "Do not power on the device on start.",
},
{
.longopt_id = OPT_OTG,
.longopt = "otg",
@ -572,7 +583,7 @@ static const struct sc_shortcut shortcuts[] = {
.text = "Click on BACK",
},
{
.shortcuts = { "MOD+s" },
.shortcuts = { "MOD+s", "4th-click" },
.text = "Click on APP_SWITCH",
},
{
@ -608,7 +619,7 @@ static const struct sc_shortcut shortcuts[] = {
.text = "Rotate device screen",
},
{
.shortcuts = { "MOD+n" },
.shortcuts = { "MOD+n", "5th-click" },
.text = "Expand notification panel",
},
{
@ -655,6 +666,11 @@ static const struct sc_envvar envvars[] = {
.name = "ADB",
.text = "Path to adb executable",
},
{
.name = "ANDROID_SERIAL",
.text = "Device serial to use if no selector (-s, -d, -e or "
"--tcpip=<addr>) is specified",
},
{
.name = "SCRCPY_ICON_PATH",
.text = "Path to the program icon",
@ -662,7 +678,22 @@ static const struct sc_envvar envvars[] = {
{
.name = "SCRCPY_SERVER_PATH",
.text = "Path to the server binary",
}
},
};
static const struct sc_exit_status exit_statuses[] = {
{
.value = 0,
.text = "Normal program termination",
},
{
.value = 1,
.text = "Start failure",
},
{
.value = 2,
.text = "Device disconnected while running",
},
};
static char *
@ -901,6 +932,25 @@ print_envvar(const struct sc_envvar *envvar, unsigned cols) {
free(text);
}
static void
print_exit_status(const struct sc_exit_status *status, unsigned cols) {
assert(cols > 8); // sc_str_wrap_lines() requires indent < columns
assert(status->text);
// The text starts at 9: 4 ident spaces, 3 chars for numeric value, 2 spaces
char *text = sc_str_wrap_lines(status->text, cols, 9);
if (!text) {
printf("<ERROR>\n");
return;
}
assert(strlen(text) >= 9); // Contains at least the initial identation
// text + 9 to remove the initial indentation
printf(" %3d %s\n", status->value, text + 9);
free(text);
}
void
scrcpy_print_usage(const char *arg0) {
#define SC_TERM_COLS_DEFAULT 80
@ -939,6 +989,11 @@ scrcpy_print_usage(const char *arg0) {
for (size_t i = 0; i < ARRAY_LEN(envvars); ++i) {
print_envvar(&envvars[i], cols);
}
printf("\nExit status:\n\n");
for (size_t i = 0; i < ARRAY_LEN(exit_statuses); ++i) {
print_exit_status(&exit_statuses[i], cols);
}
}
static bool
@ -1549,6 +1604,9 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
case OPT_NO_CLEANUP:
opts->cleanup = false;
break;
case OPT_NO_POWER_ON:
opts->power_on = false;
break;
case OPT_PRINT_FPS:
opts->start_fps_counter = true;
break;

View File

@ -1,5 +1,5 @@
#ifndef COMMON_H
#define COMMON_H
#ifndef SC_COMMON_H
#define SC_COMMON_H
#include "config.h"
#include "compat.h"

View File

@ -1,5 +1,5 @@
#ifndef COMPAT_H
#define COMPAT_H
#ifndef SC_COMPAT_H
#define SC_COMPAT_H
#include "config.h"

View File

@ -1,5 +1,5 @@
#ifndef CONTROLMSG_H
#define CONTROLMSG_H
#ifndef SC_CONTROLMSG_H
#define SC_CONTROLMSG_H
#include "common.h"

View File

@ -1,5 +1,5 @@
#ifndef CONTROLLER_H
#define CONTROLLER_H
#ifndef SC_CONTROLLER_H
#define SC_CONTROLLER_H
#include "common.h"

View File

@ -1,5 +1,5 @@
#ifndef DEVICEMSG_H
#define DEVICEMSG_H
#ifndef SC_DEVICEMSG_H
#define SC_DEVICEMSG_H
#include "common.h"

View File

@ -1,5 +1,5 @@
#ifndef FPSCOUNTER_H
#define FPSCOUNTER_H
#ifndef SC_FPSCOUNTER_H
#define SC_FPSCOUNTER_H
#include "common.h"

View File

@ -1,5 +1,5 @@
#ifndef ICON_H
#define ICON_H
#ifndef SC_ICON_H
#define SC_ICON_H
#include "common.h"

View File

@ -1,5 +1,5 @@
#ifndef INPUTMANAGER_H
#define INPUTMANAGER_H
#ifndef SC_INPUTMANAGER_H
#define SC_INPUTMANAGER_H
#include "common.h"

View File

@ -28,7 +28,7 @@ sc_opengl_init(struct sc_opengl *gl) {
sizeof(OPENGL_ES_PREFIX) - 1);
if (gl->is_opengles) {
/* skip the prefix */
version += sizeof(PREFIX) - 1;
version += sizeof(OPENGL_ES_PREFIX) - 1;
}
int r = sscanf(version, "%d.%d", &gl->version_major, &gl->version_minor);

View File

@ -64,4 +64,5 @@ const struct scrcpy_options scrcpy_options_default = {
.select_usb = false,
.cleanup = true,
.start_fps_counter = false,
.power_on = true,
};

View File

@ -139,6 +139,7 @@ struct scrcpy_options {
bool select_tcpip;
bool cleanup;
bool start_fps_counter;
bool power_on;
};
extern const struct scrcpy_options scrcpy_options_default;

View File

@ -1,5 +1,5 @@
#ifndef RECEIVER_H
#define RECEIVER_H
#ifndef SC_RECEIVER_H
#define SC_RECEIVER_H
#include "common.h"

View File

@ -324,6 +324,7 @@ scrcpy(struct scrcpy_options *options) {
.tcpip = options->tcpip,
.tcpip_dst = options->tcpip_dst,
.cleanup = options->cleanup,
.power_on = options->power_on,
};
static const struct sc_server_callbacks cbs = {

View File

@ -248,6 +248,10 @@ execute_server(struct sc_server *server,
// By default, cleanup is true
ADD_PARAM("cleanup=false");
}
if (!params->power_on) {
// By default, power_on is true
ADD_PARAM("power_on=false");
}
#undef ADD_PARAM
@ -649,7 +653,8 @@ sc_server_configure_tcpip_known_address(struct sc_server *server,
static bool
sc_server_configure_tcpip_unknown_address(struct sc_server *server,
const char *serial) {
bool is_already_tcpip = sc_adb_is_serial_tcpip(serial);
bool is_already_tcpip =
sc_adb_device_get_type(serial) == SC_ADB_DEVICE_TYPE_TCPIP;
if (is_already_tcpip) {
// Nothing to do
LOGI("Device already connected via TCP/IP: %s", serial);
@ -707,7 +712,15 @@ run_server(void *data) {
} else if (params->select_tcpip) {
selector.type = SC_ADB_DEVICE_SELECT_TCPIP;
} else {
selector.type = SC_ADB_DEVICE_SELECT_ALL;
// No explicit selection, check $ANDROID_SERIAL
const char *env_serial = getenv("ANDROID_SERIAL");
if (env_serial) {
LOGI("Using ANDROID_SERIAL: %s", env_serial);
selector.type = SC_ADB_DEVICE_SELECT_SERIAL;
selector.serial = env_serial;
} else {
selector.type = SC_ADB_DEVICE_SELECT_ALL;
}
}
struct sc_adb_device device;
ok = sc_adb_select_device(&server->intr, &selector, 0, &device);

View File

@ -47,6 +47,7 @@ struct sc_server_params {
bool select_usb;
bool select_tcpip;
bool cleanup;
bool power_on;
};
struct sc_server {

View File

@ -55,6 +55,10 @@ scrcpy_otg(struct scrcpy_options *options) {
const char *serial = options->serial;
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) {
LOGW("Could not enable linear filtering");
}
// Minimal SDL initialization
if (SDL_Init(SDL_INIT_EVENTS)) {
LOGE("Could not initialize SDL: %s", SDL_GetError());
@ -162,6 +166,8 @@ scrcpy_otg(struct scrcpy_options *options) {
.always_on_top = options->always_on_top,
.window_x = options->window_x,
.window_y = options->window_y,
.window_width = options->window_width,
.window_height = options->window_height,
.window_borderless = options->window_borderless,
};

View File

@ -69,10 +69,11 @@ sc_screen_otg_init(struct sc_screen_otg *screen,
? params->window_x : (int) SDL_WINDOWPOS_UNDEFINED;
int y = params->window_y != SC_WINDOW_POSITION_UNDEFINED
? params->window_y : (int) SDL_WINDOWPOS_UNDEFINED;
int width = 256;
int height = 256;
int width = params->window_width ? params->window_width : 256;
int height = params->window_height ? params->window_height : 256;
uint32_t window_flags = 0;
uint32_t window_flags = SDL_WINDOW_ALLOW_HIGHDPI
| SDL_WINDOW_RESIZABLE;
if (params->always_on_top) {
window_flags |= SDL_WINDOW_ALWAYS_ON_TOP;
}
@ -97,6 +98,11 @@ sc_screen_otg_init(struct sc_screen_otg *screen,
if (icon) {
SDL_SetWindowIcon(screen->window, icon);
if (!SDL_RenderSetLogicalSize(screen->renderer, icon->w, icon->h)) {
LOGW("Could not set renderer logical size: %s", SDL_GetError());
// don't fail
}
screen->texture = SDL_CreateTextureFromSurface(screen->renderer, icon);
scrcpy_icon_destroy(icon);
if (!screen->texture) {

View File

@ -29,6 +29,8 @@ struct sc_screen_otg_params {
bool always_on_top;
int16_t window_x; // accepts SC_WINDOW_POSITION_UNDEFINED
int16_t window_y; // accepts SC_WINDOW_POSITION_UNDEFINED
uint16_t window_width;
uint16_t window_height;
bool window_borderless;
};

View File

@ -1,6 +1,6 @@
// generic circular buffer (bounded queue) implementation
#ifndef CBUF_H
#define CBUF_H
#ifndef SC_CBUF_H
#define SC_CBUF_H
#include "common.h"

View File

@ -1,5 +1,5 @@
#ifndef NET_H
#define NET_H
#ifndef SC_NET_H
#define SC_NET_H
#include "common.h"

View File

@ -21,5 +21,5 @@ ffmpeg_avformat = 'avformat-58'
ffmpeg_avutil = 'avutil-56'
prebuilt_ffmpeg = 'ffmpeg-win32-4.3.1'
prebuilt_sdl2 = 'SDL2-2.0.20/i686-w64-mingw32'
prebuilt_libusb_root = 'libusb-1.0.25'
prebuilt_libusb = prebuilt_libusb_root + '/MinGW32'
prebuilt_libusb_root = 'libusb-1.0.26'
prebuilt_libusb = prebuilt_libusb_root + '/MinGW-Win32'

View File

@ -21,5 +21,5 @@ ffmpeg_avformat = 'avformat-59'
ffmpeg_avutil = 'avutil-57'
prebuilt_ffmpeg = 'ffmpeg-win64-5.0'
prebuilt_sdl2 = 'SDL2-2.0.20/x86_64-w64-mingw32'
prebuilt_libusb_root = 'libusb-1.0.25'
prebuilt_libusb = prebuilt_libusb_root + '/MinGW64'
prebuilt_libusb_root = 'libusb-1.0.26'
prebuilt_libusb = prebuilt_libusb_root + '/MinGW-x64'

View File

@ -75,12 +75,10 @@ prepare-deps-win64:
@app/prebuilt-deps/prepare-libusb.sh
build-win32: prepare-deps-win32
# -Dusb=false because of libusb-win32 build issue, cf #3011
[ -d "$(WIN32_BUILD_DIR)" ] || ( mkdir "$(WIN32_BUILD_DIR)" && \
meson "$(WIN32_BUILD_DIR)" \
--cross-file cross_win32.txt \
--buildtype release --strip -Db_lto=true \
-Dusb=false \
-Dcompile_server=false \
-Dportable=true )
ninja -C "$(WIN32_BUILD_DIR)"
@ -111,7 +109,7 @@ dist-win32: build-server build-win32
cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/SDL2-2.0.20/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
#cp app/prebuilt-deps/data/libusb-1.0.25/MinGW32/dll/libusb-1.0.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/libusb-1.0.26/MinGW-Win32/msys-usb-1.0.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
dist-win64: build-server build-win64
mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)"
@ -130,7 +128,7 @@ dist-win64: build-server build-win64
cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/SDL2-2.0.20/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/libusb-1.0.25/MinGW64/dll/libusb-1.0.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/libusb-1.0.26/MinGW-x64/msys-usb-1.0.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
zip-win32: dist-win32
cd "$(DIST)/$(WIN32_TARGET_DIR)"; \

2
run
View File

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

View File

@ -22,6 +22,7 @@ public class Controller {
private final DesktopConnection connection;
private final DeviceMessageSender sender;
private final boolean clipboardAutosync;
private final boolean powerOn;
private final KeyCharacterMap charMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
@ -32,10 +33,11 @@ public class Controller {
private boolean keepPowerModeOff;
public Controller(Device device, DesktopConnection connection, boolean clipboardAutosync) {
public Controller(Device device, DesktopConnection connection, boolean clipboardAutosync, boolean powerOn) {
this.device = device;
this.connection = connection;
this.clipboardAutosync = clipboardAutosync;
this.powerOn = powerOn;
initPointers();
sender = new DeviceMessageSender(connection);
}
@ -56,7 +58,7 @@ public class Controller {
public void control() throws IOException {
// on start, power on the device
if (!Device.isScreenOn()) {
if (powerOn && !Device.isScreenOn()) {
device.pressReleaseKeycode(KeyEvent.KEYCODE_POWER, Device.INJECT_MODE_ASYNC);
// dirty hack

View File

@ -22,6 +22,7 @@ public class Options {
private boolean clipboardAutosync = true;
private boolean downsizeOnError = true;
private boolean cleanup = true;
private boolean powerOn = true;
// Options not used by the scrcpy client, but useful to use scrcpy-server directly
private boolean sendDeviceMeta = true; // send device name and size
@ -164,6 +165,14 @@ public class Options {
this.cleanup = cleanup;
}
public boolean getPowerOn() {
return powerOn;
}
public void setPowerOn(boolean powerOn) {
this.powerOn = powerOn;
}
public boolean getSendDeviceMeta() {
return sendDeviceMeta;
}

View File

@ -82,7 +82,7 @@ public final class Server {
Thread controllerThread = null;
Thread deviceMessageSenderThread = null;
if (control) {
final Controller controller = new Controller(device, connection, options.getClipboardAutosync());
final Controller controller = new Controller(device, connection, options.getClipboardAutosync(), options.getPowerOn());
// asynchronous
controllerThread = startController(controller);
@ -248,6 +248,10 @@ public final class Server {
boolean cleanup = Boolean.parseBoolean(value);
options.setCleanup(cleanup);
break;
case "power_on":
boolean powerOn = Boolean.parseBoolean(value);
options.setPowerOn(powerOn);
break;
case "send_device_meta":
boolean sendDeviceMeta = Boolean.parseBoolean(value);
options.setSendDeviceMeta(sendDeviceMeta);

View File

@ -2,7 +2,6 @@ package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.Ln;
import android.os.IInterface;
import android.view.InputEvent;
import java.lang.reflect.InvocationTargetException;
@ -14,24 +13,18 @@ public final class InputManager {
public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1;
public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2;
private final IInterface manager;
private final android.hardware.input.InputManager manager;
private Method injectInputEventMethod;
private boolean alternativeInjectInputEventMethod;
private static Method setDisplayIdMethod;
public InputManager(IInterface manager) {
public InputManager(android.hardware.input.InputManager manager) {
this.manager = manager;
}
private Method getInjectInputEventMethod() throws NoSuchMethodException {
if (injectInputEventMethod == null) {
try {
injectInputEventMethod = manager.getClass().getMethod("injectInputEvent", InputEvent.class, int.class);
} catch (NoSuchMethodException e) {
injectInputEventMethod = manager.getClass().getMethod("injectInputEvent", InputEvent.class, int.class, int.class);
alternativeInjectInputEventMethod = true;
}
injectInputEventMethod = manager.getClass().getMethod("injectInputEvent", InputEvent.class, int.class);
}
return injectInputEventMethod;
}
@ -39,10 +32,6 @@ public final class InputManager {
public boolean injectInputEvent(InputEvent inputEvent, int mode) {
try {
Method method = getInjectInputEventMethod();
if (alternativeInjectInputEventMethod) {
// See <https://github.com/Genymobile/scrcpy/issues/2250>
return (boolean) method.invoke(manager, inputEvent, mode, 0);
}
return (boolean) method.invoke(manager, inputEvent, mode);
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
Ln.e("Could not invoke method", e);

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
import android.os.IBinder;
import android.os.IInterface;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@SuppressLint("PrivateApi,DiscouragedPrivateApi")
@ -56,7 +57,13 @@ public final class ServiceManager {
public InputManager getInputManager() {
if (inputManager == null) {
inputManager = new InputManager(getService("input", "android.hardware.input.IInputManager"));
try {
Method getInstanceMethod = android.hardware.input.InputManager.class.getDeclaredMethod("getInstance");
android.hardware.input.InputManager im = (android.hardware.input.InputManager) getInstanceMethod.invoke(null);
inputManager = new InputManager(im);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new AssertionError(e);
}
}
return inputManager;
}