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

Improve mouse events and add secondary bindings #5076

Merged
merged 8 commits into from
Jul 11, 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
10 changes: 7 additions & 3 deletions app/scrcpy.1
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,14 @@ 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
.BI "\-\-mouse\-bind " xxxx[: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).
The argument must be one or two sequences (separated by ':') of exactly 4 characters, one for each secondary click (in order: right click, middle click, 4th click, 5th click).

The first sequence defines the primary bindings, used when a mouse button is pressed alone. The second sequence defines the secondary bindings, used when a mouse button is pressed while the Shift key is held.

If the second sequence of bindings is omitted, then it is the same as the first one.

Each character must be one of the following:

Expand All @@ -272,7 +276,7 @@ Each character must be one of the following:
- 's': trigger shortcut APP_SWITCH
- 'n': trigger shortcut "expand notification panel"

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


.TP
Expand Down
115 changes: 81 additions & 34 deletions app/src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,19 +493,26 @@ static const struct sc_option options[] = {
{
.longopt_id = OPT_MOUSE_BIND,
.longopt = "mouse-bind",
.argdesc = "xxxx",
.argdesc = "xxxx[: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"
"The argument must be one or two sequences (separated by ':') "
"of exactly 4 characters, one for each secondary click (in "
"order: right click, middle click, 4th click, 5th click).\n"
"The first sequence defines the primary bindings, used when a "
"mouse button is pressed alone. The second sequence defines "
"the secondary bindings, used when a mouse button is pressed "
"while the Shift key is held.\n"
"If the second sequence of bindings is omitted, then it is the "
"same as the first one.\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.",
"Default is 'bhsn:++++' for SDK mouse, and '++++:bhsn' for AOA "
"and UHID.",
},
{
.shortopt = 'n',
Expand Down Expand Up @@ -2095,26 +2102,48 @@ parse_mouse_binding(char c, enum sc_mouse_binding *b) {
}

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);
parse_mouse_binding_set(const char *s, struct sc_mouse_binding_set *mbs) {
assert(strlen(s) >= 4);

if (!parse_mouse_binding(s[0], &mbs->right_click)) {
return false;
}

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

return true;
}

static bool
parse_mouse_bindings(const char *s, struct sc_mouse_bindings *mb) {
size_t len = strlen(s);
// either "xxxx" or "xxxx:xxxx"
if (len != 4 && (len != 9 || s[4] != ':')) {
LOGE("Invalid mouse bindings: '%s' (expected 'xxxx' or 'xxxx:xxxx', "
"with each 'x' being in {'+', '-', 'b', 'h', 's', 'n'})", s);
return false;
}

if (!parse_mouse_binding_set(s, &mb->pri)) {
return false;
}

if (len == 9) {
if (!parse_mouse_binding_set(s + 5, &mb->sec)) {
return false;
}
} else {
// use the same bindings for Shift+click
mb->sec = mb->pri;
}

return true;
}

Expand Down Expand Up @@ -2408,10 +2437,18 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
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,
.pri = {
.right_click = SC_MOUSE_BINDING_CLICK,
.middle_click = SC_MOUSE_BINDING_CLICK,
.click4 = SC_MOUSE_BINDING_CLICK,
.click5 = SC_MOUSE_BINDING_CLICK,
},
.sec = {
.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:
Expand Down Expand Up @@ -2701,26 +2738,36 @@ 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);
if (opts->mouse_bindings.pri.right_click == SC_MOUSE_BINDING_AUTO) {
assert(opts->mouse_bindings.pri.middle_click == SC_MOUSE_BINDING_AUTO);
assert(opts->mouse_bindings.pri.click4 == SC_MOUSE_BINDING_AUTO);
assert(opts->mouse_bindings.pri.click5 == SC_MOUSE_BINDING_AUTO);
assert(opts->mouse_bindings.sec.right_click == SC_MOUSE_BINDING_AUTO);
assert(opts->mouse_bindings.sec.middle_click == SC_MOUSE_BINDING_AUTO);
assert(opts->mouse_bindings.sec.click4 == SC_MOUSE_BINDING_AUTO);
assert(opts->mouse_bindings.sec.click5 == SC_MOUSE_BINDING_AUTO);

static struct sc_mouse_binding_set default_shortcuts = {
.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,
};

static struct sc_mouse_binding_set forward = {
.right_click = SC_MOUSE_BINDING_CLICK,
.middle_click = SC_MOUSE_BINDING_CLICK,
.click4 = SC_MOUSE_BINDING_CLICK,
.click5 = SC_MOUSE_BINDING_CLICK,
};

// 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,
};
opts->mouse_bindings.pri = default_shortcuts;
opts->mouse_bindings.sec = forward;
} 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,
};
opts->mouse_bindings.pri = forward;
opts->mouse_bindings.sec = default_shortcuts;
}
}

Expand Down
8 changes: 3 additions & 5 deletions app/src/control_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,11 @@ static const char *const copy_key_labels[] = {
static inline const char *
get_well_known_pointer_id_name(uint64_t pointer_id) {
switch (pointer_id) {
case POINTER_ID_MOUSE:
case SC_POINTER_ID_MOUSE:
return "mouse";
case POINTER_ID_GENERIC_FINGER:
case SC_POINTER_ID_GENERIC_FINGER:
return "finger";
case POINTER_ID_VIRTUAL_MOUSE:
return "vmouse";
case POINTER_ID_VIRTUAL_FINGER:
case SC_POINTER_ID_VIRTUAL_FINGER:
return "vfinger";
default:
return NULL;
Expand Down
7 changes: 3 additions & 4 deletions app/src/control_msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@
// type: 1 byte; sequence: 8 bytes; paste flag: 1 byte; length: 4 bytes
#define SC_CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH (SC_CONTROL_MSG_MAX_SIZE - 14)

#define POINTER_ID_MOUSE UINT64_C(-1)
#define POINTER_ID_GENERIC_FINGER UINT64_C(-2)
#define SC_POINTER_ID_MOUSE UINT64_C(-1)
#define SC_POINTER_ID_GENERIC_FINGER UINT64_C(-2)

// Used for injecting an additional virtual pointer for pinch-to-zoom
#define POINTER_ID_VIRTUAL_MOUSE UINT64_C(-3)
#define POINTER_ID_VIRTUAL_FINGER UINT64_C(-4)
#define SC_POINTER_ID_VIRTUAL_FINGER UINT64_C(-3)

enum sc_control_msg_type {
SC_CONTROL_MSG_TYPE_INJECT_KEYCODE,
Expand Down
20 changes: 3 additions & 17 deletions app/src/input_events.h
Original file line number Diff line number Diff line change
Expand Up @@ -437,25 +437,11 @@ sc_mouse_button_from_sdl(uint8_t button) {
}

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

uint8_t mask = SC_MOUSE_BUTTON_LEFT;
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;
// SC_MOUSE_BUTTON_* constants are initialized from SDL_BUTTON(index)
return buttons_state;
}

#endif
Loading