Compare commits

..

15 Commits

Author SHA1 Message Date
Romain Vimont
9d10426207 Mention in README that Ctrl is forwarded 2020-07-17 17:24:00 +02:00
Romain Vimont
0a98b4d4a6 Update copy-paste section in README
Update documentation regarding the recent copy-paste changes.
2020-07-17 17:24:00 +02:00
Romain Vimont
ae2b26fc47 Swap paste shortcuts
For consistency with MOD+c and MOD+x, use MOD+v to inject PASTE.

Use Mod+Shift+v to inject clipboard content as a sequence of text
events.
2020-07-17 17:24:00 +02:00
Romain Vimont
405f5f2704 Add shortcuts for COPY and CUT
Send COPY and CUT on MOD+c and MOD+x (only supported for Android >= 7).

The shortcuts Ctrl+c and Ctrl+x should generally also work (even before
Android 7), but the active Android app may use them for other actions
instead.
2020-07-17 17:24:00 +02:00
Romain Vimont
9ce0a475bf Change "resize to fit" shortcut to MOD+w
For convenience, MOD+x will be used for injecting the CUT keycode.
2020-07-17 17:24:00 +02:00
Romain Vimont
0987cd324e Remove "get clipboard" call
Now that every device clipboard change is automatically synchronized to
the computer, the "get clipboard" request (bound to MOD+c) is useless.
2020-07-17 17:24:00 +02:00
Romain Vimont
ecbbf5ff1c Set computer clipboard only if necessary
Do not explicitly set the clipboard text if it already contains the
expected content.

Even if copy-paste loops are avoided by the previous commit, this avoids
to trigger a clipboard change on the computer-side.

Refs #1580 <https://github.com/Genymobile/scrcpy/issues/1580>
2020-07-17 17:24:00 +02:00
Romain Vimont
25b80a85f1 Set device clipboard only if necessary
Do not explicitly set the clipboard text if it already contains the
expected content. This avoids possible copy-paste loops between the
computer and the device.
2020-07-17 17:24:00 +02:00
Romain Vimont
98d63fb24a Synchronize clipboard on Ctrl+v
Pressing Ctrl+v on the device will typically paste the clipboard
content.

Before sending the key event, synchronize the computer clipboard to the
device clipboard to allow seamless copy-paste.
2020-07-17 17:24:00 +02:00
Romain Vimont
59d30cb094 Forward Shift to the device
This allows to select text using Shift+(arrow keys).

Fixes #942 <https://github.com/Genymobile/scrcpy/issues/942>
2020-07-17 17:24:00 +02:00
Romain Vimont
ff0711fbff Forward Ctrl to the device
Now that the scrcpy shortcut modifier is Alt by default (and can be
configured), forward Ctrl to the device.

This allows to trigger Android shortcuts.

Fixes #555 <https://github.com/Genymobile/scrcpy/issues/555>
2020-07-17 17:24:00 +02:00
Romain Vimont
7bfff9704e Ignore text events for shortcuts
Pressing Alt+c generates a text event containing "c", so "c" was sent to
the device when --prefer-text was enabled.

Ignore text events when the mod state matches a shortcut modifier.
2020-07-17 17:24:00 +02:00
Romain Vimont
060d91e4ce Accept Cmd as shortcut modifier
In addition to (left) Alt, also accept (left) Cmd. This is especially
convenient for macOS users.
2020-07-17 17:23:59 +02:00
Romain Vimont
a90b08ceb3 Customize shortcut modifier
Add --shortcut-mod, and use Alt as default modifier.

This paves a way to forward the Ctrl key to the device.
2020-07-17 17:23:00 +02:00
Romain Vimont
cfa2844121 Use Ctrl for all shortcuts
Remove the Cmd modifier on macOS, which was possible only for some
shortcuts but not all.

This paves the way to make the shortcut modifier customizable.
2020-07-17 00:00:42 +02:00
17 changed files with 159 additions and 243 deletions

View File

@@ -176,8 +176,8 @@ Additionally, if you want to build the server, install Java 8 from Caskroom, and
make it avaliable from the `PATH`:
```bash
brew tap homebrew/cask-versions
brew cask install adoptopenjdk/openjdk/adoptopenjdk8
brew tap caskroom/versions
brew cask install java8
export JAVA_HOME="$(/usr/libexec/java_home --version 1.8)"
export PATH="$JAVA_HOME/bin:$PATH"
```
@@ -190,17 +190,12 @@ See [pierlon/scrcpy-docker](https://github.com/pierlon/scrcpy-docker).
## Common steps
If you want to build the server, install the [Android SDK] (_Android Studio_),
and set `ANDROID_SDK_ROOT` to its directory. For example:
and set `ANDROID_HOME` to its directory. For example:
[Android SDK]: https://developer.android.com/studio/index.html
```bash
# Linux
export ANDROID_SDK_ROOT=~/Android/Sdk
# Mac
export ANDROID_SDK_ROOT=~/Library/Android/sdk
# Windows
set ANDROID_SDK_ROOT=%LOCALAPPDATA%\Android\sdk
export ANDROID_HOME=~/android/sdk
```
If you don't want to build the server, use the [prebuilt server].
@@ -254,10 +249,10 @@ You can then [run](README.md#run) _scrcpy_.
## Prebuilt server
- [`scrcpy-server-v1.15`][direct-scrcpy-server]
_(SHA-256: e160c46784f30566eae621cad88bfb34e124f945cb8274b8dfc615b613b86dd8)_
- [`scrcpy-server-v1.14`][direct-scrcpy-server]
_(SHA-256: 1d1b18a2b80e956771fd63b99b414d2d028713a8f12ddfa5a369709ad4295620)_
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v1.15/scrcpy-server-v1.15
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v1.14/scrcpy-server-v1.14
Download the prebuilt server somewhere, and specify its path during the Meson
configuration:

View File

@@ -100,11 +100,11 @@ dist-win32: build-server build-win32 build-win32-noconsole
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.3.1-win32-shared/bin/avutil-56.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win32-shared/bin/avcodec-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win32-shared/bin/avformat-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win32-shared/bin/swresample-3.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win32-shared/bin/swscale-5.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.2.2-win32-shared/bin/avutil-56.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.2.2-win32-shared/bin/avcodec-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.2.2-win32-shared/bin/avformat-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.2.2-win32-shared/bin/swresample-3.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.2.2-win32-shared/bin/swscale-5.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/adb.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
@@ -115,11 +115,11 @@ dist-win64: build-server build-win64 build-win64-noconsole
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.3.1-win64-shared/bin/avutil-56.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win64-shared/bin/avcodec-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win64-shared/bin/avformat-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win64-shared/bin/swresample-3.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win64-shared/bin/swscale-5.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.2.2-win64-shared/bin/avutil-56.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.2.2-win64-shared/bin/avcodec-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.2.2-win64-shared/bin/avformat-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.2.2-win64-shared/bin/swresample-3.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.2.2-win64-shared/bin/swscale-5.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/adb.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"

166
README.md
View File

@@ -1,4 +1,4 @@
# scrcpy (v1.15)
# scrcpy (v1.14)
This application provides display and control of Android devices connected on
USB (or [over TCP/IP][article-tcpip]). It does not require any _root_ access.
@@ -49,11 +49,6 @@ A [Snap] package is available: [`scrcpy`][snap-link].
[snap]: https://en.wikipedia.org/wiki/Snappy_(package_manager)
For Fedora, a [COPR] package is available: [`scrcpy`][copr-link].
[COPR]: https://fedoraproject.org/wiki/Category:Copr
[copr-link]: https://copr.fedorainfracloud.org/coprs/zeno/scrcpy/
For Arch Linux, an [AUR] package is available: [`scrcpy`][aur-link].
[AUR]: https://wiki.archlinux.org/index.php/Arch_User_Repository
@@ -74,10 +69,10 @@ hard).
For Windows, for simplicity, a prebuilt archive with all the dependencies
(including `adb`) is available:
- [`scrcpy-win64-v1.15.zip`][direct-win64]
_(SHA-256: dd514bb591e63ef4cd52a53c30f1153a28f59722d64690eb07bd017849edcba2)_
- [`scrcpy-win64-v1.14.zip`][direct-win64]
_(SHA-256: 2be9139e46e29cf2f5f695848bb2b75a543b8f38be1133257dc5068252abc25f)_
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v1.15/scrcpy-win64-v1.15.zip
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v1.14/scrcpy-win64-v1.14.zip
It is also available in [Chocolatey]:
@@ -306,7 +301,7 @@ ssh -CN -L5037:localhost:5037 -L27183:localhost:27183 your_remote_computer
From another terminal:
```bash
scrcpy --force-adb-forward
scrcpy --force-adb-forwrad
```
@@ -359,7 +354,7 @@ scrcpy --fullscreen
scrcpy -f # short version
```
Fullscreen can then be toggled dynamically with <kbd>MOD</kbd>+<kbd>f</kbd>.
Fullscreen can then be toggled dynamically with `MOD`+`f`.
#### Rotation
@@ -375,19 +370,18 @@ Possibles values are:
- `2`: 180 degrees
- `3`: 90 degrees clockwise
The rotation can also be changed dynamically with <kbd>MOD</kbd>+<kbd></kbd>
_(left)_ and <kbd>MOD</kbd>+<kbd></kbd> _(right)_.
The rotation can also be changed dynamically with `MOD`+`←` _(left)_ and
`MOD`+`→` _(right)_.
Note that _scrcpy_ manages 3 different rotations:
- <kbd>MOD</kbd>+<kbd>r</kbd> requests the device to switch between portrait and
landscape (the current running app may refuse, if it does support the
requested orientation).
- `MOD`+`r` requests the device to switch between portrait and landscape (the
current running app may refuse, if it does support the requested
orientation).
- `--lock-video-orientation` changes the mirroring orientation (the orientation
of the video sent from the device to the computer). This affects the
recording.
- `--rotation` (or <kbd>MOD</kbd>+<kbd></kbd>/<kbd>MOD</kbd>+<kbd></kbd>)
rotates only the window content. This affects only the display, not the
recording.
- `--rotation` (or `MOD`+`←`/`MOD`+`→`) rotates only the window content. This
affects only the display, not the recording.
### Other mirroring options
@@ -443,16 +437,11 @@ scrcpy --turn-screen-off
scrcpy -S
```
Or by pressing <kbd>MOD</kbd>+<kbd>o</kbd> at any time.
Or by pressing `MOD`+`o` at any time.
To turn it back on, press <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>o</kbd>.
To turn it back on, press `MOD`+`Shift`+`o` (or `POWER`, `MOD`+`p`).
On Android, the `POWER` button always turns the screen on. For convenience, if
`POWER` is sent via scrcpy (via right-click or <kbd>Ctrl</kbd>+<kbd>p</kbd>), it
will force to turn the screen off after a small delay (on a best effort basis).
The physical `POWER` button will still cause the screen to be turned on.
It can also be useful to prevent the device from sleeping:
It can be useful to also prevent the device to sleep:
```bash
scrcpy --turn-screen-off --stay-awake
@@ -505,8 +494,7 @@ scrcpy --disable-screensaver
#### Rotate device screen
Press <kbd>MOD</kbd>+<kbd>r</kbd> to switch between portrait and landscape
modes.
Press `MOD`+`r` to switch between portrait and landscape modes.
Note that it rotates only if the application in foreground supports the
requested orientation.
@@ -516,34 +504,32 @@ requested orientation.
Any time the Android clipboard changes, it is automatically synchronized to the
computer clipboard.
Any <kbd>Ctrl</kbd> shortcut is forwarded to the device. In particular:
- <kbd>Ctrl</kbd>+<kbd>c</kbd> typically copies
- <kbd>Ctrl</kbd>+<kbd>x</kbd> typically cuts
- <kbd>Ctrl</kbd>+<kbd>v</kbd> typically pastes (after computer-to-device
clipboard synchronization)
Any `Ctrl` shortcut is forwarded to the device. In particular:
- `Ctrl`+`c` typically copies
- `Ctrl`+`x` typically cuts
- `Ctrl`+`v` typically pastes (after computer-to-device clipboard
synchronization)
This typically works as you expect.
The actual behavior depends on the active application though. For example,
_Termux_ sends SIGINT on <kbd>Ctrl</kbd>+<kbd>c</kbd> instead, and _K-9 Mail_
composes a new message.
_Termux_ sends SIGINT on `Ctrl`+`c` instead, and _K-9 Mail_ composes a new
message.
To copy, cut and paste in such cases (but only supported on Android >= 7):
- <kbd>MOD</kbd>+<kbd>c</kbd> injects `COPY`
- <kbd>MOD</kbd>+<kbd>x</kbd> injects `CUT`
- <kbd>MOD</kbd>+<kbd>v</kbd> injects `PASTE` (after computer-to-device
clipboard synchronization)
To copy, cut and paste in all cases (but only supported on Android >= 7):
- `MOD`+`c` injects `COPY`
- `MOD`+`x` injects `CUT`
- `MOD`+`v` injects `PASTE` (after computer-to-device clipboard
synchronization)
In addition, <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>v</kbd> allows to inject the
computer clipboard text as a sequence of key events. This is useful when the
component does not accept text pasting (for example in _Termux_), but it can
break non-ASCII content.
In addition, `MOD`+`Shift`+`v` allows to inject the computer clipboard text as a
sequence of key events. This is useful when the component does not accept text
pasting (for example in _Termux_), but it can break non-ASCII content.
**WARNING:** Pasting the computer clipboard to the device (either via
<kbd>Ctrl</kbd>+<kbd>v</kbd> or <kbd>MOD</kbd>+<kbd>v</kbd>) copies the content
into the device clipboard. As a consequence, any Android application could read
its content. You should avoid to paste sensitive content (like passwords) that
way.
*WARNING:* Pasting the computer clipboard to the device (either via `Ctrl`+`v`
or `MOD`+`v`) copies the content in the device clipboard. As a consequence, any
Android application could read its content. You should avoid to paste sensitive
content (like passwords) that way.
#### Text injection preference
@@ -567,18 +553,6 @@ scrcpy --prefer-text
[prefertext]: https://github.com/Genymobile/scrcpy/issues/650#issuecomment-512945343
#### Key repeat
By default, holding a key down generates repeated key events. This can cause
performance problems in some games, where these events are useless anyway.
To avoid forwarding repeated key events:
```bash
scrcpy --no-key-repeat
```
### File drop
#### Install APK
@@ -605,66 +579,62 @@ scrcpy --push-target /sdcard/foo/bar/
### Audio forwarding
Audio is not forwarded by _scrcpy_. Use [sndcpy].
Audio is not forwarded by _scrcpy_. Use [USBaudio] (Linux-only).
Also see [issue #14].
[sndcpy]: https://github.com/rom1v/sndcpy
[USBaudio]: https://github.com/rom1v/usbaudio
[issue #14]: https://github.com/Genymobile/scrcpy/issues/14
## Shortcuts
In the following list, <kbd>MOD</kbd> is the shortcut modifier. By default, it's
(left) <kbd>Alt</kbd> or (left) <kbd>Super</kbd>.
In the following list, `MOD` is the shortcut modifier. By default, it's (left)
`Alt` or (left) `Cmd`.
It can be changed using `--shortcut-mod`. Possible keys are `lctrl`, `rctrl`,
`lalt`, `ralt`, `lsuper` and `rsuper`. For example:
`lalt`, `ralt`, `lcmd` and `rcmd`. For example:
```bash
# use RCtrl for shortcuts
scrcpy --shortcut-mod=rctrl
# use either LCtrl+LAlt or LSuper for shortcuts
scrcpy --shortcut-mod=lctrl+lalt,lsuper
# use either LCtrl+LAlt or LCmd for shortcuts
scrcpy --shortcut-mod=lctrl+lalt,lcmd
```
_<kbd>[Super]</kbd> is typically the <kbd>Windows</kbd> or <kbd>Cmd</kbd> key._
[Super]: https://en.wikipedia.org/wiki/Super_key_(keyboard_button)
| Action | Shortcut
| ------------------------------------------- |:-----------------------------
| Switch fullscreen mode | <kbd>MOD</kbd>+<kbd>f</kbd>
| Rotate display left | <kbd>MOD</kbd>+<kbd></kbd> _(left)_
| Rotate display right | <kbd>MOD</kbd>+<kbd></kbd> _(right)_
| Resize window to 1:1 (pixel-perfect) | <kbd>MOD</kbd>+<kbd>g</kbd>
| Resize window to remove black borders | <kbd>MOD</kbd>+<kbd>w</kbd> \| _Double-click¹_
| Click on `HOME` | <kbd>MOD</kbd>+<kbd>h</kbd> \| _Middle-click_
| Click on `BACK` | <kbd>MOD</kbd>+<kbd>b</kbd> \| _Right-click²_
| Click on `APP_SWITCH` | <kbd>MOD</kbd>+<kbd>s</kbd>
| Click on `MENU` (unlock screen) | <kbd>MOD</kbd>+<kbd>m</kbd>
| Click on `VOLUME_UP` | <kbd>MOD</kbd>+<kbd></kbd> _(up)_
| Click on `VOLUME_DOWN` | <kbd>MOD</kbd>+<kbd></kbd> _(down)_
| Click on `POWER` | <kbd>MOD</kbd>+<kbd>p</kbd>
| Switch fullscreen mode | `MOD`+`f`
| Rotate display left | `MOD`+`←` _(left)_
| Rotate display right | `MOD`+`→` _(right)_
| Resize window to 1:1 (pixel-perfect) | `MOD`+`g`
| Resize window to remove black borders | `MOD`+`w` \| _Double-click¹_
| Click on `HOME` | `MOD`+`h` \| _Middle-click_
| Click on `BACK` | `MOD`+`b` \| _Right-click²_
| Click on `APP_SWITCH` | `MOD`+`s`
| Click on `MENU` | `MOD`+`m`
| Click on `VOLUME_UP` | `MOD`+`↑` _(up)_
| Click on `VOLUME_DOWN` | `MOD`+`↓` _(down)_
| Click on `POWER` | `MOD`+`p`
| Power on | _Right-click²_
| Turn device screen off (keep mirroring) | <kbd>MOD</kbd>+<kbd>o</kbd>
| Turn device screen on | <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>o</kbd>
| Rotate device screen | <kbd>MOD</kbd>+<kbd>r</kbd>
| Expand notification panel | <kbd>MOD</kbd>+<kbd>n</kbd>
| Collapse notification panel | <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>n</kbd>
| Copy to clipboard³ | <kbd>MOD</kbd>+<kbd>c</kbd>
| Cut to clipboard³ | <kbd>MOD</kbd>+<kbd>x</kbd>
| Synchronize clipboards and paste³ | <kbd>MOD</kbd>+<kbd>v</kbd>
| Inject computer clipboard text | <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>v</kbd>
| Enable/disable FPS counter (on stdout) | <kbd>MOD</kbd>+<kbd>i</kbd>
| Turn device screen off (keep mirroring) | `MOD`+`o`
| Turn device screen on | `MOD`+`Shift`+`o`
| Rotate device screen | `MOD`+`r`
| Expand notification panel | `MOD`+`n`
| Collapse notification panel | `MOD`+`Shift`+`n`
| Copy to clipboard³ | `MOD`+`c`
| Cut to clipboard³ | `MOD`+`x`
| Synchronize clipboards and paste³ | `MOD`+`v`
| Inject computer clipboard text | `MOD`+`Shift`+`v`
| Enable/disable FPS counter (on stdout) | `MOD`+`i`
_¹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._
_³Only on Android >= 7._
All <kbd>Ctrl</kbd>+_key_ shortcuts are forwarded to the device, so they are
handled by the active application.
All `Ctrl`+_key_ shortcuts are forwarded to the device, so they are handled by
the active application.
## Custom paths

View File

@@ -96,10 +96,6 @@ Do not display device (only when screen recording is enabled).
.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\-key\-repeat
Do not forward repeated key events when a key is held down.
.TP
.BI "\-p, \-\-port " port[:port]
Set the TCP port (range) used by the client to listen.
@@ -155,13 +151,13 @@ The device serial number. Mandatory only if several devices are connected to adb
.TP
.BI "\-\-shortcut\-mod " key[+...]][,...]
Specify the modifiers to use for scrcpy shortcuts. Possible keys are "lctrl", "rctrl", "lalt", "ralt", "lsuper" and "rsuper".
Specify the modifiers to use for scrcpy shortcuts. Possible keys are "lctrl", "rctrl", "lalt", "ralt", "lcmd" and "rcmd".
A shortcut can consist in several keys, separated by '+'. Several shortcuts can be specified, separated by ','.
For example, to use either LCtrl+LAlt or LSuper for scrcpy shortcuts, pass "lctrl+lalt,lsuper".
For example, to use either LCtrl+LAlt or LCmd for scrcpy shortcuts, pass "lctrl+lalt,lcmd".
Default is "lalt,lsuper" (left-Alt or left-Super).
Default is "lalt,lcmd" (left-Alt or left-Cmd).
.TP
.B \-S, \-\-turn\-screen\-off
@@ -222,7 +218,7 @@ Default is 0 (automatic).\n
.SH SHORTCUTS
In the following list, MOD is the shortcut modifier. By default, it's (left)
Alt or (left) Super, but it can be configured by \-\-shortcut-mod.
Alt or (left) Cmd, but it can be configured by \-\-shortcut-mod.
.TP
.B MOD+f

View File

@@ -92,9 +92,6 @@ scrcpy_print_usage(const char *arg0) {
" mipmaps are automatically generated to improve downscaling\n"
" quality. This option disables the generation of mipmaps.\n"
"\n"
" --no-key-repeat\n"
" Do not forward repeated key events when a key is held down.\n"
"\n"
" -p, --port port[:port]\n"
" Set the TCP port (range) used by the client to listen.\n"
" Default is %d:%d.\n"
@@ -142,17 +139,17 @@ scrcpy_print_usage(const char *arg0) {
" are connected to adb.\n"
"\n"
" --shortcut-mod key[+...]][,...]\n"
" Specify the modifiers to use for scrcpy shortcuts.\n"
" Possible keys are \"lctrl\", \"rctrl\", \"lalt\", \"ralt\",\n"
" \"lsuper\" and \"rsuper\".\n"
" Specify the modifiers to use for scrcpy shortcuts. Possible\n"
" keys are \"lctrl\", \"rctrl\", \"lalt\", \"ralt\", \"lcmd\"\n"
" and \"rcmd\".\n"
"\n"
" A shortcut can consist in several keys, separated by '+'.\n"
" Several shortcuts can be specified, separated by ','.\n"
"\n"
" For example, to use either LCtrl+LAlt or LSuper for scrcpy\n"
" shortcuts, pass \"lctrl+lalt,lsuper\".\n"
" For example, to use either LCtrl+LAlt or LCmd for scrcpy\n"
" shortcuts, pass \"lctrl+lalt,lcmd\".\n"
"\n"
" Default is \"lalt,lsuper\" (left-Alt or left-Super).\n"
" Default is \"lalt,lcmd\" (left-Alt or left-Cmd).\n"
"\n"
" -S, --turn-screen-off\n"
" Turn the device screen off immediately.\n"
@@ -202,7 +199,7 @@ scrcpy_print_usage(const char *arg0) {
"Shortcuts:\n"
"\n"
" In the following list, MOD is the shortcut modifier. By default,\n"
" it's (left) Alt or (left) Super, but it can be configured by\n"
" it's (left) Alt or (left) Cmd, but it can be configured by\n"
" --shortcut-mod.\n"
"\n"
" MOD+f\n"
@@ -524,10 +521,10 @@ parse_shortcut_mods_item(const char *item, size_t len) {
mod |= SC_MOD_LALT;
} else if (STREQ("ralt", item, key_len)) {
mod |= SC_MOD_RALT;
} else if (STREQ("lsuper", item, key_len)) {
mod |= SC_MOD_LSUPER;
} else if (STREQ("rsuper", item, key_len)) {
mod |= SC_MOD_RSUPER;
} else if (STREQ("lcmd", item, key_len)) {
mod |= SC_MOD_LCMD;
} else if (STREQ("rcmd", item, key_len)) {
mod |= SC_MOD_RCMD;
} else {
LOGW("Unknown modifier key: %.*s", (int) key_len, item);
return 0;
@@ -551,7 +548,7 @@ parse_shortcut_mods(const char *s, struct sc_shortcut_mods *mods) {
unsigned count = 0;
unsigned current = 0;
// LCtrl+LAlt or RCtrl or LCtrl+RSuper: "lctrl+lalt,rctrl,lctrl+rsuper"
// LCtrl+LAlt or RCtrl or LCtrl+RCmd: "lctrl+lalt,rctrl,lctrl+rcmd"
for (;;) {
char *comma = strchr(s, ',');
@@ -645,7 +642,6 @@ guess_record_format(const char *filename) {
#define OPT_FORCE_ADB_FORWARD 1019
#define OPT_DISABLE_SCREENSAVER 1020
#define OPT_SHORTCUT_MOD 1021
#define OPT_NO_KEY_REPEAT 1022
bool
scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
@@ -668,7 +664,6 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
{"no-control", no_argument, NULL, 'n'},
{"no-display", no_argument, NULL, 'N'},
{"no-mipmaps", no_argument, NULL, OPT_NO_MIPMAPS},
{"no-key-repeat", no_argument, NULL, OPT_NO_KEY_REPEAT},
{"port", required_argument, NULL, 'p'},
{"prefer-text", no_argument, NULL, OPT_PREFER_TEXT},
{"push-target", required_argument, NULL, OPT_PUSH_TARGET},
@@ -834,9 +829,6 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
case OPT_NO_MIPMAPS:
opts->mipmaps = false;
break;
case OPT_NO_KEY_REPEAT:
opts->forward_key_repeat = false;
break;
case OPT_CODEC_OPTIONS:
opts->codec_options = optarg;
break;

View File

@@ -28,10 +28,10 @@ to_sdl_mod(unsigned mod) {
if (mod & SC_MOD_RALT) {
sdl_mod |= KMOD_RALT;
}
if (mod & SC_MOD_LSUPER) {
if (mod & SC_MOD_LCMD) {
sdl_mod |= KMOD_LGUI;
}
if (mod & SC_MOD_RSUPER) {
if (mod & SC_MOD_RCMD) {
sdl_mod |= KMOD_RGUI;
}
return sdl_mod;
@@ -54,14 +54,11 @@ is_shortcut_mod(struct input_manager *im, uint16_t sdl_mod) {
}
void
input_manager_init(struct input_manager *im,
const struct scrcpy_options *options)
input_manager_init(struct input_manager *im, bool prefer_text,
const struct sc_shortcut_mods *shortcut_mods)
{
im->control = options->control;
im->forward_key_repeat = options->forward_key_repeat;
im->prefer_text = options->prefer_text;
im->prefer_text = prefer_text;
const struct sc_shortcut_mods *shortcut_mods = &options->shortcut_mods;
assert(shortcut_mods->count);
assert(shortcut_mods->count < SC_MAX_SHORTCUT_MODS);
for (unsigned i = 0; i < shortcut_mods->count; ++i) {
@@ -80,7 +77,6 @@ send_keycode(struct controller *controller, enum android_keycode keycode,
msg.type = CONTROL_MSG_TYPE_INJECT_KEYCODE;
msg.inject_keycode.keycode = keycode;
msg.inject_keycode.metastate = 0;
msg.inject_keycode.repeat = 0;
if (actions & ACTION_DOWN) {
msg.inject_keycode.action = AKEY_EVENT_ACTION_DOWN;
@@ -322,9 +318,9 @@ convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to,
void
input_manager_process_key(struct input_manager *im,
const SDL_KeyboardEvent *event) {
const SDL_KeyboardEvent *event,
bool control) {
// control: indicates the state of the command-line option --no-control
bool control = im->control;
bool smod = is_shortcut_mod(im, event->keysym.mod);
@@ -463,9 +459,6 @@ input_manager_process_key(struct input_manager *im,
}
if (event->repeat) {
if (!im->forward_key_repeat) {
return;
}
++im->repeat;
} else {
im->repeat = 0;
@@ -580,9 +573,8 @@ convert_mouse_button(const SDL_MouseButtonEvent *from, struct screen *screen,
void
input_manager_process_mouse_button(struct input_manager *im,
const SDL_MouseButtonEvent *event) {
bool control = im->control;
const SDL_MouseButtonEvent *event,
bool control) {
if (event->which == SDL_TOUCH_MOUSEID) {
// simulated from touch events, so it's a duplicate
return;

View File

@@ -22,8 +22,6 @@ struct input_manager {
// number of repetitions. This variable keeps track of the count.
unsigned repeat;
bool control;
bool forward_key_repeat;
bool prefer_text;
struct {
@@ -33,8 +31,8 @@ struct input_manager {
};
void
input_manager_init(struct input_manager *im,
const struct scrcpy_options *options);
input_manager_init(struct input_manager *im, bool prefer_text,
const struct sc_shortcut_mods *shortcut_mods);
void
input_manager_process_text_input(struct input_manager *im,
@@ -42,7 +40,8 @@ input_manager_process_text_input(struct input_manager *im,
void
input_manager_process_key(struct input_manager *im,
const SDL_KeyboardEvent *event);
const SDL_KeyboardEvent *event,
bool control);
void
input_manager_process_mouse_motion(struct input_manager *im,
@@ -54,7 +53,8 @@ input_manager_process_touch(struct input_manager *im,
void
input_manager_process_mouse_button(struct input_manager *im,
const SDL_MouseButtonEvent *event);
const SDL_MouseButtonEvent *event,
bool control);
void
input_manager_process_mouse_wheel(struct input_manager *im,

View File

@@ -170,7 +170,7 @@ enum event_result {
};
static enum event_result
handle_event(SDL_Event *event, const struct scrcpy_options *options) {
handle_event(SDL_Event *event, bool control) {
switch (event->type) {
case EVENT_STREAM_STOPPED:
LOGD("Video stream stopped");
@@ -192,7 +192,7 @@ handle_event(SDL_Event *event, const struct scrcpy_options *options) {
screen_handle_window_event(&screen, &event->window);
break;
case SDL_TEXTINPUT:
if (!options->control) {
if (!control) {
break;
}
input_manager_process_text_input(&input_manager, &event->text);
@@ -201,16 +201,16 @@ handle_event(SDL_Event *event, const struct scrcpy_options *options) {
case SDL_KEYUP:
// some key events do not interact with the device, so process the
// event even if control is disabled
input_manager_process_key(&input_manager, &event->key);
input_manager_process_key(&input_manager, &event->key, control);
break;
case SDL_MOUSEMOTION:
if (!options->control) {
if (!control) {
break;
}
input_manager_process_mouse_motion(&input_manager, &event->motion);
break;
case SDL_MOUSEWHEEL:
if (!options->control) {
if (!control) {
break;
}
input_manager_process_mouse_wheel(&input_manager, &event->wheel);
@@ -219,7 +219,8 @@ handle_event(SDL_Event *event, const struct scrcpy_options *options) {
case SDL_MOUSEBUTTONUP:
// some mouse events do not interact with the device, so process
// the event even if control is disabled
input_manager_process_mouse_button(&input_manager, &event->button);
input_manager_process_mouse_button(&input_manager, &event->button,
control);
break;
case SDL_FINGERMOTION:
case SDL_FINGERDOWN:
@@ -227,7 +228,7 @@ handle_event(SDL_Event *event, const struct scrcpy_options *options) {
input_manager_process_touch(&input_manager, &event->tfinger);
break;
case SDL_DROPFILE: {
if (!options->control) {
if (!control) {
break;
}
file_handler_action_t action;
@@ -244,15 +245,16 @@ handle_event(SDL_Event *event, const struct scrcpy_options *options) {
}
static bool
event_loop(const struct scrcpy_options *options) {
event_loop(bool display, bool control) {
(void) display;
#ifdef CONTINUOUS_RESIZING_WORKAROUND
if (options->display) {
if (display) {
SDL_AddEventWatch(event_watcher, NULL);
}
#endif
SDL_Event event;
while (SDL_WaitEvent(&event)) {
enum event_result result = handle_event(&event, options);
enum event_result result = handle_event(&event, control);
switch (result) {
case EVENT_RESULT_STOPPED_BY_USER:
return true;
@@ -441,9 +443,10 @@ scrcpy(const struct scrcpy_options *options) {
}
}
input_manager_init(&input_manager, options);
input_manager_init(&input_manager, options->prefer_text,
&options->shortcut_mods);
ret = event_loop(options);
ret = event_loop(options->display, options->control);
LOGD("quit...");
screen_destroy(&screen);

View File

@@ -27,8 +27,8 @@ enum sc_shortcut_mod {
SC_MOD_RCTRL = 1 << 1,
SC_MOD_LALT = 1 << 2,
SC_MOD_RALT = 1 << 3,
SC_MOD_LSUPER = 1 << 4,
SC_MOD_RSUPER = 1 << 5,
SC_MOD_LCMD = 1 << 4,
SC_MOD_RCMD = 1 << 5,
};
struct sc_shortcut_mods {
@@ -78,7 +78,6 @@ struct scrcpy_options {
bool stay_awake;
bool force_adb_forward;
bool disable_screensaver;
bool forward_key_repeat;
};
#define SCRCPY_OPTIONS_DEFAULT { \
@@ -96,7 +95,7 @@ struct scrcpy_options {
.last = DEFAULT_LOCAL_PORT_RANGE_LAST, \
}, \
.shortcut_mods = { \
.data = {SC_MOD_LALT, SC_MOD_LSUPER}, \
.data = {SC_MOD_LALT, SC_MOD_LCMD}, \
.count = 2, \
}, \
.max_size = DEFAULT_MAX_SIZE, \
@@ -122,7 +121,6 @@ struct scrcpy_options {
.stay_awake = false, \
.force_adb_forward = false, \
.disable_screensaver = false, \
.forward_key_repeat = true, \
}
bool

View File

@@ -143,11 +143,11 @@ static void test_parse_shortcut_mods(void) {
assert(mods.data[0] == SC_MOD_RCTRL);
assert(mods.data[1] == SC_MOD_LALT);
ok = sc_parse_shortcut_mods("lsuper,rsuper+lalt,lctrl+rctrl+ralt", &mods);
ok = sc_parse_shortcut_mods("lcmd,rcmd+lalt,lctrl+rctrl+ralt", &mods);
assert(ok);
assert(mods.count == 3);
assert(mods.data[0] == SC_MOD_LSUPER);
assert(mods.data[1] == (SC_MOD_RSUPER | SC_MOD_LALT));
assert(mods.data[0] == SC_MOD_LCMD);
assert(mods.data[1] == (SC_MOD_RCMD | SC_MOD_LALT));
assert(mods.data[2] == (SC_MOD_LCTRL | SC_MOD_RCTRL | SC_MOD_RALT));
ok = sc_parse_shortcut_mods("", &mods);

View File

@@ -15,6 +15,6 @@ cpu = 'i686'
endian = 'little'
[properties]
prebuilt_ffmpeg_shared = 'ffmpeg-4.3.1-win32-shared'
prebuilt_ffmpeg_dev = 'ffmpeg-4.3.1-win32-dev'
prebuilt_ffmpeg_shared = 'ffmpeg-4.2.2-win32-shared'
prebuilt_ffmpeg_dev = 'ffmpeg-4.2.2-win32-dev'
prebuilt_sdl2 = 'SDL2-2.0.12/i686-w64-mingw32'

View File

@@ -15,6 +15,6 @@ cpu = 'x86_64'
endian = 'little'
[properties]
prebuilt_ffmpeg_shared = 'ffmpeg-4.3.1-win64-shared'
prebuilt_ffmpeg_dev = 'ffmpeg-4.3.1-win64-dev'
prebuilt_ffmpeg_shared = 'ffmpeg-4.2.2-win64-shared'
prebuilt_ffmpeg_dev = 'ffmpeg-4.2.2-win64-dev'
prebuilt_sdl2 = 'SDL2-2.0.12/x86_64-w64-mingw32'

View File

@@ -1,5 +1,5 @@
project('scrcpy', 'c',
version: '1.15',
version: '1.14',
meson_version: '>= 0.48',
default_options: [
'c_std=c11',

View File

@@ -10,24 +10,24 @@ prepare-win32: prepare-sdl2 prepare-ffmpeg-shared-win32 prepare-ffmpeg-dev-win32
prepare-win64: prepare-sdl2 prepare-ffmpeg-shared-win64 prepare-ffmpeg-dev-win64 prepare-adb
prepare-ffmpeg-shared-win32:
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win32/shared/ffmpeg-4.3.1-win32-shared.zip \
357af9901a456f4dcbacd107e83a934d344c9cb07ddad8aaf80612eeab7d26d2 \
ffmpeg-4.3.1-win32-shared
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win32/shared/ffmpeg-4.2.2-win32-shared.zip \
ab5d603aaa54de360db2c2ffe378c82376b9343ea1175421dd644639aa07ee31 \
ffmpeg-4.2.2-win32-shared
prepare-ffmpeg-dev-win32:
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win32/dev/ffmpeg-4.3.1-win32-dev.zip \
230efb08e9bcf225bd474da29676c70e591fc94d8790a740ca801408fddcb78b \
ffmpeg-4.3.1-win32-dev
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win32/dev/ffmpeg-4.2.2-win32-dev.zip \
8d224be567a2950cad4be86f4aabdd045bfa52ad758e87c72cedd278613bc6c8 \
ffmpeg-4.2.2-win32-dev
prepare-ffmpeg-shared-win64:
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win64/shared/ffmpeg-4.3.1-win64-shared.zip \
dd29b7f92f48dead4dd940492c7509138c0f99db445076d0a597007298a79940 \
ffmpeg-4.3.1-win64-shared
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win64/shared/ffmpeg-4.2.2-win64-shared.zip \
5aedf268952b7d9f6541dbfcb47cd86a7e7881a3b7ba482fd3bc4ca33bda7bf5 \
ffmpeg-4.2.2-win64-shared
prepare-ffmpeg-dev-win64:
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win64/dev/ffmpeg-4.3.1-win64-dev.zip \
2e8038242cf8e1bd095c2978f196ff0462b122cc6ef7e74626a6af15459d8b81 \
ffmpeg-4.3.1-win64-dev
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win64/dev/ffmpeg-4.2.2-win64-dev.zip \
f4885f859c5b0d6663c2a0a4c1cf035b1c60b146402790b796bd3ad84f4f3ca2 \
ffmpeg-4.2.2-win64-dev
prepare-sdl2:
@./prepare-dep https://libsdl.org/release/SDL2-devel-2.0.12-mingw.tar.gz \
@@ -35,6 +35,6 @@ prepare-sdl2:
SDL2-2.0.12
prepare-adb:
@./prepare-dep https://dl.google.com/android/repository/platform-tools_r30.0.4-windows.zip \
413182fff6c5957911e231b9e97e6be4fc6a539035e3dfb580b5c54bd5950fee \
@./prepare-dep https://dl.google.com/android/repository/platform-tools_r30.0.0-windows.zip \
854305f9a702f5ea2c3de73edde402bd26afa0ee944c9b0c4380420f5a862e0d \
platform-tools

View File

@@ -6,8 +6,8 @@ android {
applicationId "com.genymobile.scrcpy"
minSdkVersion 21
targetSdkVersion 29
versionCode 17
versionName "1.15"
versionCode 16
versionName "1.14"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {

View File

@@ -12,7 +12,7 @@
set -e
SCRCPY_DEBUG=false
SCRCPY_VERSION_NAME=1.15
SCRCPY_VERSION_NAME=1.14
PLATFORM=${ANDROID_PLATFORM:-29}
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-29.0.2}
@@ -42,8 +42,6 @@ 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
"$ANDROID_HOME/build-tools/$BUILD_TOOLS/aidl" -o"$CLASSES_DIR" \
android/content/IOnPrimaryClipChangedListener.aidl
echo "Compiling java sources..."
cd ../java
@@ -57,7 +55,6 @@ cd "$CLASSES_DIR"
"$ANDROID_HOME/build-tools/$BUILD_TOOLS/dx" --dex \
--output "$BUILD_DIR/classes.dex" \
android/view/*.class \
android/content/*.class \
com/genymobile/scrcpy/*.class \
com/genymobile/scrcpy/wrappers/*.class

View File

@@ -8,16 +8,11 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Controller {
private static final int DEVICE_ID_VIRTUAL = -1;
private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();
private final Device device;
private final DesktopConnection connection;
private final DeviceMessageSender sender;
@@ -29,8 +24,6 @@ public class Controller {
private final MotionEvent.PointerProperties[] pointerProperties = new MotionEvent.PointerProperties[PointersState.MAX_POINTERS];
private final MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[PointersState.MAX_POINTERS];
private boolean keepPowerModeOff;
public Controller(Device device, DesktopConnection connection) {
this.device = device;
this.connection = connection;
@@ -124,7 +117,6 @@ public class Controller {
int mode = msg.getAction();
boolean setPowerModeOk = Device.setScreenPowerMode(mode);
if (setPowerModeOk) {
keepPowerModeOff = mode == Device.POWER_MODE_OFF;
Ln.i("Device screen turned " + (mode == Device.POWER_MODE_OFF ? "off" : "on"));
}
}
@@ -138,9 +130,6 @@ public class Controller {
}
private boolean injectKeycode(int action, int keycode, int repeat, int metaState) {
if (keepPowerModeOff && action == KeyEvent.ACTION_UP && (keycode == KeyEvent.KEYCODE_POWER || keycode == KeyEvent.KEYCODE_WAKEUP)) {
schedulePowerModeOff();
}
return device.injectKeyEvent(action, keycode, repeat, metaState);
}
@@ -234,24 +223,8 @@ public class Controller {
return device.injectEvent(event);
}
/**
* Schedule a call to set power mode to off after a small delay.
*/
private static void schedulePowerModeOff() {
EXECUTOR.schedule(new Runnable() {
@Override
public void run() {
Ln.i("Forcing screen off");
Device.setScreenPowerMode(Device.POWER_MODE_OFF);
}
}, 200, TimeUnit.MILLISECONDS);
}
private boolean pressBackOrTurnScreenOn() {
int keycode = device.isScreenOn() ? KeyEvent.KEYCODE_BACK : KeyEvent.KEYCODE_WAKEUP;
if (keepPowerModeOff && keycode == KeyEvent.KEYCODE_WAKEUP) {
schedulePowerModeOff();
}
return device.injectKeycode(keycode);
}