mirror of
https://github.com/Genymobile/scrcpy.git
synced 2024-09-12 05:21:18 +02:00
Add option to configure mouse bindings
Add a new option --mouse-bind=xxxx. The argument must be exactly 4 characters, one for each secondary click: --mouse-bind=xxxx ^^^^ |||| ||| `- 5th click || `-- 4th click | `--- middle click `---- right 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" This deprecates --forward-all-clicks (use --mouse-bind=++++ instead). Refs <https://github.com/Genymobile/scrcpy/pull/2258#issuecomment-2182394460> PR #5022 <https://github.com/Genymobile/scrcpy/pull/5022>
This commit is contained in:
parent
40493dff60
commit
035d60cf5d
15 changed files with 261 additions and 69 deletions
|
@ -25,7 +25,6 @@ _scrcpy() {
|
||||||
-e --select-tcpip
|
-e --select-tcpip
|
||||||
-f --fullscreen
|
-f --fullscreen
|
||||||
--force-adb-forward
|
--force-adb-forward
|
||||||
--forward-all-clicks
|
|
||||||
-h --help
|
-h --help
|
||||||
-K
|
-K
|
||||||
--keyboard=
|
--keyboard=
|
||||||
|
@ -41,6 +40,7 @@ _scrcpy() {
|
||||||
-M
|
-M
|
||||||
--max-fps=
|
--max-fps=
|
||||||
--mouse=
|
--mouse=
|
||||||
|
--mouse-bind=
|
||||||
-n --no-control
|
-n --no-control
|
||||||
-N --no-playback
|
-N --no-playback
|
||||||
--no-audio
|
--no-audio
|
||||||
|
|
|
@ -32,7 +32,6 @@ arguments=(
|
||||||
{-e,--select-tcpip}'[Use TCP/IP device]'
|
{-e,--select-tcpip}'[Use TCP/IP device]'
|
||||||
{-f,--fullscreen}'[Start in fullscreen]'
|
{-f,--fullscreen}'[Start in fullscreen]'
|
||||||
'--force-adb-forward[Do not attempt to use \"adb reverse\" to connect to the device]'
|
'--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]'
|
{-h,--help}'[Print the help]'
|
||||||
'-K[Use UHID keyboard (same as --keyboard=uhid)]'
|
'-K[Use UHID keyboard (same as --keyboard=uhid)]'
|
||||||
'--keyboard=[Set the keyboard input mode]:mode:(disabled sdk uhid aoa)'
|
'--keyboard=[Set the keyboard input mode]:mode:(disabled sdk uhid aoa)'
|
||||||
|
@ -47,6 +46,7 @@ arguments=(
|
||||||
'-M[Use UHID mouse (same as --mouse=uhid)]'
|
'-M[Use UHID mouse (same as --mouse=uhid)]'
|
||||||
'--max-fps=[Limit the frame rate of screen capture]'
|
'--max-fps=[Limit the frame rate of screen capture]'
|
||||||
'--mouse=[Set the mouse input mode]:mode:(disabled sdk uhid aoa)'
|
'--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-control}'[Disable device control \(mirror the device in read only\)]'
|
||||||
{-N,--no-playback}'[Disable video and audio playback]'
|
{-N,--no-playback}'[Disable video and audio playback]'
|
||||||
'--no-audio[Disable audio forwarding]'
|
'--no-audio[Disable audio forwarding]'
|
||||||
|
|
21
app/scrcpy.1
21
app/scrcpy.1
|
@ -163,10 +163,6 @@ Start in fullscreen.
|
||||||
.B \-\-force\-adb\-forward
|
.B \-\-force\-adb\-forward
|
||||||
Do not attempt to use "adb reverse" to connect to the device.
|
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
|
.TP
|
||||||
.B \-h, \-\-help
|
.B \-h, \-\-help
|
||||||
Print this help.
|
Print this help.
|
||||||
|
@ -261,6 +257,23 @@ LAlt, LSuper or RSuper toggle the capture mode, to give control of the mouse bac
|
||||||
|
|
||||||
Also see \fB\-\-keyboard\fR.
|
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'.
|
||||||
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-n, \-\-no\-control
|
.B \-n, \-\-no\-control
|
||||||
|
|
|
@ -98,6 +98,7 @@ enum {
|
||||||
OPT_HID_KEYBOARD_DEPRECATED,
|
OPT_HID_KEYBOARD_DEPRECATED,
|
||||||
OPT_HID_MOUSE_DEPRECATED,
|
OPT_HID_MOUSE_DEPRECATED,
|
||||||
OPT_NO_WINDOW,
|
OPT_NO_WINDOW,
|
||||||
|
OPT_MOUSE_BIND,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sc_option {
|
struct sc_option {
|
||||||
|
@ -352,11 +353,9 @@ static const struct sc_option options[] = {
|
||||||
"device.",
|
"device.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// deprecated
|
||||||
.longopt_id = OPT_FORWARD_ALL_CLICKS,
|
.longopt_id = OPT_FORWARD_ALL_CLICKS,
|
||||||
.longopt = "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',
|
.shortopt = 'h',
|
||||||
|
@ -490,6 +489,23 @@ static const struct sc_option options[] = {
|
||||||
"control of the mouse back to the computer.\n"
|
"control of the mouse back to the computer.\n"
|
||||||
"Also see --keyboard.",
|
"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'.",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.shortopt = 'n',
|
.shortopt = 'n',
|
||||||
.longopt = "no-control",
|
.longopt = "no-control",
|
||||||
|
@ -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
|
static bool
|
||||||
parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||||
const char *optstring, const struct option *longopts) {
|
const char *optstring, const struct option *longopts) {
|
||||||
|
@ -2125,6 +2193,11 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case OPT_MOUSE_BIND:
|
||||||
|
if (!parse_mouse_bindings(optarg, &opts->mouse_bindings)) {
|
||||||
|
return 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.");
|
||||||
|
@ -2322,7 +2395,14 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPT_FORWARD_ALL_CLICKS:
|
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;
|
break;
|
||||||
case OPT_LEGACY_PASTE:
|
case OPT_LEGACY_PASTE:
|
||||||
opts->legacy_paste = true;
|
opts->legacy_paste = true;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <SDL2/SDL_events.h>
|
#include <SDL2/SDL_events.h>
|
||||||
|
|
||||||
#include "coords.h"
|
#include "coords.h"
|
||||||
|
#include "options.h"
|
||||||
|
|
||||||
/* The representation of input events in scrcpy is very close to the SDL API,
|
/* The representation of input events in scrcpy is very close to the SDL API,
|
||||||
* for simplicity.
|
* for simplicity.
|
||||||
|
@ -437,15 +438,21 @@ sc_mouse_button_from_sdl(uint8_t button) {
|
||||||
|
|
||||||
static inline uint8_t
|
static inline uint8_t
|
||||||
sc_mouse_buttons_state_from_sdl(uint32_t buttons_state,
|
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
|
assert(buttons_state < 0x100); // fits in uint8_t
|
||||||
|
|
||||||
uint8_t mask = SC_MOUSE_BUTTON_LEFT;
|
uint8_t mask = SC_MOUSE_BUTTON_LEFT;
|
||||||
if (forward_all_clicks) {
|
if (!mb || mb->right_click == SC_MOUSE_BINDING_CLICK) {
|
||||||
mask |= SC_MOUSE_BUTTON_RIGHT
|
mask |= SC_MOUSE_BUTTON_RIGHT;
|
||||||
| SC_MOUSE_BUTTON_MIDDLE
|
}
|
||||||
| SC_MOUSE_BUTTON_X1
|
if (!mb || mb->middle_click == SC_MOUSE_BINDING_CLICK) {
|
||||||
| SC_MOUSE_BUTTON_X2;
|
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;
|
return buttons_state & mask;
|
||||||
|
|
|
@ -52,6 +52,14 @@ is_shortcut_key(struct sc_input_manager *im, SDL_Keycode keycode) {
|
||||||
|| (im->sdl_shortcut_mods & KMOD_RGUI && keycode == SDLK_RGUI);
|
|| (im->sdl_shortcut_mods & KMOD_RGUI && keycode == SDLK_RGUI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
mouse_bindings_has_secondary_click(const struct sc_mouse_bindings *mb) {
|
||||||
|
return mb->right_click == SC_MOUSE_BINDING_CLICK
|
||||||
|
|| mb->middle_click == SC_MOUSE_BINDING_CLICK
|
||||||
|
|| mb->click4 == SC_MOUSE_BINDING_CLICK
|
||||||
|
|| mb->click5 == SC_MOUSE_BINDING_CLICK;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sc_input_manager_init(struct sc_input_manager *im,
|
sc_input_manager_init(struct sc_input_manager *im,
|
||||||
const struct sc_input_manager_params *params) {
|
const struct sc_input_manager_params *params) {
|
||||||
|
@ -67,7 +75,9 @@ sc_input_manager_init(struct sc_input_manager *im,
|
||||||
im->kp = params->kp;
|
im->kp = params->kp;
|
||||||
im->mp = params->mp;
|
im->mp = params->mp;
|
||||||
|
|
||||||
im->forward_all_clicks = params->forward_all_clicks;
|
im->mouse_bindings = params->mouse_bindings;
|
||||||
|
im->has_secondary_click =
|
||||||
|
mouse_bindings_has_secondary_click(&im->mouse_bindings);
|
||||||
im->legacy_paste = params->legacy_paste;
|
im->legacy_paste = params->legacy_paste;
|
||||||
im->clipboard_autosync = params->clipboard_autosync;
|
im->clipboard_autosync = params->clipboard_autosync;
|
||||||
|
|
||||||
|
@ -366,8 +376,8 @@ simulate_virtual_finger(struct sc_input_manager *im,
|
||||||
msg.inject_touch_event.position.screen_size = im->screen->frame_size;
|
msg.inject_touch_event.position.screen_size = im->screen->frame_size;
|
||||||
msg.inject_touch_event.position.point = point;
|
msg.inject_touch_event.position.point = point;
|
||||||
msg.inject_touch_event.pointer_id =
|
msg.inject_touch_event.pointer_id =
|
||||||
im->forward_all_clicks ? POINTER_ID_VIRTUAL_MOUSE
|
im->has_secondary_click ? POINTER_ID_VIRTUAL_MOUSE
|
||||||
: POINTER_ID_VIRTUAL_FINGER;
|
: POINTER_ID_VIRTUAL_FINGER;
|
||||||
msg.inject_touch_event.pressure = up ? 0.0f : 1.0f;
|
msg.inject_touch_event.pressure = up ? 0.0f : 1.0f;
|
||||||
msg.inject_touch_event.action_button = 0;
|
msg.inject_touch_event.action_button = 0;
|
||||||
msg.inject_touch_event.buttons = 0;
|
msg.inject_touch_event.buttons = 0;
|
||||||
|
@ -652,13 +662,12 @@ sc_input_manager_process_mouse_motion(struct sc_input_manager *im,
|
||||||
|
|
||||||
struct sc_mouse_motion_event evt = {
|
struct sc_mouse_motion_event evt = {
|
||||||
.position = sc_input_manager_get_position(im, event->x, event->y),
|
.position = sc_input_manager_get_position(im, event->x, event->y),
|
||||||
.pointer_id = im->forward_all_clicks ? POINTER_ID_MOUSE
|
.pointer_id = im->has_secondary_click ? POINTER_ID_MOUSE
|
||||||
: POINTER_ID_GENERIC_FINGER,
|
: POINTER_ID_GENERIC_FINGER,
|
||||||
.xrel = event->xrel,
|
.xrel = event->xrel,
|
||||||
.yrel = event->yrel,
|
.yrel = event->yrel,
|
||||||
.buttons_state =
|
.buttons_state =
|
||||||
sc_mouse_buttons_state_from_sdl(event->state,
|
sc_mouse_buttons_state_from_sdl(event->state, &im->mouse_bindings),
|
||||||
im->forward_all_clicks),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
assert(im->mp->ops->process_mouse_motion);
|
assert(im->mp->ops->process_mouse_motion);
|
||||||
|
@ -709,6 +718,25 @@ sc_input_manager_process_touch(struct sc_input_manager *im,
|
||||||
im->mp->ops->process_touch(im->mp, &evt);
|
im->mp->ops->process_touch(im->mp, &evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum sc_mouse_binding
|
||||||
|
sc_input_manager_get_binding(const struct sc_mouse_bindings *bindings,
|
||||||
|
uint8_t sdl_button) {
|
||||||
|
switch (sdl_button) {
|
||||||
|
case SDL_BUTTON_LEFT:
|
||||||
|
return SC_MOUSE_BINDING_CLICK;
|
||||||
|
case SDL_BUTTON_RIGHT:
|
||||||
|
return bindings->right_click;
|
||||||
|
case SDL_BUTTON_MIDDLE:
|
||||||
|
return bindings->middle_click;
|
||||||
|
case SDL_BUTTON_X1:
|
||||||
|
return bindings->click4;
|
||||||
|
case SDL_BUTTON_X2:
|
||||||
|
return bindings->click5;
|
||||||
|
default:
|
||||||
|
return SC_MOUSE_BINDING_DISABLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
||||||
const SDL_MouseButtonEvent *event) {
|
const SDL_MouseButtonEvent *event) {
|
||||||
|
@ -720,28 +748,42 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
||||||
bool control = im->controller;
|
bool control = im->controller;
|
||||||
bool paused = im->screen->paused;
|
bool paused = im->screen->paused;
|
||||||
bool down = event->type == SDL_MOUSEBUTTONDOWN;
|
bool down = event->type == SDL_MOUSEBUTTONDOWN;
|
||||||
if (control && !paused && !im->forward_all_clicks) {
|
if (control && !paused) {
|
||||||
enum sc_action action = down ? SC_ACTION_DOWN : SC_ACTION_UP;
|
enum sc_action action = down ? SC_ACTION_DOWN : SC_ACTION_UP;
|
||||||
|
|
||||||
if (im->kp && event->button == SDL_BUTTON_X1) {
|
enum sc_mouse_binding binding =
|
||||||
action_app_switch(im, action);
|
sc_input_manager_get_binding(&im->mouse_bindings, event->button);
|
||||||
return;
|
switch (binding) {
|
||||||
}
|
case SC_MOUSE_BINDING_DISABLED:
|
||||||
if (event->button == SDL_BUTTON_X2 && down) {
|
// ignore click
|
||||||
if (event->clicks < 2) {
|
return;
|
||||||
expand_notification_panel(im);
|
case SC_MOUSE_BINDING_BACK:
|
||||||
} else {
|
if (im->kp) {
|
||||||
expand_settings_panel(im);
|
press_back_or_turn_screen_on(im, action);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
case SC_MOUSE_BINDING_HOME:
|
||||||
if (im->kp && event->button == SDL_BUTTON_RIGHT) {
|
if (im->kp) {
|
||||||
press_back_or_turn_screen_on(im, action);
|
action_home(im, action);
|
||||||
return;
|
}
|
||||||
}
|
return;
|
||||||
if (im->kp && event->button == SDL_BUTTON_MIDDLE) {
|
case SC_MOUSE_BINDING_APP_SWITCH:
|
||||||
action_home(im, action);
|
if (im->kp) {
|
||||||
return;
|
action_app_switch(im, action);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case SC_MOUSE_BINDING_EXPAND_NOTIFICATION_PANEL:
|
||||||
|
if (down) {
|
||||||
|
if (event->clicks < 2) {
|
||||||
|
expand_notification_panel(im);
|
||||||
|
} else {
|
||||||
|
expand_settings_panel(im);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
assert(binding == SC_MOUSE_BINDING_CLICK);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,11 +816,10 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
||||||
.position = sc_input_manager_get_position(im, event->x, event->y),
|
.position = sc_input_manager_get_position(im, event->x, event->y),
|
||||||
.action = sc_action_from_sdl_mousebutton_type(event->type),
|
.action = sc_action_from_sdl_mousebutton_type(event->type),
|
||||||
.button = sc_mouse_button_from_sdl(event->button),
|
.button = sc_mouse_button_from_sdl(event->button),
|
||||||
.pointer_id = im->forward_all_clicks ? POINTER_ID_MOUSE
|
.pointer_id = im->has_secondary_click ? POINTER_ID_MOUSE
|
||||||
: POINTER_ID_GENERIC_FINGER,
|
: POINTER_ID_GENERIC_FINGER,
|
||||||
.buttons_state =
|
.buttons_state = sc_mouse_buttons_state_from_sdl(sdl_buttons_state,
|
||||||
sc_mouse_buttons_state_from_sdl(sdl_buttons_state,
|
&im->mouse_bindings),
|
||||||
im->forward_all_clicks),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
assert(im->mp->ops->process_mouse_click);
|
assert(im->mp->ops->process_mouse_click);
|
||||||
|
@ -854,8 +895,8 @@ sc_input_manager_process_mouse_wheel(struct sc_input_manager *im,
|
||||||
.hscroll = CLAMP(event->x, -1, 1),
|
.hscroll = CLAMP(event->x, -1, 1),
|
||||||
.vscroll = CLAMP(event->y, -1, 1),
|
.vscroll = CLAMP(event->y, -1, 1),
|
||||||
#endif
|
#endif
|
||||||
.buttons_state =
|
.buttons_state = sc_mouse_buttons_state_from_sdl(buttons,
|
||||||
sc_mouse_buttons_state_from_sdl(buttons, im->forward_all_clicks),
|
&im->mouse_bindings),
|
||||||
};
|
};
|
||||||
|
|
||||||
im->mp->ops->process_mouse_scroll(im->mp, &evt);
|
im->mp->ops->process_mouse_scroll(im->mp, &evt);
|
||||||
|
|
|
@ -22,7 +22,8 @@ struct sc_input_manager {
|
||||||
struct sc_key_processor *kp;
|
struct sc_key_processor *kp;
|
||||||
struct sc_mouse_processor *mp;
|
struct sc_mouse_processor *mp;
|
||||||
|
|
||||||
bool forward_all_clicks;
|
struct sc_mouse_bindings mouse_bindings;
|
||||||
|
bool has_secondary_click;
|
||||||
bool legacy_paste;
|
bool legacy_paste;
|
||||||
bool clipboard_autosync;
|
bool clipboard_autosync;
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ struct sc_input_manager_params {
|
||||||
struct sc_key_processor *kp;
|
struct sc_key_processor *kp;
|
||||||
struct sc_mouse_processor *mp;
|
struct sc_mouse_processor *mp;
|
||||||
|
|
||||||
bool forward_all_clicks;
|
struct sc_mouse_bindings mouse_bindings;
|
||||||
bool legacy_paste;
|
bool legacy_paste;
|
||||||
bool clipboard_autosync;
|
bool clipboard_autosync;
|
||||||
uint8_t shortcut_mods; // OR of enum sc_shortcut_mod values
|
uint8_t shortcut_mods; // OR of enum sc_shortcut_mod values
|
||||||
|
|
|
@ -23,6 +23,12 @@ const struct scrcpy_options scrcpy_options_default = {
|
||||||
.record_format = SC_RECORD_FORMAT_AUTO,
|
.record_format = SC_RECORD_FORMAT_AUTO,
|
||||||
.keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_AUTO,
|
.keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_AUTO,
|
||||||
.mouse_input_mode = SC_MOUSE_INPUT_MODE_AUTO,
|
.mouse_input_mode = SC_MOUSE_INPUT_MODE_AUTO,
|
||||||
|
.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,
|
||||||
|
},
|
||||||
.camera_facing = SC_CAMERA_FACING_ANY,
|
.camera_facing = SC_CAMERA_FACING_ANY,
|
||||||
.port_range = {
|
.port_range = {
|
||||||
.first = DEFAULT_LOCAL_PORT_RANGE_FIRST,
|
.first = DEFAULT_LOCAL_PORT_RANGE_FIRST,
|
||||||
|
@ -68,7 +74,6 @@ const struct scrcpy_options scrcpy_options_default = {
|
||||||
.force_adb_forward = false,
|
.force_adb_forward = false,
|
||||||
.disable_screensaver = false,
|
.disable_screensaver = false,
|
||||||
.forward_key_repeat = true,
|
.forward_key_repeat = true,
|
||||||
.forward_all_clicks = false,
|
|
||||||
.legacy_paste = false,
|
.legacy_paste = false,
|
||||||
.power_off_on_close = false,
|
.power_off_on_close = false,
|
||||||
.clipboard_autosync = true,
|
.clipboard_autosync = true,
|
||||||
|
|
|
@ -155,6 +155,22 @@ enum sc_mouse_input_mode {
|
||||||
SC_MOUSE_INPUT_MODE_AOA,
|
SC_MOUSE_INPUT_MODE_AOA,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum sc_mouse_binding {
|
||||||
|
SC_MOUSE_BINDING_DISABLED,
|
||||||
|
SC_MOUSE_BINDING_CLICK,
|
||||||
|
SC_MOUSE_BINDING_BACK,
|
||||||
|
SC_MOUSE_BINDING_HOME,
|
||||||
|
SC_MOUSE_BINDING_APP_SWITCH,
|
||||||
|
SC_MOUSE_BINDING_EXPAND_NOTIFICATION_PANEL,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sc_mouse_bindings {
|
||||||
|
enum sc_mouse_binding right_click;
|
||||||
|
enum sc_mouse_binding middle_click;
|
||||||
|
enum sc_mouse_binding click4;
|
||||||
|
enum sc_mouse_binding click5;
|
||||||
|
};
|
||||||
|
|
||||||
enum sc_key_inject_mode {
|
enum sc_key_inject_mode {
|
||||||
// Inject special keys, letters and space as key events.
|
// Inject special keys, letters and space as key events.
|
||||||
// Inject numbers and punctuation as text events.
|
// Inject numbers and punctuation as text events.
|
||||||
|
@ -208,6 +224,7 @@ struct scrcpy_options {
|
||||||
enum sc_record_format record_format;
|
enum sc_record_format record_format;
|
||||||
enum sc_keyboard_input_mode keyboard_input_mode;
|
enum sc_keyboard_input_mode keyboard_input_mode;
|
||||||
enum sc_mouse_input_mode mouse_input_mode;
|
enum sc_mouse_input_mode mouse_input_mode;
|
||||||
|
struct sc_mouse_bindings mouse_bindings;
|
||||||
enum sc_camera_facing camera_facing;
|
enum sc_camera_facing camera_facing;
|
||||||
struct sc_port_range port_range;
|
struct sc_port_range port_range;
|
||||||
uint32_t tunnel_host;
|
uint32_t tunnel_host;
|
||||||
|
@ -250,7 +267,6 @@ struct scrcpy_options {
|
||||||
bool force_adb_forward;
|
bool force_adb_forward;
|
||||||
bool disable_screensaver;
|
bool disable_screensaver;
|
||||||
bool forward_key_repeat;
|
bool forward_key_repeat;
|
||||||
bool forward_all_clicks;
|
|
||||||
bool legacy_paste;
|
bool legacy_paste;
|
||||||
bool power_off_on_close;
|
bool power_off_on_close;
|
||||||
bool clipboard_autosync;
|
bool clipboard_autosync;
|
||||||
|
|
|
@ -712,7 +712,7 @@ scrcpy(struct scrcpy_options *options) {
|
||||||
.fp = fp,
|
.fp = fp,
|
||||||
.kp = kp,
|
.kp = kp,
|
||||||
.mp = mp,
|
.mp = mp,
|
||||||
.forward_all_clicks = options->forward_all_clicks,
|
.mouse_bindings = options->mouse_bindings,
|
||||||
.legacy_paste = options->legacy_paste,
|
.legacy_paste = options->legacy_paste,
|
||||||
.clipboard_autosync = options->clipboard_autosync,
|
.clipboard_autosync = options->clipboard_autosync,
|
||||||
.shortcut_mods = options->shortcut_mods,
|
.shortcut_mods = options->shortcut_mods,
|
||||||
|
|
|
@ -481,7 +481,7 @@ sc_screen_init(struct sc_screen *screen,
|
||||||
.screen = screen,
|
.screen = screen,
|
||||||
.kp = params->kp,
|
.kp = params->kp,
|
||||||
.mp = params->mp,
|
.mp = params->mp,
|
||||||
.forward_all_clicks = params->forward_all_clicks,
|
.mouse_bindings = params->mouse_bindings,
|
||||||
.legacy_paste = params->legacy_paste,
|
.legacy_paste = params->legacy_paste,
|
||||||
.clipboard_autosync = params->clipboard_autosync,
|
.clipboard_autosync = params->clipboard_autosync,
|
||||||
.shortcut_mods = params->shortcut_mods,
|
.shortcut_mods = params->shortcut_mods,
|
||||||
|
|
|
@ -79,7 +79,7 @@ struct sc_screen_params {
|
||||||
struct sc_key_processor *kp;
|
struct sc_key_processor *kp;
|
||||||
struct sc_mouse_processor *mp;
|
struct sc_mouse_processor *mp;
|
||||||
|
|
||||||
bool forward_all_clicks;
|
struct sc_mouse_bindings mouse_bindings;
|
||||||
bool legacy_paste;
|
bool legacy_paste;
|
||||||
bool clipboard_autosync;
|
bool clipboard_autosync;
|
||||||
uint8_t shortcut_mods; // OR of enum sc_shortcut_mod values
|
uint8_t shortcut_mods; // OR of enum sc_shortcut_mod values
|
||||||
|
|
|
@ -169,7 +169,7 @@ sc_screen_otg_process_mouse_motion(struct sc_screen_otg *screen,
|
||||||
// .position not used for HID events
|
// .position not used for HID events
|
||||||
.xrel = event->xrel,
|
.xrel = event->xrel,
|
||||||
.yrel = event->yrel,
|
.yrel = event->yrel,
|
||||||
.buttons_state = sc_mouse_buttons_state_from_sdl(event->state, true),
|
.buttons_state = sc_mouse_buttons_state_from_sdl(event->state, NULL),
|
||||||
};
|
};
|
||||||
|
|
||||||
assert(mp->ops->process_mouse_motion);
|
assert(mp->ops->process_mouse_motion);
|
||||||
|
@ -189,7 +189,7 @@ sc_screen_otg_process_mouse_button(struct sc_screen_otg *screen,
|
||||||
.action = sc_action_from_sdl_mousebutton_type(event->type),
|
.action = sc_action_from_sdl_mousebutton_type(event->type),
|
||||||
.button = sc_mouse_button_from_sdl(event->button),
|
.button = sc_mouse_button_from_sdl(event->button),
|
||||||
.buttons_state =
|
.buttons_state =
|
||||||
sc_mouse_buttons_state_from_sdl(sdl_buttons_state, true),
|
sc_mouse_buttons_state_from_sdl(sdl_buttons_state, NULL),
|
||||||
};
|
};
|
||||||
|
|
||||||
assert(mp->ops->process_mouse_click);
|
assert(mp->ops->process_mouse_click);
|
||||||
|
@ -209,7 +209,7 @@ sc_screen_otg_process_mouse_wheel(struct sc_screen_otg *screen,
|
||||||
.hscroll = event->x,
|
.hscroll = event->x,
|
||||||
.vscroll = event->y,
|
.vscroll = event->y,
|
||||||
.buttons_state =
|
.buttons_state =
|
||||||
sc_mouse_buttons_state_from_sdl(sdl_buttons_state, true),
|
sc_mouse_buttons_state_from_sdl(sdl_buttons_state, NULL),
|
||||||
};
|
};
|
||||||
|
|
||||||
assert(mp->ops->process_mouse_scroll);
|
assert(mp->ops->process_mouse_scroll);
|
||||||
|
|
|
@ -106,15 +106,6 @@ only inverts _x_.
|
||||||
This only works for the default mouse mode (`--mouse=sdk`).
|
This only works for the default mouse mode (`--mouse=sdk`).
|
||||||
|
|
||||||
|
|
||||||
## Right-click and middle-click
|
|
||||||
|
|
||||||
By default, right-click triggers BACK (or POWER on) and middle-click triggers
|
|
||||||
HOME. To disable these shortcuts and forward the clicks to the device instead:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
scrcpy --forward-all-clicks
|
|
||||||
```
|
|
||||||
|
|
||||||
## File drop
|
## File drop
|
||||||
|
|
||||||
### Install APK
|
### Install APK
|
||||||
|
|
38
doc/mouse.md
38
doc/mouse.md
|
@ -68,3 +68,41 @@ debugging disabled (see [OTG](otg.md)).
|
||||||
Note: On Windows, it may only work in [OTG mode](otg.md), not while mirroring
|
Note: On Windows, it may only work in [OTG mode](otg.md), not while mirroring
|
||||||
(it is not possible to open a USB device if it is already open by another
|
(it is not possible to open a USB device if it is already open by another
|
||||||
process like the _adb daemon_).
|
process like the _adb daemon_).
|
||||||
|
|
||||||
|
|
||||||
|
## Mouse bindings
|
||||||
|
|
||||||
|
By default, right-click triggers BACK (or POWER on) and middle-click triggers
|
||||||
|
HOME. In addition, the 4th click triggers APP_SWITCH and the 5th click expands
|
||||||
|
the notification panel.
|
||||||
|
|
||||||
|
The shortcuts can be configured using `--mouse-bind=xxxx`. The argument must be
|
||||||
|
exactly 4 characters, one for each secondary click:
|
||||||
|
|
||||||
|
```
|
||||||
|
--mouse-bind=xxxx
|
||||||
|
^^^^
|
||||||
|
||||
|
||||||
|
||| `- 5th click
|
||||||
|
|| `-- 4th click
|
||||||
|
| `--- middle click
|
||||||
|
`---- right 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"
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scrcpy --mouse-bind=bhsn # the default mode
|
||||||
|
scrcpy --mouse-bind=++++ # forward all clicks
|
||||||
|
scrcpy --mouse-bind=++bh # forward right and middle clicks,
|
||||||
|
# use 4th and 5th for BACK and HOME
|
||||||
|
```
|
||||||
|
|
Loading…
Reference in a new issue