Compare commits
31
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43aff4af73 | ||
|
|
cba84f6999 | ||
|
|
ed2e45ee29 | ||
|
|
aee1b39790 | ||
|
|
17d01b5bf7 | ||
|
|
40fca82b60 | ||
|
|
643293752d | ||
|
|
b5855e5deb | ||
|
|
924375487e | ||
|
|
7121a0dc53 | ||
|
|
f04812fc71 | ||
|
|
5ce1ccde85 | ||
|
|
6102a0b5bb | ||
|
|
2b34e1224e | ||
|
|
a9d23400cd | ||
|
|
cca3c953da | ||
|
|
57f1655d4b | ||
|
|
bc674721dc | ||
|
|
63e29b1782 | ||
|
|
3c15cbdaf8 | ||
|
|
96e0e89740 | ||
|
|
a1f2f5fbd3 | ||
|
|
9460bdd87b | ||
|
|
b4b638e8fe | ||
|
|
e4396e34c2 | ||
|
|
b8fed50639 | ||
|
|
d540c72e7c | ||
|
|
cd5891fee6 | ||
|
|
26ee7ce566 | ||
|
|
ba28d817fb | ||
|
|
37124e1452 |
@@ -31,6 +31,8 @@ Its features include:
|
|||||||
- device screen [as a webcam (V4L2)](#v4l2loopback) (Linux-only)
|
- device screen [as a webcam (V4L2)](#v4l2loopback) (Linux-only)
|
||||||
- [physical keyboard simulation (HID)](#physical-keyboard-simulation-hid)
|
- [physical keyboard simulation (HID)](#physical-keyboard-simulation-hid)
|
||||||
(Linux-only)
|
(Linux-only)
|
||||||
|
- [physical mouse simulation (HID)](#physical-mouse-simulation-hid)
|
||||||
|
(Linux-only)
|
||||||
- and more…
|
- and more…
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
@@ -815,6 +817,35 @@ a physical keyboard is connected).
|
|||||||
|
|
||||||
[Physical keyboard]: https://github.com/Genymobile/scrcpy/pull/2632#issuecomment-923756915
|
[Physical keyboard]: https://github.com/Genymobile/scrcpy/pull/2632#issuecomment-923756915
|
||||||
|
|
||||||
|
#### Physical mouse simulation (HID)
|
||||||
|
|
||||||
|
Similarly to the physical keyboard simulation, it is possible to simulate a
|
||||||
|
physical mouse. Likewise, it only works if the device is connected by USB, and
|
||||||
|
is currently only supported on Linux.
|
||||||
|
|
||||||
|
By default, scrcpy uses Android mouse events injection, using absolute
|
||||||
|
coordinates. By simulating a physical mouse, a mouse pointer appears on the
|
||||||
|
Android device, and relative mouse motion, clicks and scrolls are injected.
|
||||||
|
|
||||||
|
To enable this mode:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scrcpy --hid-mouse
|
||||||
|
scrcpy -M # short version
|
||||||
|
```
|
||||||
|
|
||||||
|
You could also add `--forward-all-clicks` to [forward all mouse
|
||||||
|
buttons][forward_all_clicks].
|
||||||
|
|
||||||
|
[forward_all_clicks]: #right-click-and-middle-click
|
||||||
|
|
||||||
|
When this mode is enabled, the computer mouse is "captured" (the mouse pointer
|
||||||
|
disappears from the computer and appears on the Android device instead).
|
||||||
|
|
||||||
|
Special capture keys, either <kbd>Alt</kbd> or <kbd>Super</kbd>, toggle
|
||||||
|
(disable or enable) the mouse capture. Use one of them to give the control of
|
||||||
|
the mouse back to the computer.
|
||||||
|
|
||||||
|
|
||||||
#### Text injection preference
|
#### Text injection preference
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ The keyboard layout must be configured (once and for all) on the device, via Set
|
|||||||
|
|
||||||
However, the option is only available when the HID keyboard is enabled (or a physical keyboard is connected).
|
However, the option is only available when the HID keyboard is enabled (or a physical keyboard is connected).
|
||||||
|
|
||||||
|
Also see \fB\-\-hid\-mouse\fR.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-legacy\-paste
|
.B \-\-legacy\-paste
|
||||||
Inject computer clipboard text as a sequence of key events on Ctrl+v (like MOD+Shift+v).
|
Inject computer clipboard text as a sequence of key events on Ctrl+v (like MOD+Shift+v).
|
||||||
@@ -120,6 +122,18 @@ Limit both the width and height of the video to \fIvalue\fR. The other dimension
|
|||||||
|
|
||||||
Default is 0 (unlimited).
|
Default is 0 (unlimited).
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-M, \-\-hid\-mouse
|
||||||
|
Simulate a physical mouse by using HID over AOAv2.
|
||||||
|
|
||||||
|
In this mode, the computer mouse is captured to control the device directly (relative mouse mode).
|
||||||
|
|
||||||
|
LAlt, LSuper or RSuper toggle the capture mode, to give control of the mouse back to the computer.
|
||||||
|
|
||||||
|
It may only work over USB, and is currently only supported on Linux.
|
||||||
|
|
||||||
|
Also see \fB\-\-hid\-keyboard\fR.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-no\-clipboard\-autosync
|
.B \-\-no\-clipboard\-autosync
|
||||||
By default, scrcpy automatically synchronizes the computer clipboard to the device clipboard before injecting Ctrl+v, and the device clipboard to the computer clipboard whenever it changes.
|
By default, scrcpy automatically synchronizes the computer clipboard to the device clipboard before injecting Ctrl+v, and the device clipboard to the computer clipboard whenever it changes.
|
||||||
|
|||||||
+6
-4
@@ -178,7 +178,8 @@ static const struct sc_option options[] = {
|
|||||||
"directly: `adb shell am start -a "
|
"directly: `adb shell am start -a "
|
||||||
"android.settings.HARD_KEYBOARD_SETTINGS`.\n"
|
"android.settings.HARD_KEYBOARD_SETTINGS`.\n"
|
||||||
"However, the option is only available when the HID keyboard "
|
"However, the option is only available when the HID keyboard "
|
||||||
"is enabled (or a physical keyboard is connected).",
|
"is enabled (or a physical keyboard is connected).\n"
|
||||||
|
"Also see --hid-mouse.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.shortopt = 'h',
|
.shortopt = 'h',
|
||||||
@@ -223,7 +224,8 @@ static const struct sc_option options[] = {
|
|||||||
"LAlt, LSuper or RSuper toggle the capture mode, to give "
|
"LAlt, LSuper or RSuper toggle the capture mode, to give "
|
||||||
"control of the mouse back to the computer.\n"
|
"control of the mouse back to the computer.\n"
|
||||||
"It may only work over USB, and is currently only supported "
|
"It may only work over USB, and is currently only supported "
|
||||||
"on Linux.\n",
|
"on Linux.\n"
|
||||||
|
"Also see --hid-keyboard.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.shortopt = 'm',
|
.shortopt = 'm',
|
||||||
@@ -406,8 +408,8 @@ static const struct sc_option options[] = {
|
|||||||
"frames. This increases latency to compensate for jitter.\n"
|
"frames. This increases latency to compensate for jitter.\n"
|
||||||
"This option is similar to --display-buffer, but specific to "
|
"This option is similar to --display-buffer, but specific to "
|
||||||
"V4L2 sink.\n"
|
"V4L2 sink.\n"
|
||||||
"This feature is only available on Linux.\n"
|
"Default is 0 (no buffering).\n"
|
||||||
"Default is 0 (no buffering).",
|
"This option is only available on Linux.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.shortopt = 'V',
|
.shortopt = 'V',
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ enum sc_mod {
|
|||||||
|
|
||||||
SC_MOD_NUM = KMOD_NUM,
|
SC_MOD_NUM = KMOD_NUM,
|
||||||
SC_MOD_CAPS = KMOD_CAPS,
|
SC_MOD_CAPS = KMOD_CAPS,
|
||||||
SC_MOD_SCROLL = KMOD_SCROLL,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum sc_action {
|
enum sc_action {
|
||||||
|
|||||||
+7
-12
@@ -171,7 +171,6 @@ send_keycode(struct controller *controller, enum android_keycode keycode,
|
|||||||
|
|
||||||
if (!controller_push_msg(controller, &msg)) {
|
if (!controller_push_msg(controller, &msg)) {
|
||||||
LOGW("Could not request 'inject %s'", name);
|
LOGW("Could not request 'inject %s'", name);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +222,6 @@ press_back_or_turn_screen_on(struct controller *controller,
|
|||||||
|
|
||||||
if (!controller_push_msg(controller, &msg)) {
|
if (!controller_push_msg(controller, &msg)) {
|
||||||
LOGW("Could not request 'press back or turn screen on'");
|
LOGW("Could not request 'press back or turn screen on'");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,14 +632,6 @@ static void
|
|||||||
input_manager_process_mouse_motion(struct input_manager *im,
|
input_manager_process_mouse_motion(struct input_manager *im,
|
||||||
const SDL_MouseMotionEvent *event) {
|
const SDL_MouseMotionEvent *event) {
|
||||||
|
|
||||||
uint32_t mask = SDL_BUTTON_LMASK;
|
|
||||||
if (im->forward_all_clicks) {
|
|
||||||
mask |= SDL_BUTTON_MMASK | SDL_BUTTON_RMASK;
|
|
||||||
}
|
|
||||||
//if (!(event->state & mask)) {
|
|
||||||
// // do not send motion events when no click is pressed
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
if (event->which == SDL_TOUCH_MOUSEID) {
|
if (event->which == SDL_TOUCH_MOUSEID) {
|
||||||
// simulated from touch events, so it's a duplicate
|
// simulated from touch events, so it's a duplicate
|
||||||
return;
|
return;
|
||||||
@@ -663,7 +653,11 @@ input_manager_process_mouse_motion(struct input_manager *im,
|
|||||||
assert(im->mp->ops->process_mouse_motion);
|
assert(im->mp->ops->process_mouse_motion);
|
||||||
im->mp->ops->process_mouse_motion(im->mp, &evt);
|
im->mp->ops->process_mouse_motion(im->mp, &evt);
|
||||||
|
|
||||||
|
// vfinger must never be used in relative mode
|
||||||
|
assert(!im->mp->relative_mode || !im->vfinger_down);
|
||||||
|
|
||||||
if (im->vfinger_down) {
|
if (im->vfinger_down) {
|
||||||
|
assert(!im->mp->relative_mode); // assert one more time
|
||||||
struct sc_point mouse =
|
struct sc_point mouse =
|
||||||
screen_convert_window_to_frame_coords(im->screen, event->x,
|
screen_convert_window_to_frame_coords(im->screen, event->x,
|
||||||
event->y);
|
event->y);
|
||||||
@@ -792,8 +786,9 @@ input_manager_process_mouse_button(struct input_manager *im,
|
|||||||
// In other words, the center of the rotation/scaling is the center of the
|
// In other words, the center of the rotation/scaling is the center of the
|
||||||
// screen.
|
// screen.
|
||||||
#define CTRL_PRESSED (SDL_GetModState() & (KMOD_LCTRL | KMOD_RCTRL))
|
#define CTRL_PRESSED (SDL_GetModState() & (KMOD_LCTRL | KMOD_RCTRL))
|
||||||
if ((down && !im->vfinger_down && CTRL_PRESSED)
|
if (event->button == SDL_BUTTON_LEFT &&
|
||||||
|| (!down && im->vfinger_down)) {
|
((down && !im->vfinger_down && CTRL_PRESSED) ||
|
||||||
|
(!down && im->vfinger_down))) {
|
||||||
struct sc_point mouse =
|
struct sc_point mouse =
|
||||||
screen_convert_window_to_frame_coords(im->screen, event->x,
|
screen_convert_window_to_frame_coords(im->screen, event->x,
|
||||||
event->y);
|
event->y);
|
||||||
|
|||||||
@@ -13,8 +13,6 @@
|
|||||||
#include "trait/key_processor.h"
|
#include "trait/key_processor.h"
|
||||||
#include "trait/mouse_processor.h"
|
#include "trait/mouse_processor.h"
|
||||||
|
|
||||||
struct screen; // forward declaration to avoid cycle
|
|
||||||
|
|
||||||
struct input_manager {
|
struct input_manager {
|
||||||
struct controller *controller;
|
struct controller *controller;
|
||||||
struct screen *screen;
|
struct screen *screen;
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ convert_touch_action(enum sc_touch_action action) {
|
|||||||
static void
|
static void
|
||||||
sc_mouse_processor_process_mouse_motion(struct sc_mouse_processor *mp,
|
sc_mouse_processor_process_mouse_motion(struct sc_mouse_processor *mp,
|
||||||
const struct sc_mouse_motion_event *event) {
|
const struct sc_mouse_motion_event *event) {
|
||||||
|
if (!event->buttons_state) {
|
||||||
|
// Do not send motion events when no click is pressed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
struct sc_mouse_inject *mi = DOWNCAST(mp);
|
struct sc_mouse_inject *mi = DOWNCAST(mp);
|
||||||
|
|
||||||
struct control_msg msg = {
|
struct control_msg msg = {
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ unwrap(sc_socket socket) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_SOCK_CLOEXEC // avoid unused-function warning
|
||||||
static inline bool
|
static inline bool
|
||||||
sc_raw_socket_close(sc_raw_socket raw_sock) {
|
sc_raw_socket_close(sc_raw_socket raw_sock) {
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
@@ -91,6 +92,7 @@ sc_raw_socket_close(sc_raw_socket raw_sock) {
|
|||||||
return !closesocket(raw_sock);
|
return !closesocket(raw_sock);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_SOCK_CLOEXEC
|
#ifndef HAVE_SOCK_CLOEXEC
|
||||||
// If SOCK_CLOEXEC does not exist, the flag must be set manually once the
|
// If SOCK_CLOEXEC does not exist, the flag must be set manually once the
|
||||||
|
|||||||
Reference in New Issue
Block a user