diff --git a/app/scrcpy.1 b/app/scrcpy.1 index 1dafbc6a..203395a4 100644 --- a/app/scrcpy.1 +++ b/app/scrcpy.1 @@ -61,6 +61,13 @@ Set the TCP port the client listens on. Default is 27183. +.TP +.B \-\-prefer\-text +Inject alpha characters and space as text events instead of key events. + +This avoids issues when combining multiple keys to enter special characters, +but breaks the expected behavior of alpha keys in games (typically WASD). + .TP .BI "\-\-push\-target " path Set the target directory for pushing files to the device by drag & drop. It is passed as\-is to "adb push". diff --git a/app/src/event_converter.c b/app/src/event_converter.c index 00e989f7..80ead615 100644 --- a/app/src/event_converter.c +++ b/app/src/event_converter.c @@ -75,7 +75,8 @@ convert_meta_state(SDL_Keymod mod) { } bool -convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod) { +convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod, + bool prefer_text) { switch (from) { MAP(SDLK_RETURN, AKEYCODE_ENTER); MAP(SDLK_KP_ENTER, AKEYCODE_NUMPAD_ENTER); @@ -92,6 +93,12 @@ convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod) { MAP(SDLK_DOWN, AKEYCODE_DPAD_DOWN); MAP(SDLK_UP, AKEYCODE_DPAD_UP); } + + if (prefer_text) { + // do not forward alpha and space key events + return false; + } + if (mod & (KMOD_LALT | KMOD_RALT | KMOD_LGUI | KMOD_RGUI)) { return false; } diff --git a/app/src/event_converter.h b/app/src/event_converter.h index 8bad7358..c41887e1 100644 --- a/app/src/event_converter.h +++ b/app/src/event_converter.h @@ -14,7 +14,8 @@ enum android_metastate convert_meta_state(SDL_Keymod mod); bool -convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod); +convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod, + bool prefer_text); enum android_motionevent_buttons convert_mouse_buttons(uint32_t state); diff --git a/app/src/input_manager.c b/app/src/input_manager.c index fe891990..7d333c1b 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -214,12 +214,15 @@ clipboard_paste(struct controller *controller) { void input_manager_process_text_input(struct input_manager *im, const SDL_TextInputEvent *event) { - char c = event->text[0]; - if (isalpha(c) || c == ' ') { - SDL_assert(event->text[1] == '\0'); - // letters and space are handled as raw key event - return; + if (!im->prefer_text) { + char c = event->text[0]; + if (isalpha(c) || c == ' ') { + SDL_assert(event->text[1] == '\0'); + // letters and space are handled as raw key event + return; + } } + struct control_msg msg; msg.type = CONTROL_MSG_TYPE_INJECT_TEXT; msg.inject_text.text = SDL_strdup(event->text); @@ -234,7 +237,8 @@ input_manager_process_text_input(struct input_manager *im, } static bool -convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to) { +convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to, + bool prefer_text) { to->type = CONTROL_MSG_TYPE_INJECT_KEYCODE; if (!convert_keycode_action(from->type, &to->inject_keycode.action)) { @@ -242,7 +246,8 @@ convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to) { } uint16_t mod = from->keysym.mod; - if (!convert_keycode(from->keysym.sym, &to->inject_keycode.keycode, mod)) { + if (!convert_keycode(from->keysym.sym, &to->inject_keycode.keycode, mod, + prefer_text)) { return false; } @@ -393,7 +398,7 @@ input_manager_process_key(struct input_manager *im, } struct control_msg msg; - if (convert_input_key(event, &msg)) { + if (convert_input_key(event, &msg, im->prefer_text)) { if (!controller_push_msg(controller, &msg)) { LOGW("Could not request 'inject keycode'"); } diff --git a/app/src/input_manager.h b/app/src/input_manager.h index 934c529e..43fc0eeb 100644 --- a/app/src/input_manager.h +++ b/app/src/input_manager.h @@ -14,6 +14,7 @@ struct input_manager { struct controller *controller; struct video_buffer *video_buffer; struct screen *screen; + bool prefer_text; }; void diff --git a/app/src/main.c b/app/src/main.c index 1d5beb64..12c65ed4 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -67,6 +67,13 @@ static void usage(const char *arg0) { " Set the TCP port the client listens on.\n" " Default is %d.\n" "\n" + " --prefer-text\n" + " Inject alpha characters and space as text events instead of\n" + " key events.\n" + " This avoids issues when combining multiple keys to enter a\n" + " special character, but breaks the expected behavior of alpha\n" + " keys in games (typically WASD).\n" + "\n" " --push-target path\n" " Set the target directory for pushing files to the device by\n" " drag & drop. It is passed as-is to \"adb push\".\n" @@ -300,6 +307,7 @@ guess_record_format(const char *filename) { #define OPT_ALWAYS_ON_TOP 1003 #define OPT_CROP 1004 #define OPT_RECORD_FORMAT 1005 +#define OPT_PREFER_TEXT 1006 static bool parse_args(struct args *args, int argc, char *argv[]) { @@ -321,6 +329,7 @@ parse_args(struct args *args, int argc, char *argv[]) { {"serial", required_argument, NULL, 's'}, {"show-touches", no_argument, NULL, 't'}, {"turn-screen-off", no_argument, NULL, 'S'}, + {"prefer-text", no_argument, NULL, OPT_PREFER_TEXT}, {"version", no_argument, NULL, 'v'}, {"window-title", required_argument, NULL, OPT_WINDOW_TITLE}, @@ -404,6 +413,9 @@ parse_args(struct args *args, int argc, char *argv[]) { case OPT_PUSH_TARGET: opts->push_target = optarg; break; + case OPT_PREFER_TEXT: + opts->prefer_text = true; + break; default: // getopt prints the error message on stderr return false; diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index c219c9e5..16f1b4f7 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -42,6 +42,7 @@ static struct input_manager input_manager = { .controller = &controller, .video_buffer = &video_buffer, .screen = &screen, + .prefer_text = false, // initialized later }; // init SDL and set appropriate hints @@ -414,6 +415,8 @@ scrcpy(const struct scrcpy_options *options) { show_touches_waited = true; } + input_manager.prefer_text = options->prefer_text; + ret = event_loop(options->display, options->control); LOGD("quit..."); diff --git a/app/src/scrcpy.h b/app/src/scrcpy.h index 4bc24742..70a41ec1 100644 --- a/app/src/scrcpy.h +++ b/app/src/scrcpy.h @@ -5,6 +5,7 @@ #include #include "config.h" +#include "input_manager.h" #include "recorder.h" struct scrcpy_options { @@ -24,6 +25,7 @@ struct scrcpy_options { bool display; bool turn_screen_off; bool render_expired_frames; + bool prefer_text; }; #define SCRCPY_OPTIONS_DEFAULT { \ @@ -43,6 +45,7 @@ struct scrcpy_options { .display = true, \ .turn_screen_off = false, \ .render_expired_frames = false, \ + .prefer_text = false, \ } bool