Compare commits

...

18 Commits

Author SHA1 Message Date
73c0f3ee05 Add compilation flag for HIDPI workaround
The HIDPI workaround is enabled by default. Expose a flag to be able to
disable it.
2019-11-06 19:27:42 +01:00
78d9d82091 Reset renderer on hidpi scaling change
Moving a window between hidpi and non-hidpi monitors is not correctly
handled by SDL.

Detect when this happens, and recreate the renderer.

Fixes <https://github.com/Genymobile/scrcpy/issues/15>.

Signed-off-by: Romain Vimont <rom@rom1v.com>
2019-11-06 19:27:38 +01:00
c8c921caf5 Remove HIDPI compilation flag
The flag had been added to avoid hidpi bugs.

A workaround will be implemented for these bugs, so the flag is not
needed anymore.
2019-11-06 19:15:30 +01:00
39ff8d9900 Handle window resizing in screen
Only the screen knows what to do when the window is resized.

This paves the way to do other actions on window resizing.
2019-11-06 18:25:37 +01:00
683f7ca848 Document how to attach a debugger to the server 2019-11-03 19:42:37 +01:00
120f08ee96 Fix manpage option parameter format
The parameter for --window-title was not underlined the same way as
others.
2019-11-03 16:51:47 +01:00
0415672a75 Merge branch 'master' into dev 2019-11-03 15:56:10 +01:00
3ea4742321 Call ninja without changing directory
In build instructions, use:

    ninja -Cx ...

instead of:

    cd x
    ninja ...
2019-10-31 21:05:04 +01:00
95fd64b5de Add scrcpy version in recorded video metadata
It might help to understand problems in recorded videos.
2019-10-31 20:57:57 +01:00
ab205084dc Merge pull request #896 from yangfl/upstream
Add manpage for scrcpy
2019-10-31 13:44:01 +01:00
4696878a97 Add manpage for scrcpy 2019-10-31 18:18:19 +08:00
3da95b52bd Rename scrcpy-server.jar to scrcpy-server
The server name ending with .jar has several drawbacks:
 - meson requires the jar executable to attempt to modify it:
     <https://github.com/Genymobile/scrcpy/issues/404#issuecomment-456065923>
     <https://github.com/mesonbuild/meson/issues/4844>
 - meson warns during "ninja install"
     <https://github.com/Genymobile/scrcpy/issues/458>
 - some users try to execute it on the computer as a java executable

Removing the extension solves all these problems.
2019-10-31 10:54:29 +01:00
c72f677435 Merge branch 'master' into dev 2019-10-30 23:29:44 +01:00
1380f6e00f Fix help for --record-format
Record format requires a parameter.
2019-10-30 22:51:40 +01:00
d841718956 Add a script to build the server without gradle
Gradle versions may sometimes cause problems. This script offers an
alternative.
2019-10-30 21:47:20 +01:00
17d53be3ef Fix mouse events conversion
The conversion from SDL mouse state to Android mouse state used wrong
constants as mask.

Fixes <https://github.com/Genymobile/scrcpy/issues/635>
2019-10-25 11:09:06 +02:00
f9938dbf88 Inject button state for touch/mouse events
The buttons state was forwarded, but ignored by the server.
2019-10-25 11:04:04 +02:00
f6c8460ebb Rename window size functions for clarity
Now, get_window_size() returns the current window size (fullscreen or
not), while get_windowed_window_size() always returned the windowed size
(the size when fullscreen is disabled).
2019-10-20 16:08:16 +02:00
21 changed files with 487 additions and 68 deletions

View File

@ -195,8 +195,7 @@ Then, build:
```bash
meson x --buildtype release --strip -Db_lto=true
cd x
ninja
ninja -Cx
```
_Note: `ninja` [must][ninja-user] be run as a non-root user (only `ninja
@ -219,13 +218,13 @@ To run without installing:
After a successful build, you can install _scrcpy_ on the system:
```bash
sudo ninja install # without sudo on Windows
sudo ninja -Cx install # without sudo on Windows
```
This installs two files:
- `/usr/local/bin/scrcpy`
- `/usr/local/share/scrcpy/scrcpy-server.jar`
- `/usr/local/share/scrcpy/scrcpy-server`
Just remove them to "uninstall" the application.
@ -244,8 +243,7 @@ configuration:
```bash
meson x --buildtype release --strip -Db_lto=true \
-Dprebuilt_server=/path/to/scrcpy-server.jar
cd x
ninja
sudo ninja install
-Dprebuilt_server=/path/to/scrcpy-server
ninja -Cx
sudo ninja -Cx install
```

View File

@ -3,7 +3,7 @@
## Overview
This application is composed of two parts:
- the server (`scrcpy-server.jar`), to be executed on the device,
- the server (`scrcpy-server`), to be executed on the device,
- the client (the `scrcpy` binary), executed on the host computer.
The client is responsible to push the server to the device and start its
@ -49,7 +49,7 @@ application may not replace the server just before the client executes it._
Instead of a raw _dex_ file, `app_process` accepts a _jar_ containing
`classes.dex` (e.g. an [APK]). For simplicity, and to benefit from the gradle
build system, the server is built to an (unsigned) APK (renamed to
`scrcpy-server.jar`).
`scrcpy-server`).
[dex]: https://en.wikipedia.org/wiki/Dalvik_(software)
[apk]: https://en.wikipedia.org/wiki/Android_application_package
@ -268,3 +268,33 @@ For more details, go read the code!
If you find a bug, or have an awesome idea to implement, please discuss and
contribute ;-)
### Debug the server
The server is pushed to the device by the client on startup.
To debug it, enable the server debugger during configuration:
```bash
meson x -Dserver_debugger=true
# or, if x is already configured
meson configure x -Dserver_debugger=true
```
Then recompile.
When you start scrcpy, it will start a debugger on port 5005 on the device.
Redirect that port to the computer:
```bash
adb forward tcp:5005 tcp:5005
```
In Android Studio, _Run_ > _Debug_ > _Edit configurations..._ On the left, click on
`+`, _Remote_, and fill the form:
- Host: `localhost`
- Port: `5005`
Then click on _Debug_.

View File

@ -3,7 +3,7 @@
#
# Here, "portable" means that the client and server binaries are expected to be
# anywhere, but in the same directory, instead of well-defined separate
# locations (e.g. /usr/bin/scrcpy and /usr/share/scrcpy/scrcpy-server.jar).
# locations (e.g. /usr/bin/scrcpy and /usr/share/scrcpy/scrcpy-server).
#
# In particular, this implies to change the location from where the client push
# the server to the device.
@ -97,7 +97,7 @@ build-win64-noconsole: prepare-deps-win64
dist-win32: build-server build-win32 build-win32-noconsole
mkdir -p "$(DIST)/$(WIN32_TARGET_DIR)"
cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server.jar "$(DIST)/$(WIN32_TARGET_DIR)/"
cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server "$(DIST)/$(WIN32_TARGET_DIR)/"
cp "$(WIN32_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
cp "$(WIN32_NOCONSOLE_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN32_TARGET_DIR)/scrcpy-noconsole.exe"
cp prebuilt-deps/ffmpeg-4.1.4-win32-shared/bin/avutil-56.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
@ -112,7 +112,7 @@ dist-win32: build-server build-win32 build-win32-noconsole
dist-win64: build-server build-win64 build-win64-noconsole
mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)"
cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server.jar "$(DIST)/$(WIN64_TARGET_DIR)/"
cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server "$(DIST)/$(WIN64_TARGET_DIR)/"
cp "$(WIN64_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
cp "$(WIN64_NOCONSOLE_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN64_TARGET_DIR)/scrcpy-noconsole.exe"
cp prebuilt-deps/ffmpeg-4.1.4-win64-shared/bin/avutil-56.dll "$(DIST)/$(WIN64_TARGET_DIR)/"

View File

@ -358,7 +358,7 @@ To use a specific _adb_ binary, configure its path in the environment variable
ADB=/path/to/adb scrcpy
To override the path of the `scrcpy-server.jar` file, configure its path in
To override the path of the `scrcpy-server` file, configure its path in
`SCRCPY_SERVER_PATH`.
[useful]: https://github.com/Genymobile/scrcpy/issues/278#issuecomment-429330345

View File

@ -93,7 +93,7 @@ conf.set_quoted('SCRCPY_VERSION', meson.project_version())
# the prefix used during configuration (meson --prefix=PREFIX)
conf.set_quoted('PREFIX', get_option('prefix'))
# build a "portable" version (with scrcpy-server.jar accessible from the same
# build a "portable" version (with scrcpy-server accessible from the same
# directory as the executable)
conf.set('PORTABLE', get_option('portable'))
@ -109,12 +109,15 @@ conf.set('DEFAULT_MAX_SIZE', '0') # 0: unlimited
# overridden by option --bit-rate
conf.set('DEFAULT_BIT_RATE', '8000000') # 8Mbps
# enable High DPI support
conf.set('HIDPI_SUPPORT', get_option('hidpi_support'))
# disable console on Windows
conf.set('WINDOWS_NOCONSOLE', get_option('windows_noconsole'))
# run a server debugger and wait for a client to be attached
conf.set('SERVER_DEBUGGER', get_option('server_debugger'))
# enable a workaround for bug #15
conf.set('HIDPI_WORKAROUND', get_option('hidpi_workaround'))
configure_file(configuration: conf, output: 'config.h')
src_dir = include_directories('src')
@ -134,6 +137,8 @@ executable('scrcpy', src,
c_args: c_args,
link_args: link_args)
install_man('scrcpy.1')
### TESTS

231
app/scrcpy.1 Normal file
View File

@ -0,0 +1,231 @@
.TH "scrcpy" "1"
.SH NAME
scrcpy \- Display and control your Android device
.SH SYNOPSIS
.B scrcpy
.RI [ options ]
.SH DESCRIPTION
.B scrcpy
provides display and control of Android devices connected on USB (or over TCP/IP). It does not require any root access.
.SH OPTIONS
.TP
.BI "\-b, \-\-bit\-rate " value
Encode the video at the given bit\-rate, expressed in bits/s. Unit suffixes are supported: '\fBK\fR' (x1000) and '\fBM\fR' (x1000000).
Default is 8000000.
.TP
.BI "\-c, \-\-crop " width\fR:\fIheight\fR:\fIx\fR:\fIy
Crop the device screen on the server.
The values are expressed in the device natural orientation (typically, portrait for a phone, landscape for a tablet). Any
.B \-\-max\-size
value is computed on the cropped size.
.TP
.B \-f, \-\-fullscreen
Start in fullscreen.
.TP
.BI "\-F, \-\-record\-format " format
Force recording format (either mp4 or mkv).
.TP
.B \-h, \-\-help
Print this help.
.TP
.BI "\-m, \-\-max\-size " value
Limit both the width and height of the video to \fIvalue\fR. The other dimension is computed so that the device aspect\-ratio is preserved.
Default is 0 (unlimited).
.TP
.B \-n, \-\-no\-control
Disable device control (mirror the device in read\-only).
.TP
.B \-N, \-\-no\-display
Do not display device (only when screen recording is enabled).
.TP
.BI "\-p, \-\-port " port
Set the TCP port the client listens on.
Default is 27183.
.TP
.BI "\-\-push\-target " path
Set the target directory for pushing files to the device by drag & drop. It is passed as\-is to "adb push".
Default is "/sdcard/".
.TP
.BI "\-r, \-\-record " file
Record screen to
.IR file .
The format is determined by the
.B \-F/\-\-record\-format
option if set, or by the file extension (.mp4 or .mkv).
.TP
.B \-\-render\-expired\-frames
By default, to minimize latency, scrcpy always renders the last available decoded frame, and drops any previous ones. This flag forces to render all frames, at a cost of a possible increased latency.
.TP
.BI "\-s, \-\-serial " number
The device serial number. Mandatory only if several devices are connected to adb.
.TP
.B \-S, \-\-turn\-screen\-off
Turn the device screen off immediately.
.TP
.B \-t, \-\-show\-touches
Enable "show touches" on start, disable on quit.
It only shows physical touches (not clicks from scrcpy).
.TP
.B \-T, \-\-always\-on\-top
Make scrcpy window always on top (above other windows).
.TP
.B \-v, \-\-version
Print the version of scrcpy.
.TP
.BI \-\-window\-title " text
Set a custom window title.
.SH SHORTCUTS
.TP
.B Ctrl+f
switch fullscreen mode
.TP
.B Ctrl+g
resize window to 1:1 (pixel\-perfect)
.TP
.B Ctrl+x, Double\-click on black borders
resize window to remove black borders
.TP
.B Ctrl+h, Home, Middle\-click
Click on HOME
.TP
.B Ctrl+b, Ctrl+Backspace, Right\-click (when screen is on)
Click on BACK
.TP
.B Ctrl+s
Click on APP_SWITCH
.TP
.B Ctrl+m
Click on MENU
.TP
.B Ctrl+Up
Click on VOLUME_UP
.TP
.B Ctrl+Down
Click on VOLUME_DOWN
.TP
.B Ctrl+p
Click on POWER (turn screen on/off)
.TP
.B Right\-click (when screen is off)
turn screen on
.TP
.B Ctrl+o
turn device screen off (keep mirroring)
.TP
.B Ctrl+n
expand notification panel
.TP
.B Ctrl+Shift+n
collapse notification panel
.TP
.B Ctrl+c
copy device clipboard to computer
.TP
.B Ctrl+v
paste computer clipboard to device
.TP
.B Ctrl+Shift+v
copy computer clipboard to device
.TP
.B Ctrl+i
enable/disable FPS counter (print frames/second in logs)
.TP
.B Drag & drop APK file
install APK from computer
.SH Environment variables
.TP
.B ADB
Specify the path to adb.
.TP
.B SCRCPY_SERVER_PATH
Specify the path to server binary.
.SH AUTHORS
.B scrcpy
is written by Romain Vimont.
This manual page was written by
.MT mmyangfl@gmail.com
Yangfl
.ME
for the Debian Project (and may be used by others).
.SH "REPORTING BUGS"
Report bugs to
.UR https://github.com/Genymobile/scrcpy/issues
.UE .
.SH COPYRIGHT
Copyright \(co 2018 Genymobile
.UR https://www.genymobile.com
Genymobile
.UE
Copyright \(co 2018\-2019
.MT rom@rom1v.com
Romain Vimont
.ME
Licensed under the Apache License, Version 2.0.
.SH WWW
.UR https://github.com/Genymobile/scrcpy
.UE

View File

@ -140,10 +140,10 @@ convert_mouse_buttons(uint32_t state) {
if (state & SDL_BUTTON_MMASK) {
buttons |= AMOTION_EVENT_BUTTON_TERTIARY;
}
if (state & SDL_BUTTON_X1) {
if (state & SDL_BUTTON_X1MASK) {
buttons |= AMOTION_EVENT_BUTTON_BACK;
}
if (state & SDL_BUTTON_X2) {
if (state & SDL_BUTTON_X2MASK) {
buttons |= AMOTION_EVENT_BUTTON_FORWARD;
}
return buttons;

View File

@ -59,7 +59,7 @@ static void usage(const char *arg0) {
" -f, --fullscreen\n"
" Start in fullscreen.\n"
"\n"
" -F, --record-format\n"
" -F, --record-format format\n"
" Force recording format (either mp4 or mkv).\n"
"\n"
" -h, --help\n"

View File

@ -135,6 +135,9 @@ recorder_open(struct recorder *recorder, const AVCodec *input_codec) {
// <https://github.com/FFmpeg/FFmpeg/commit/0694d8702421e7aff1340038559c438b61bb30dd>
recorder->ctx->oformat = (AVOutputFormat *) format;
av_dict_set(&recorder->ctx->metadata, "comment",
"Recorded by scrcpy " SCRCPY_VERSION, 0);
AVStream *ostream = avformat_new_stream(recorder->ctx, input_codec);
if (!ostream) {
avformat_free_context(recorder->ctx);

View File

@ -145,9 +145,11 @@ handle_event(SDL_Event *event, bool control) {
case SDL_WINDOWEVENT:
switch (event->window.event) {
case SDL_WINDOWEVENT_EXPOSED:
case SDL_WINDOWEVENT_SIZE_CHANGED:
screen_render(&screen);
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
screen_window_resized(&screen);
break;
}
break;
case SDL_TEXTINPUT:

View File

@ -16,7 +16,7 @@
// get the window size in a struct size
static struct size
get_native_window_size(SDL_Window *window) {
get_window_size(SDL_Window *window) {
int width;
int height;
SDL_GetWindowSize(window, &width, &height);
@ -29,11 +29,11 @@ get_native_window_size(SDL_Window *window) {
// get the windowed window size
static struct size
get_window_size(const struct screen *screen) {
get_windowed_window_size(const struct screen *screen) {
if (screen->fullscreen) {
return screen->windowed_window_size;
}
return get_native_window_size(screen->window);
return get_window_size(screen->window);
}
// set the window size to be applied when fullscreen is disabled
@ -112,8 +112,8 @@ get_optimal_size(struct size current_size, struct size frame_size) {
// same as get_optimal_size(), but read the current size from the window
static inline struct size
get_optimal_window_size(const struct screen *screen, struct size frame_size) {
struct size current_size = get_window_size(screen);
return get_optimal_size(current_size, frame_size);
struct size windowed_size = get_windowed_window_size(screen);
return get_optimal_size(windowed_size, frame_size);
}
// initially, there is no current size, so use the frame size as current size
@ -134,16 +134,57 @@ create_texture(SDL_Renderer *renderer, struct size frame_size) {
frame_size.width, frame_size.height);
}
#ifdef HIDPI_WORKAROUND
static void
screen_get_sizes(struct screen *screen, struct screen_sizes *out) {
int ww, wh, dw, dh;
SDL_GetWindowSize(screen->window, &ww, &wh);
SDL_GL_GetDrawableSize(screen->window, &dw, &dh);
out->window.width = ww;
out->window.height = wh;
out->window.width = dw;
out->window.height = dh;
}
#endif
// This may be called more than once to work around SDL bugs
static bool
screen_init_renderer_and_texture(struct screen *screen) {
screen->renderer = SDL_CreateRenderer(screen->window, -1,
SDL_RENDERER_ACCELERATED);
if (!screen->renderer) {
LOGC("Could not create renderer: %s", SDL_GetError());
return false;
}
if (SDL_RenderSetLogicalSize(screen->renderer, screen->frame_size.width,
screen->frame_size.height)) {
LOGE("Could not set renderer logical size: %s", SDL_GetError());
return false;
}
screen->texture = create_texture(screen->renderer, screen->frame_size);
if (!screen->texture) {
LOGC("Could not create texture: %s", SDL_GetError());
return false;
}
#ifdef HIDPI_WORKAROUND
screen_get_sizes(screen, &screen->sizes);
#endif
return true;
}
bool
screen_init_rendering(struct screen *screen, const char *window_title,
struct size frame_size, bool always_on_top) {
screen->frame_size = frame_size;
struct size window_size = get_initial_optimal_size(frame_size);
uint32_t window_flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
#ifdef HIDPI_SUPPORT
window_flags |= SDL_WINDOW_ALLOW_HIGHDPI;
#endif
uint32_t window_flags = SDL_WINDOW_HIDDEN
| SDL_WINDOW_RESIZABLE
| SDL_WINDOW_ALLOW_HIGHDPI;
if (always_on_top) {
#ifdef SCRCPY_SDL_HAS_WINDOW_ALWAYS_ON_TOP
window_flags |= SDL_WINDOW_ALWAYS_ON_TOP;
@ -162,21 +203,6 @@ screen_init_rendering(struct screen *screen, const char *window_title,
return false;
}
screen->renderer = SDL_CreateRenderer(screen->window, -1,
SDL_RENDERER_ACCELERATED);
if (!screen->renderer) {
LOGC("Could not create renderer: %s", SDL_GetError());
screen_destroy(screen);
return false;
}
if (SDL_RenderSetLogicalSize(screen->renderer, frame_size.width,
frame_size.height)) {
LOGE("Could not set renderer logical size: %s", SDL_GetError());
screen_destroy(screen);
return false;
}
SDL_Surface *icon = read_xpm(icon_xpm);
if (icon) {
SDL_SetWindowIcon(screen->window, icon);
@ -187,9 +213,7 @@ screen_init_rendering(struct screen *screen, const char *window_title,
LOGI("Initial texture: %" PRIu16 "x%" PRIu16, frame_size.width,
frame_size.height);
screen->texture = create_texture(screen->renderer, frame_size);
if (!screen->texture) {
LOGC("Could not create texture: %s", SDL_GetError());
if (!screen_init_renderer_and_texture(screen)) {
screen_destroy(screen);
return false;
}
@ -229,11 +253,11 @@ prepare_for_frame(struct screen *screen, struct size new_frame_size) {
// frame dimension changed, destroy texture
SDL_DestroyTexture(screen->texture);
struct size current_size = get_window_size(screen);
struct size windowed_size = get_windowed_window_size(screen);
struct size target_size = {
(uint32_t) current_size.width * new_frame_size.width
(uint32_t) windowed_size.width * new_frame_size.width
/ screen->frame_size.width,
(uint32_t) current_size.height * new_frame_size.height
(uint32_t) windowed_size.height * new_frame_size.height
/ screen->frame_size.height,
};
target_size = get_optimal_size(target_size, new_frame_size);
@ -278,6 +302,43 @@ screen_update_frame(struct screen *screen, struct video_buffer *vb) {
return true;
}
#ifdef HIDPI_WORKAROUND
// workaround for <https://github.com/Genymobile/scrcpy/issues/15>
static inline bool
screen_fix_hidpi(struct screen *screen) {
struct screen_sizes cur;
screen_get_sizes(screen, &cur);
struct screen_sizes *prev = &screen->sizes;
bool width_ratio_changed = cur.window.width * prev->drawable.width !=
cur.drawable.width * prev->window.width;
bool height_ratio_changed = cur.window.height * prev->drawable.height !=
cur.drawable.height * prev->window.height;
if (width_ratio_changed || height_ratio_changed) {
SDL_DestroyTexture(screen->texture);
SDL_DestroyRenderer(screen->renderer);
if (!screen_init_renderer_and_texture(screen)) {
screen->texture = NULL;
screen->renderer = NULL;
return false;
}
LOGI("Renderer reset after hidpi scaling changed");
}
return true;
}
#endif
void
screen_window_resized(struct screen *screen) {
#ifdef HIDPI_WORKAROUND
screen_fix_hidpi(screen);
#endif
screen_render(screen);
}
void
screen_render(struct screen *screen) {
SDL_RenderClear(screen->renderer);
@ -289,7 +350,7 @@ void
screen_switch_fullscreen(struct screen *screen) {
if (!screen->fullscreen) {
// going to fullscreen, store the current windowed window size
screen->windowed_window_size = get_native_window_size(screen->window);
screen->windowed_window_size = get_window_size(screen->window);
}
uint32_t new_mode = screen->fullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP;
if (SDL_SetWindowFullscreen(screen->window, new_mode)) {

View File

@ -20,6 +20,12 @@ struct screen {
bool has_frame;
bool fullscreen;
bool no_window;
#ifdef HIDPI_WORKAROUND
struct screen_sizes {
struct size window;
struct size drawable;
} sizes;
#endif
};
#define SCREEN_INITIALIZER { \
@ -60,6 +66,10 @@ screen_destroy(struct screen *screen);
bool
screen_update_frame(struct screen *screen, struct video_buffer *vb);
// update content after window resizing
void
screen_window_resized(struct screen *screen);
// render the texture to the renderer
void
screen_render(struct screen *screen);

View File

@ -13,7 +13,7 @@
#include "net.h"
#define SOCKET_NAME "scrcpy"
#define SERVER_FILENAME "scrcpy-server.jar"
#define SERVER_FILENAME "scrcpy-server"
#define DEFAULT_SERVER_PATH PREFIX "/share/scrcpy/" SERVER_FILENAME
#define DEVICE_SERVER_PATH "/data/local/tmp/" SERVER_FILENAME
@ -32,7 +32,7 @@ get_server_path(void) {
// the absolute path is hardcoded
return DEFAULT_SERVER_PATH;
#else
// use scrcpy-server.jar in the same directory as the executable
// use scrcpy-server in the same directory as the executable
char *executable_path = get_executable_path();
if (!executable_path) {
LOGE("Could not get executable path, "
@ -124,6 +124,11 @@ execute_server(struct server *server, const struct server_params *params) {
"shell",
"CLASSPATH=/data/local/tmp/" SERVER_FILENAME,
"app_process",
#ifdef SERVER_DEBUGGER
# define SERVER_DEBUGGER_PORT "5005"
"-agentlib:jdwp=transport=dt_socket,suspend=y,server=y,address="
SERVER_DEBUGGER_PORT,
#endif
"/", // unused
"com.genymobile.scrcpy.Server",
max_size_string,
@ -133,6 +138,17 @@ execute_server(struct server *server, const struct server_params *params) {
"true", // always send frame meta (packet boundaries + timestamp)
params->control ? "true" : "false",
};
#ifdef SERVER_DEBUGGER
LOGI("Server debugger waiting for a client on device port "
SERVER_DEBUGGER_PORT "...");
// From the computer, run
// adb forward tcp:5005 tcp:5005
// Then, from Android Studio: Run > Debug > Edit configurations...
// On the left, click on '+', "Remote", with:
// Host: localhost
// Port: 5005
// Then click on "Debug"
#endif
return adb_execute(server->serial, cmd, sizeof(cmd) / sizeof(cmd[0]));
}

View File

@ -3,5 +3,6 @@ option('compile_server', type: 'boolean', value: true, description: 'Build the s
option('crossbuild_windows', type: 'boolean', value: false, description: 'Build for Windows from Linux')
option('windows_noconsole', type: 'boolean', value: false, description: 'Disable console on Windows (pass -mwindows flag)')
option('prebuilt_server', type: 'string', description: 'Path of the prebuilt server')
option('portable', type: 'boolean', value: false, description: 'Use scrcpy-server.jar from the same directory as the scrcpy executable')
option('hidpi_support', type: 'boolean', value: true, description: 'Enable High DPI support')
option('portable', type: 'boolean', value: false, description: 'Use scrcpy-server from the same directory as the scrcpy executable')
option('server_debugger', type: 'boolean', value: false, description: 'Run a server debugger and wait for a client to be attached')
option('hidpi_workaround', type: 'boolean', value: true, description: 'Enable a workaround for bug #15')

View File

@ -23,21 +23,21 @@ cd -
make -f Makefile.CrossWindows
# the generated server must be the same everywhere
cmp "$BUILDDIR/server/scrcpy-server.jar" dist/scrcpy-win32/scrcpy-server.jar
cmp "$BUILDDIR/server/scrcpy-server.jar" dist/scrcpy-win64/scrcpy-server.jar
cmp "$BUILDDIR/server/scrcpy-server" dist/scrcpy-win32/scrcpy-server
cmp "$BUILDDIR/server/scrcpy-server" dist/scrcpy-win64/scrcpy-server
# get version name
TAG=$(git describe --tags --always)
# create release directory
mkdir -p "release-$TAG"
cp "$BUILDDIR/server/scrcpy-server.jar" "release-$TAG/scrcpy-server-$TAG.jar"
cp "$BUILDDIR/server/scrcpy-server" "release-$TAG/scrcpy-server-$TAG"
cp "dist/scrcpy-win32-$TAG.zip" "release-$TAG/"
cp "dist/scrcpy-win64-$TAG.zip" "release-$TAG/"
# generate checksums
cd "release-$TAG"
sha256sum "scrcpy-server-$TAG.jar" \
sha256sum "scrcpy-server-$TAG" \
"scrcpy-win32-$TAG.zip" \
"scrcpy-win64-$TAG.zip" > SHA256SUMS.txt

2
run
View File

@ -20,4 +20,4 @@ then
exit 1
fi
SCRCPY_SERVER_PATH="$BUILDDIR/server/scrcpy-server.jar" "$BUILDDIR/app/scrcpy" "$@"
SCRCPY_SERVER_PATH="$BUILDDIR/server/scrcpy-server" "$BUILDDIR/app/scrcpy" "$@"

View File

@ -1,2 +1,2 @@
#!/bin/bash
SCRCPY_SERVER_PATH="$MESON_BUILD_ROOT/server/scrcpy-server.jar" "$MESON_BUILD_ROOT/app/scrcpy"
SCRCPY_SERVER_PATH="$MESON_BUILD_ROOT/server/scrcpy-server" "$MESON_BUILD_ROOT/app/scrcpy"

62
server/build_without_gradle.sh Executable file
View File

@ -0,0 +1,62 @@
#!/bin/bash
#
# This script generates the scrcpy binary "manually" (without gradle).
#
# Adapt Android platform and build tools versions (via ANDROID_PLATFORM and
# ANDROID_BUILD_TOOLS environment variables).
#
# Then execute:
#
# BUILD_DIR=my_build_dir ./build_without_gradle.sh
set -e
PLATFORM=${ANDROID_PLATFORM:-29}
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-29.0.2}
BUILD_DIR="$(realpath ${BUILD_DIR:-build_manual})"
CLASSES_DIR="$BUILD_DIR/classes"
SERVER_DIR=$(dirname "$0")
SERVER_BINARY=scrcpy-server
echo "Platform: android-$PLATFORM"
echo "Build-tools: $BUILD_TOOLS"
echo "Build dir: $BUILD_DIR"
rm -rf "$CLASSES_DIR" "$BUILD_DIR/$SERVER_BINARY" classes.dex
mkdir -p "$CLASSES_DIR/com/genymobile/scrcpy"
<< EOF cat > "$CLASSES_DIR/com/genymobile/scrcpy/BuildConfig.java"
package com.genymobile.scrcpy;
public final class BuildConfig {
public static final boolean DEBUG = false;
}
EOF
echo "Generating java from aidl..."
cd "$SERVER_DIR/src/main/aidl"
"$ANDROID_HOME/build-tools/$BUILD_TOOLS/aidl" -o "$CLASSES_DIR" \
android/view/IRotationWatcher.aidl
echo "Compiling java sources..."
cd ../java
javac -bootclasspath "$ANDROID_HOME/platforms/android-$PLATFORM/android.jar" \
-cp "$CLASSES_DIR" -d "$CLASSES_DIR" -source 1.8 -target 1.8 \
com/genymobile/scrcpy/*.java \
com/genymobile/scrcpy/wrappers/*.java
echo "Dexing..."
cd "$CLASSES_DIR"
"$ANDROID_HOME/build-tools/$BUILD_TOOLS/dx" --dex \
--output "$BUILD_DIR/classes.dex" \
android/view/*.class \
com/genymobile/scrcpy/*.class \
com/genymobile/scrcpy/wrappers/*.class
echo "Archiving..."
cd "$BUILD_DIR"
jar cvf "$SERVER_BINARY" classes.dex
rm -rf classes.dex classes
echo "Server generated in $BUILD_DIR/$SERVER_BINARY"

View File

@ -4,7 +4,7 @@ prebuilt_server = get_option('prebuilt_server')
if prebuilt_server == ''
custom_target('scrcpy-server',
build_always: true, # gradle is responsible for tracking source changes
output: 'scrcpy-server.jar',
output: 'scrcpy-server',
command: [find_program('./scripts/build-wrapper.sh'), meson.current_source_dir(), '@OUTPUT@', get_option('buildtype')],
console: true,
install: true,
@ -16,7 +16,7 @@ else
endif
custom_target('scrcpy-server-prebuilt',
input: prebuilt_server,
output: 'scrcpy-server.jar',
output: 'scrcpy-server',
command: ['cp', '@INPUT@', '@OUTPUT@'],
install: true,
install_dir: 'share/scrcpy')

View File

@ -82,7 +82,7 @@ public class Controller {
injectText(msg.getText());
break;
case ControlMessage.TYPE_INJECT_TOUCH_EVENT:
injectTouch(msg.getAction(), msg.getPointerId(), msg.getPosition(), msg.getPressure(), 0);
injectTouch(msg.getAction(), msg.getPointerId(), msg.getPosition(), msg.getPressure(), msg.getButtons());
break;
case ControlMessage.TYPE_INJECT_SCROLL_EVENT:
injectScroll(msg.getPosition(), msg.getHScroll(), msg.getVScroll());
@ -177,7 +177,7 @@ public class Controller {
}
MotionEvent event = MotionEvent.obtain(lastTouchDown, now, action, pointerCount, pointerProperties,
pointerCoords, 0, 0, 1f, 1f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
pointerCoords, 0, buttons, 1f, 1f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
return injectEvent(event);
}

View File

@ -7,7 +7,7 @@ import java.io.IOException;
public final class Server {
private static final String SERVER_PATH = "/data/local/tmp/scrcpy-server.jar";
private static final String SERVER_PATH = "/data/local/tmp/scrcpy-server";
private Server() {
// not instantiable