Add --raw-key-events

This option allows to inject all input keys as key events, and ignore
text events.

Fixes #2816 <https://github.com/Genymobile/scrcpy/issues/2816>
PR #2831 <https://github.com/Genymobile/scrcpy/pull/2831>
rawkeyevents_2021
Romain Vimont 3 years ago
parent 5e918ac0c3
commit bd56d81f72

@ -833,7 +833,13 @@ scrcpy --prefer-text
(but this will break keyboard behavior in games) (but this will break keyboard behavior in games)
This option has no effect on HID keyboard (all key events are sent as On the contrary, you could force to always inject raw key events:
```bash
scrcpy --raw-key-events
```
These options have no effect on HID keyboard (all key events are sent as
scancodes in this mode). scancodes in this mode).
[textevents]: https://blog.rom1v.com/2018/03/introducing-scrcpy/#handle-text-input [textevents]: https://blog.rom1v.com/2018/03/introducing-scrcpy/#handle-text-input

@ -165,6 +165,10 @@ Set the target directory for pushing files to the device by drag & drop. It is p
Default is "/sdcard/Download/". Default is "/sdcard/Download/".
.TP
.B \-\-raw\-key\-events
Inject key events for all input keys, and ignore text events.
.TP .TP
.BI "\-r, \-\-record " file .BI "\-r, \-\-record " file
Record screen to Record screen to

@ -51,6 +51,7 @@
#define OPT_TUNNEL_PORT 1031 #define OPT_TUNNEL_PORT 1031
#define OPT_NO_CLIPBOARD_AUTOSYNC 1032 #define OPT_NO_CLIPBOARD_AUTOSYNC 1032
#define OPT_TCPIP 1033 #define OPT_TCPIP 1033
#define OPT_RAW_KEY_EVENTS 1034
struct sc_option { struct sc_option {
char shortopt; char shortopt;
@ -282,6 +283,11 @@ static const struct sc_option options[] = {
"drag & drop. It is passed as is to \"adb push\".\n" "drag & drop. It is passed as is to \"adb push\".\n"
"Default is \"/sdcard/Download/\".", "Default is \"/sdcard/Download/\".",
}, },
{
.longopt_id = OPT_RAW_KEY_EVENTS,
.longopt = "raw-key-events",
.text = "Inject key events for all input keys, and ignore text events."
},
{ {
.shortopt = 'r', .shortopt = 'r',
.longopt = "record", .longopt = "record",
@ -1350,8 +1356,19 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
opts->push_target = optarg; opts->push_target = optarg;
break; break;
case OPT_PREFER_TEXT: case OPT_PREFER_TEXT:
if (opts->key_inject_mode != SC_KEY_INJECT_MODE_MIXED) {
LOGE("--prefer-text is incompatible with --raw-key-events");
return false;
}
opts->key_inject_mode = SC_KEY_INJECT_MODE_TEXT; opts->key_inject_mode = SC_KEY_INJECT_MODE_TEXT;
break; break;
case OPT_RAW_KEY_EVENTS:
if (opts->key_inject_mode != SC_KEY_INJECT_MODE_MIXED) {
LOGE("--prefer-text is incompatible with --raw-key-events");
return false;
}
opts->key_inject_mode = SC_KEY_INJECT_MODE_RAW;
break;
case OPT_ROTATION: case OPT_ROTATION:
if (!parse_rotation(optarg, &opts->rotation)) { if (!parse_rotation(optarg, &opts->rotation)) {
return false; return false;

@ -101,6 +101,55 @@ convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod,
{SDLK_SPACE, AKEYCODE_SPACE}, {SDLK_SPACE, AKEYCODE_SPACE},
}; };
// Numbers and punctuation keys.
// Used in raw mode only.
static const struct sc_intmap_entry numbers_punct_keys[] = {
{SDLK_HASH, AKEYCODE_POUND},
{SDLK_PERCENT, AKEYCODE_PERIOD},
{SDLK_QUOTE, AKEYCODE_APOSTROPHE},
{SDLK_ASTERISK, AKEYCODE_STAR},
{SDLK_PLUS, AKEYCODE_PLUS},
{SDLK_COMMA, AKEYCODE_COMMA},
{SDLK_MINUS, AKEYCODE_MINUS},
{SDLK_PERIOD, AKEYCODE_PERIOD},
{SDLK_SLASH, AKEYCODE_SLASH},
{SDLK_0, AKEYCODE_0},
{SDLK_1, AKEYCODE_1},
{SDLK_2, AKEYCODE_2},
{SDLK_3, AKEYCODE_3},
{SDLK_4, AKEYCODE_4},
{SDLK_5, AKEYCODE_5},
{SDLK_6, AKEYCODE_6},
{SDLK_7, AKEYCODE_7},
{SDLK_8, AKEYCODE_8},
{SDLK_9, AKEYCODE_9},
{SDLK_SEMICOLON, AKEYCODE_SEMICOLON},
{SDLK_EQUALS, AKEYCODE_EQUALS},
{SDLK_AT, AKEYCODE_AT},
{SDLK_LEFTBRACKET, AKEYCODE_LEFT_BRACKET},
{SDLK_BACKSLASH, AKEYCODE_BACKSLASH},
{SDLK_RIGHTBRACKET, AKEYCODE_RIGHT_BRACKET},
{SDLK_BACKQUOTE, AKEYCODE_GRAVE},
{SDLK_KP_1, AKEYCODE_NUMPAD_1},
{SDLK_KP_2, AKEYCODE_NUMPAD_2},
{SDLK_KP_3, AKEYCODE_NUMPAD_3},
{SDLK_KP_4, AKEYCODE_NUMPAD_4},
{SDLK_KP_5, AKEYCODE_NUMPAD_5},
{SDLK_KP_6, AKEYCODE_NUMPAD_6},
{SDLK_KP_7, AKEYCODE_NUMPAD_7},
{SDLK_KP_8, AKEYCODE_NUMPAD_8},
{SDLK_KP_9, AKEYCODE_NUMPAD_9},
{SDLK_KP_0, AKEYCODE_NUMPAD_0},
{SDLK_KP_DIVIDE, AKEYCODE_NUMPAD_DIVIDE},
{SDLK_KP_MULTIPLY, AKEYCODE_NUMPAD_MULTIPLY},
{SDLK_KP_MINUS, AKEYCODE_NUMPAD_SUBTRACT},
{SDLK_KP_PLUS, AKEYCODE_NUMPAD_ADD},
{SDLK_KP_PERIOD, AKEYCODE_NUMPAD_DOT},
{SDLK_KP_EQUALS, AKEYCODE_NUMPAD_EQUALS},
{SDLK_KP_LEFTPAREN, AKEYCODE_NUMPAD_LEFT_PAREN},
{SDLK_KP_RIGHTPAREN, AKEYCODE_NUMPAD_RIGHT_PAREN},
};
const struct sc_intmap_entry *entry = const struct sc_intmap_entry *entry =
SC_INTMAP_FIND_ENTRY(special_keys, from); SC_INTMAP_FIND_ENTRY(special_keys, from);
if (entry) { if (entry) {
@ -134,6 +183,14 @@ convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod,
return true; return true;
} }
if (key_inject_mode == SC_KEY_INJECT_MODE_RAW) {
entry = SC_INTMAP_FIND_ENTRY(numbers_punct_keys, from);
if (entry) {
*to = entry->value;
return true;
}
}
return false; return false;
} }
@ -251,6 +308,11 @@ sc_key_processor_process_text(struct sc_key_processor *kp,
const SDL_TextInputEvent *event) { const SDL_TextInputEvent *event) {
struct sc_keyboard_inject *ki = DOWNCAST(kp); struct sc_keyboard_inject *ki = DOWNCAST(kp);
if (ki->key_inject_mode == SC_KEY_INJECT_MODE_RAW) {
// Never inject text events
return;
}
if (ki->key_inject_mode == SC_KEY_INJECT_MODE_MIXED) { if (ki->key_inject_mode == SC_KEY_INJECT_MODE_MIXED) {
char c = event->text[0]; char c = event->text[0];
if (isalpha(c) || c == ' ') { if (isalpha(c) || c == ' ') {

@ -47,6 +47,9 @@ enum sc_key_inject_mode {
// Inject special keys as key events. // Inject special keys as key events.
// Inject letters and space, numbers and punctuation as text events. // Inject letters and space, numbers and punctuation as text events.
SC_KEY_INJECT_MODE_TEXT, SC_KEY_INJECT_MODE_TEXT,
// Inject everything as key events.
SC_KEY_INJECT_MODE_RAW,
}; };
#define SC_MAX_SHORTCUT_MODS 8 #define SC_MAX_SHORTCUT_MODS 8

Loading…
Cancel
Save