Skip to content

Commit 44791d6

Browse files
committed
Add --prefer-text-events option
Expose an option to configure how key/text events are forwarded to the Android device. Fixes <#650>
1 parent 2d90e1b commit 44791d6

8 files changed

+101
-9
lines changed

app/scrcpy.1

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

6262
Default is 27183.
6363

64+
.TP
65+
.BI \-\-prefer\-text\-events " mode
66+
Configure how key/text events are forwarded to the Android device.
67+
68+
Possible \fImode\fRs are "always" (every text is sent as text), "non-alpha"
69+
(only letters are sent as a sequence of key events, other characters are sent
70+
as text) and "never" (every text is sent as a sequence of key events).
71+
72+
Default is "non-alpha".
73+
6474
.TP
6575
.BI "\-\-push\-target " path
6676
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

+12-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+
enum text_events_pref pref) {
7980
switch (from) {
8081
MAP(SDLK_RETURN, AKEYCODE_ENTER);
8182
MAP(SDLK_KP_ENTER, AKEYCODE_NUMPAD_ENTER);
@@ -92,6 +93,16 @@ 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 (pref == PREFER_TEXT_EVENTS_ALWAYS) {
98+
// never forward key events
99+
return false;
100+
}
101+
102+
// forward all supported key events
103+
SDL_assert(pref == PREFER_TEXT_EVENTS_NEVER ||
104+
pref == PREFER_TEXT_EVENTS_NON_ALPHA);
105+
95106
if (mod & (KMOD_LALT | KMOD_RALT | KMOD_LGUI | KMOD_RGUI)) {
96107
return false;
97108
}

app/src/event_converter.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
#define CONVERT_H
33

44
#include <stdbool.h>
5+
#include <SDL2/SDL_assert.h>
56
#include <SDL2/SDL_events.h>
67

78
#include "config.h"
89
#include "control_msg.h"
10+
#include "input_manager.h"
911

1012
bool
1113
convert_keycode_action(SDL_EventType from, enum android_keyevent_action *to);
@@ -14,7 +16,8 @@ enum android_metastate
1416
convert_meta_state(SDL_Keymod mod);
1517

1618
bool
17-
convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod);
19+
convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod,
20+
enum text_events_pref pref);
1821

1922
enum android_motionevent_buttons
2023
convert_mouse_buttons(uint32_t state);

app/src/input_manager.c

+17-7
Original file line numberDiff line numberDiff line change
@@ -214,12 +214,20 @@ 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
217+
if (im->text_events_pref == PREFER_TEXT_EVENTS_NEVER) {
218+
// ignore all text events (key events will be injected instead)
221219
return;
222220
}
221+
222+
if (im->text_events_pref == PREFER_TEXT_EVENTS_NON_ALPHA) {
223+
char c = event->text[0];
224+
if (isalpha(c) || c == ' ') {
225+
SDL_assert(event->text[1] == '\0');
226+
// letters and space are handled as raw key event
227+
return;
228+
}
229+
}
230+
223231
struct control_msg msg;
224232
msg.type = CONTROL_MSG_TYPE_INJECT_TEXT;
225233
msg.inject_text.text = SDL_strdup(event->text);
@@ -234,15 +242,17 @@ input_manager_process_text_input(struct input_manager *im,
234242
}
235243

236244
static bool
237-
convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to) {
245+
convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to,
246+
enum text_events_pref pref) {
238247
to->type = CONTROL_MSG_TYPE_INJECT_KEYCODE;
239248

240249
if (!convert_keycode_action(from->type, &to->inject_keycode.action)) {
241250
return false;
242251
}
243252

244253
uint16_t mod = from->keysym.mod;
245-
if (!convert_keycode(from->keysym.sym, &to->inject_keycode.keycode, mod)) {
254+
if (!convert_keycode(from->keysym.sym, &to->inject_keycode.keycode, mod,
255+
pref)) {
246256
return false;
247257
}
248258

@@ -393,7 +403,7 @@ input_manager_process_key(struct input_manager *im,
393403
}
394404

395405
struct control_msg msg;
396-
if (convert_input_key(event, &msg)) {
406+
if (convert_input_key(event, &msg, im->text_events_pref)) {
397407
if (!controller_push_msg(controller, &msg)) {
398408
LOGW("Could not request 'inject keycode'");
399409
}

app/src/input_manager.h

+7
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,17 @@
1010
#include "video_buffer.h"
1111
#include "screen.h"
1212

13+
enum text_events_pref {
14+
PREFER_TEXT_EVENTS_ALWAYS,
15+
PREFER_TEXT_EVENTS_NON_ALPHA,
16+
PREFER_TEXT_EVENTS_NEVER,
17+
};
18+
1319
struct input_manager {
1420
struct controller *controller;
1521
struct video_buffer *video_buffer;
1622
struct screen *screen;
23+
enum text_events_pref text_events_pref;
1724
};
1825

1926
void

app/src/main.c

+45
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "config.h"
1212
#include "compat.h"
1313
#include "log.h"
14+
#include "input_manager.h"
1415
#include "recorder.h"
1516

1617
struct args {
@@ -67,6 +68,18 @@ static void usage(const char *arg0) {
6768
" Set the TCP port the client listens on.\n"
6869
" Default is %d.\n"
6970
"\n"
71+
" --prefer-text-events mode\n"
72+
" Configure how key/text events are forwarded to the Android\n"
73+
" device.\n"
74+
" Possible values are:\n"
75+
" always:\n"
76+
" Every text is sent as text.\n"
77+
" non-alpha:\n"
78+
" Only letters are sent as a sequence of key events, other\n"
79+
" characters are sent as text. (default)\n"
80+
" never:\n"
81+
" Every text is sent as a sequence of key events.\n"
82+
"\n"
7083
" --push-target path\n"
7184
" Set the target directory for pushing files to the device by\n"
7285
" drag & drop. It is passed as-is to \"adb push\".\n"
@@ -294,9 +307,33 @@ guess_record_format(const char *filename) {
294307
return 0;
295308
}
296309

310+
static bool
311+
parse_prefer_text_events(const char *optarg,
312+
enum text_events_pref *pref) {
313+
if (!strcmp(optarg, "always")) {
314+
*pref = PREFER_TEXT_EVENTS_ALWAYS;
315+
return true;
316+
}
317+
318+
if (!strcmp(optarg, "non-alpha")) {
319+
*pref = PREFER_TEXT_EVENTS_NON_ALPHA;
320+
return true;
321+
}
322+
323+
if (!strcmp(optarg, "never")) {
324+
*pref = PREFER_TEXT_EVENTS_NEVER;
325+
return true;
326+
}
327+
328+
LOGE("Unsupported text events preference: %s"
329+
"(expected 'always', 'non-alpha' or 'never')", optarg);
330+
return false;
331+
}
332+
297333
#define OPT_RENDER_EXPIRED_FRAMES 1000
298334
#define OPT_WINDOW_TITLE 1001
299335
#define OPT_PUSH_TARGET 1002
336+
#define OPT_PREFER_TEXT_EVENTS 1003
300337

301338
static bool
302339
parse_args(struct args *args, int argc, char *argv[]) {
@@ -319,6 +356,8 @@ parse_args(struct args *args, int argc, char *argv[]) {
319356
{"serial", required_argument, NULL, 's'},
320357
{"show-touches", no_argument, NULL, 't'},
321358
{"turn-screen-off", no_argument, NULL, 'S'},
359+
{"prefer-text-events", required_argument, NULL,
360+
OPT_PREFER_TEXT_EVENTS},
322361
{"version", no_argument, NULL, 'v'},
323362
{"window-title", required_argument, NULL,
324363
OPT_WINDOW_TITLE},
@@ -393,6 +432,12 @@ parse_args(struct args *args, int argc, char *argv[]) {
393432
case OPT_PUSH_TARGET:
394433
opts->push_target = optarg;
395434
break;
435+
case OPT_PREFER_TEXT_EVENTS:
436+
if (!parse_prefer_text_events(optarg,
437+
&opts->text_events_pref)) {
438+
return false;
439+
}
440+
break;
396441
default:
397442
// getopt prints the error message on stderr
398443
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+
.text_events_pref = 0, // 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.text_events_pref = options->text_events_pref;
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 {
@@ -14,6 +15,7 @@ struct scrcpy_options {
1415
const char *window_title;
1516
const char *push_target;
1617
enum recorder_format record_format;
18+
enum text_events_pref text_events_pref;
1719
uint16_t port;
1820
uint16_t max_size;
1921
uint32_t bit_rate;
@@ -33,6 +35,7 @@ struct scrcpy_options {
3335
.window_title = NULL, \
3436
.push_target = NULL, \
3537
.record_format = RECORDER_FORMAT_AUTO, \
38+
.text_events_pref = PREFER_TEXT_EVENTS_NON_ALPHA, \
3639
.port = DEFAULT_LOCAL_PORT, \
3740
.max_size = DEFAULT_LOCAL_PORT, \
3841
.bit_rate = DEFAULT_BIT_RATE, \

0 commit comments

Comments
 (0)