Forward mouse hover events

Also add an option --no-mouse-hover to get the old behavior.

Fixes #2743 <https://github.com/Genymobile/scrcpy/issues/2743>
Fixes #3070 <https://github.com/Genymobile/scrcpy/issues/3070>
PR #5039 <https://github.com/Genymobile/scrcpy/pull/5039>
This commit is contained in:
Romain Vimont 2024-06-21 16:54:00 +02:00
parent f5e6b8092a
commit 7633228278
10 changed files with 45 additions and 7 deletions

View File

@ -50,6 +50,7 @@ _scrcpy() {
--no-downsize-on-error --no-downsize-on-error
--no-key-repeat --no-key-repeat
--no-mipmaps --no-mipmaps
--no-mouse-hover
--no-power-on --no-power-on
--no-video --no-video
--no-video-playback --no-video-playback

View File

@ -56,6 +56,7 @@ arguments=(
'--no-downsize-on-error[Disable lowering definition on MediaCodec error]' '--no-downsize-on-error[Disable lowering definition on MediaCodec error]'
'--no-key-repeat[Do not forward repeated key events when a key is held down]' '--no-key-repeat[Do not forward repeated key events when a key is held down]'
'--no-mipmaps[Disable the generation of mipmaps]' '--no-mipmaps[Disable the generation of mipmaps]'
'--no-mouse-hover[Do not forward mouse hover events]'
'--no-power-on[Do not power on the device on start]' '--no-power-on[Do not power on the device on start]'
'--no-video[Disable video forwarding]' '--no-video[Disable video forwarding]'
'--no-video-playback[Disable video playback]' '--no-video-playback[Disable video playback]'

View File

@ -317,6 +317,10 @@ Do not forward repeated key events when a key is held down.
.B \-\-no\-mipmaps .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. 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\-mouse\-hover
Do not forward mouse hover (mouse motion without any clicks) events.
.TP .TP
.B \-\-no\-power\-on .B \-\-no\-power\-on
Do not power on the device on start. Do not power on the device on start.

View File

@ -99,6 +99,7 @@ enum {
OPT_HID_MOUSE_DEPRECATED, OPT_HID_MOUSE_DEPRECATED,
OPT_NO_WINDOW, OPT_NO_WINDOW,
OPT_MOUSE_BIND, OPT_MOUSE_BIND,
OPT_NO_MOUSE_HOVER,
}; };
struct sc_option { struct sc_option {
@ -568,6 +569,12 @@ static const struct sc_option options[] = {
"mipmaps are automatically generated to improve downscaling " "mipmaps are automatically generated to improve downscaling "
"quality. This option disables the generation of mipmaps.", "quality. This option disables the generation of mipmaps.",
}, },
{
.longopt_id = OPT_NO_MOUSE_HOVER,
.longopt = "no-mouse-hover",
.text = "Do not forward mouse hover (mouse motion without any clicks) "
"events.",
},
{ {
.longopt_id = OPT_NO_POWER_ON, .longopt_id = OPT_NO_POWER_ON,
.longopt = "no-power-on", .longopt = "no-power-on",
@ -2198,6 +2205,9 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
return false; return false;
} }
break; break;
case OPT_NO_MOUSE_HOVER:
opts->mouse_hover = false;
break;
case OPT_HID_MOUSE_DEPRECATED: case OPT_HID_MOUSE_DEPRECATED:
LOGE("--hid-mouse has been removed, use --mouse=aoa or " LOGE("--hid-mouse has been removed, use --mouse=aoa or "
"--mouse=uhid instead."); "--mouse=uhid instead.");
@ -2758,6 +2768,12 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
} }
} }
if (opts->mouse_input_mode != SC_MOUSE_INPUT_MODE_SDK
&& !opts->mouse_hover) {
LOGE("--no-mouse-over is specific to --mouse=sdk");
return false;
}
if ((opts->tunnel_host || opts->tunnel_port) && !opts->force_adb_forward) { if ((opts->tunnel_host || opts->tunnel_port) && !opts->force_adb_forward) {
LOGI("Tunnel host/port is set, " LOGI("Tunnel host/port is set, "
"--force-adb-forward automatically enabled."); "--force-adb-forward automatically enabled.");

View File

@ -58,17 +58,18 @@ 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) { struct sc_mouse_sdk *m = DOWNCAST(mp);
if (!m->mouse_hover && !event->buttons_state) {
// Do not send motion events when no click is pressed // Do not send motion events when no click is pressed
return; return;
} }
struct sc_mouse_sdk *m = DOWNCAST(mp);
struct sc_control_msg msg = { struct sc_control_msg msg = {
.type = SC_CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT, .type = SC_CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT,
.inject_touch_event = { .inject_touch_event = {
.action = AMOTION_EVENT_ACTION_MOVE, .action = event->buttons_state ? AMOTION_EVENT_ACTION_MOVE
: AMOTION_EVENT_ACTION_HOVER_MOVE,
.pointer_id = event->pointer_id, .pointer_id = event->pointer_id,
.position = event->position, .position = event->position,
.pressure = 1.f, .pressure = 1.f,
@ -145,8 +146,10 @@ sc_mouse_processor_process_touch(struct sc_mouse_processor *mp,
} }
void void
sc_mouse_sdk_init(struct sc_mouse_sdk *m, struct sc_controller *controller) { sc_mouse_sdk_init(struct sc_mouse_sdk *m, struct sc_controller *controller,
bool mouse_hover) {
m->controller = controller; m->controller = controller;
m->mouse_hover = mouse_hover;
static const struct sc_mouse_processor_ops ops = { static const struct sc_mouse_processor_ops ops = {
.process_mouse_motion = sc_mouse_processor_process_mouse_motion, .process_mouse_motion = sc_mouse_processor_process_mouse_motion,

View File

@ -13,9 +13,11 @@ struct sc_mouse_sdk {
struct sc_mouse_processor mouse_processor; // mouse processor trait struct sc_mouse_processor mouse_processor; // mouse processor trait
struct sc_controller *controller; struct sc_controller *controller;
bool mouse_hover;
}; };
void void
sc_mouse_sdk_init(struct sc_mouse_sdk *m, struct sc_controller *controller); sc_mouse_sdk_init(struct sc_mouse_sdk *m, struct sc_controller *controller,
bool mouse_hover);
#endif #endif

View File

@ -92,6 +92,7 @@ const struct scrcpy_options scrcpy_options_default = {
.camera_high_speed = false, .camera_high_speed = false,
.list = 0, .list = 0,
.window = true, .window = true,
.mouse_hover = true,
}; };
enum sc_orientation enum sc_orientation

View File

@ -290,6 +290,7 @@ struct scrcpy_options {
#define SC_OPTION_LIST_CAMERA_SIZES 0x8 #define SC_OPTION_LIST_CAMERA_SIZES 0x8
uint8_t list; uint8_t list;
bool window; bool window;
bool mouse_hover;
}; };
extern const struct scrcpy_options scrcpy_options_default; extern const struct scrcpy_options scrcpy_options_default;

View File

@ -681,7 +681,8 @@ scrcpy(struct scrcpy_options *options) {
} }
if (options->mouse_input_mode == SC_MOUSE_INPUT_MODE_SDK) { if (options->mouse_input_mode == SC_MOUSE_INPUT_MODE_SDK) {
sc_mouse_sdk_init(&s->mouse_sdk, &s->controller); sc_mouse_sdk_init(&s->mouse_sdk, &s->controller,
options->mouse_hover);
mp = &s->mouse_sdk.mouse_processor; mp = &s->mouse_sdk.mouse_processor;
} else if (options->mouse_input_mode == SC_MOUSE_INPUT_MODE_UHID) { } else if (options->mouse_input_mode == SC_MOUSE_INPUT_MODE_UHID) {
bool ok = sc_mouse_uhid_init(&s->mouse_uhid, &s->controller); bool ok = sc_mouse_uhid_init(&s->mouse_uhid, &s->controller);

View File

@ -18,6 +18,14 @@ Note that on some devices, an additional option must be enabled in developer
options for this mouse mode to work. See options for this mouse mode to work. See
[prerequisites](/README.md#prerequisites). [prerequisites](/README.md#prerequisites).
### Mouse hover
By default, mouse hover (mouse motion without any clicks) events are forwarded
to the device. This can be disabled with:
```
scrcpy --no-mouse-hover
```
## Physical mouse simulation ## Physical mouse simulation