Compare commits
4 Commits
v1.15.1
...
pinch_zoom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eff50368bf | ||
|
|
a59a15777d | ||
|
|
a2cb63e344 | ||
|
|
f03a3edde6 |
6
BUILD.md
6
BUILD.md
@@ -254,10 +254,10 @@ You can then [run](README.md#run) _scrcpy_.
|
||||
|
||||
## Prebuilt server
|
||||
|
||||
- [`scrcpy-server-v1.15`][direct-scrcpy-server]
|
||||
_(SHA-256: e160c46784f30566eae621cad88bfb34e124f945cb8274b8dfc615b613b86dd8)_
|
||||
- [`scrcpy-server-v1.15.1`][direct-scrcpy-server]
|
||||
_(SHA-256: fe06bd6a30da8c89860bf5e16eecce2b5054d4644c84289670ce00ca5d1637c3)_
|
||||
|
||||
[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.15.1/scrcpy-server-v1.15.1
|
||||
|
||||
Download the prebuilt server somewhere, and specify its path during the Meson
|
||||
configuration:
|
||||
|
||||
11
README.md
11
README.md
@@ -1,4 +1,4 @@
|
||||
# scrcpy (v1.15)
|
||||
# scrcpy (v1.15.1)
|
||||
|
||||
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.
|
||||
@@ -34,6 +34,7 @@ control it using keyboard and mouse.
|
||||
|
||||
## Get the app
|
||||
|
||||
<a href="https://repology.org/project/scrcpy/versions"><img src="https://repology.org/badge/vertical-allrepos/scrcpy.svg" alt="Packaging status" align="right"></a>
|
||||
|
||||
### Linux
|
||||
|
||||
@@ -74,10 +75,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.15.1.zip`][direct-win64]
|
||||
_(SHA-256: 78fba4caad6328016ea93219254b5df391f24224c519a2c8e3f070695b8b38ff)_
|
||||
|
||||
[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.15.1/scrcpy-win64-v1.15.1.zip
|
||||
|
||||
It is also available in [Chocolatey]:
|
||||
|
||||
@@ -448,7 +449,7 @@ Or by pressing <kbd>MOD</kbd>+<kbd>o</kbd> at any time.
|
||||
To turn it back on, press <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>o</kbd>.
|
||||
|
||||
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
|
||||
`POWER` is sent via scrcpy (via right-click or <kbd>MOD</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.
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH (CONTROL_MSG_MAX_SIZE - 6)
|
||||
|
||||
#define POINTER_ID_MOUSE UINT64_C(-1);
|
||||
#define POINTER_ID_VIRTUAL_FINGER UINT64_C(-2);
|
||||
|
||||
enum control_msg_type {
|
||||
CONTROL_MSG_TYPE_INJECT_KEYCODE,
|
||||
|
||||
@@ -70,6 +70,8 @@ input_manager_init(struct input_manager *im,
|
||||
im->sdl_shortcut_mods.data[i] = sdl_mod;
|
||||
}
|
||||
im->sdl_shortcut_mods.count = shortcut_mods->count;
|
||||
|
||||
im->vfinger_down = false;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -299,6 +301,36 @@ input_manager_process_text_input(struct input_manager *im,
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
simulate_virtual_finger(struct input_manager *im,
|
||||
enum android_motionevent_action action,
|
||||
struct point point) {
|
||||
bool up = action == AMOTION_EVENT_ACTION_UP;
|
||||
|
||||
struct control_msg msg;
|
||||
msg.type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT;
|
||||
msg.inject_touch_event.action = action;
|
||||
msg.inject_touch_event.position.screen_size = im->screen->frame_size;
|
||||
msg.inject_touch_event.position.point = point;
|
||||
msg.inject_touch_event.pointer_id = POINTER_ID_VIRTUAL_FINGER;
|
||||
msg.inject_touch_event.pressure = up ? 0.0f : 1.0f;
|
||||
msg.inject_touch_event.buttons = 0;
|
||||
|
||||
if (!controller_push_msg(im->controller, &msg)) {
|
||||
LOGW("Could not request 'inject virtual finger event'");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct point
|
||||
inverse_point(struct point point, struct size size) {
|
||||
point.x = size.width - point.x;
|
||||
point.y = size.height - point.y;
|
||||
return point;
|
||||
}
|
||||
|
||||
static bool
|
||||
convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to,
|
||||
bool prefer_text, uint32_t repeat) {
|
||||
@@ -512,9 +544,19 @@ input_manager_process_mouse_motion(struct input_manager *im,
|
||||
return;
|
||||
}
|
||||
struct control_msg msg;
|
||||
if (convert_mouse_motion(event, im->screen, &msg)) {
|
||||
if (!controller_push_msg(im->controller, &msg)) {
|
||||
LOGW("Could not request 'inject mouse motion event'");
|
||||
if (!convert_mouse_motion(event, im->screen, &msg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!controller_push_msg(im->controller, &msg)) {
|
||||
LOGW("Could not request 'inject mouse motion event'");
|
||||
}
|
||||
|
||||
if (im->vfinger_down) {
|
||||
struct point mouse = msg.inject_touch_event.position.point;
|
||||
struct point vfinger = inverse_point(mouse, im->screen->frame_size);
|
||||
if (!simulate_virtual_finger(im, AMOTION_EVENT_ACTION_MOVE, vfinger)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -587,7 +629,9 @@ input_manager_process_mouse_button(struct input_manager *im,
|
||||
// simulated from touch events, so it's a duplicate
|
||||
return;
|
||||
}
|
||||
if (event->type == SDL_MOUSEBUTTONDOWN) {
|
||||
|
||||
bool down = event->type == SDL_MOUSEBUTTONDOWN;
|
||||
if (down) {
|
||||
if (control && event->button == SDL_BUTTON_RIGHT) {
|
||||
press_back_or_turn_screen_on(im->controller);
|
||||
return;
|
||||
@@ -618,10 +662,36 @@ input_manager_process_mouse_button(struct input_manager *im,
|
||||
}
|
||||
|
||||
struct control_msg msg;
|
||||
if (convert_mouse_button(event, im->screen, &msg)) {
|
||||
if (!controller_push_msg(im->controller, &msg)) {
|
||||
LOGW("Could not request 'inject mouse button event'");
|
||||
if (!convert_mouse_button(event, im->screen, &msg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!controller_push_msg(im->controller, &msg)) {
|
||||
LOGW("Could not request 'inject mouse button event'");
|
||||
return;
|
||||
}
|
||||
|
||||
// Pinch-to-zoom simulation.
|
||||
//
|
||||
// If Ctrl is hold when the left-click button is pressed, then
|
||||
// pinch-to-zoom mode is enabled: on every mouse event until the left-click
|
||||
// button is released, an additional "virtual finger" event is generated,
|
||||
// having a position inversed with respect to the center of the screen.
|
||||
//
|
||||
// In other words, the center of the rotation/scaling is the center of the
|
||||
// screen.
|
||||
#define CTRL_PRESSED (SDL_GetModState() & (KMOD_LCTRL | KMOD_RCTRL))
|
||||
if ((down && !im->vfinger_down && CTRL_PRESSED)
|
||||
|| (!down && im->vfinger_down)) {
|
||||
struct point mouse = msg.inject_touch_event.position.point;
|
||||
struct point vfinger = inverse_point(mouse, im->screen->frame_size);
|
||||
enum android_motionevent_action action = down
|
||||
? AMOTION_EVENT_ACTION_DOWN
|
||||
: AMOTION_EVENT_ACTION_UP;
|
||||
if (!simulate_virtual_finger(im, action, vfinger)) {
|
||||
return;
|
||||
}
|
||||
im->vfinger_down = down;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ struct input_manager {
|
||||
unsigned data[SC_MAX_SHORTCUT_MODS];
|
||||
unsigned count;
|
||||
} sdl_shortcut_mods;
|
||||
|
||||
bool vfinger_down;
|
||||
};
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user