Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
266644560d | ||
|
e572e841a8 | ||
|
faf99d4d2f |
@ -27,8 +27,8 @@ _scrcpy() {
|
|||||||
--force-adb-forward
|
--force-adb-forward
|
||||||
--forward-all-clicks
|
--forward-all-clicks
|
||||||
-h --help
|
-h --help
|
||||||
|
--keyboard
|
||||||
--kill-adb-on-close
|
--kill-adb-on-close
|
||||||
-K --hid-keyboard
|
|
||||||
--legacy-paste
|
--legacy-paste
|
||||||
--list-camera-sizes
|
--list-camera-sizes
|
||||||
--list-cameras
|
--list-cameras
|
||||||
@ -39,6 +39,7 @@ _scrcpy() {
|
|||||||
-m --max-size=
|
-m --max-size=
|
||||||
-M --hid-mouse
|
-M --hid-mouse
|
||||||
--max-fps=
|
--max-fps=
|
||||||
|
--mouse=
|
||||||
-n --no-control
|
-n --no-control
|
||||||
-N --no-playback
|
-N --no-playback
|
||||||
--no-audio
|
--no-audio
|
||||||
@ -115,6 +116,14 @@ _scrcpy() {
|
|||||||
COMPREPLY=($(compgen -W 'front back external' -- "$cur"))
|
COMPREPLY=($(compgen -W 'front back external' -- "$cur"))
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
|
--keyboard)
|
||||||
|
COMPREPLY=($(compgen -W 'disabled sdk aoa' -- "$cur"))
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
--mouse)
|
||||||
|
COMPREPLY=($(compgen -W 'disabled sdk aoa' -- "$cur"))
|
||||||
|
return
|
||||||
|
;;
|
||||||
--orientation|--display-orientation)
|
--orientation|--display-orientation)
|
||||||
COMPREPLY=($(compgen -W '0 90 180 270 flip0 flip90 flip180 flip270' -- "$cur"))
|
COMPREPLY=($(compgen -W '0 90 180 270 flip0 flip90 flip180 flip270' -- "$cur"))
|
||||||
return
|
return
|
||||||
|
@ -34,8 +34,8 @@ arguments=(
|
|||||||
'--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]'
|
'--forward-all-clicks[Forward clicks to device]'
|
||||||
{-h,--help}'[Print the help]'
|
{-h,--help}'[Print the help]'
|
||||||
|
'--keyboard[Set the keyboard input mode]:mode:(disabled sdk aoa)'
|
||||||
'--kill-adb-on-close[Kill adb when scrcpy terminates]'
|
'--kill-adb-on-close[Kill adb when scrcpy terminates]'
|
||||||
{-K,--hid-keyboard}'[Simulate a physical keyboard by using HID over AOAv2]'
|
|
||||||
'--legacy-paste[Inject computer clipboard text as a sequence of key events on Ctrl+v]'
|
'--legacy-paste[Inject computer clipboard text as a sequence of key events on Ctrl+v]'
|
||||||
'--list-camera-sizes[List the valid camera capture sizes]'
|
'--list-camera-sizes[List the valid camera capture sizes]'
|
||||||
'--list-cameras[List cameras available on the device]'
|
'--list-cameras[List cameras available on the device]'
|
||||||
@ -45,6 +45,7 @@ arguments=(
|
|||||||
{-m,--max-size=}'[Limit both the width and height of the video to value]'
|
{-m,--max-size=}'[Limit both the width and height of the video to value]'
|
||||||
{-M,--hid-mouse}'[Simulate a physical mouse by using HID over AOAv2]'
|
{-M,--hid-mouse}'[Simulate a physical mouse by using HID over AOAv2]'
|
||||||
'--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 aoa)'
|
||||||
{-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]'
|
||||||
|
47
app/scrcpy.1
47
app/scrcpy.1
@ -172,24 +172,26 @@ By default, right-click triggers BACK (or POWER on) and middle-click triggers HO
|
|||||||
Print this help.
|
Print this help.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-kill\-adb\-on\-close
|
.BI "\-\-keyboard " mode
|
||||||
Kill adb when scrcpy terminates.
|
Select how to send keyboard inputs to the device.
|
||||||
|
|
||||||
.TP
|
Possible values are "disabled", "sdk" and "aoa":
|
||||||
.B \-K, \-\-hid\-keyboard
|
|
||||||
Simulate a physical keyboard by using HID over AOAv2.
|
|
||||||
|
|
||||||
This provides a better experience for IME users, and allows to generate non-ASCII characters, contrary to the default injection method.
|
- "disabled" does not send keyboard inputs to the device.
|
||||||
|
- "sdk" uses the Android system API to deliver keyboard events to applications.
|
||||||
|
- "aoa" simulates a physical keyboard using the AOAv2 protocol. It may only work over USB.
|
||||||
|
|
||||||
It may only work over USB.
|
For "aoa", the keyboard layout must be configured (once and for all) on the device, via Settings -> System -> Languages and input -> Physical keyboard. This settings page can be started directly:
|
||||||
|
|
||||||
The keyboard layout must be configured (once and for all) on the device, via Settings -> System -> Languages and input -> Physical keyboard. This settings page can be started directly:
|
|
||||||
|
|
||||||
adb shell am start -a android.settings.HARD_KEYBOARD_SETTINGS
|
adb shell am start -a android.settings.HARD_KEYBOARD_SETTINGS
|
||||||
|
|
||||||
However, the option is only available when the HID keyboard is enabled (or a physical keyboard is connected).
|
This option is only available when the HID keyboard is enabled (or a physical keyboard is connected).
|
||||||
|
|
||||||
Also see \fB\-\-hid\-mouse\fR.
|
Also see \fB\-\-mouse\fR.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-kill\-adb\-on\-close
|
||||||
|
Kill adb when scrcpy terminates.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-legacy\-paste
|
.B \-\-legacy\-paste
|
||||||
@ -230,20 +232,25 @@ Limit both the width and height of the video to \fIvalue\fR. The other dimension
|
|||||||
Default is 0 (unlimited).
|
Default is 0 (unlimited).
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-M, \-\-hid\-mouse
|
.BI "\-\-max\-fps " value
|
||||||
Simulate a physical mouse by using HID over AOAv2.
|
Limit the framerate of screen capture (officially supported since Android 10, but may work on earlier versions).
|
||||||
|
|
||||||
In this mode, the computer mouse is captured to control the device directly (relative mouse mode).
|
.TP
|
||||||
|
.BI "\-\-mouse " mode
|
||||||
|
Select how to send mouse inputs to the device.
|
||||||
|
|
||||||
|
Possible values are "disabled", "sdk" and "aoa":
|
||||||
|
|
||||||
|
- "disabled" does not send mouse inputs to the device.
|
||||||
|
- "sdk" uses the Android system API to deliver mouse events to applications.
|
||||||
|
- "aoa" simulates a physical mouse using the AOAv2 protocol. It may only work over USB.
|
||||||
|
|
||||||
|
In "aoa" mode, the computer mouse is captured to control the device directly (relative mouse mode).
|
||||||
|
|
||||||
LAlt, LSuper or RSuper toggle the capture mode, to give control of the mouse back to the computer.
|
LAlt, LSuper or RSuper toggle the capture mode, to give control of the mouse back to the computer.
|
||||||
|
|
||||||
It may only work over USB.
|
Also see \fB\-\-keyboard\fR.
|
||||||
|
|
||||||
Also see \fB\-\-hid\-keyboard\fR.
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.BI "\-\-max\-fps " value
|
|
||||||
Limit the framerate of screen capture (officially supported since Android 10, but may work on earlier versions).
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-n, \-\-no\-control
|
.B \-n, \-\-no\-control
|
||||||
|
169
app/src/cli.c
169
app/src/cli.c
@ -93,6 +93,8 @@ enum {
|
|||||||
OPT_DISPLAY_ORIENTATION,
|
OPT_DISPLAY_ORIENTATION,
|
||||||
OPT_RECORD_ORIENTATION,
|
OPT_RECORD_ORIENTATION,
|
||||||
OPT_ORIENTATION,
|
OPT_ORIENTATION,
|
||||||
|
OPT_KEYBOARD,
|
||||||
|
OPT_MOUSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sc_option {
|
struct sc_option {
|
||||||
@ -358,27 +360,35 @@ static const struct sc_option options[] = {
|
|||||||
.longopt = "help",
|
.longopt = "help",
|
||||||
.text = "Print this help.",
|
.text = "Print this help.",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.longopt_id = OPT_KEYBOARD,
|
||||||
|
.longopt = "keyboard",
|
||||||
|
.argdesc = "mode",
|
||||||
|
.text = "Select how to send keyboard inputs to the device.\n"
|
||||||
|
"Possible values are \"disabled\", \"sdk\" and \"aoa\".\n"
|
||||||
|
"\"disabled\" does not send keyboard inputs to the device.\n"
|
||||||
|
"\"sdk\" uses the Android system API to deliver keyboard\n"
|
||||||
|
"events to applications.\n"
|
||||||
|
"\"aoa\" simulates a physical keyboard using the AOAv2\n"
|
||||||
|
"protocol. It may only work over USB.\n"
|
||||||
|
"For \"aoa\", the keyboard layout must be configured (once and "
|
||||||
|
"for all) on the device, via Settings -> System -> Languages "
|
||||||
|
"and input -> Physical keyboard. This settings page can be "
|
||||||
|
"started directly: `adb shell am start -a "
|
||||||
|
"android.settings.HARD_KEYBOARD_SETTINGS`.\n"
|
||||||
|
"This option is only available when the HID keyboard is "
|
||||||
|
"enabled (or a physical keyboard is connected).\n"
|
||||||
|
"Also see --mouse.",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.longopt_id = OPT_KILL_ADB_ON_CLOSE,
|
.longopt_id = OPT_KILL_ADB_ON_CLOSE,
|
||||||
.longopt = "kill-adb-on-close",
|
.longopt = "kill-adb-on-close",
|
||||||
.text = "Kill adb when scrcpy terminates.",
|
.text = "Kill adb when scrcpy terminates.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// deprecated
|
||||||
.shortopt = 'K',
|
.shortopt = 'K',
|
||||||
.longopt = "hid-keyboard",
|
.longopt = "hid-keyboard",
|
||||||
.text = "Simulate a physical keyboard by using HID over AOAv2.\n"
|
|
||||||
"It provides a better experience for IME users, and allows to "
|
|
||||||
"generate non-ASCII characters, contrary to the default "
|
|
||||||
"injection method.\n"
|
|
||||||
"It may only work over USB.\n"
|
|
||||||
"The keyboard layout must be configured (once and for all) on "
|
|
||||||
"the device, via Settings -> System -> Languages and input -> "
|
|
||||||
"Physical keyboard. This settings page can be started "
|
|
||||||
"directly: `adb shell am start -a "
|
|
||||||
"android.settings.HARD_KEYBOARD_SETTINGS`.\n"
|
|
||||||
"However, the option is only available when the HID keyboard "
|
|
||||||
"is enabled (or a physical keyboard is connected).\n"
|
|
||||||
"Also see --hid-mouse.",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.longopt_id = OPT_LEGACY_PASTE,
|
.longopt_id = OPT_LEGACY_PASTE,
|
||||||
@ -432,15 +442,9 @@ static const struct sc_option options[] = {
|
|||||||
"Default is 0 (unlimited).",
|
"Default is 0 (unlimited).",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// deprecated
|
||||||
.shortopt = 'M',
|
.shortopt = 'M',
|
||||||
.longopt = "hid-mouse",
|
.longopt = "hid-mouse",
|
||||||
.text = "Simulate a physical mouse by using HID over AOAv2.\n"
|
|
||||||
"In this mode, the computer mouse is captured to control the "
|
|
||||||
"device directly (relative mouse mode).\n"
|
|
||||||
"LAlt, LSuper or RSuper toggle the capture mode, to give "
|
|
||||||
"control of the mouse back to the computer.\n"
|
|
||||||
"It may only work over USB.\n"
|
|
||||||
"Also see --hid-keyboard.",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.longopt_id = OPT_MAX_FPS,
|
.longopt_id = OPT_MAX_FPS,
|
||||||
@ -449,6 +453,23 @@ static const struct sc_option options[] = {
|
|||||||
.text = "Limit the frame rate of screen capture (officially supported "
|
.text = "Limit the frame rate of screen capture (officially supported "
|
||||||
"since Android 10, but may work on earlier versions).",
|
"since Android 10, but may work on earlier versions).",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.longopt_id = OPT_MOUSE,
|
||||||
|
.longopt = "mouse",
|
||||||
|
.argdesc = "mode",
|
||||||
|
.text = "Select how to send mouse inputs to the device.\n"
|
||||||
|
"Possible values are \"disabled\", \"sdk\" and \"aoa\".\n"
|
||||||
|
"\"disabled\" does not send mouse inputs to the device.\n"
|
||||||
|
"\"sdk\" uses the Android system API to deliver mouse\n"
|
||||||
|
"events to applications.\n"
|
||||||
|
"\"aoa\" simulates a physical mouse using the AOAv2 protocol\n"
|
||||||
|
"It may only work over USB.\n"
|
||||||
|
"In \"aoa\" mode, the computer mouse is captured to control "
|
||||||
|
"the device directly (relative mouse mode).\n"
|
||||||
|
"LAlt, LSuper or RSuper toggle the capture mode, to give "
|
||||||
|
"control of the mouse back to the computer.\n"
|
||||||
|
"Also see --keyboard.",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.shortopt = 'n',
|
.shortopt = 'n',
|
||||||
.longopt = "no-control",
|
.longopt = "no-control",
|
||||||
@ -543,10 +564,10 @@ static const struct sc_option options[] = {
|
|||||||
"mirroring is disabled.\n"
|
"mirroring is disabled.\n"
|
||||||
"LAlt, LSuper or RSuper toggle the mouse capture mode, to give "
|
"LAlt, LSuper or RSuper toggle the mouse capture mode, to give "
|
||||||
"control of the mouse back to the computer.\n"
|
"control of the mouse back to the computer.\n"
|
||||||
"If any of --hid-keyboard or --hid-mouse is set, only enable "
|
"Keyboard and mouse may be disabled separately using\n"
|
||||||
"keyboard or mouse respectively, otherwise enable both.\n"
|
"--keyboard=disabled and --mouse=disabled.\n"
|
||||||
"It may only work over USB.\n"
|
"It may only work over USB.\n"
|
||||||
"See --hid-keyboard and --hid-mouse.",
|
"See --keyboard and --mouse.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.shortopt = 'p',
|
.shortopt = 'p',
|
||||||
@ -1902,6 +1923,58 @@ parse_camera_fps(const char *s, uint16_t *camera_fps) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_keyboard(const char *optarg, enum sc_keyboard_input_mode *mode) {
|
||||||
|
if (!strcmp(optarg, "disabled")) {
|
||||||
|
*mode = SC_KEYBOARD_INPUT_MODE_DISABLED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(optarg, "sdk")) {
|
||||||
|
*mode = SC_KEYBOARD_INPUT_MODE_SDK;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(optarg, "aoa")) {
|
||||||
|
#ifdef HAVE_USB
|
||||||
|
*mode = SC_KEYBOARD_INPUT_MODE_AOA;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
LOGE("--keyboard=aoa is disabled.");
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGE("Unsupported keyboard: %s (expected disabled, sdk or aoa)", optarg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_mouse(const char *optarg, enum sc_mouse_input_mode *mode) {
|
||||||
|
if (!strcmp(optarg, "disabled")) {
|
||||||
|
*mode = SC_MOUSE_INPUT_MODE_DISABLED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(optarg, "sdk")) {
|
||||||
|
*mode = SC_MOUSE_INPUT_MODE_SDK;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(optarg, "aoa")) {
|
||||||
|
#ifdef HAVE_USB
|
||||||
|
*mode = SC_MOUSE_INPUT_MODE_AOA;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
LOGE("--mouse=aoa is disabled.");
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGE("Unsupported mouse: %s (expected disabled, sdk or aoa)", optarg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
parse_time_limit(const char *s, sc_tick *tick) {
|
parse_time_limit(const char *s, sc_tick *tick) {
|
||||||
long value;
|
long value;
|
||||||
@ -1991,12 +2064,19 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
|||||||
break;
|
break;
|
||||||
case 'K':
|
case 'K':
|
||||||
#ifdef HAVE_USB
|
#ifdef HAVE_USB
|
||||||
opts->keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_HID;
|
LOGW("-K/--hid-keyboard is deprecated, use --keyboard=aoa "
|
||||||
|
"instead.");
|
||||||
|
opts->keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_AOA;
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
LOGE("HID over AOA (-K/--hid-keyboard) is disabled.");
|
LOGE("HID over AOA (-K/--hid-keyboard) is disabled.");
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
case OPT_KEYBOARD:
|
||||||
|
if (!parse_keyboard(optarg, &opts->keyboard_input_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case OPT_MAX_FPS:
|
case OPT_MAX_FPS:
|
||||||
if (!parse_max_fps(optarg, &opts->max_fps)) {
|
if (!parse_max_fps(optarg, &opts->max_fps)) {
|
||||||
return false;
|
return false;
|
||||||
@ -2009,12 +2089,18 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
|||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
#ifdef HAVE_USB
|
#ifdef HAVE_USB
|
||||||
opts->mouse_input_mode = SC_MOUSE_INPUT_MODE_HID;
|
LOGW("-M/--hid-mouse is deprecated, use --mouse=aoa instead.");
|
||||||
|
opts->mouse_input_mode = SC_MOUSE_INPUT_MODE_AOA;
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
LOGE("HID over AOA (-M/--hid-mouse) is disabled.");
|
LOGE("HID over AOA (-M/--hid-mouse) is disabled.");
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
case OPT_MOUSE:
|
||||||
|
if (!parse_mouse(optarg, &opts->mouse_input_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case OPT_LOCK_VIDEO_ORIENTATION:
|
case OPT_LOCK_VIDEO_ORIENTATION:
|
||||||
if (!parse_lock_video_orientation(optarg,
|
if (!parse_lock_video_orientation(optarg,
|
||||||
&opts->lock_video_orientation)) {
|
&opts->lock_video_orientation)) {
|
||||||
@ -2461,6 +2547,31 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (opts->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_AUTO) {
|
||||||
|
opts->keyboard_input_mode = otg ? SC_KEYBOARD_INPUT_MODE_AOA
|
||||||
|
: SC_KEYBOARD_INPUT_MODE_SDK;
|
||||||
|
}
|
||||||
|
if (opts->mouse_input_mode == SC_MOUSE_INPUT_MODE_AUTO) {
|
||||||
|
opts->mouse_input_mode = otg ? SC_MOUSE_INPUT_MODE_AOA
|
||||||
|
: SC_MOUSE_INPUT_MODE_SDK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (otg) {
|
||||||
|
enum sc_keyboard_input_mode kmode = opts->keyboard_input_mode;
|
||||||
|
if (kmode != SC_KEYBOARD_INPUT_MODE_AOA
|
||||||
|
&& kmode != SC_KEYBOARD_INPUT_MODE_DISABLED) {
|
||||||
|
LOGE("In OTG mode, --keyboard only supports aoa or disabled.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum sc_mouse_input_mode mmode = opts->mouse_input_mode;
|
||||||
|
if (mmode != SC_MOUSE_INPUT_MODE_AOA
|
||||||
|
&& mmode != SC_MOUSE_INPUT_MODE_DISABLED) {
|
||||||
|
LOGE("In OTG mode, --mouse only supports aoa or disabled.");
|
||||||
|
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.");
|
||||||
@ -2621,12 +2732,12 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
if (!otg && (opts->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_HID
|
if (!otg && (opts->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_AOA
|
||||||
|| opts->mouse_input_mode == SC_MOUSE_INPUT_MODE_HID)) {
|
|| opts->mouse_input_mode == SC_MOUSE_INPUT_MODE_AOA)) {
|
||||||
LOGE("On Windows, it is not possible to open a USB device already open "
|
LOGE("On Windows, it is not possible to open a USB device already open "
|
||||||
"by another process (like adb).");
|
"by another process (like adb).");
|
||||||
LOGE("Therefore, -K/--hid-keyboard and -M/--hid-mouse may only work in "
|
LOGE("Therefore, --keyboard=aoa and --mouse=aoa may only work in OTG"
|
||||||
"OTG mode (--otg).");
|
"mode (--otg).");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
@ -52,8 +52,11 @@ is_shortcut_mod(struct sc_input_manager *im, uint16_t sdl_mod) {
|
|||||||
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) {
|
||||||
assert(!params->controller || (params->kp && params->kp->ops));
|
// A key/mouse processor may not be present if there is no controller
|
||||||
assert(!params->controller || (params->mp && params->mp->ops));
|
assert((!params->kp && !params->mp) || params->controller);
|
||||||
|
// A processor must have ops initialized
|
||||||
|
assert(!params->kp || params->kp->ops);
|
||||||
|
assert(!params->mp || params->mp->ops);
|
||||||
|
|
||||||
im->controller = params->controller;
|
im->controller = params->controller;
|
||||||
im->fp = params->fp;
|
im->fp = params->fp;
|
||||||
@ -87,8 +90,10 @@ sc_input_manager_init(struct sc_input_manager *im,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
send_keycode(struct sc_controller *controller, enum android_keycode keycode,
|
send_keycode(struct sc_input_manager *im, enum android_keycode keycode,
|
||||||
enum sc_action action, const char *name) {
|
enum sc_action action, const char *name) {
|
||||||
|
assert(im->controller && im->kp);
|
||||||
|
|
||||||
// send DOWN event
|
// send DOWN event
|
||||||
struct sc_control_msg msg;
|
struct sc_control_msg msg;
|
||||||
msg.type = SC_CONTROL_MSG_TYPE_INJECT_KEYCODE;
|
msg.type = SC_CONTROL_MSG_TYPE_INJECT_KEYCODE;
|
||||||
@ -99,100 +104,109 @@ send_keycode(struct sc_controller *controller, enum android_keycode keycode,
|
|||||||
msg.inject_keycode.metastate = 0;
|
msg.inject_keycode.metastate = 0;
|
||||||
msg.inject_keycode.repeat = 0;
|
msg.inject_keycode.repeat = 0;
|
||||||
|
|
||||||
if (!sc_controller_push_msg(controller, &msg)) {
|
if (!sc_controller_push_msg(im->controller, &msg)) {
|
||||||
LOGW("Could not request 'inject %s'", name);
|
LOGW("Could not request 'inject %s'", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
action_home(struct sc_controller *controller, enum sc_action action) {
|
action_home(struct sc_input_manager *im, enum sc_action action) {
|
||||||
send_keycode(controller, AKEYCODE_HOME, action, "HOME");
|
send_keycode(im, AKEYCODE_HOME, action, "HOME");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
action_back(struct sc_controller *controller, enum sc_action action) {
|
action_back(struct sc_input_manager *im, enum sc_action action) {
|
||||||
send_keycode(controller, AKEYCODE_BACK, action, "BACK");
|
send_keycode(im, AKEYCODE_BACK, action, "BACK");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
action_app_switch(struct sc_controller *controller, enum sc_action action) {
|
action_app_switch(struct sc_input_manager *im, enum sc_action action) {
|
||||||
send_keycode(controller, AKEYCODE_APP_SWITCH, action, "APP_SWITCH");
|
send_keycode(im, AKEYCODE_APP_SWITCH, action, "APP_SWITCH");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
action_power(struct sc_controller *controller, enum sc_action action) {
|
action_power(struct sc_input_manager *im, enum sc_action action) {
|
||||||
send_keycode(controller, AKEYCODE_POWER, action, "POWER");
|
send_keycode(im, AKEYCODE_POWER, action, "POWER");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
action_volume_up(struct sc_controller *controller, enum sc_action action) {
|
action_volume_up(struct sc_input_manager *im, enum sc_action action) {
|
||||||
send_keycode(controller, AKEYCODE_VOLUME_UP, action, "VOLUME_UP");
|
send_keycode(im, AKEYCODE_VOLUME_UP, action, "VOLUME_UP");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
action_volume_down(struct sc_controller *controller, enum sc_action action) {
|
action_volume_down(struct sc_input_manager *im, enum sc_action action) {
|
||||||
send_keycode(controller, AKEYCODE_VOLUME_DOWN, action, "VOLUME_DOWN");
|
send_keycode(im, AKEYCODE_VOLUME_DOWN, action, "VOLUME_DOWN");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
action_menu(struct sc_controller *controller, enum sc_action action) {
|
action_menu(struct sc_input_manager *im, enum sc_action action) {
|
||||||
send_keycode(controller, AKEYCODE_MENU, action, "MENU");
|
send_keycode(im, AKEYCODE_MENU, action, "MENU");
|
||||||
}
|
}
|
||||||
|
|
||||||
// turn the screen on if it was off, press BACK otherwise
|
// turn the screen on if it was off, press BACK otherwise
|
||||||
// If the screen is off, it is turned on only on ACTION_DOWN
|
// If the screen is off, it is turned on only on ACTION_DOWN
|
||||||
static void
|
static void
|
||||||
press_back_or_turn_screen_on(struct sc_controller *controller,
|
press_back_or_turn_screen_on(struct sc_input_manager *im,
|
||||||
enum sc_action action) {
|
enum sc_action action) {
|
||||||
|
assert(im->controller && im->kp);
|
||||||
|
|
||||||
struct sc_control_msg msg;
|
struct sc_control_msg msg;
|
||||||
msg.type = SC_CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON;
|
msg.type = SC_CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON;
|
||||||
msg.back_or_screen_on.action = action == SC_ACTION_DOWN
|
msg.back_or_screen_on.action = action == SC_ACTION_DOWN
|
||||||
? AKEY_EVENT_ACTION_DOWN
|
? AKEY_EVENT_ACTION_DOWN
|
||||||
: AKEY_EVENT_ACTION_UP;
|
: AKEY_EVENT_ACTION_UP;
|
||||||
|
|
||||||
if (!sc_controller_push_msg(controller, &msg)) {
|
if (!sc_controller_push_msg(im->controller, &msg)) {
|
||||||
LOGW("Could not request 'press back or turn screen on'");
|
LOGW("Could not request 'press back or turn screen on'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
expand_notification_panel(struct sc_controller *controller) {
|
expand_notification_panel(struct sc_input_manager *im) {
|
||||||
|
assert(im->controller);
|
||||||
|
|
||||||
struct sc_control_msg msg;
|
struct sc_control_msg msg;
|
||||||
msg.type = SC_CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL;
|
msg.type = SC_CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL;
|
||||||
|
|
||||||
if (!sc_controller_push_msg(controller, &msg)) {
|
if (!sc_controller_push_msg(im->controller, &msg)) {
|
||||||
LOGW("Could not request 'expand notification panel'");
|
LOGW("Could not request 'expand notification panel'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
expand_settings_panel(struct sc_controller *controller) {
|
expand_settings_panel(struct sc_input_manager *im) {
|
||||||
|
assert(im->controller);
|
||||||
|
|
||||||
struct sc_control_msg msg;
|
struct sc_control_msg msg;
|
||||||
msg.type = SC_CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL;
|
msg.type = SC_CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL;
|
||||||
|
|
||||||
if (!sc_controller_push_msg(controller, &msg)) {
|
if (!sc_controller_push_msg(im->controller, &msg)) {
|
||||||
LOGW("Could not request 'expand settings panel'");
|
LOGW("Could not request 'expand settings panel'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
collapse_panels(struct sc_controller *controller) {
|
collapse_panels(struct sc_input_manager *im) {
|
||||||
|
assert(im->controller);
|
||||||
|
|
||||||
struct sc_control_msg msg;
|
struct sc_control_msg msg;
|
||||||
msg.type = SC_CONTROL_MSG_TYPE_COLLAPSE_PANELS;
|
msg.type = SC_CONTROL_MSG_TYPE_COLLAPSE_PANELS;
|
||||||
|
|
||||||
if (!sc_controller_push_msg(controller, &msg)) {
|
if (!sc_controller_push_msg(im->controller, &msg)) {
|
||||||
LOGW("Could not request 'collapse notification panel'");
|
LOGW("Could not request 'collapse notification panel'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
get_device_clipboard(struct sc_controller *controller,
|
get_device_clipboard(struct sc_input_manager *im, enum sc_copy_key copy_key) {
|
||||||
enum sc_copy_key copy_key) {
|
assert(im->controller && im->kp);
|
||||||
|
|
||||||
struct sc_control_msg msg;
|
struct sc_control_msg msg;
|
||||||
msg.type = SC_CONTROL_MSG_TYPE_GET_CLIPBOARD;
|
msg.type = SC_CONTROL_MSG_TYPE_GET_CLIPBOARD;
|
||||||
msg.get_clipboard.copy_key = copy_key;
|
msg.get_clipboard.copy_key = copy_key;
|
||||||
|
|
||||||
if (!sc_controller_push_msg(controller, &msg)) {
|
if (!sc_controller_push_msg(im->controller, &msg)) {
|
||||||
LOGW("Could not request 'get device clipboard'");
|
LOGW("Could not request 'get device clipboard'");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -201,8 +215,10 @@ get_device_clipboard(struct sc_controller *controller,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
set_device_clipboard(struct sc_controller *controller, bool paste,
|
set_device_clipboard(struct sc_input_manager *im, bool paste,
|
||||||
uint64_t sequence) {
|
uint64_t sequence) {
|
||||||
|
assert(im->controller && im->kp);
|
||||||
|
|
||||||
char *text = SDL_GetClipboardText();
|
char *text = SDL_GetClipboardText();
|
||||||
if (!text) {
|
if (!text) {
|
||||||
LOGW("Could not get clipboard text: %s", SDL_GetError());
|
LOGW("Could not get clipboard text: %s", SDL_GetError());
|
||||||
@ -222,7 +238,7 @@ set_device_clipboard(struct sc_controller *controller, bool paste,
|
|||||||
msg.set_clipboard.text = text_dup;
|
msg.set_clipboard.text = text_dup;
|
||||||
msg.set_clipboard.paste = paste;
|
msg.set_clipboard.paste = paste;
|
||||||
|
|
||||||
if (!sc_controller_push_msg(controller, &msg)) {
|
if (!sc_controller_push_msg(im->controller, &msg)) {
|
||||||
free(text_dup);
|
free(text_dup);
|
||||||
LOGW("Could not request 'set device clipboard'");
|
LOGW("Could not request 'set device clipboard'");
|
||||||
return false;
|
return false;
|
||||||
@ -232,19 +248,23 @@ set_device_clipboard(struct sc_controller *controller, bool paste,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_screen_power_mode(struct sc_controller *controller,
|
set_screen_power_mode(struct sc_input_manager *im,
|
||||||
enum sc_screen_power_mode mode) {
|
enum sc_screen_power_mode mode) {
|
||||||
|
assert(im->controller);
|
||||||
|
|
||||||
struct sc_control_msg msg;
|
struct sc_control_msg msg;
|
||||||
msg.type = SC_CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE;
|
msg.type = SC_CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE;
|
||||||
msg.set_screen_power_mode.mode = mode;
|
msg.set_screen_power_mode.mode = mode;
|
||||||
|
|
||||||
if (!sc_controller_push_msg(controller, &msg)) {
|
if (!sc_controller_push_msg(im->controller, &msg)) {
|
||||||
LOGW("Could not request 'set screen power mode'");
|
LOGW("Could not request 'set screen power mode'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
switch_fps_counter_state(struct sc_fps_counter *fps_counter) {
|
switch_fps_counter_state(struct sc_input_manager *im) {
|
||||||
|
struct sc_fps_counter *fps_counter = &im->screen->fps_counter;
|
||||||
|
|
||||||
// the started state can only be written from the current thread, so there
|
// the started state can only be written from the current thread, so there
|
||||||
// is no ToCToU issue
|
// is no ToCToU issue
|
||||||
if (sc_fps_counter_is_started(fps_counter)) {
|
if (sc_fps_counter_is_started(fps_counter)) {
|
||||||
@ -256,7 +276,9 @@ switch_fps_counter_state(struct sc_fps_counter *fps_counter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clipboard_paste(struct sc_controller *controller) {
|
clipboard_paste(struct sc_input_manager *im) {
|
||||||
|
assert(im->controller && im->kp);
|
||||||
|
|
||||||
char *text = SDL_GetClipboardText();
|
char *text = SDL_GetClipboardText();
|
||||||
if (!text) {
|
if (!text) {
|
||||||
LOGW("Could not get clipboard text: %s", SDL_GetError());
|
LOGW("Could not get clipboard text: %s", SDL_GetError());
|
||||||
@ -278,25 +300,28 @@ clipboard_paste(struct sc_controller *controller) {
|
|||||||
struct sc_control_msg msg;
|
struct sc_control_msg msg;
|
||||||
msg.type = SC_CONTROL_MSG_TYPE_INJECT_TEXT;
|
msg.type = SC_CONTROL_MSG_TYPE_INJECT_TEXT;
|
||||||
msg.inject_text.text = text_dup;
|
msg.inject_text.text = text_dup;
|
||||||
if (!sc_controller_push_msg(controller, &msg)) {
|
if (!sc_controller_push_msg(im->controller, &msg)) {
|
||||||
free(text_dup);
|
free(text_dup);
|
||||||
LOGW("Could not request 'paste clipboard'");
|
LOGW("Could not request 'paste clipboard'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rotate_device(struct sc_controller *controller) {
|
rotate_device(struct sc_input_manager *im) {
|
||||||
|
assert(im->controller);
|
||||||
|
|
||||||
struct sc_control_msg msg;
|
struct sc_control_msg msg;
|
||||||
msg.type = SC_CONTROL_MSG_TYPE_ROTATE_DEVICE;
|
msg.type = SC_CONTROL_MSG_TYPE_ROTATE_DEVICE;
|
||||||
|
|
||||||
if (!sc_controller_push_msg(controller, &msg)) {
|
if (!sc_controller_push_msg(im->controller, &msg)) {
|
||||||
LOGW("Could not request device rotation");
|
LOGW("Could not request device rotation");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
apply_orientation_transform(struct sc_screen *screen,
|
apply_orientation_transform(struct sc_input_manager *im,
|
||||||
enum sc_orientation transform) {
|
enum sc_orientation transform) {
|
||||||
|
struct sc_screen *screen = im->screen;
|
||||||
enum sc_orientation new_orientation =
|
enum sc_orientation new_orientation =
|
||||||
sc_orientation_apply(screen->orientation, transform);
|
sc_orientation_apply(screen->orientation, transform);
|
||||||
sc_screen_set_orientation(screen, new_orientation);
|
sc_screen_set_orientation(screen, new_orientation);
|
||||||
@ -364,7 +389,7 @@ static void
|
|||||||
sc_input_manager_process_key(struct sc_input_manager *im,
|
sc_input_manager_process_key(struct sc_input_manager *im,
|
||||||
const SDL_KeyboardEvent *event) {
|
const SDL_KeyboardEvent *event) {
|
||||||
// controller is NULL if --no-control is requested
|
// controller is NULL if --no-control is requested
|
||||||
struct sc_controller *controller = im->controller;
|
bool control = im->controller;
|
||||||
|
|
||||||
SDL_Keycode keycode = event->keysym.sym;
|
SDL_Keycode keycode = event->keysym.sym;
|
||||||
uint16_t mod = event->keysym.mod;
|
uint16_t mod = event->keysym.mod;
|
||||||
@ -390,68 +415,68 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||||||
enum sc_action action = down ? SC_ACTION_DOWN : SC_ACTION_UP;
|
enum sc_action action = down ? SC_ACTION_DOWN : SC_ACTION_UP;
|
||||||
switch (keycode) {
|
switch (keycode) {
|
||||||
case SDLK_h:
|
case SDLK_h:
|
||||||
if (controller && !shift && !repeat) {
|
if (im->kp && !shift && !repeat) {
|
||||||
action_home(controller, action);
|
action_home(im, action);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_b: // fall-through
|
case SDLK_b: // fall-through
|
||||||
case SDLK_BACKSPACE:
|
case SDLK_BACKSPACE:
|
||||||
if (controller && !shift && !repeat) {
|
if (im->kp && !shift && !repeat) {
|
||||||
action_back(controller, action);
|
action_back(im, action);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_s:
|
case SDLK_s:
|
||||||
if (controller && !shift && !repeat) {
|
if (im->kp && !shift && !repeat) {
|
||||||
action_app_switch(controller, action);
|
action_app_switch(im, action);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_m:
|
case SDLK_m:
|
||||||
if (controller && !shift && !repeat) {
|
if (im->kp && !shift && !repeat) {
|
||||||
action_menu(controller, action);
|
action_menu(im, action);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_p:
|
case SDLK_p:
|
||||||
if (controller && !shift && !repeat) {
|
if (im->kp && !shift && !repeat) {
|
||||||
action_power(controller, action);
|
action_power(im, action);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_o:
|
case SDLK_o:
|
||||||
if (controller && !repeat && down) {
|
if (control && !repeat && down) {
|
||||||
enum sc_screen_power_mode mode = shift
|
enum sc_screen_power_mode mode = shift
|
||||||
? SC_SCREEN_POWER_MODE_NORMAL
|
? SC_SCREEN_POWER_MODE_NORMAL
|
||||||
: SC_SCREEN_POWER_MODE_OFF;
|
: SC_SCREEN_POWER_MODE_OFF;
|
||||||
set_screen_power_mode(controller, mode);
|
set_screen_power_mode(im, mode);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_DOWN:
|
case SDLK_DOWN:
|
||||||
if (shift) {
|
if (shift) {
|
||||||
if (!repeat & down) {
|
if (!repeat & down) {
|
||||||
apply_orientation_transform(im->screen,
|
apply_orientation_transform(im,
|
||||||
SC_ORIENTATION_FLIP_180);
|
SC_ORIENTATION_FLIP_180);
|
||||||
}
|
}
|
||||||
} else if (controller) {
|
} else if (im->kp) {
|
||||||
// forward repeated events
|
// forward repeated events
|
||||||
action_volume_down(controller, action);
|
action_volume_down(im, action);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_UP:
|
case SDLK_UP:
|
||||||
if (shift) {
|
if (shift) {
|
||||||
if (!repeat & down) {
|
if (!repeat & down) {
|
||||||
apply_orientation_transform(im->screen,
|
apply_orientation_transform(im,
|
||||||
SC_ORIENTATION_FLIP_180);
|
SC_ORIENTATION_FLIP_180);
|
||||||
}
|
}
|
||||||
} else if (controller) {
|
} else if (im->kp) {
|
||||||
// forward repeated events
|
// forward repeated events
|
||||||
action_volume_up(controller, action);
|
action_volume_up(im, action);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_LEFT:
|
case SDLK_LEFT:
|
||||||
if (!repeat && down) {
|
if (!repeat && down) {
|
||||||
if (shift) {
|
if (shift) {
|
||||||
apply_orientation_transform(im->screen,
|
apply_orientation_transform(im,
|
||||||
SC_ORIENTATION_FLIP_0);
|
SC_ORIENTATION_FLIP_0);
|
||||||
} else {
|
} else {
|
||||||
apply_orientation_transform(im->screen,
|
apply_orientation_transform(im,
|
||||||
SC_ORIENTATION_270);
|
SC_ORIENTATION_270);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -459,34 +484,33 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||||||
case SDLK_RIGHT:
|
case SDLK_RIGHT:
|
||||||
if (!repeat && down) {
|
if (!repeat && down) {
|
||||||
if (shift) {
|
if (shift) {
|
||||||
apply_orientation_transform(im->screen,
|
apply_orientation_transform(im,
|
||||||
SC_ORIENTATION_FLIP_0);
|
SC_ORIENTATION_FLIP_0);
|
||||||
} else {
|
} else {
|
||||||
apply_orientation_transform(im->screen,
|
apply_orientation_transform(im,
|
||||||
SC_ORIENTATION_90);
|
SC_ORIENTATION_90);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_c:
|
case SDLK_c:
|
||||||
if (controller && !shift && !repeat && down) {
|
if (im->kp && !shift && !repeat && down) {
|
||||||
get_device_clipboard(controller, SC_COPY_KEY_COPY);
|
get_device_clipboard(im, SC_COPY_KEY_COPY);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_x:
|
case SDLK_x:
|
||||||
if (controller && !shift && !repeat && down) {
|
if (im->kp && !shift && !repeat && down) {
|
||||||
get_device_clipboard(controller, SC_COPY_KEY_CUT);
|
get_device_clipboard(im, SC_COPY_KEY_CUT);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_v:
|
case SDLK_v:
|
||||||
if (controller && !repeat && down) {
|
if (im->kp && !repeat && down) {
|
||||||
if (shift || im->legacy_paste) {
|
if (shift || im->legacy_paste) {
|
||||||
// inject the text as input events
|
// inject the text as input events
|
||||||
clipboard_paste(controller);
|
clipboard_paste(im);
|
||||||
} else {
|
} else {
|
||||||
// store the text in the device clipboard and paste,
|
// store the text in the device clipboard and paste,
|
||||||
// without requesting an acknowledgment
|
// without requesting an acknowledgment
|
||||||
set_device_clipboard(controller, true,
|
set_device_clipboard(im, true, SC_SEQUENCE_INVALID);
|
||||||
SC_SEQUENCE_INVALID);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -507,23 +531,23 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||||||
return;
|
return;
|
||||||
case SDLK_i:
|
case SDLK_i:
|
||||||
if (!shift && !repeat && down) {
|
if (!shift && !repeat && down) {
|
||||||
switch_fps_counter_state(&im->screen->fps_counter);
|
switch_fps_counter_state(im);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_n:
|
case SDLK_n:
|
||||||
if (controller && !repeat && down) {
|
if (control && !repeat && down) {
|
||||||
if (shift) {
|
if (shift) {
|
||||||
collapse_panels(controller);
|
collapse_panels(im);
|
||||||
} else if (im->key_repeat == 0) {
|
} else if (im->key_repeat == 0) {
|
||||||
expand_notification_panel(controller);
|
expand_notification_panel(im);
|
||||||
} else {
|
} else {
|
||||||
expand_settings_panel(controller);
|
expand_settings_panel(im);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_r:
|
case SDLK_r:
|
||||||
if (controller && !shift && !repeat && down) {
|
if (control && !shift && !repeat && down) {
|
||||||
rotate_device(controller);
|
rotate_device(im);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -531,7 +555,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!controller) {
|
if (!im->kp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,7 +564,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||||||
if (im->clipboard_autosync && is_ctrl_v) {
|
if (im->clipboard_autosync && is_ctrl_v) {
|
||||||
if (im->legacy_paste) {
|
if (im->legacy_paste) {
|
||||||
// inject the text as input events
|
// inject the text as input events
|
||||||
clipboard_paste(controller);
|
clipboard_paste(im);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,7 +574,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||||||
|
|
||||||
// Synchronize the computer clipboard to the device clipboard before
|
// Synchronize the computer clipboard to the device clipboard before
|
||||||
// sending Ctrl+v, to allow seamless copy-paste.
|
// sending Ctrl+v, to allow seamless copy-paste.
|
||||||
bool ok = set_device_clipboard(controller, false, sequence);
|
bool ok = set_device_clipboard(im, false, sequence);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
LOGW("Clipboard could not be synchronized, Ctrl+v not injected");
|
LOGW("Clipboard could not be synchronized, Ctrl+v not injected");
|
||||||
return;
|
return;
|
||||||
@ -652,7 +676,7 @@ sc_input_manager_process_touch(struct sc_input_manager *im,
|
|||||||
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) {
|
||||||
struct sc_controller *controller = im->controller;
|
bool control = im->controller;
|
||||||
|
|
||||||
if (event->which == SDL_TOUCH_MOUSEID) {
|
if (event->which == SDL_TOUCH_MOUSEID) {
|
||||||
// simulated from touch events, so it's a duplicate
|
// simulated from touch events, so it's a duplicate
|
||||||
@ -661,27 +685,27 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
|||||||
|
|
||||||
bool down = event->type == SDL_MOUSEBUTTONDOWN;
|
bool down = event->type == SDL_MOUSEBUTTONDOWN;
|
||||||
if (!im->forward_all_clicks) {
|
if (!im->forward_all_clicks) {
|
||||||
if (controller) {
|
if (control) {
|
||||||
enum sc_action action = down ? SC_ACTION_DOWN : SC_ACTION_UP;
|
enum sc_action action = down ? SC_ACTION_DOWN : SC_ACTION_UP;
|
||||||
|
|
||||||
if (event->button == SDL_BUTTON_X1) {
|
if (im->kp && event->button == SDL_BUTTON_X1) {
|
||||||
action_app_switch(controller, action);
|
action_app_switch(im, action);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event->button == SDL_BUTTON_X2 && down) {
|
if (event->button == SDL_BUTTON_X2 && down) {
|
||||||
if (event->clicks < 2) {
|
if (event->clicks < 2) {
|
||||||
expand_notification_panel(controller);
|
expand_notification_panel(im);
|
||||||
} else {
|
} else {
|
||||||
expand_settings_panel(controller);
|
expand_settings_panel(im);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event->button == SDL_BUTTON_RIGHT) {
|
if (im->kp && event->button == SDL_BUTTON_RIGHT) {
|
||||||
press_back_or_turn_screen_on(controller, action);
|
press_back_or_turn_screen_on(im, action);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event->button == SDL_BUTTON_MIDDLE) {
|
if (im->kp && event->button == SDL_BUTTON_MIDDLE) {
|
||||||
action_home(controller, action);
|
action_home(im, action);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -704,7 +728,7 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
|||||||
// otherwise, send the click event to the device
|
// otherwise, send the click event to the device
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!controller) {
|
if (!im->mp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,7 +868,7 @@ sc_input_manager_handle_event(struct sc_input_manager *im,
|
|||||||
bool control = im->controller;
|
bool control = im->controller;
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case SDL_TEXTINPUT:
|
case SDL_TEXTINPUT:
|
||||||
if (!control) {
|
if (!im->kp) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sc_input_manager_process_text_input(im, &event->text);
|
sc_input_manager_process_text_input(im, &event->text);
|
||||||
@ -856,13 +880,13 @@ sc_input_manager_handle_event(struct sc_input_manager *im,
|
|||||||
sc_input_manager_process_key(im, &event->key);
|
sc_input_manager_process_key(im, &event->key);
|
||||||
break;
|
break;
|
||||||
case SDL_MOUSEMOTION:
|
case SDL_MOUSEMOTION:
|
||||||
if (!control) {
|
if (!im->mp) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sc_input_manager_process_mouse_motion(im, &event->motion);
|
sc_input_manager_process_mouse_motion(im, &event->motion);
|
||||||
break;
|
break;
|
||||||
case SDL_MOUSEWHEEL:
|
case SDL_MOUSEWHEEL:
|
||||||
if (!control) {
|
if (!im->mp) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sc_input_manager_process_mouse_wheel(im, &event->wheel);
|
sc_input_manager_process_mouse_wheel(im, &event->wheel);
|
||||||
@ -876,7 +900,7 @@ sc_input_manager_handle_event(struct sc_input_manager *im,
|
|||||||
case SDL_FINGERMOTION:
|
case SDL_FINGERMOTION:
|
||||||
case SDL_FINGERDOWN:
|
case SDL_FINGERDOWN:
|
||||||
case SDL_FINGERUP:
|
case SDL_FINGERUP:
|
||||||
if (!control) {
|
if (!im->mp) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sc_input_manager_process_touch(im, &event->tfinger);
|
sc_input_manager_process_touch(im, &event->tfinger);
|
||||||
|
@ -21,8 +21,8 @@ const struct scrcpy_options scrcpy_options_default = {
|
|||||||
.video_source = SC_VIDEO_SOURCE_DISPLAY,
|
.video_source = SC_VIDEO_SOURCE_DISPLAY,
|
||||||
.audio_source = SC_AUDIO_SOURCE_AUTO,
|
.audio_source = SC_AUDIO_SOURCE_AUTO,
|
||||||
.record_format = SC_RECORD_FORMAT_AUTO,
|
.record_format = SC_RECORD_FORMAT_AUTO,
|
||||||
.keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_INJECT,
|
.keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_AUTO,
|
||||||
.mouse_input_mode = SC_MOUSE_INPUT_MODE_INJECT,
|
.mouse_input_mode = SC_MOUSE_INPUT_MODE_AUTO,
|
||||||
.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,
|
||||||
|
@ -140,13 +140,17 @@ enum sc_lock_video_orientation {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum sc_keyboard_input_mode {
|
enum sc_keyboard_input_mode {
|
||||||
SC_KEYBOARD_INPUT_MODE_INJECT,
|
SC_KEYBOARD_INPUT_MODE_AUTO,
|
||||||
SC_KEYBOARD_INPUT_MODE_HID,
|
SC_KEYBOARD_INPUT_MODE_DISABLED,
|
||||||
|
SC_KEYBOARD_INPUT_MODE_SDK,
|
||||||
|
SC_KEYBOARD_INPUT_MODE_AOA,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum sc_mouse_input_mode {
|
enum sc_mouse_input_mode {
|
||||||
SC_MOUSE_INPUT_MODE_INJECT,
|
SC_MOUSE_INPUT_MODE_AUTO,
|
||||||
SC_MOUSE_INPUT_MODE_HID,
|
SC_MOUSE_INPUT_MODE_DISABLED,
|
||||||
|
SC_MOUSE_INPUT_MODE_SDK,
|
||||||
|
SC_MOUSE_INPUT_MODE_AOA,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum sc_key_inject_mode {
|
enum sc_key_inject_mode {
|
||||||
|
@ -543,11 +543,11 @@ scrcpy(struct scrcpy_options *options) {
|
|||||||
|
|
||||||
if (options->control) {
|
if (options->control) {
|
||||||
#ifdef HAVE_USB
|
#ifdef HAVE_USB
|
||||||
bool use_hid_keyboard =
|
bool use_aoa_keyboard =
|
||||||
options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_HID;
|
options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_AOA;
|
||||||
bool use_hid_mouse =
|
bool use_aoa_mouse =
|
||||||
options->mouse_input_mode == SC_MOUSE_INPUT_MODE_HID;
|
options->mouse_input_mode == SC_MOUSE_INPUT_MODE_AOA;
|
||||||
if (use_hid_keyboard || use_hid_mouse) {
|
if (use_aoa_keyboard || use_aoa_mouse) {
|
||||||
bool ok = sc_acksync_init(&s->acksync);
|
bool ok = sc_acksync_init(&s->acksync);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
goto end;
|
goto end;
|
||||||
@ -590,7 +590,7 @@ scrcpy(struct scrcpy_options *options) {
|
|||||||
goto aoa_hid_end;
|
goto aoa_hid_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_hid_keyboard) {
|
if (use_aoa_keyboard) {
|
||||||
if (sc_hid_keyboard_init(&s->keyboard_hid, &s->aoa)) {
|
if (sc_hid_keyboard_init(&s->keyboard_hid, &s->aoa)) {
|
||||||
hid_keyboard_initialized = true;
|
hid_keyboard_initialized = true;
|
||||||
kp = &s->keyboard_hid.key_processor;
|
kp = &s->keyboard_hid.key_processor;
|
||||||
@ -599,7 +599,7 @@ scrcpy(struct scrcpy_options *options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_hid_mouse) {
|
if (use_aoa_mouse) {
|
||||||
if (sc_hid_mouse_init(&s->mouse_hid, &s->aoa)) {
|
if (sc_hid_mouse_init(&s->mouse_hid, &s->aoa)) {
|
||||||
hid_mouse_initialized = true;
|
hid_mouse_initialized = true;
|
||||||
mp = &s->mouse_hid.mouse_processor;
|
mp = &s->mouse_hid.mouse_processor;
|
||||||
@ -634,25 +634,23 @@ aoa_hid_end:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_hid_keyboard && !hid_keyboard_initialized) {
|
if (use_aoa_keyboard && !hid_keyboard_initialized) {
|
||||||
LOGE("Fallback to default keyboard injection method "
|
LOGE("Fallback to --keyboard=sdk (--keyboard=aoa ignored)");
|
||||||
"(-K/--hid-keyboard ignored)");
|
options->keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_SDK;
|
||||||
options->keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_INJECT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_hid_mouse && !hid_mouse_initialized) {
|
if (use_aoa_mouse && !hid_mouse_initialized) {
|
||||||
LOGE("Fallback to default mouse injection method "
|
LOGE("Fallback to --keyboard=sdk (--keyboard=aoa ignored)");
|
||||||
"(-M/--hid-mouse ignored)");
|
options->mouse_input_mode = SC_MOUSE_INPUT_MODE_SDK;
|
||||||
options->mouse_input_mode = SC_MOUSE_INPUT_MODE_INJECT;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
assert(options->keyboard_input_mode != SC_KEYBOARD_INPUT_MODE_HID);
|
assert(options->keyboard_input_mode != SC_KEYBOARD_INPUT_MODE_AOA);
|
||||||
assert(options->mouse_input_mode != SC_MOUSE_INPUT_MODE_HID);
|
assert(options->mouse_input_mode != SC_MOUSE_INPUT_MODE_AOA);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// keyboard_input_mode may have been reset if HID mode failed
|
// keyboard_input_mode may have been reset if HID mode failed
|
||||||
if (options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_INJECT) {
|
if (options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_SDK) {
|
||||||
sc_keyboard_inject_init(&s->keyboard_inject, &s->controller,
|
sc_keyboard_inject_init(&s->keyboard_inject, &s->controller,
|
||||||
options->key_inject_mode,
|
options->key_inject_mode,
|
||||||
options->forward_key_repeat);
|
options->forward_key_repeat);
|
||||||
@ -660,7 +658,7 @@ aoa_hid_end:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// mouse_input_mode may have been reset if HID mode failed
|
// mouse_input_mode may have been reset if HID mode failed
|
||||||
if (options->mouse_input_mode == SC_MOUSE_INPUT_MODE_INJECT) {
|
if (options->mouse_input_mode == SC_MOUSE_INPUT_MODE_SDK) {
|
||||||
sc_mouse_inject_init(&s->mouse_inject, &s->controller);
|
sc_mouse_inject_init(&s->mouse_inject, &s->controller);
|
||||||
mp = &s->mouse_inject.mouse_processor;
|
mp = &s->mouse_inject.mouse_processor;
|
||||||
}
|
}
|
||||||
|
@ -117,10 +117,15 @@ scrcpy_otg(struct scrcpy_options *options) {
|
|||||||
}
|
}
|
||||||
aoa_initialized = true;
|
aoa_initialized = true;
|
||||||
|
|
||||||
|
assert(options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_AOA
|
||||||
|
|| options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_DISABLED);
|
||||||
|
assert(options->mouse_input_mode == SC_MOUSE_INPUT_MODE_AOA
|
||||||
|
|| options->mouse_input_mode == SC_MOUSE_INPUT_MODE_DISABLED);
|
||||||
|
|
||||||
bool enable_keyboard =
|
bool enable_keyboard =
|
||||||
options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_HID;
|
options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_AOA;
|
||||||
bool enable_mouse =
|
bool enable_mouse =
|
||||||
options->mouse_input_mode == SC_MOUSE_INPUT_MODE_HID;
|
options->mouse_input_mode == SC_MOUSE_INPUT_MODE_AOA;
|
||||||
|
|
||||||
// If neither --hid-keyboard or --hid-mouse is passed, enable both
|
// If neither --hid-keyboard or --hid-mouse is passed, enable both
|
||||||
if (!enable_keyboard && !enable_mouse) {
|
if (!enable_keyboard && !enable_mouse) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user