Skip to content

Commit c916af0

Browse files
committed
Add --prefer-text option
Expose an option to configure how key/text events are forwarded to the Android device. Enabling the option avoids issues when combining multiple keys to enter special characters, but breaks the expected behavior of alpha keys in games (typically WASD). Fixes <#650>
1 parent ff061b4 commit c916af0

8 files changed

+49
-10
lines changed

app/scrcpy.1

+7
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ Set the TCP port the client listens on.
6161

6262
Default is 27183.
6363

64+
.TP
65+
.B \-\-prefer\-text
66+
Inject alpha characters and space as text events instead of key events.
67+
68+
This avoids issues when combining multiple keys to enter special characters,
69+
but breaks the expected behavior of alpha keys in games (typically WASD).
70+
6471
.TP
6572
.BI "\-\-push\-target " path
6673
Set the target directory for pushing files to the device by drag & drop. It is passed as\-is to "adb push".

app/src/event_converter.c

+8-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ convert_meta_state(SDL_Keymod mod) {
7575
}
7676

7777
bool
78-
convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod) {
78+
convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod,
79+
bool prefer_text) {
7980
switch (from) {
8081
MAP(SDLK_RETURN, AKEYCODE_ENTER);
8182
MAP(SDLK_KP_ENTER, AKEYCODE_NUMPAD_ENTER);
@@ -92,6 +93,12 @@ convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod) {
9293
MAP(SDLK_DOWN, AKEYCODE_DPAD_DOWN);
9394
MAP(SDLK_UP, AKEYCODE_DPAD_UP);
9495
}
96+
97+
if (prefer_text) {
98+
// do not forward alpha and space key events
99+
return false;
100+
}
101+
95102
if (mod & (KMOD_LALT | KMOD_RALT | KMOD_LGUI | KMOD_RGUI)) {
96103
return false;
97104
}

app/src/event_converter.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ enum android_metastate
1414
convert_meta_state(SDL_Keymod mod);
1515

1616
bool
17-
convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod);
17+
convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod,
18+
bool prefer_text);
1819

1920
enum android_motionevent_buttons
2021
convert_mouse_buttons(uint32_t state);

app/src/input_manager.c

+13-8
Original file line numberDiff line numberDiff line change
@@ -214,12 +214,15 @@ clipboard_paste(struct controller *controller) {
214214
void
215215
input_manager_process_text_input(struct input_manager *im,
216216
const SDL_TextInputEvent *event) {
217-
char c = event->text[0];
218-
if (isalpha(c) || c == ' ') {
219-
SDL_assert(event->text[1] == '\0');
220-
// letters and space are handled as raw key event
221-
return;
217+
if (!im->prefer_text) {
218+
char c = event->text[0];
219+
if (isalpha(c) || c == ' ') {
220+
SDL_assert(event->text[1] == '\0');
221+
// letters and space are handled as raw key event
222+
return;
223+
}
222224
}
225+
223226
struct control_msg msg;
224227
msg.type = CONTROL_MSG_TYPE_INJECT_TEXT;
225228
msg.inject_text.text = SDL_strdup(event->text);
@@ -234,15 +237,17 @@ input_manager_process_text_input(struct input_manager *im,
234237
}
235238

236239
static bool
237-
convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to) {
240+
convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to,
241+
bool prefer_text) {
238242
to->type = CONTROL_MSG_TYPE_INJECT_KEYCODE;
239243

240244
if (!convert_keycode_action(from->type, &to->inject_keycode.action)) {
241245
return false;
242246
}
243247

244248
uint16_t mod = from->keysym.mod;
245-
if (!convert_keycode(from->keysym.sym, &to->inject_keycode.keycode, mod)) {
249+
if (!convert_keycode(from->keysym.sym, &to->inject_keycode.keycode, mod,
250+
prefer_text)) {
246251
return false;
247252
}
248253

@@ -393,7 +398,7 @@ input_manager_process_key(struct input_manager *im,
393398
}
394399

395400
struct control_msg msg;
396-
if (convert_input_key(event, &msg)) {
401+
if (convert_input_key(event, &msg, im->prefer_text)) {
397402
if (!controller_push_msg(controller, &msg)) {
398403
LOGW("Could not request 'inject keycode'");
399404
}

app/src/input_manager.h

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ struct input_manager {
1414
struct controller *controller;
1515
struct video_buffer *video_buffer;
1616
struct screen *screen;
17+
bool prefer_text;
1718
};
1819

1920
void

app/src/main.c

+12
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,13 @@ static void usage(const char *arg0) {
6767
" Set the TCP port the client listens on.\n"
6868
" Default is %d.\n"
6969
"\n"
70+
" --prefer-text\n"
71+
" Inject alpha characters and space as text events instead of\n"
72+
" key events.\n"
73+
" This avoids issues when combining multiple keys to enter a\n"
74+
" special character, but breaks the expected behavior of alpha\n"
75+
" keys in games (typically WASD).\n"
76+
"\n"
7077
" --push-target path\n"
7178
" Set the target directory for pushing files to the device by\n"
7279
" drag & drop. It is passed as-is to \"adb push\".\n"
@@ -300,6 +307,7 @@ guess_record_format(const char *filename) {
300307
#define OPT_ALWAYS_ON_TOP 1003
301308
#define OPT_CROP 1004
302309
#define OPT_RECORD_FORMAT 1005
310+
#define OPT_PREFER_TEXT 1006
303311

304312
static bool
305313
parse_args(struct args *args, int argc, char *argv[]) {
@@ -321,6 +329,7 @@ parse_args(struct args *args, int argc, char *argv[]) {
321329
{"serial", required_argument, NULL, 's'},
322330
{"show-touches", no_argument, NULL, 't'},
323331
{"turn-screen-off", no_argument, NULL, 'S'},
332+
{"prefer-text", no_argument, NULL, OPT_PREFER_TEXT},
324333
{"version", no_argument, NULL, 'v'},
325334
{"window-title", required_argument, NULL,
326335
OPT_WINDOW_TITLE},
@@ -404,6 +413,9 @@ parse_args(struct args *args, int argc, char *argv[]) {
404413
case OPT_PUSH_TARGET:
405414
opts->push_target = optarg;
406415
break;
416+
case OPT_PREFER_TEXT:
417+
opts->prefer_text = true;
418+
break;
407419
default:
408420
// getopt prints the error message on stderr
409421
return false;

app/src/scrcpy.c

+3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ static struct input_manager input_manager = {
4242
.controller = &controller,
4343
.video_buffer = &video_buffer,
4444
.screen = &screen,
45+
.prefer_text = false, // initialized later
4546
};
4647

4748
// init SDL and set appropriate hints
@@ -414,6 +415,8 @@ scrcpy(const struct scrcpy_options *options) {
414415
show_touches_waited = true;
415416
}
416417

418+
input_manager.prefer_text = options->prefer_text;
419+
417420
ret = event_loop(options->display, options->control);
418421
LOGD("quit...");
419422

app/src/scrcpy.h

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <stdint.h>
66

77
#include "config.h"
8+
#include "input_manager.h"
89
#include "recorder.h"
910

1011
struct scrcpy_options {
@@ -24,6 +25,7 @@ struct scrcpy_options {
2425
bool display;
2526
bool turn_screen_off;
2627
bool render_expired_frames;
28+
bool prefer_text;
2729
};
2830

2931
#define SCRCPY_OPTIONS_DEFAULT { \
@@ -43,6 +45,7 @@ struct scrcpy_options {
4345
.display = true, \
4446
.turn_screen_off = false, \
4547
.render_expired_frames = false, \
48+
.prefer_text = false, \
4649
}
4750

4851
bool

0 commit comments

Comments
 (0)