Skip to content

Commit

Permalink
Add --prefer-text-events option
Browse files Browse the repository at this point in the history
Expose an option to configure how key/text events are forwarded to the
Android device.

Fixes <#650>
  • Loading branch information
rom1v committed Nov 6, 2019
1 parent 2d90e1b commit 44791d6
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 9 deletions.
10 changes: 10 additions & 0 deletions app/scrcpy.1
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ Set the TCP port the client listens on.

Default is 27183.

.TP
.BI \-\-prefer\-text\-events " mode
Configure how key/text events are forwarded to the Android device.

Possible \fImode\fRs are "always" (every text is sent as text), "non-alpha"
(only letters are sent as a sequence of key events, other characters are sent
as text) and "never" (every text is sent as a sequence of key events).

Default is "non-alpha".

.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".
Expand Down
13 changes: 12 additions & 1 deletion app/src/event_converter.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
enum text_events_pref pref) {
switch (from) {
MAP(SDLK_RETURN, AKEYCODE_ENTER);
MAP(SDLK_KP_ENTER, AKEYCODE_NUMPAD_ENTER);
Expand All @@ -92,6 +93,16 @@ 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 (pref == PREFER_TEXT_EVENTS_ALWAYS) {
// never forward key events
return false;
}

// forward all supported key events
SDL_assert(pref == PREFER_TEXT_EVENTS_NEVER ||
pref == PREFER_TEXT_EVENTS_NON_ALPHA);

if (mod & (KMOD_LALT | KMOD_RALT | KMOD_LGUI | KMOD_RGUI)) {
return false;
}
Expand Down
5 changes: 4 additions & 1 deletion app/src/event_converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
#define CONVERT_H

#include <stdbool.h>
#include <SDL2/SDL_assert.h>
#include <SDL2/SDL_events.h>

#include "config.h"
#include "control_msg.h"
#include "input_manager.h"

bool
convert_keycode_action(SDL_EventType from, enum android_keyevent_action *to);
Expand All @@ -14,7 +16,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,
enum text_events_pref pref);

enum android_motionevent_buttons
convert_mouse_buttons(uint32_t state);
Expand Down
24 changes: 17 additions & 7 deletions app/src/input_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,12 +214,20 @@ 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
if (im->text_events_pref == PREFER_TEXT_EVENTS_NEVER) {
// ignore all text events (key events will be injected instead)
return;
}

if (im->text_events_pref == PREFER_TEXT_EVENTS_NON_ALPHA) {
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);
Expand All @@ -234,15 +242,17 @@ 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,
enum text_events_pref pref) {
to->type = CONTROL_MSG_TYPE_INJECT_KEYCODE;

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

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,
pref)) {
return false;
}

Expand Down Expand Up @@ -393,7 +403,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->text_events_pref)) {
if (!controller_push_msg(controller, &msg)) {
LOGW("Could not request 'inject keycode'");
}
Expand Down
7 changes: 7 additions & 0 deletions app/src/input_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,17 @@
#include "video_buffer.h"
#include "screen.h"

enum text_events_pref {
PREFER_TEXT_EVENTS_ALWAYS,
PREFER_TEXT_EVENTS_NON_ALPHA,
PREFER_TEXT_EVENTS_NEVER,
};

struct input_manager {
struct controller *controller;
struct video_buffer *video_buffer;
struct screen *screen;
enum text_events_pref text_events_pref;
};

void
Expand Down
45 changes: 45 additions & 0 deletions app/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "config.h"
#include "compat.h"
#include "log.h"
#include "input_manager.h"
#include "recorder.h"

struct args {
Expand Down Expand Up @@ -67,6 +68,18 @@ static void usage(const char *arg0) {
" Set the TCP port the client listens on.\n"
" Default is %d.\n"
"\n"
" --prefer-text-events mode\n"
" Configure how key/text events are forwarded to the Android\n"
" device.\n"
" Possible values are:\n"
" always:\n"
" Every text is sent as text.\n"
" non-alpha:\n"
" Only letters are sent as a sequence of key events, other\n"
" characters are sent as text. (default)\n"
" never:\n"
" Every text is sent as a sequence of key events.\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"
Expand Down Expand Up @@ -294,9 +307,33 @@ guess_record_format(const char *filename) {
return 0;
}

static bool
parse_prefer_text_events(const char *optarg,
enum text_events_pref *pref) {
if (!strcmp(optarg, "always")) {
*pref = PREFER_TEXT_EVENTS_ALWAYS;
return true;
}

if (!strcmp(optarg, "non-alpha")) {
*pref = PREFER_TEXT_EVENTS_NON_ALPHA;
return true;
}

if (!strcmp(optarg, "never")) {
*pref = PREFER_TEXT_EVENTS_NEVER;
return true;
}

LOGE("Unsupported text events preference: %s"
"(expected 'always', 'non-alpha' or 'never')", optarg);
return false;
}

#define OPT_RENDER_EXPIRED_FRAMES 1000
#define OPT_WINDOW_TITLE 1001
#define OPT_PUSH_TARGET 1002
#define OPT_PREFER_TEXT_EVENTS 1003

static bool
parse_args(struct args *args, int argc, char *argv[]) {
Expand All @@ -319,6 +356,8 @@ 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-events", required_argument, NULL,
OPT_PREFER_TEXT_EVENTS},
{"version", no_argument, NULL, 'v'},
{"window-title", required_argument, NULL,
OPT_WINDOW_TITLE},
Expand Down Expand Up @@ -393,6 +432,12 @@ parse_args(struct args *args, int argc, char *argv[]) {
case OPT_PUSH_TARGET:
opts->push_target = optarg;
break;
case OPT_PREFER_TEXT_EVENTS:
if (!parse_prefer_text_events(optarg,
&opts->text_events_pref)) {
return false;
}
break;
default:
// getopt prints the error message on stderr
return false;
Expand Down
3 changes: 3 additions & 0 deletions app/src/scrcpy.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ static struct input_manager input_manager = {
.controller = &controller,
.video_buffer = &video_buffer,
.screen = &screen,
.text_events_pref = 0, // initialized later
};

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

input_manager.text_events_pref = options->text_events_pref;

ret = event_loop(options->display, options->control);
LOGD("quit...");

Expand Down
3 changes: 3 additions & 0 deletions app/src/scrcpy.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <stdint.h>

#include "config.h"
#include "input_manager.h"
#include "recorder.h"

struct scrcpy_options {
Expand All @@ -14,6 +15,7 @@ struct scrcpy_options {
const char *window_title;
const char *push_target;
enum recorder_format record_format;
enum text_events_pref text_events_pref;
uint16_t port;
uint16_t max_size;
uint32_t bit_rate;
Expand All @@ -33,6 +35,7 @@ struct scrcpy_options {
.window_title = NULL, \
.push_target = NULL, \
.record_format = RECORDER_FORMAT_AUTO, \
.text_events_pref = PREFER_TEXT_EVENTS_NON_ALPHA, \
.port = DEFAULT_LOCAL_PORT, \
.max_size = DEFAULT_LOCAL_PORT, \
.bit_rate = DEFAULT_BIT_RATE, \
Expand Down

0 comments on commit 44791d6

Please sign in to comment.