The serial is needed for many server actions, but this is an
implementation detail, so the caller should not have to provide it on
every call.
Instead, store the serial in the server instance on server_start().
This paves the way to implement the "adb forward" fallback properly.
The text input control_event was initially designed for mapping
SDL_TextInputEvent, limited to 32 characters.
For simplicity, the copy/paste feature was implemented using the same
control_event: it just sends the text to paste.
However, the pasted text might have a length breaking some assumptions:
- on the client, the event max-size was smaller than the text
max-length,
- on the server, the raw buffer storing the events was smaller than the
max event size.
Fix these inconsistencies, and encode the length on 2 bytes, to accept
more than 256 characters.
Fixes <https://github.com/Genymobile/scrcpy/issues/10>.
Paste computer clipboard to the device on Ctrl+v.
The other direction (pasting the device clipboard to the computer) is
not implemented. It would require a communication channel from the
device to the computer, other than the socket used by the video stream.
The High DPI support is enabled by default, so that the renderer use the
full definition of High DPI screens.
However, there are still mouse coordinates problems on some MacOS having
High DPI support (but not all), so expose a way to disable it.
The decoder sometimes returned a non-zero value on error, but not on
every path.
Since we never use the value, always return 0 at the end (like in the
controller).
SDL_MouseWheelEvent does not provide the mouse location, so we used
SDL_GetMouseState() to retrieve it.
Unfortunately, SDL_GetMouseState() returns a position expressed in the
window coordinate system while the position filled in SDL events are
expressed in the renderer coordinate system. As a consequence, the
scroll was not applied at the right position on the device.
Therefore, convert the coordinate system.
See <https://stackoverflow.com/questions/49111054/how-to-get-mouse-position-on-mouse-wheel-event>.
Use high DPI if available.
Note that on Mac OS X, setting this flag is not sufficient:
> On Apple's OS X you must set the NSHighResolutionCapable Info.plist
> property to YES, otherwise you will not receive a High DPI OpenGL
> display.
<https://wiki.libsdl.org/SDL_CreateWindow#flags>
On user request to quit, two kinds of blocking calls must be interrupted
on the server:
1. the reads from and writes to the socket;
2. the call to MediaCodec.dequeueOutputBuffer().
The former case was handled by calling shutdown() on the socket from the
client, but the latter was not managed.
There is no easy way to wake this call properly, so just terminate the
process from the client (i.e. send SIGTERM on Linux) instead.
The server is copied to /data/local/tmp/scrcpy-server.jar and executed
on the device.
As soon as we are connected, we can unlink (rm) it from /data/local/tmp,
to keep the device clean.
The server is currently a JAR, but it may ba an APK or a DEX, so the
variable name should not contain the type.
Rename the environment variable, the Meson options and the C
definitions.
Expose net_recv_all() and net_send_all(), equivalent of net_recv() and
net_send(), but that waits/retries until the requested length has been
transferred.
Use these new functions where it was (wrongly) assumed that the
requested length had been transferred.
SDL_net is not very suitable for scrcpy.
For example, SDLNet_TCP_Accept() is non-blocking, so we have to wrap it
by calling many SDL_Net-specific functions to make it blocking.
But above all, SDLNet_TCP_Open() is a server socket only when no IP is
provided; otherwise, it's a client socket. Therefore, it is not possible
to create a server socket bound to localhost, so it accepts connections
from anywhere.
This is a problem for scrcpy, because on start, the application listens
for nearly 1 second until it accepts the first connection, supposedly
from the device. If someone on the local network manages to connect to
the server socket first, then they can stream arbitrary H.264 video.
This may be troublesome, for example during a public presentation ;-)
Provide our own simplified API (net.h) instead, implemented for the
different platforms.
The syntax was correct, but less readable, and it unnecessarily zeroed
the fields other than "type".
Create the event properly, from a separate method.
screen_render() should not be called on initialization:
1. it is useless, since the window is hidden until the first frame;
2. it writes an empty texture (probably green) to the renderer.
The "screen control" handled user input, which happened to be only
used to control the screen.
The controller and screen were passed to every function. Instead, group
them in a struct input_manager.
The purpose is to add a new shortcut to enable/disable FPS counter. This
feature is not related to "screen control", and will require access to
the "frames" instance.
The device serial was provided as a positional argument:
scrcpy 0123456789abcdef
Instead, expose it as an optional argument, -s or --serial:
scrcpy -s 0123456789abcdef
This avoids inconsistency between platforms when the positional
argument is passed before the options (which is undefined).
Since Meson 0.44, subproject_dir may not be '.' anymore. This implies we
must move app/ and server/ to a subprojects/ directory, which requires
to also change some gradle files.
Instead, just use subdir(), with options to disable building of the app
or the server.
The client was built with Meson, the server with Gradle, and were run by
a Makefile.
Add a Meson script for the server (which delegates to Gradle), and a
parent script to build and install both the client and the server to the
system, typically with:
meson --buildtype release build
cd build
ninja
sudo ninja install
In addition, use a separate Makefile to build a "portable" version of
the application (where the client expects the server to be in the
current directory). Typically:
make release-portable
cd dist/scrcpy
./scrcpy
This is especially useful for Windows builds, which are not "installed".