Skip to content

Commit 9a7e8da

Browse files
xeropresencerom1v
authored andcommitted
Handle repeating keycodes
Initialize "repeat" count on key events. PR #1519 <#1519> Refs #1013 <#1013> Signed-off-by: Romain Vimont <rom@rom1v.com>
1 parent dc7b60e commit 9a7e8da

File tree

10 files changed

+45
-11
lines changed

10 files changed

+45
-11
lines changed

app/src/control_msg.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ control_msg_serialize(const struct control_msg *msg, unsigned char *buf) {
4242
case CONTROL_MSG_TYPE_INJECT_KEYCODE:
4343
buf[1] = msg->inject_keycode.action;
4444
buffer_write32be(&buf[2], msg->inject_keycode.keycode);
45-
buffer_write32be(&buf[6], msg->inject_keycode.metastate);
46-
return 10;
45+
buffer_write32be(&buf[6], msg->inject_keycode.repeat);
46+
buffer_write32be(&buf[10], msg->inject_keycode.metastate);
47+
return 14;
4748
case CONTROL_MSG_TYPE_INJECT_TEXT: {
4849
size_t len =
4950
write_string(msg->inject_text.text,

app/src/control_msg.h

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ struct control_msg {
4444
struct {
4545
enum android_keyevent_action action;
4646
enum android_keycode keycode;
47+
uint32_t repeat;
4748
enum android_metastate metastate;
4849
} inject_keycode;
4950
struct {

app/src/input_manager.c

+9-2
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ input_manager_process_text_input(struct input_manager *im,
234234

235235
static bool
236236
convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to,
237-
bool prefer_text) {
237+
bool prefer_text, uint32_t repeat) {
238238
to->type = CONTROL_MSG_TYPE_INJECT_KEYCODE;
239239

240240
if (!convert_keycode_action(from->type, &to->inject_keycode.action)) {
@@ -247,6 +247,7 @@ convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to,
247247
return false;
248248
}
249249

250+
to->inject_keycode.repeat = repeat;
250251
to->inject_keycode.metastate = convert_meta_state(mod);
251252

252253
return true;
@@ -411,8 +412,14 @@ input_manager_process_key(struct input_manager *im,
411412
return;
412413
}
413414

415+
if (event->repeat) {
416+
++im->repeat;
417+
} else {
418+
im->repeat = 0;
419+
}
420+
414421
struct control_msg msg;
415-
if (convert_input_key(event, &msg, im->prefer_text)) {
422+
if (convert_input_key(event, &msg, im->prefer_text, im->repeat)) {
416423
if (!controller_push_msg(controller, &msg)) {
417424
LOGW("Could not request 'inject keycode'");
418425
}

app/src/input_manager.h

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ struct input_manager {
1414
struct controller *controller;
1515
struct video_buffer *video_buffer;
1616
struct screen *screen;
17+
18+
// SDL reports repeated events as a boolean, but Android expects the actual
19+
// number of repetitions. This variable keeps track of the count.
20+
unsigned repeat;
21+
1722
bool prefer_text;
1823
};
1924

app/src/scrcpy.c

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ static struct input_manager input_manager = {
4646
.controller = &controller,
4747
.video_buffer = &video_buffer,
4848
.screen = &screen,
49+
.repeat = 0,
4950
.prefer_text = false, // initialized later
5051
};
5152

app/tests/test_control_msg_serialize.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,20 @@ static void test_serialize_inject_keycode(void) {
99
.inject_keycode = {
1010
.action = AKEY_EVENT_ACTION_UP,
1111
.keycode = AKEYCODE_ENTER,
12+
.repeat = 5,
1213
.metastate = AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON,
1314
},
1415
};
1516

1617
unsigned char buf[CONTROL_MSG_MAX_SIZE];
1718
int size = control_msg_serialize(&msg, buf);
18-
assert(size == 10);
19+
assert(size == 14);
1920

2021
const unsigned char expected[] = {
2122
CONTROL_MSG_TYPE_INJECT_KEYCODE,
2223
0x01, // AKEY_EVENT_ACTION_UP
2324
0x00, 0x00, 0x00, 0x42, // AKEYCODE_ENTER
25+
0x00, 0x00, 0x00, 0X05, // repeat
2426
0x00, 0x00, 0x00, 0x41, // AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON
2527
};
2628
assert(!memcmp(buf, expected, sizeof(expected)));

server/src/main/java/com/genymobile/scrcpy/ControlMessage.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,17 @@ public final class ControlMessage {
3131
private int hScroll;
3232
private int vScroll;
3333
private int flags;
34+
private int repeat;
3435

3536
private ControlMessage() {
3637
}
3738

38-
public static ControlMessage createInjectKeycode(int action, int keycode, int metaState) {
39+
public static ControlMessage createInjectKeycode(int action, int keycode, int repeat, int metaState) {
3940
ControlMessage msg = new ControlMessage();
4041
msg.type = TYPE_INJECT_KEYCODE;
4142
msg.action = action;
4243
msg.keycode = keycode;
44+
msg.repeat = repeat;
4345
msg.metaState = metaState;
4446
return msg;
4547
}
@@ -144,4 +146,8 @@ public int getVScroll() {
144146
public int getFlags() {
145147
return flags;
146148
}
149+
150+
public int getRepeat() {
151+
return repeat;
152+
}
147153
}

server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
public class ControlMessageReader {
1010

11-
static final int INJECT_KEYCODE_PAYLOAD_LENGTH = 9;
11+
static final int INJECT_KEYCODE_PAYLOAD_LENGTH = 13;
1212
static final int INJECT_TOUCH_EVENT_PAYLOAD_LENGTH = 27;
1313
static final int INJECT_SCROLL_EVENT_PAYLOAD_LENGTH = 20;
1414
static final int SET_SCREEN_POWER_MODE_PAYLOAD_LENGTH = 1;
@@ -98,8 +98,9 @@ private ControlMessage parseInjectKeycode() {
9898
}
9999
int action = toUnsigned(buffer.get());
100100
int keycode = buffer.getInt();
101+
int repeat = buffer.getInt();
101102
int metaState = buffer.getInt();
102-
return ControlMessage.createInjectKeycode(action, keycode, metaState);
103+
return ControlMessage.createInjectKeycode(action, keycode, repeat, metaState);
103104
}
104105

105106
private String parseString() {

server/src/main/java/com/genymobile/scrcpy/Controller.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ private void handleEvent() throws IOException {
7474
switch (msg.getType()) {
7575
case ControlMessage.TYPE_INJECT_KEYCODE:
7676
if (device.supportsInputEvents()) {
77-
injectKeycode(msg.getAction(), msg.getKeycode(), msg.getMetaState());
77+
injectKeycode(msg.getAction(), msg.getKeycode(), msg.getRepeat(), msg.getMetaState());
7878
}
7979
break;
8080
case ControlMessage.TYPE_INJECT_TEXT:
@@ -130,8 +130,8 @@ private void handleEvent() throws IOException {
130130
}
131131
}
132132

133-
private boolean injectKeycode(int action, int keycode, int metaState) {
134-
return device.injectKeyEvent(action, keycode, 0, metaState);
133+
private boolean injectKeycode(int action, int keycode, int repeat, int metaState) {
134+
return device.injectKeyEvent(action, keycode, repeat, metaState);
135135
}
136136

137137
private boolean injectChar(char c) {

server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java

+10
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public void testParseKeycodeEvent() throws IOException {
2525
dos.writeByte(ControlMessage.TYPE_INJECT_KEYCODE);
2626
dos.writeByte(KeyEvent.ACTION_UP);
2727
dos.writeInt(KeyEvent.KEYCODE_ENTER);
28+
dos.writeInt(5); // repeat
2829
dos.writeInt(KeyEvent.META_CTRL_ON);
2930
byte[] packet = bos.toByteArray();
3031

@@ -37,6 +38,7 @@ public void testParseKeycodeEvent() throws IOException {
3738
Assert.assertEquals(ControlMessage.TYPE_INJECT_KEYCODE, event.getType());
3839
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
3940
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
41+
Assert.assertEquals(5, event.getRepeat());
4042
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
4143
}
4244

@@ -308,11 +310,13 @@ public void testMultiEvents() throws IOException {
308310
dos.writeByte(ControlMessage.TYPE_INJECT_KEYCODE);
309311
dos.writeByte(KeyEvent.ACTION_UP);
310312
dos.writeInt(KeyEvent.KEYCODE_ENTER);
313+
dos.writeInt(0); // repeat
311314
dos.writeInt(KeyEvent.META_CTRL_ON);
312315

313316
dos.writeByte(ControlMessage.TYPE_INJECT_KEYCODE);
314317
dos.writeByte(MotionEvent.ACTION_DOWN);
315318
dos.writeInt(MotionEvent.BUTTON_PRIMARY);
319+
dos.writeInt(1); // repeat
316320
dos.writeInt(KeyEvent.META_CTRL_ON);
317321

318322
byte[] packet = bos.toByteArray();
@@ -322,12 +326,14 @@ public void testMultiEvents() throws IOException {
322326
Assert.assertEquals(ControlMessage.TYPE_INJECT_KEYCODE, event.getType());
323327
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
324328
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
329+
Assert.assertEquals(0, event.getRepeat());
325330
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
326331

327332
event = reader.next();
328333
Assert.assertEquals(ControlMessage.TYPE_INJECT_KEYCODE, event.getType());
329334
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
330335
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getKeycode());
336+
Assert.assertEquals(1, event.getRepeat());
331337
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
332338
}
333339

@@ -341,6 +347,7 @@ public void testPartialEvents() throws IOException {
341347
dos.writeByte(ControlMessage.TYPE_INJECT_KEYCODE);
342348
dos.writeByte(KeyEvent.ACTION_UP);
343349
dos.writeInt(KeyEvent.KEYCODE_ENTER);
350+
dos.writeInt(4); // repeat
344351
dos.writeInt(KeyEvent.META_CTRL_ON);
345352

346353
dos.writeByte(ControlMessage.TYPE_INJECT_KEYCODE);
@@ -353,13 +360,15 @@ public void testPartialEvents() throws IOException {
353360
Assert.assertEquals(ControlMessage.TYPE_INJECT_KEYCODE, event.getType());
354361
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
355362
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
363+
Assert.assertEquals(4, event.getRepeat());
356364
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
357365

358366
event = reader.next();
359367
Assert.assertNull(event); // the event is not complete
360368

361369
bos.reset();
362370
dos.writeInt(MotionEvent.BUTTON_PRIMARY);
371+
dos.writeInt(5); // repeat
363372
dos.writeInt(KeyEvent.META_CTRL_ON);
364373
packet = bos.toByteArray();
365374
reader.readFrom(new ByteArrayInputStream(packet));
@@ -369,6 +378,7 @@ public void testPartialEvents() throws IOException {
369378
Assert.assertEquals(ControlMessage.TYPE_INJECT_KEYCODE, event.getType());
370379
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
371380
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getKeycode());
381+
Assert.assertEquals(5, event.getRepeat());
372382
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
373383
}
374384
}

0 commit comments

Comments
 (0)