mirror of
https://github.com/Genymobile/scrcpy.git
synced 2026-03-06 12:14:28 +01:00
Compare commits
10 Commits
device_dis
...
bindings_s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9989668226 | ||
|
|
6baea57987 | ||
|
|
86b8286217 | ||
|
|
51fee79bf5 | ||
|
|
6808288823 | ||
|
|
0bce4d7f56 | ||
|
|
6d98766cd5 | ||
|
|
487a6b9cf4 | ||
|
|
b50f9eb41d | ||
|
|
46041e0cc0 |
10
app/scrcpy.1
10
app/scrcpy.1
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
119
app/src/cli.c
119
app/src/cli.c
@@ -493,11 +493,17 @@ 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"
|
||||
@@ -505,7 +511,8 @@ static const struct sc_option options[] = {
|
||||
" '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',
|
||||
@@ -2095,24 +2102,46 @@ 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[1], &mbs->middle_click)) {
|
||||
return false;
|
||||
}
|
||||
if (!parse_mouse_binding(s[2], &mbs->click4)) {
|
||||
return false;
|
||||
}
|
||||
if (!parse_mouse_binding(s[3], &mbs->click5)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parse_mouse_binding(s[0], &mb->right_click)) {
|
||||
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(s[1], &mb->middle_click)) {
|
||||
|
||||
if (!parse_mouse_binding_set(s, &mb->pri)) {
|
||||
return false;
|
||||
}
|
||||
if (!parse_mouse_binding(s[2], &mb->click4)) {
|
||||
return false;
|
||||
}
|
||||
if (!parse_mouse_binding(s[3], &mb->click5)) {
|
||||
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;
|
||||
@@ -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:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -43,6 +43,10 @@ sc_display_init(struct sc_display *display, SDL_Window *window,
|
||||
|
||||
display->mipmaps = false;
|
||||
|
||||
#ifdef SC_DISPLAY_FORCE_OPENGL_CORE_PROFILE
|
||||
display->gl_context = NULL;
|
||||
#endif
|
||||
|
||||
// starts with "opengl"
|
||||
bool use_opengl = renderer_name && !strncmp(renderer_name, "opengl", 6);
|
||||
if (use_opengl) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -52,14 +52,6 @@ is_shortcut_key(struct sc_input_manager *im, SDL_Keycode keycode) {
|
||||
|| (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
|
||||
sc_input_manager_init(struct sc_input_manager *im,
|
||||
const struct sc_input_manager_params *params) {
|
||||
@@ -76,8 +68,6 @@ sc_input_manager_init(struct sc_input_manager *im,
|
||||
im->mp = params->mp;
|
||||
|
||||
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->clipboard_autosync = params->clipboard_autosync;
|
||||
|
||||
@@ -87,6 +77,8 @@ sc_input_manager_init(struct sc_input_manager *im,
|
||||
im->vfinger_invert_x = false;
|
||||
im->vfinger_invert_y = false;
|
||||
|
||||
im->mouse_buttons_state = 0;
|
||||
|
||||
im->last_keycode = SDLK_UNKNOWN;
|
||||
im->last_mod = 0;
|
||||
im->key_repeat = 0;
|
||||
@@ -375,9 +367,7 @@ simulate_virtual_finger(struct sc_input_manager *im,
|
||||
msg.inject_touch_event.action = action;
|
||||
msg.inject_touch_event.position.screen_size = im->screen->frame_size;
|
||||
msg.inject_touch_event.position.point = point;
|
||||
msg.inject_touch_event.pointer_id =
|
||||
im->has_secondary_click ? POINTER_ID_VIRTUAL_MOUSE
|
||||
: POINTER_ID_VIRTUAL_FINGER;
|
||||
msg.inject_touch_event.pointer_id = SC_POINTER_ID_VIRTUAL_FINGER;
|
||||
msg.inject_touch_event.pressure = up ? 0.0f : 1.0f;
|
||||
msg.inject_touch_event.action_button = 0;
|
||||
msg.inject_touch_event.buttons = 0;
|
||||
@@ -662,12 +652,11 @@ sc_input_manager_process_mouse_motion(struct sc_input_manager *im,
|
||||
|
||||
struct sc_mouse_motion_event evt = {
|
||||
.position = sc_input_manager_get_position(im, event->x, event->y),
|
||||
.pointer_id = im->has_secondary_click ? POINTER_ID_MOUSE
|
||||
: POINTER_ID_GENERIC_FINGER,
|
||||
.pointer_id = im->vfinger_down ? SC_POINTER_ID_GENERIC_FINGER
|
||||
: SC_POINTER_ID_MOUSE,
|
||||
.xrel = event->xrel,
|
||||
.yrel = event->yrel,
|
||||
.buttons_state =
|
||||
sc_mouse_buttons_state_from_sdl(event->state, &im->mouse_bindings),
|
||||
.buttons_state = im->mouse_buttons_state,
|
||||
};
|
||||
|
||||
assert(im->mp->ops->process_mouse_motion);
|
||||
@@ -719,7 +708,7 @@ sc_input_manager_process_touch(struct sc_input_manager *im,
|
||||
}
|
||||
|
||||
static enum sc_mouse_binding
|
||||
sc_input_manager_get_binding(const struct sc_mouse_bindings *bindings,
|
||||
sc_input_manager_get_binding(const struct sc_mouse_binding_set *bindings,
|
||||
uint8_t sdl_button) {
|
||||
switch (sdl_button) {
|
||||
case SDL_BUTTON_LEFT:
|
||||
@@ -748,11 +737,25 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
||||
bool control = im->controller;
|
||||
bool paused = im->screen->paused;
|
||||
bool down = event->type == SDL_MOUSEBUTTONDOWN;
|
||||
|
||||
enum sc_mouse_button button = sc_mouse_button_from_sdl(event->button);
|
||||
if (!down) {
|
||||
// Mark the button as released
|
||||
im->mouse_buttons_state &= ~button;
|
||||
}
|
||||
|
||||
SDL_Keymod keymod = SDL_GetModState();
|
||||
bool ctrl_pressed = keymod & KMOD_CTRL;
|
||||
bool shift_pressed = keymod & KMOD_SHIFT;
|
||||
|
||||
if (control && !paused) {
|
||||
enum sc_action action = down ? SC_ACTION_DOWN : SC_ACTION_UP;
|
||||
|
||||
struct sc_mouse_binding_set *bindings = !shift_pressed
|
||||
? &im->mouse_bindings.pri
|
||||
: &im->mouse_bindings.sec;
|
||||
enum sc_mouse_binding binding =
|
||||
sc_input_manager_get_binding(&im->mouse_bindings, event->button);
|
||||
sc_input_manager_get_binding(bindings, event->button);
|
||||
assert(binding != SC_MOUSE_BINDING_AUTO);
|
||||
switch (binding) {
|
||||
case SC_MOUSE_BINDING_DISABLED:
|
||||
@@ -811,16 +814,23 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t sdl_buttons_state = SDL_GetMouseState(NULL, NULL);
|
||||
if (down) {
|
||||
// Mark the button as pressed
|
||||
im->mouse_buttons_state |= button;
|
||||
}
|
||||
|
||||
bool change_vfinger = event->button == SDL_BUTTON_LEFT &&
|
||||
((down && !im->vfinger_down && (ctrl_pressed ^ shift_pressed)) ||
|
||||
(!down && im->vfinger_down));
|
||||
bool use_finger = im->vfinger_down || change_vfinger;
|
||||
|
||||
struct sc_mouse_click_event evt = {
|
||||
.position = sc_input_manager_get_position(im, event->x, event->y),
|
||||
.action = sc_action_from_sdl_mousebutton_type(event->type),
|
||||
.button = sc_mouse_button_from_sdl(event->button),
|
||||
.pointer_id = im->has_secondary_click ? POINTER_ID_MOUSE
|
||||
: POINTER_ID_GENERIC_FINGER,
|
||||
.buttons_state = sc_mouse_buttons_state_from_sdl(sdl_buttons_state,
|
||||
&im->mouse_bindings),
|
||||
.pointer_id = use_finger ? SC_POINTER_ID_GENERIC_FINGER
|
||||
: SC_POINTER_ID_MOUSE,
|
||||
.buttons_state = im->mouse_buttons_state,
|
||||
};
|
||||
|
||||
assert(im->mp->ops->process_mouse_click);
|
||||
@@ -846,14 +856,7 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
||||
// can be used instead of Ctrl. The "virtual finger" has a position
|
||||
// inverted with respect to the vertical axis of symmetry in the middle of
|
||||
// the screen.
|
||||
const SDL_Keymod keymod = SDL_GetModState();
|
||||
const bool ctrl_pressed = keymod & KMOD_CTRL;
|
||||
const bool shift_pressed = keymod & KMOD_SHIFT;
|
||||
if (event->button == SDL_BUTTON_LEFT &&
|
||||
((down && !im->vfinger_down &&
|
||||
((ctrl_pressed && !shift_pressed) ||
|
||||
(!ctrl_pressed && shift_pressed))) ||
|
||||
(!down && im->vfinger_down))) {
|
||||
if (change_vfinger) {
|
||||
struct sc_point mouse =
|
||||
sc_screen_convert_window_to_frame_coords(im->screen, event->x,
|
||||
event->y);
|
||||
@@ -886,6 +889,7 @@ sc_input_manager_process_mouse_wheel(struct sc_input_manager *im,
|
||||
int mouse_x;
|
||||
int mouse_y;
|
||||
uint32_t buttons = SDL_GetMouseState(&mouse_x, &mouse_y);
|
||||
(void) buttons; // Actual buttons are tracked manually to ignore shortcuts
|
||||
|
||||
struct sc_mouse_scroll_event evt = {
|
||||
.position = sc_input_manager_get_position(im, mouse_x, mouse_y),
|
||||
@@ -896,8 +900,7 @@ sc_input_manager_process_mouse_wheel(struct sc_input_manager *im,
|
||||
.hscroll = CLAMP(event->x, -1, 1),
|
||||
.vscroll = CLAMP(event->y, -1, 1),
|
||||
#endif
|
||||
.buttons_state = sc_mouse_buttons_state_from_sdl(buttons,
|
||||
&im->mouse_bindings),
|
||||
.buttons_state = im->mouse_buttons_state,
|
||||
};
|
||||
|
||||
im->mp->ops->process_mouse_scroll(im->mp, &evt);
|
||||
|
||||
@@ -23,7 +23,6 @@ struct sc_input_manager {
|
||||
struct sc_mouse_processor *mp;
|
||||
|
||||
struct sc_mouse_bindings mouse_bindings;
|
||||
bool has_secondary_click;
|
||||
bool legacy_paste;
|
||||
bool clipboard_autosync;
|
||||
|
||||
@@ -33,6 +32,8 @@ struct sc_input_manager {
|
||||
bool vfinger_invert_x;
|
||||
bool vfinger_invert_y;
|
||||
|
||||
uint8_t mouse_buttons_state; // OR of enum sc_mouse_button values
|
||||
|
||||
// Tracks the number of identical consecutive shortcut key down events.
|
||||
// Not to be confused with event->repeat, which counts the number of
|
||||
// system-generated repeated key presses.
|
||||
|
||||
@@ -24,10 +24,18 @@ const struct scrcpy_options scrcpy_options_default = {
|
||||
.keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_AUTO,
|
||||
.mouse_input_mode = SC_MOUSE_INPUT_MODE_AUTO,
|
||||
.mouse_bindings = {
|
||||
.right_click = SC_MOUSE_BINDING_AUTO,
|
||||
.middle_click = SC_MOUSE_BINDING_AUTO,
|
||||
.click4 = SC_MOUSE_BINDING_AUTO,
|
||||
.click5 = SC_MOUSE_BINDING_AUTO,
|
||||
.pri = {
|
||||
.right_click = SC_MOUSE_BINDING_AUTO,
|
||||
.middle_click = SC_MOUSE_BINDING_AUTO,
|
||||
.click4 = SC_MOUSE_BINDING_AUTO,
|
||||
.click5 = SC_MOUSE_BINDING_AUTO,
|
||||
},
|
||||
.sec = {
|
||||
.right_click = SC_MOUSE_BINDING_AUTO,
|
||||
.middle_click = SC_MOUSE_BINDING_AUTO,
|
||||
.click4 = SC_MOUSE_BINDING_AUTO,
|
||||
.click5 = SC_MOUSE_BINDING_AUTO,
|
||||
},
|
||||
},
|
||||
.camera_facing = SC_CAMERA_FACING_ANY,
|
||||
.port_range = {
|
||||
|
||||
@@ -165,13 +165,18 @@ enum sc_mouse_binding {
|
||||
SC_MOUSE_BINDING_EXPAND_NOTIFICATION_PANEL,
|
||||
};
|
||||
|
||||
struct sc_mouse_bindings {
|
||||
struct sc_mouse_binding_set {
|
||||
enum sc_mouse_binding right_click;
|
||||
enum sc_mouse_binding middle_click;
|
||||
enum sc_mouse_binding click4;
|
||||
enum sc_mouse_binding click5;
|
||||
};
|
||||
|
||||
struct sc_mouse_bindings {
|
||||
struct sc_mouse_binding_set pri;
|
||||
struct sc_mouse_binding_set sec; // When Shift is pressed
|
||||
};
|
||||
|
||||
enum sc_key_inject_mode {
|
||||
// Inject special keys, letters and space as key events.
|
||||
// Inject numbers and punctuation as text events.
|
||||
|
||||
@@ -169,7 +169,7 @@ sc_screen_otg_process_mouse_motion(struct sc_screen_otg *screen,
|
||||
// .position not used for HID events
|
||||
.xrel = event->xrel,
|
||||
.yrel = event->yrel,
|
||||
.buttons_state = sc_mouse_buttons_state_from_sdl(event->state, NULL),
|
||||
.buttons_state = sc_mouse_buttons_state_from_sdl(event->state),
|
||||
};
|
||||
|
||||
assert(mp->ops->process_mouse_motion);
|
||||
@@ -188,8 +188,7 @@ sc_screen_otg_process_mouse_button(struct sc_screen_otg *screen,
|
||||
// .position not used for HID events
|
||||
.action = sc_action_from_sdl_mousebutton_type(event->type),
|
||||
.button = sc_mouse_button_from_sdl(event->button),
|
||||
.buttons_state =
|
||||
sc_mouse_buttons_state_from_sdl(sdl_buttons_state, NULL),
|
||||
.buttons_state = sc_mouse_buttons_state_from_sdl(sdl_buttons_state),
|
||||
};
|
||||
|
||||
assert(mp->ops->process_mouse_click);
|
||||
@@ -208,8 +207,7 @@ sc_screen_otg_process_mouse_wheel(struct sc_screen_otg *screen,
|
||||
// .position not used for HID events
|
||||
.hscroll = event->x,
|
||||
.vscroll = event->y,
|
||||
.buttons_state =
|
||||
sc_mouse_buttons_state_from_sdl(sdl_buttons_state, NULL),
|
||||
.buttons_state = sc_mouse_buttons_state_from_sdl(sdl_buttons_state),
|
||||
};
|
||||
|
||||
assert(mp->ops->process_mouse_scroll);
|
||||
|
||||
52
doc/mouse.md
52
doc/mouse.md
@@ -80,21 +80,37 @@ process like the _adb daemon_).
|
||||
|
||||
## Mouse bindings
|
||||
|
||||
By default, with SDK mouse, 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.
|
||||
By default, with SDK mouse:
|
||||
- right-click triggers BACK (or POWER on)
|
||||
- middle-click triggers HOME
|
||||
- the 4th click triggers APP_SWITCH
|
||||
- the 5th click expands the notification panel
|
||||
|
||||
In AOA and UHID mouse modes, all clicks are forwarded by default.
|
||||
The secondary clicks may be forwarded to the device instead by pressing the
|
||||
<kbd>Shift</kbd> key (e.g. <kbd>Shift</kbd>+right-click injects a right click to
|
||||
the device).
|
||||
|
||||
The shortcuts can be configured using `--mouse-bind=xxxx` for any mouse mode.
|
||||
The argument must be exactly 4 characters, one for each secondary click:
|
||||
In AOA and UHID mouse modes, the default bindings are reversed: all clicks are
|
||||
forwarded by default, and pressing <kbd>Shift</kbd> gives access to the
|
||||
shortcuts (since the cursor is handled on the device side, it makes more sense
|
||||
to forward all mouse buttons by default in these modes).
|
||||
|
||||
The shortcuts can be configured using `--mouse-bind=xxxx:xxxx` for any mouse
|
||||
mode. The argument must be one or two sequences (separated by `:`) of exactly 4
|
||||
characters, one for each secondary click:
|
||||
|
||||
```
|
||||
--mouse-bind=xxxx
|
||||
.---- Shift + right click
|
||||
SECONDARY |.--- Shift + middle click
|
||||
BINDINGS ||.-- Shift + 4th click
|
||||
|||.- Shift + 5th click
|
||||
||||
|
||||
vvvv
|
||||
--mouse-bind=xxxx:xxxx
|
||||
^^^^
|
||||
||||
|
||||
||| `- 5th click
|
||||
|| `-- 4th click
|
||||
PRIMARY ||| `- 5th click
|
||||
BINDINGS || `-- 4th click
|
||||
| `--- middle click
|
||||
`---- right click
|
||||
```
|
||||
@@ -111,8 +127,18 @@ Each character must be one of the following:
|
||||
For example:
|
||||
|
||||
```bash
|
||||
scrcpy --mouse-bind=bhsn # the default mode with SDK mouse
|
||||
scrcpy --mouse-bind=++++ # forward all clicks (default for AOA/UHID)
|
||||
scrcpy --mouse-bind=++bh # forward right and middle clicks,
|
||||
# use 4th and 5th for BACK and HOME
|
||||
scrcpy --mouse-bind=bhsn:++++ # the default mode for SDK mouse
|
||||
scrcpy --mouse-bind=++++:bhsn # the default mode for AOA and UHID
|
||||
scrcpy --mouse-bind=++bh:++sn # forward right and middle clicks,
|
||||
# use 4th and 5th for BACK and HOME,
|
||||
# use Shift+4th and Shift+5th for APP_SWITCH
|
||||
# and expand notification panel
|
||||
```
|
||||
|
||||
The second sequence of bindings may be omitted. In that case, it is the same as
|
||||
the first one:
|
||||
|
||||
```bash
|
||||
scrcpy --mouse-bind=bhsn
|
||||
scrcpy --mouse-bind=bhsn:bhsn # equivalent
|
||||
```
|
||||
|
||||
@@ -22,7 +22,6 @@ public class Controller implements AsyncProcessor {
|
||||
|
||||
// control_msg.h values of the pointerId field in inject_touch_event message
|
||||
private static final int POINTER_ID_MOUSE = -1;
|
||||
private static final int POINTER_ID_VIRTUAL_MOUSE = -3;
|
||||
|
||||
private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
@@ -273,8 +272,8 @@ public class Controller implements AsyncProcessor {
|
||||
pointer.setPressure(pressure);
|
||||
|
||||
int source;
|
||||
if (pointerId == POINTER_ID_MOUSE || pointerId == POINTER_ID_VIRTUAL_MOUSE) {
|
||||
// real mouse event (forced by the client when --forward-on-click)
|
||||
if (pointerId == POINTER_ID_MOUSE) {
|
||||
// real mouse event
|
||||
pointerProperties[pointerIndex].toolType = MotionEvent.TOOL_TYPE_MOUSE;
|
||||
source = InputDevice.SOURCE_MOUSE;
|
||||
pointer.setUp(buttons == 0);
|
||||
|
||||
@@ -63,9 +63,11 @@ public final class Workarounds {
|
||||
// - <https://github.com/Genymobile/scrcpy/issues/940>
|
||||
// - <https://github.com/Genymobile/scrcpy/issues/994>
|
||||
mustFillAppInfo = true;
|
||||
} else if (Build.BRAND.equalsIgnoreCase("honor")) {
|
||||
} else if (Build.BRAND.equalsIgnoreCase("honor") || Build.MANUFACTURER.equalsIgnoreCase("skyworth")) {
|
||||
// More workarounds must be applied for Honor devices:
|
||||
// - <https://github.com/Genymobile/scrcpy/issues/4015>
|
||||
// and Skyworth devices:
|
||||
// - <https://github.com/Genymobile/scrcpy/issues/4922>
|
||||
//
|
||||
// The system context must not be set for all devices, because it would cause other problems:
|
||||
// - <https://github.com/Genymobile/scrcpy/issues/4015#issuecomment-1595382142>
|
||||
|
||||
Reference in New Issue
Block a user