Compare commits

...

6 Commits

Author SHA1 Message Date
1c3801a0b1 Add a shortcut to pause/unpause display
Pause/unpause display on MOD+z and MOD+Shift+z.

It only impacts rendering, the device is still captured, the video
stream continues to be transmitted to the device and recorded (if
recording is enabled).

Fixes #1632 <https://github.com/Genymobile/scrcpy/issues/1632>
PR #4748 <https://github.com/Genymobile/scrcpy/pull/4748>
2024-03-30 14:20:51 +01:00
be3d357a6d Use source repo tarball for libusb
Legitimate or not, we should not use sources that do not match the
repository.

Refs <https://github.com/libusb/libusb/issues/1468#issuecomment-1974787595>
Refs <https://news.ycombinator.com/item?id=39866309>
Refs #4713 <https://github.com/Genymobile/scrcpy/pull/4713>
2024-03-30 14:18:47 +01:00
79968a0ae6 Reorder documentation
Present the --tcpip option without arguments first.
2024-03-11 18:05:27 +01:00
7f23ff3f2c Add videos for pinch-to-zoom and tilt
A video is worth a thousand words.
2024-03-03 00:06:54 +01:00
cc7719079a Italicize coordinates letters in documentation 2024-03-03 00:05:26 +01:00
0c94b75eef Update links to 2.4 2024-03-03 00:00:24 +01:00
13 changed files with 137 additions and 54 deletions

View File

@ -2,7 +2,7 @@
source for the project. Do not download releases from random websites, even if
their name contains `scrcpy`.**
# scrcpy (v2.3.1)
# scrcpy (v2.4)
<img src="app/data/icon.svg" width="128" height="128" alt="scrcpy" align="right" />

View File

@ -5,9 +5,9 @@ cd "$DEPS_DIR"
. common
VERSION=1.0.27
FILENAME=libusb-$VERSION.tar.bz2
FILENAME=libusb-$VERSION.tar.gz
PROJECT_DIR=libusb-$VERSION
SHA256SUM=ffaa41d741a8a3bee244ac8e54a72ea05bf2879663c098c82fc5757853441575
SHA256SUM=e8f18a7a36ecbb11fb820bd71540350d8f61bcd9db0d2e8c18a6fb80b214a3de
cd "$SOURCES_DIR"
@ -15,7 +15,7 @@ if [[ -d "$PROJECT_DIR" ]]
then
echo "$PWD/$PROJECT_DIR" found
else
get_file "https://github.com/libusb/libusb/releases/download/v$VERSION/libusb-$VERSION.tar.bz2" "$FILENAME" "$SHA256SUM"
get_file "https://github.com/libusb/libusb/archive/refs/tags/v$VERSION.tar.gz" "$FILENAME" "$SHA256SUM"
tar xf "$FILENAME" # First level directory is "$PROJECT_DIR"
fi
@ -33,6 +33,7 @@ else
mkdir "$HOST"
cd "$HOST"
"$SOURCES_DIR/$PROJECT_DIR"/bootstrap.sh
"$SOURCES_DIR/$PROJECT_DIR"/configure \
--prefix="$INSTALL_DIR/$HOST" \
--host="$HOST_TRIPLET" \

View File

@ -577,6 +577,14 @@ Flip display horizontally
.B MOD+Shift+Up, MOD+Shift+Down
Flip display vertically
.TP
.B MOD+z
Pause or re-pause display
.TP
.B MOD+Shift+z
Unpause display
.TP
.B MOD+g
Resize window to 1:1 (pixel\-perfect)

View File

@ -900,6 +900,14 @@ static const struct sc_shortcut shortcuts[] = {
.shortcuts = { "MOD+Shift+Up", "MOD+Shift+Down" },
.text = "Flip display vertically",
},
{
.shortcuts = { "MOD+z" },
.text = "Pause or re-pause display",
},
{
.shortcuts = { "MOD+Shift+z" },
.text = "Unpause display",
},
{
.shortcuts = { "MOD+g" },
.text = "Resize window to 1:1 (pixel-perfect)",

View File

@ -402,6 +402,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
const SDL_KeyboardEvent *event) {
// controller is NULL if --no-control is requested
bool control = im->controller;
bool paused = im->screen->paused;
SDL_Keycode keycode = event->keysym.sym;
uint16_t mod = event->keysym.mod;
@ -427,46 +428,51 @@ sc_input_manager_process_key(struct sc_input_manager *im,
enum sc_action action = down ? SC_ACTION_DOWN : SC_ACTION_UP;
switch (keycode) {
case SDLK_h:
if (im->kp && !shift && !repeat) {
if (im->kp && !shift && !repeat && !paused) {
action_home(im, action);
}
return;
case SDLK_b: // fall-through
case SDLK_BACKSPACE:
if (im->kp && !shift && !repeat) {
if (im->kp && !shift && !repeat && !paused) {
action_back(im, action);
}
return;
case SDLK_s:
if (im->kp && !shift && !repeat) {
if (im->kp && !shift && !repeat && !paused) {
action_app_switch(im, action);
}
return;
case SDLK_m:
if (im->kp && !shift && !repeat) {
if (im->kp && !shift && !repeat && !paused) {
action_menu(im, action);
}
return;
case SDLK_p:
if (im->kp && !shift && !repeat) {
if (im->kp && !shift && !repeat && !paused) {
action_power(im, action);
}
return;
case SDLK_o:
if (control && !repeat && down) {
if (control && !repeat && down && !paused) {
enum sc_screen_power_mode mode = shift
? SC_SCREEN_POWER_MODE_NORMAL
: SC_SCREEN_POWER_MODE_OFF;
set_screen_power_mode(im, mode);
}
return;
case SDLK_z:
if (down && !repeat) {
sc_screen_set_paused(im->screen, !shift);
}
return;
case SDLK_DOWN:
if (shift) {
if (!repeat & down) {
apply_orientation_transform(im,
SC_ORIENTATION_FLIP_180);
}
} else if (im->kp) {
} else if (im->kp && !paused) {
// forward repeated events
action_volume_down(im, action);
}
@ -477,7 +483,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
apply_orientation_transform(im,
SC_ORIENTATION_FLIP_180);
}
} else if (im->kp) {
} else if (im->kp && !paused) {
// forward repeated events
action_volume_up(im, action);
}
@ -505,17 +511,17 @@ sc_input_manager_process_key(struct sc_input_manager *im,
}
return;
case SDLK_c:
if (im->kp && !shift && !repeat && down) {
if (im->kp && !shift && !repeat && down && !paused) {
get_device_clipboard(im, SC_COPY_KEY_COPY);
}
return;
case SDLK_x:
if (im->kp && !shift && !repeat && down) {
if (im->kp && !shift && !repeat && down && !paused) {
get_device_clipboard(im, SC_COPY_KEY_CUT);
}
return;
case SDLK_v:
if (im->kp && !repeat && down) {
if (im->kp && !repeat && down && !paused) {
if (shift || im->legacy_paste) {
// inject the text as input events
clipboard_paste(im);
@ -547,7 +553,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
}
return;
case SDLK_n:
if (control && !repeat && down) {
if (control && !repeat && down && !paused) {
if (shift) {
collapse_panels(im);
} else if (im->key_repeat == 0) {
@ -558,12 +564,12 @@ sc_input_manager_process_key(struct sc_input_manager *im,
}
return;
case SDLK_r:
if (control && !shift && !repeat && down) {
if (control && !shift && !repeat && down && !paused) {
rotate_device(im);
}
return;
case SDLK_k:
if (control && !shift && !repeat && down
if (control && !shift && !repeat && down && !paused
&& im->kp && im->kp->hid) {
// Only if the current keyboard is hid
open_hard_keyboard_settings(im);
@ -574,7 +580,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
return;
}
if (!im->kp) {
if (!im->kp || paused) {
return;
}
@ -622,7 +628,6 @@ sc_input_manager_process_key(struct sc_input_manager *im,
static void
sc_input_manager_process_mouse_motion(struct sc_input_manager *im,
const SDL_MouseMotionEvent *event) {
if (event->which == SDL_TOUCH_MOUSEID) {
// simulated from touch events, so it's a duplicate
return;
@ -695,16 +700,16 @@ sc_input_manager_process_touch(struct sc_input_manager *im,
static void
sc_input_manager_process_mouse_button(struct sc_input_manager *im,
const SDL_MouseButtonEvent *event) {
bool control = im->controller;
if (event->which == SDL_TOUCH_MOUSEID) {
// simulated from touch events, so it's a duplicate
return;
}
bool control = im->controller;
bool paused = im->screen->paused;
bool down = event->type == SDL_MOUSEBUTTONDOWN;
if (!im->forward_all_clicks) {
if (control) {
if (control && !paused) {
enum sc_action action = down ? SC_ACTION_DOWN : SC_ACTION_UP;
if (im->kp && event->button == SDL_BUTTON_X1) {
@ -747,7 +752,7 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
// otherwise, send the click event to the device
}
if (!im->mp) {
if (!im->mp || paused) {
return;
}
@ -885,9 +890,10 @@ void
sc_input_manager_handle_event(struct sc_input_manager *im,
const SDL_Event *event) {
bool control = im->controller;
bool paused = im->screen->paused;
switch (event->type) {
case SDL_TEXTINPUT:
if (!im->kp) {
if (!im->kp || paused) {
break;
}
sc_input_manager_process_text_input(im, &event->text);
@ -899,13 +905,13 @@ sc_input_manager_handle_event(struct sc_input_manager *im,
sc_input_manager_process_key(im, &event->key);
break;
case SDL_MOUSEMOTION:
if (!im->mp) {
if (!im->mp || paused) {
break;
}
sc_input_manager_process_mouse_motion(im, &event->motion);
break;
case SDL_MOUSEWHEEL:
if (!im->mp) {
if (!im->mp || paused) {
break;
}
sc_input_manager_process_mouse_wheel(im, &event->wheel);
@ -919,7 +925,7 @@ sc_input_manager_handle_event(struct sc_input_manager *im,
case SDL_FINGERMOTION:
case SDL_FINGERDOWN:
case SDL_FINGERUP:
if (!im->mp) {
if (!im->mp || paused) {
break;
}
sc_input_manager_process_touch(im, &event->tfinger);

View File

@ -362,6 +362,8 @@ sc_screen_init(struct sc_screen *screen,
screen->maximized = false;
screen->minimized = false;
screen->mouse_capture_key_pressed = 0;
screen->paused = false;
screen->resume_frame = NULL;
screen->req.x = params->window_x;
screen->req.y = params->window_y;
@ -614,13 +616,10 @@ prepare_for_frame(struct sc_screen *screen, struct sc_size new_frame_size) {
}
static bool
sc_screen_update_frame(struct sc_screen *screen) {
av_frame_unref(screen->frame);
sc_frame_buffer_consume(&screen->fb, screen->frame);
AVFrame *frame = screen->frame;
sc_screen_apply_frame(struct sc_screen *screen) {
sc_fps_counter_add_rendered_frame(&screen->fps_counter);
AVFrame *frame = screen->frame;
struct sc_size new_frame_size = {frame->width, frame->height};
enum sc_display_result res = prepare_for_frame(screen, new_frame_size);
if (res == SC_DISPLAY_RESULT_ERROR) {
@ -655,6 +654,54 @@ sc_screen_update_frame(struct sc_screen *screen) {
return true;
}
static bool
sc_screen_update_frame(struct sc_screen *screen) {
if (screen->paused) {
if (!screen->resume_frame) {
screen->resume_frame = av_frame_alloc();
if (!screen->resume_frame) {
LOG_OOM();
return false;
}
} else {
av_frame_unref(screen->resume_frame);
}
sc_frame_buffer_consume(&screen->fb, screen->resume_frame);
return true;
}
av_frame_unref(screen->frame);
sc_frame_buffer_consume(&screen->fb, screen->frame);
return sc_screen_apply_frame(screen);
}
void
sc_screen_set_paused(struct sc_screen *screen, bool paused) {
if (!paused && !screen->paused) {
// nothing to do
return;
}
if (screen->paused && screen->resume_frame) {
// If display screen was paused, refresh the frame immediately, even if
// the new state is also paused.
av_frame_free(&screen->frame);
screen->frame = screen->resume_frame;
screen->resume_frame = NULL;
sc_screen_apply_frame(screen);
}
if (!paused) {
LOGI("Display screen unpaused");
} else if (!screen->paused) {
LOGI("Display screen paused");
} else {
LOGI("Display screen re-paused");
}
screen->paused = paused;
}
void
sc_screen_switch_fullscreen(struct sc_screen *screen) {
uint32_t new_mode = screen->fullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP;

View File

@ -64,6 +64,9 @@ struct sc_screen {
SDL_Keycode mouse_capture_key_pressed;
AVFrame *frame;
bool paused;
AVFrame *resume_frame;
};
struct sc_screen_params {
@ -135,6 +138,10 @@ void
sc_screen_set_orientation(struct sc_screen *screen,
enum sc_orientation orientation);
// set the display pause state
void
sc_screen_set_paused(struct sc_screen *screen, bool paused);
// react to SDL events
// If this function returns false, scrcpy must exit with an error.
bool

View File

@ -233,10 +233,10 @@ install` must be run as root)._
#### Option 2: Use prebuilt server
- [`scrcpy-server-v2.3.1`][direct-scrcpy-server]
<sub>SHA-256: `f6814822fc308a7a532f253485c9038183c6296a6c5df470a9e383b4f8e7605b`</sub>
- [`scrcpy-server-v2.4`][direct-scrcpy-server]
<sub>SHA-256: `93c272b7438605c055e127f7444064ed78fa9ca49f81156777fd201e79ce7ba3`</sub>
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v2.3.1/scrcpy-server-v2.3.1
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v2.4/scrcpy-server-v2.4
Download the prebuilt server somewhere, and specify its path during the Meson
configuration:

View File

@ -67,14 +67,6 @@ computer.
An option `--tcpip` allows to configure the connection automatically. There are
two variants.
If the device (accessible at 192.168.1.1 in this example) already listens on a
port (typically 5555) for incoming _adb_ connections, then run:
```bash
scrcpy --tcpip=192.168.1.1 # default port is 5555
scrcpy --tcpip=192.168.1.1:5555
```
If _adb_ TCP/IP mode is disabled on the device (or if you don't know the IP
address), connect the device over USB, then run:
@ -85,6 +77,14 @@ scrcpy --tcpip # without arguments
It will automatically find the device IP address and adb port, enable TCP/IP
mode if necessary, then connect to the device before starting.
If the device (accessible at 192.168.1.1 in this example) already listens on a
port (typically 5555) for incoming _adb_ connections, then run:
```bash
scrcpy --tcpip=192.168.1.1 # default port is 5555
scrcpy --tcpip=192.168.1.1:5555
```
### Manual

View File

@ -67,12 +67,16 @@ More precisely, hold down <kbd>Ctrl</kbd> while pressing the left-click button.
Until the left-click button is released, all mouse movements scale and rotate
the content (if supported by the app) relative to the center of the screen.
https://github.com/Genymobile/scrcpy/assets/543275/26c4a920-9805-43f1-8d4c-608752d04767
To simulate a tilt gesture: <kbd>Shift</kbd>+_click-and-move-up-or-down_.
https://github.com/Genymobile/scrcpy/assets/543275/1e252341-4a90-4b29-9d11-9153b324669f
Technically, _scrcpy_ generates additional touch events from a "virtual finger"
at a location inverted through the center of the screen. When pressing
<kbd>Ctrl</kbd> the x and y coordinates are inverted. Using <kbd>Shift</kbd>
only inverts x.
<kbd>Ctrl</kbd> the _x_ and _y_ coordinates are inverted. Using <kbd>Shift</kbd>
only inverts _x_.
This only works for the default mouse mode (`--mouse=sdk`).

View File

@ -28,6 +28,8 @@ _<kbd>[Super]</kbd> is typically the <kbd>Windows</kbd> or <kbd>Cmd</kbd> key._
| Rotate display right | <kbd>MOD</kbd>+<kbd></kbd> _(right)_
| Flip display horizontally | <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd></kbd> _(left)_ \| <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd></kbd> _(right)_
| Flip display vertically | <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd></kbd> _(up)_ \| <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd></kbd> _(down)_
| Pause or re-pause display | <kbd>MOD</kbd>+<kbd>z</kbd>
| Unpause display | <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>z</kbd>
| 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-left-click¹_
| Click on `HOME` | <kbd>MOD</kbd>+<kbd>h</kbd> \| _Middle-click_

View File

@ -4,14 +4,14 @@
Download the [latest release]:
- [`scrcpy-win64-v2.3.1.zip`][direct-win64] (64-bit)
<sub>SHA-256: `f1f78ac98214078425804e524a1bed515b9d4b8a05b78d210a4ced2b910b262d`</sub>
- [`scrcpy-win32-v2.3.1.zip`][direct-win32] (32-bit)
<sub>SHA-256: `5dffc2d432e9b8b5b0e16f12e71428c37c70d9124cfbe7620df0b41b7efe91ff`</sub>
- [`scrcpy-win64-v2.4.zip`][direct-win64] (64-bit)
<sub>SHA-256: `9dc56f21bfa455352ec0c58b40feaf2fb02d67372910a4235e298ece286ff3a9`</sub>
- [`scrcpy-win32-v2.4.zip`][direct-win32] (32-bit)
<sub>SHA-256: `cf92acc45eef37c6ee2db819f92e420ced3bc50f1348dd57f7d6ca1fc80f6116`</sub>
[latest release]: https://github.com/Genymobile/scrcpy/releases/latest
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v2.3.1/scrcpy-win64-v2.3.1.zip
[direct-win32]: https://github.com/Genymobile/scrcpy/releases/download/v2.3.1/scrcpy-win32-v2.3.1.zip
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v2.4/scrcpy-win64-v2.4.zip
[direct-win32]: https://github.com/Genymobile/scrcpy/releases/download/v2.4/scrcpy-win32-v2.4.zip
and extract it.

View File

@ -2,8 +2,8 @@
set -e
BUILDDIR=build-auto
PREBUILT_SERVER_URL=https://github.com/Genymobile/scrcpy/releases/download/v2.3.1/scrcpy-server-v2.3.1
PREBUILT_SERVER_SHA256=f6814822fc308a7a532f253485c9038183c6296a6c5df470a9e383b4f8e7605b
PREBUILT_SERVER_URL=https://github.com/Genymobile/scrcpy/releases/download/v2.4/scrcpy-server-v2.4
PREBUILT_SERVER_SHA256=93c272b7438605c055e127f7444064ed78fa9ca49f81156777fd201e79ce7ba3
echo "[scrcpy] Downloading prebuilt server..."
wget "$PREBUILT_SERVER_URL" -O scrcpy-server