Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to configure mouse bindings #5022

Merged
merged 2 commits into from
Jun 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/data/bash-completion/scrcpy
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ _scrcpy() {
-e --select-tcpip
-f --fullscreen
--force-adb-forward
--forward-all-clicks
-h --help
-K
--keyboard=
Expand All @@ -41,6 +40,7 @@ _scrcpy() {
-M
--max-fps=
--mouse=
--mouse-bind=
-n --no-control
-N --no-playback
--no-audio
Expand Down
2 changes: 1 addition & 1 deletion app/data/zsh-completion/_scrcpy
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ arguments=(
{-e,--select-tcpip}'[Use TCP/IP device]'
{-f,--fullscreen}'[Start in fullscreen]'
'--force-adb-forward[Do not attempt to use \"adb reverse\" to connect to the device]'
'--forward-all-clicks[Forward clicks to device]'
{-h,--help}'[Print the help]'
'-K[Use UHID keyboard (same as --keyboard=uhid)]'
'--keyboard=[Set the keyboard input mode]:mode:(disabled sdk uhid aoa)'
Expand All @@ -47,6 +46,7 @@ arguments=(
'-M[Use UHID mouse (same as --mouse=uhid)]'
'--max-fps=[Limit the frame rate of screen capture]'
'--mouse=[Set the mouse input mode]:mode:(disabled sdk uhid aoa)'
'--mouse-bind=[Configure bindings of secondary clicks]'
{-n,--no-control}'[Disable device control \(mirror the device in read only\)]'
{-N,--no-playback}'[Disable video and audio playback]'
'--no-audio[Disable audio forwarding]'
Expand Down
21 changes: 17 additions & 4 deletions app/scrcpy.1
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,6 @@ Start in fullscreen.
.B \-\-force\-adb\-forward
Do not attempt to use "adb reverse" to connect to the device.

.TP
.B \-\-forward\-all\-clicks
By default, right-click triggers BACK (or POWER on) and middle-click triggers HOME. This option disables these shortcuts and forward the clicks to the device instead.

.TP
.B \-h, \-\-help
Print this help.
Expand Down Expand Up @@ -261,6 +257,23 @@ LAlt, LSuper or RSuper toggle the capture mode, to give control of the mouse bac

Also see \fB\-\-keyboard\fR.

.TP
.BI "\-\-mouse\-bind " xxxx
Configure bindings of secondary clicks.

The argument must be exactly 4 characters, one for each secondary click (in order: right click, middle click, 4th click, 5th click).

Each character must be one of the following:

- '+': forward the click to the device
- '-': ignore the click
- 'b': trigger shortcut BACK (or turn screen on if off)
- 'h': trigger shortcut HOME
- 's': trigger shortcut APP_SWITCH
- 'n': trigger shortcut "expand notification panel"

Default is 'bhsn' for SDK mouse, and '++++' for AOA and UHID.


.TP
.B \-n, \-\-no\-control
Expand Down
112 changes: 108 additions & 4 deletions app/src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ enum {
OPT_HID_KEYBOARD_DEPRECATED,
OPT_HID_MOUSE_DEPRECATED,
OPT_NO_WINDOW,
OPT_MOUSE_BIND,
};

struct sc_option {
Expand Down Expand Up @@ -352,11 +353,9 @@ static const struct sc_option options[] = {
"device.",
},
{
// deprecated
.longopt_id = OPT_FORWARD_ALL_CLICKS,
.longopt = "forward-all-clicks",
.text = "By default, right-click triggers BACK (or POWER on) and "
"middle-click triggers HOME. This option disables these "
"shortcuts and forwards the clicks to the device instead.",
},
{
.shortopt = 'h',
Expand Down Expand Up @@ -490,6 +489,23 @@ static const struct sc_option options[] = {
"control of the mouse back to the computer.\n"
"Also see --keyboard.",
},
{
.longopt_id = OPT_MOUSE_BIND,
.longopt = "mouse-bind",
.argdesc = "xxxx",
.text = "Configure bindings of secondary clicks.\n"
"The argument must be exactly 4 characters, one for each "
"secondary click (in order: right click, middle click, 4th "
"click, 5th click).\n"
"Each character must be one of the following:\n"
" '+': forward the click to the device\n"
" '-': ignore the click\n"
" 'b': trigger shortcut BACK (or turn screen on if off)\n"
" 'h': trigger shortcut HOME\n"
" 's': trigger shortcut APP_SWITCH\n"
" 'n': trigger shortcut \"expand notification panel\"\n"
"Default is 'bhsn' for SDK mouse, and '++++' for AOA and UHID.",
},
{
.shortopt = 'n',
.longopt = "no-control",
Expand Down Expand Up @@ -2043,6 +2059,58 @@ parse_pause_on_exit(const char *s, enum sc_pause_on_exit *pause_on_exit) {

}

static bool
parse_mouse_binding(char c, enum sc_mouse_binding *b) {
switch (c) {
case '+':
*b = SC_MOUSE_BINDING_CLICK;
return true;
case '-':
*b = SC_MOUSE_BINDING_DISABLED;
return true;
case 'b':
*b = SC_MOUSE_BINDING_BACK;
return true;
case 'h':
*b = SC_MOUSE_BINDING_HOME;
return true;
case 's':
*b = SC_MOUSE_BINDING_APP_SWITCH;
return true;
case 'n':
*b = SC_MOUSE_BINDING_EXPAND_NOTIFICATION_PANEL;
return true;
default:
LOGE("Invalid mouse binding: '%c' "
"(expected '+', '-', 'b', 'h', 's' or 'n')", c);
return false;
}
}

static bool
parse_mouse_bindings(const char *s, struct sc_mouse_bindings *mb) {
if (strlen(s) != 4) {
LOGE("Invalid mouse bindings: '%s' (expected exactly 4 characters from "
"{'+', '-', 'b', 'h', 's', 'n'})", s);
return false;
}

if (!parse_mouse_binding(s[0], &mb->right_click)) {
return false;
}
if (!parse_mouse_binding(s[1], &mb->middle_click)) {
return false;
}
if (!parse_mouse_binding(s[2], &mb->click4)) {
return false;
}
if (!parse_mouse_binding(s[3], &mb->click5)) {
return false;
}

return true;
}

static bool
parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
const char *optstring, const struct option *longopts) {
Expand Down Expand Up @@ -2125,6 +2193,11 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
return false;
}
break;
case OPT_MOUSE_BIND:
if (!parse_mouse_bindings(optarg, &opts->mouse_bindings)) {
return false;
}
break;
case OPT_HID_MOUSE_DEPRECATED:
LOGE("--hid-mouse has been removed, use --mouse=aoa or "
"--mouse=uhid instead.");
Expand Down Expand Up @@ -2322,7 +2395,14 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
}
break;
case OPT_FORWARD_ALL_CLICKS:
opts->forward_all_clicks = true;
LOGW("--forward-all-clicks is deprecated, "
"use --mouse-bind=++++ instead.");
opts->mouse_bindings = (struct sc_mouse_bindings) {
.right_click = SC_MOUSE_BINDING_CLICK,
.middle_click = SC_MOUSE_BINDING_CLICK,
.click4 = SC_MOUSE_BINDING_CLICK,
.click5 = SC_MOUSE_BINDING_CLICK,
};
break;
case OPT_LEGACY_PASTE:
opts->legacy_paste = true;
Expand Down Expand Up @@ -2610,6 +2690,30 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
}
}

// If mouse bindings are not explictly set, configure default bindings
if (opts->mouse_bindings.right_click == SC_MOUSE_BINDING_AUTO) {
assert(opts->mouse_bindings.middle_click == SC_MOUSE_BINDING_AUTO);
assert(opts->mouse_bindings.click4 == SC_MOUSE_BINDING_AUTO);
assert(opts->mouse_bindings.click5 == SC_MOUSE_BINDING_AUTO);

// By default, forward all clicks only for UHID and AOA
if (opts->mouse_input_mode == SC_MOUSE_INPUT_MODE_SDK) {
opts->mouse_bindings = (struct sc_mouse_bindings) {
.right_click = SC_MOUSE_BINDING_BACK,
.middle_click = SC_MOUSE_BINDING_HOME,
.click4 = SC_MOUSE_BINDING_APP_SWITCH,
.click5 = SC_MOUSE_BINDING_EXPAND_NOTIFICATION_PANEL,
};
} else {
opts->mouse_bindings = (struct sc_mouse_bindings) {
.right_click = SC_MOUSE_BINDING_CLICK,
.middle_click = SC_MOUSE_BINDING_CLICK,
.click4 = SC_MOUSE_BINDING_CLICK,
.click5 = SC_MOUSE_BINDING_CLICK,
};
}
}

if (otg) {
if (!opts->control) {
LOGE("--no-control is not allowed in OTG mode");
Expand Down
19 changes: 13 additions & 6 deletions app/src/input_events.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <SDL2/SDL_events.h>

#include "coords.h"
#include "options.h"

/* The representation of input events in scrcpy is very close to the SDL API,
* for simplicity.
Expand Down Expand Up @@ -437,15 +438,21 @@ sc_mouse_button_from_sdl(uint8_t button) {

static inline uint8_t
sc_mouse_buttons_state_from_sdl(uint32_t buttons_state,
bool forward_all_clicks) {
const struct sc_mouse_bindings *mb) {
assert(buttons_state < 0x100); // fits in uint8_t

uint8_t mask = SC_MOUSE_BUTTON_LEFT;
if (forward_all_clicks) {
mask |= SC_MOUSE_BUTTON_RIGHT
| SC_MOUSE_BUTTON_MIDDLE
| SC_MOUSE_BUTTON_X1
| SC_MOUSE_BUTTON_X2;
if (!mb || mb->right_click == SC_MOUSE_BINDING_CLICK) {
mask |= SC_MOUSE_BUTTON_RIGHT;
}
if (!mb || mb->middle_click == SC_MOUSE_BINDING_CLICK) {
mask |= SC_MOUSE_BUTTON_MIDDLE;
}
if (!mb || mb->click4 == SC_MOUSE_BINDING_CLICK) {
mask |= SC_MOUSE_BUTTON_X1;
}
if (!mb || mb->click5 == SC_MOUSE_BINDING_CLICK) {
mask |= SC_MOUSE_BUTTON_X2;
}

return buttons_state & mask;
Expand Down
Loading