After the recent refactorings, a "control event" is not necessarily an "event" (it may be a "command"). Similarly, the unique "device event" used to send the device clipboard content is more a "reponse" to the request from the client than an "event". Rename both to "message", and rename the message types to better describe their intent.master
parent
f710d76c9e
commit
28980bbc90
@ -1,81 +0,0 @@
|
|||||||
#include "control_event.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "buffer_util.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "str_util.h"
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_position(uint8_t *buf, const struct position *position) {
|
|
||||||
buffer_write32be(&buf[0], position->point.x);
|
|
||||||
buffer_write32be(&buf[4], position->point.y);
|
|
||||||
buffer_write16be(&buf[8], position->screen_size.width);
|
|
||||||
buffer_write16be(&buf[10], position->screen_size.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// write length (2 bytes) + string (non nul-terminated)
|
|
||||||
static size_t
|
|
||||||
write_string(const char *utf8, size_t max_len, unsigned char *buf) {
|
|
||||||
size_t len = utf8_truncation_index(utf8, max_len);
|
|
||||||
buffer_write16be(buf, (uint16_t) len);
|
|
||||||
memcpy(&buf[2], utf8, len);
|
|
||||||
return 2 + len;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
control_event_serialize(const struct control_event *event, unsigned char *buf) {
|
|
||||||
buf[0] = event->type;
|
|
||||||
switch (event->type) {
|
|
||||||
case CONTROL_EVENT_TYPE_KEYCODE:
|
|
||||||
buf[1] = event->keycode_event.action;
|
|
||||||
buffer_write32be(&buf[2], event->keycode_event.keycode);
|
|
||||||
buffer_write32be(&buf[6], event->keycode_event.metastate);
|
|
||||||
return 10;
|
|
||||||
case CONTROL_EVENT_TYPE_TEXT: {
|
|
||||||
size_t len = write_string(event->text_event.text,
|
|
||||||
CONTROL_EVENT_TEXT_MAX_LENGTH, &buf[1]);
|
|
||||||
return 1 + len;
|
|
||||||
}
|
|
||||||
case CONTROL_EVENT_TYPE_MOUSE:
|
|
||||||
buf[1] = event->mouse_event.action;
|
|
||||||
buffer_write32be(&buf[2], event->mouse_event.buttons);
|
|
||||||
write_position(&buf[6], &event->mouse_event.position);
|
|
||||||
return 18;
|
|
||||||
case CONTROL_EVENT_TYPE_SCROLL:
|
|
||||||
write_position(&buf[1], &event->scroll_event.position);
|
|
||||||
buffer_write32be(&buf[13], (uint32_t) event->scroll_event.hscroll);
|
|
||||||
buffer_write32be(&buf[17], (uint32_t) event->scroll_event.vscroll);
|
|
||||||
return 21;
|
|
||||||
case CONTROL_EVENT_TYPE_SET_CLIPBOARD: {
|
|
||||||
size_t len = write_string(event->text_event.text,
|
|
||||||
CONTROL_EVENT_CLIPBOARD_TEXT_MAX_LENGTH,
|
|
||||||
&buf[1]);
|
|
||||||
return 1 + len;
|
|
||||||
}
|
|
||||||
case CONTROL_EVENT_TYPE_BACK_OR_SCREEN_ON:
|
|
||||||
case CONTROL_EVENT_TYPE_EXPAND_NOTIFICATION_PANEL:
|
|
||||||
case CONTROL_EVENT_TYPE_COLLAPSE_NOTIFICATION_PANEL:
|
|
||||||
case CONTROL_EVENT_TYPE_GET_CLIPBOARD:
|
|
||||||
// no additional data
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
LOGW("Unknown event type: %u", (unsigned) event->type);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
control_event_destroy(struct control_event *event) {
|
|
||||||
switch (event->type) {
|
|
||||||
case CONTROL_EVENT_TYPE_TEXT:
|
|
||||||
SDL_free(event->text_event.text);
|
|
||||||
break;
|
|
||||||
case CONTROL_EVENT_TYPE_SET_CLIPBOARD:
|
|
||||||
SDL_free(event->set_clipboard_event.text);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// do nothing
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
#ifndef CONTROLEVENT_H
|
|
||||||
#define CONTROLEVENT_H
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "android/input.h"
|
|
||||||
#include "android/keycodes.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#define CONTROL_EVENT_TEXT_MAX_LENGTH 300
|
|
||||||
#define CONTROL_EVENT_CLIPBOARD_TEXT_MAX_LENGTH 4093
|
|
||||||
#define CONTROL_EVENT_SERIALIZED_MAX_SIZE \
|
|
||||||
(3 + CONTROL_EVENT_CLIPBOARD_TEXT_MAX_LENGTH)
|
|
||||||
|
|
||||||
enum control_event_type {
|
|
||||||
CONTROL_EVENT_TYPE_KEYCODE,
|
|
||||||
CONTROL_EVENT_TYPE_TEXT,
|
|
||||||
CONTROL_EVENT_TYPE_MOUSE,
|
|
||||||
CONTROL_EVENT_TYPE_SCROLL,
|
|
||||||
CONTROL_EVENT_TYPE_BACK_OR_SCREEN_ON,
|
|
||||||
CONTROL_EVENT_TYPE_EXPAND_NOTIFICATION_PANEL,
|
|
||||||
CONTROL_EVENT_TYPE_COLLAPSE_NOTIFICATION_PANEL,
|
|
||||||
CONTROL_EVENT_TYPE_GET_CLIPBOARD,
|
|
||||||
CONTROL_EVENT_TYPE_SET_CLIPBOARD,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct control_event {
|
|
||||||
enum control_event_type type;
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
enum android_keyevent_action action;
|
|
||||||
enum android_keycode keycode;
|
|
||||||
enum android_metastate metastate;
|
|
||||||
} keycode_event;
|
|
||||||
struct {
|
|
||||||
char *text; // owned, to be freed by SDL_free()
|
|
||||||
} text_event;
|
|
||||||
struct {
|
|
||||||
enum android_motionevent_action action;
|
|
||||||
enum android_motionevent_buttons buttons;
|
|
||||||
struct position position;
|
|
||||||
} mouse_event;
|
|
||||||
struct {
|
|
||||||
struct position position;
|
|
||||||
int32_t hscroll;
|
|
||||||
int32_t vscroll;
|
|
||||||
} scroll_event;
|
|
||||||
struct {
|
|
||||||
char *text; // owned, to be freed by SDL_free()
|
|
||||||
} set_clipboard_event;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// buf size must be at least CONTROL_EVENT_SERIALIZED_MAX_SIZE
|
|
||||||
// return the number of bytes written
|
|
||||||
size_t
|
|
||||||
control_event_serialize(const struct control_event *event, unsigned char *buf);
|
|
||||||
|
|
||||||
void
|
|
||||||
control_event_destroy(struct control_event *event);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
#include "control_msg.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "buffer_util.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "str_util.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_position(uint8_t *buf, const struct position *position) {
|
||||||
|
buffer_write32be(&buf[0], position->point.x);
|
||||||
|
buffer_write32be(&buf[4], position->point.y);
|
||||||
|
buffer_write16be(&buf[8], position->screen_size.width);
|
||||||
|
buffer_write16be(&buf[10], position->screen_size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write length (2 bytes) + string (non nul-terminated)
|
||||||
|
static size_t
|
||||||
|
write_string(const char *utf8, size_t max_len, unsigned char *buf) {
|
||||||
|
size_t len = utf8_truncation_index(utf8, max_len);
|
||||||
|
buffer_write16be(buf, (uint16_t) len);
|
||||||
|
memcpy(&buf[2], utf8, len);
|
||||||
|
return 2 + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
control_msg_serialize(const struct control_msg *msg, unsigned char *buf) {
|
||||||
|
buf[0] = msg->type;
|
||||||
|
switch (msg->type) {
|
||||||
|
case CONTROL_MSG_TYPE_INJECT_KEYCODE:
|
||||||
|
buf[1] = msg->inject_keycode.action;
|
||||||
|
buffer_write32be(&buf[2], msg->inject_keycode.keycode);
|
||||||
|
buffer_write32be(&buf[6], msg->inject_keycode.metastate);
|
||||||
|
return 10;
|
||||||
|
case CONTROL_MSG_TYPE_INJECT_TEXT: {
|
||||||
|
size_t len = write_string(msg->inject_text.text,
|
||||||
|
CONTROL_MSG_TEXT_MAX_LENGTH, &buf[1]);
|
||||||
|
return 1 + len;
|
||||||
|
}
|
||||||
|
case CONTROL_MSG_TYPE_INJECT_MOUSE_EVENT:
|
||||||
|
buf[1] = msg->inject_mouse_event.action;
|
||||||
|
buffer_write32be(&buf[2], msg->inject_mouse_event.buttons);
|
||||||
|
write_position(&buf[6], &msg->inject_mouse_event.position);
|
||||||
|
return 18;
|
||||||
|
case CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT:
|
||||||
|
write_position(&buf[1], &msg->inject_scroll_event.position);
|
||||||
|
buffer_write32be(&buf[13],
|
||||||
|
(uint32_t) msg->inject_scroll_event.hscroll);
|
||||||
|
buffer_write32be(&buf[17],
|
||||||
|
(uint32_t) msg->inject_scroll_event.vscroll);
|
||||||
|
return 21;
|
||||||
|
case CONTROL_MSG_TYPE_SET_CLIPBOARD: {
|
||||||
|
size_t len = write_string(msg->inject_text.text,
|
||||||
|
CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH,
|
||||||
|
&buf[1]);
|
||||||
|
return 1 + len;
|
||||||
|
}
|
||||||
|
case CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON:
|
||||||
|
case CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL:
|
||||||
|
case CONTROL_MSG_TYPE_COLLAPSE_NOTIFICATION_PANEL:
|
||||||
|
case CONTROL_MSG_TYPE_GET_CLIPBOARD:
|
||||||
|
// no additional data
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
LOGW("Unknown message type: %u", (unsigned) msg->type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
control_msg_destroy(struct control_msg *msg) {
|
||||||
|
switch (msg->type) {
|
||||||
|
case CONTROL_MSG_TYPE_INJECT_TEXT:
|
||||||
|
SDL_free(msg->inject_text.text);
|
||||||
|
break;
|
||||||
|
case CONTROL_MSG_TYPE_SET_CLIPBOARD:
|
||||||
|
SDL_free(msg->set_clipboard.text);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// do nothing
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
#ifndef CONTROLMSG_H
|
||||||
|
#define CONTROLMSG_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "android/input.h"
|
||||||
|
#include "android/keycodes.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define CONTROL_MSG_TEXT_MAX_LENGTH 300
|
||||||
|
#define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH 4093
|
||||||
|
#define CONTROL_MSG_SERIALIZED_MAX_SIZE \
|
||||||
|
(3 + CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH)
|
||||||
|
|
||||||
|
enum control_msg_type {
|
||||||
|
CONTROL_MSG_TYPE_INJECT_KEYCODE,
|
||||||
|
CONTROL_MSG_TYPE_INJECT_TEXT,
|
||||||
|
CONTROL_MSG_TYPE_INJECT_MOUSE_EVENT,
|
||||||
|
CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT,
|
||||||
|
CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON,
|
||||||
|
CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL,
|
||||||
|
CONTROL_MSG_TYPE_COLLAPSE_NOTIFICATION_PANEL,
|
||||||
|
CONTROL_MSG_TYPE_GET_CLIPBOARD,
|
||||||
|
CONTROL_MSG_TYPE_SET_CLIPBOARD,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct control_msg {
|
||||||
|
enum control_msg_type type;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
enum android_keyevent_action action;
|
||||||
|
enum android_keycode keycode;
|
||||||
|
enum android_metastate metastate;
|
||||||
|
} inject_keycode;
|
||||||
|
struct {
|
||||||
|
char *text; // owned, to be freed by SDL_free()
|
||||||
|
} inject_text;
|
||||||
|
struct {
|
||||||
|
enum android_motionevent_action action;
|
||||||
|
enum android_motionevent_buttons buttons;
|
||||||
|
struct position position;
|
||||||
|
} inject_mouse_event;
|
||||||
|
struct {
|
||||||
|
struct position position;
|
||||||
|
int32_t hscroll;
|
||||||
|
int32_t vscroll;
|
||||||
|
} inject_scroll_event;
|
||||||
|
struct {
|
||||||
|
char *text; // owned, to be freed by SDL_free()
|
||||||
|
} set_clipboard;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// buf size must be at least CONTROL_MSG_SERIALIZED_MAX_SIZE
|
||||||
|
// return the number of bytes written
|
||||||
|
size_t
|
||||||
|
control_msg_serialize(const struct control_msg *msg, unsigned char *buf);
|
||||||
|
|
||||||
|
void
|
||||||
|
control_msg_destroy(struct control_msg *msg);
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -1,33 +0,0 @@
|
|||||||
#ifndef DEVICEEVENT_H
|
|
||||||
#define DEVICEEVENT_H
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#define DEVICE_EVENT_QUEUE_SIZE 64
|
|
||||||
#define DEVICE_EVENT_TEXT_MAX_LENGTH 4093
|
|
||||||
#define DEVICE_EVENT_SERIALIZED_MAX_SIZE (3 + DEVICE_EVENT_TEXT_MAX_LENGTH)
|
|
||||||
|
|
||||||
enum device_event_type {
|
|
||||||
DEVICE_EVENT_TYPE_GET_CLIPBOARD,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct device_event {
|
|
||||||
enum device_event_type type;
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
char *text; // owned, to be freed by SDL_free()
|
|
||||||
} clipboard_event;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// return the number of bytes consumed (0 for no event available, -1 on error)
|
|
||||||
ssize_t
|
|
||||||
device_event_deserialize(const unsigned char *buf, size_t len,
|
|
||||||
struct device_event *event);
|
|
||||||
|
|
||||||
void
|
|
||||||
device_event_destroy(struct device_event *event);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef DEVICEMSG_H
|
||||||
|
#define DEVICEMSG_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define DEVICE_MSG_TEXT_MAX_LENGTH 4093
|
||||||
|
#define DEVICE_MSG_SERIALIZED_MAX_SIZE (3 + DEVICE_MSG_TEXT_MAX_LENGTH)
|
||||||
|
|
||||||
|
enum device_msg_type {
|
||||||
|
DEVICE_MSG_TYPE_CLIPBOARD,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct device_msg {
|
||||||
|
enum device_msg_type type;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
char *text; // owned, to be freed by SDL_free()
|
||||||
|
} clipboard;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// return the number of bytes consumed (0 for no msg available, -1 on error)
|
||||||
|
ssize_t
|
||||||
|
device_msg_deserialize(const unsigned char *buf, size_t len,
|
||||||
|
struct device_msg *msg);
|
||||||
|
|
||||||
|
void
|
||||||
|
device_msg_destroy(struct device_msg *msg);
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -1,228 +0,0 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "control_event.h"
|
|
||||||
|
|
||||||
static void test_serialize_keycode_event(void) {
|
|
||||||
struct control_event event = {
|
|
||||||
.type = CONTROL_EVENT_TYPE_KEYCODE,
|
|
||||||
.keycode_event = {
|
|
||||||
.action = AKEY_EVENT_ACTION_UP,
|
|
||||||
.keycode = AKEYCODE_ENTER,
|
|
||||||
.metastate = AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned char buf[CONTROL_EVENT_SERIALIZED_MAX_SIZE];
|
|
||||||
int size = control_event_serialize(&event, buf);
|
|
||||||
assert(size == 10);
|
|
||||||
|
|
||||||
const unsigned char expected[] = {
|
|
||||||
0x00, // CONTROL_EVENT_TYPE_KEYCODE
|
|
||||||
0x01, // AKEY_EVENT_ACTION_UP
|
|
||||||
0x00, 0x00, 0x00, 0x42, // AKEYCODE_ENTER
|
|
||||||
0x00, 0x00, 0x00, 0x41, // AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON
|
|
||||||
};
|
|
||||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_serialize_text_event(void) {
|
|
||||||
struct control_event event = {
|
|
||||||
.type = CONTROL_EVENT_TYPE_TEXT,
|
|
||||||
.text_event = {
|
|
||||||
.text = "hello, world!",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned char buf[CONTROL_EVENT_SERIALIZED_MAX_SIZE];
|
|
||||||
int size = control_event_serialize(&event, buf);
|
|
||||||
assert(size == 16);
|
|
||||||
|
|
||||||
const unsigned char expected[] = {
|
|
||||||
0x01, // CONTROL_EVENT_TYPE_TEXT
|
|
||||||
0x00, 0x0d, // text length
|
|
||||||
'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', // text
|
|
||||||
};
|
|
||||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_serialize_long_text_event(void) {
|
|
||||||
struct control_event event;
|
|
||||||
event.type = CONTROL_EVENT_TYPE_TEXT;
|
|
||||||
char text[CONTROL_EVENT_TEXT_MAX_LENGTH + 1];
|
|
||||||
memset(text, 'a', sizeof(text));
|
|
||||||
text[CONTROL_EVENT_TEXT_MAX_LENGTH] = '\0';
|
|
||||||
event.text_event.text = text;
|
|
||||||
|
|
||||||
unsigned char buf[CONTROL_EVENT_SERIALIZED_MAX_SIZE];
|
|
||||||
int size = control_event_serialize(&event, buf);
|
|
||||||
assert(size == 3 + CONTROL_EVENT_TEXT_MAX_LENGTH);
|
|
||||||
|
|
||||||
unsigned char expected[3 + CONTROL_EVENT_TEXT_MAX_LENGTH];
|
|
||||||
expected[0] = 0x01; // CONTROL_EVENT_TYPE_KEYCODE
|
|
||||||
expected[1] = 0x01;
|
|
||||||
expected[2] = 0x2c; // text length (16 bits)
|
|
||||||
memset(&expected[3], 'a', CONTROL_EVENT_TEXT_MAX_LENGTH);
|
|
||||||
|
|
||||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_serialize_mouse_event(void) {
|
|
||||||
struct control_event event = {
|
|
||||||
.type = CONTROL_EVENT_TYPE_MOUSE,
|
|
||||||
.mouse_event = {
|
|
||||||
.action = AMOTION_EVENT_ACTION_DOWN,
|
|
||||||
.buttons = AMOTION_EVENT_BUTTON_PRIMARY,
|
|
||||||
.position = {
|
|
||||||
.point = {
|
|
||||||
.x = 260,
|
|
||||||
.y = 1026,
|
|
||||||
},
|
|
||||||
.screen_size = {
|
|
||||||
.width = 1080,
|
|
||||||
.height = 1920,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned char buf[CONTROL_EVENT_SERIALIZED_MAX_SIZE];
|
|
||||||
int size = control_event_serialize(&event, buf);
|
|
||||||
assert(size == 18);
|
|
||||||
|
|
||||||
const unsigned char expected[] = {
|
|
||||||
0x02, // CONTROL_EVENT_TYPE_MOUSE
|
|
||||||
0x00, // AKEY_EVENT_ACTION_DOWN
|
|
||||||
0x00, 0x00, 0x00, 0x01, // AMOTION_EVENT_BUTTON_PRIMARY
|
|
||||||
0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x04, 0x02, // 260 1026
|
|
||||||
0x04, 0x38, 0x07, 0x80, // 1080 1920
|
|
||||||
};
|
|
||||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_serialize_scroll_event(void) {
|
|
||||||
struct control_event event = {
|
|
||||||
.type = CONTROL_EVENT_TYPE_SCROLL,
|
|
||||||
.scroll_event = {
|
|
||||||
.position = {
|
|
||||||
.point = {
|
|
||||||
.x = 260,
|
|
||||||
.y = 1026,
|
|
||||||
},
|
|
||||||
.screen_size = {
|
|
||||||
.width = 1080,
|
|
||||||
.height = 1920,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.hscroll = 1,
|
|
||||||
.vscroll = -1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned char buf[CONTROL_EVENT_SERIALIZED_MAX_SIZE];
|
|
||||||
int size = control_event_serialize(&event, buf);
|
|
||||||
assert(size == 21);
|
|
||||||
|
|
||||||
const unsigned char expected[] = {
|
|
||||||
0x03, // CONTROL_EVENT_TYPE_SCROLL
|
|
||||||
0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x04, 0x02, // 260 1026
|
|
||||||
0x04, 0x38, 0x07, 0x80, // 1080 1920
|
|
||||||
0x00, 0x00, 0x00, 0x01, // 1
|
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, // -1
|
|
||||||
};
|
|
||||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_serialize_back_or_screen_on_event(void) {
|
|
||||||
struct control_event event = {
|
|
||||||
.type = CONTROL_EVENT_TYPE_BACK_OR_SCREEN_ON,
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned char buf[CONTROL_EVENT_SERIALIZED_MAX_SIZE];
|
|
||||||
int size = control_event_serialize(&event, buf);
|
|
||||||
assert(size == 1);
|
|
||||||
|
|
||||||
const unsigned char expected[] = {
|
|
||||||
0x04, // CONTROL_EVENT_TYPE_BACK_OR_SCREEN_ON
|
|
||||||
};
|
|
||||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_serialize_expand_notification_panel_event(void) {
|
|
||||||
struct control_event event = {
|
|
||||||
.type = CONTROL_EVENT_TYPE_EXPAND_NOTIFICATION_PANEL,
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned char buf[CONTROL_EVENT_SERIALIZED_MAX_SIZE];
|
|
||||||
int size = control_event_serialize(&event, buf);
|
|
||||||
assert(size == 1);
|
|
||||||
|
|
||||||
const unsigned char expected[] = {
|
|
||||||
0x05, // CONTROL_EVENT_TYPE_EXPAND_NOTIFICATION_PANEL
|
|
||||||
};
|
|
||||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_serialize_collapse_notification_panel_event(void) {
|
|
||||||
struct control_event event = {
|
|
||||||
.type = CONTROL_EVENT_TYPE_COLLAPSE_NOTIFICATION_PANEL,
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned char buf[CONTROL_EVENT_SERIALIZED_MAX_SIZE];
|
|
||||||
int size = control_event_serialize(&event, buf);
|
|
||||||
assert(size == 1);
|
|
||||||
|
|
||||||
const unsigned char expected[] = {
|
|
||||||
0x06, // CONTROL_EVENT_TYPE_COLLAPSE_NOTIFICATION_PANEL
|
|
||||||
};
|
|
||||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_serialize_get_clipboard_event(void) {
|
|
||||||
struct control_event event = {
|
|
||||||
.type = CONTROL_EVENT_TYPE_GET_CLIPBOARD,
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned char buf[CONTROL_EVENT_SERIALIZED_MAX_SIZE];
|
|
||||||
int size = control_event_serialize(&event, buf);
|
|
||||||
assert(size == 1);
|
|
||||||
|
|
||||||
const unsigned char expected[] = {
|
|
||||||
0x07, // CONTROL_EVENT_TYPE_GET_CLIPBOARD
|
|
||||||
};
|
|
||||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_serialize_set_clipboard_event(void) {
|
|
||||||
struct control_event event = {
|
|
||||||
.type = CONTROL_EVENT_TYPE_SET_CLIPBOARD,
|
|
||||||
.text_event = {
|
|
||||||
.text = "hello, world!",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned char buf[CONTROL_EVENT_SERIALIZED_MAX_SIZE];
|
|
||||||
int size = control_event_serialize(&event, buf);
|
|
||||||
assert(size == 16);
|
|
||||||
|
|
||||||
const unsigned char expected[] = {
|
|
||||||
0x08, // CONTROL_EVENT_TYPE_SET_CLIPBOARD
|
|
||||||
0x00, 0x0d, // text length
|
|
||||||
'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', // text
|
|
||||||
};
|
|
||||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
test_serialize_keycode_event();
|
|
||||||
test_serialize_text_event();
|
|
||||||
test_serialize_long_text_event();
|
|
||||||
test_serialize_mouse_event();
|
|
||||||
test_serialize_scroll_event();
|
|
||||||
test_serialize_back_or_screen_on_event();
|
|
||||||
test_serialize_expand_notification_panel_event();
|
|
||||||
test_serialize_collapse_notification_panel_event();
|
|
||||||
test_serialize_get_clipboard_event();
|
|
||||||
test_serialize_set_clipboard_event();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -0,0 +1,228 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "control_msg.h"
|
||||||
|
|
||||||
|
static void test_serialize_inject_keycode(void) {
|
||||||
|
struct control_msg msg = {
|
||||||
|
.type = CONTROL_MSG_TYPE_INJECT_KEYCODE,
|
||||||
|
.inject_keycode = {
|
||||||
|
.action = AKEY_EVENT_ACTION_UP,
|
||||||
|
.keycode = AKEYCODE_ENTER,
|
||||||
|
.metastate = AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char buf[CONTROL_MSG_SERIALIZED_MAX_SIZE];
|
||||||
|
int size = control_msg_serialize(&msg, buf);
|
||||||
|
assert(size == 10);
|
||||||
|
|
||||||
|
const unsigned char expected[] = {
|
||||||
|
CONTROL_MSG_TYPE_INJECT_KEYCODE,
|
||||||
|
0x01, // AKEY_EVENT_ACTION_UP
|
||||||
|
0x00, 0x00, 0x00, 0x42, // AKEYCODE_ENTER
|
||||||
|
0x00, 0x00, 0x00, 0x41, // AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON
|
||||||
|
};
|
||||||
|
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_serialize_inject_text(void) {
|
||||||
|
struct control_msg msg = {
|
||||||
|
.type = CONTROL_MSG_TYPE_INJECT_TEXT,
|
||||||
|
.inject_text = {
|
||||||
|
.text = "hello, world!",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char buf[CONTROL_MSG_SERIALIZED_MAX_SIZE];
|
||||||
|
int size = control_msg_serialize(&msg, buf);
|
||||||
|
assert(size == 16);
|
||||||
|
|
||||||
|
const unsigned char expected[] = {
|
||||||
|
CONTROL_MSG_TYPE_INJECT_TEXT,
|
||||||
|
0x00, 0x0d, // text length
|
||||||
|
'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', // text
|
||||||
|
};
|
||||||
|
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_serialize_inject_text_long(void) {
|
||||||
|
struct control_msg msg;
|
||||||
|
msg.type = CONTROL_MSG_TYPE_INJECT_TEXT;
|
||||||
|
char text[CONTROL_MSG_TEXT_MAX_LENGTH + 1];
|
||||||
|
memset(text, 'a', sizeof(text));
|
||||||
|
text[CONTROL_MSG_TEXT_MAX_LENGTH] = '\0';
|
||||||
|
msg.inject_text.text = text;
|
||||||
|
|
||||||
|
unsigned char buf[CONTROL_MSG_SERIALIZED_MAX_SIZE];
|
||||||
|
int size = control_msg_serialize(&msg, buf);
|
||||||
|
assert(size == 3 + CONTROL_MSG_TEXT_MAX_LENGTH);
|
||||||
|
|
||||||
|
unsigned char expected[3 + CONTROL_MSG_TEXT_MAX_LENGTH];
|
||||||
|
expected[0] = CONTROL_MSG_TYPE_INJECT_TEXT;
|
||||||
|
expected[1] = 0x01;
|
||||||
|
expected[2] = 0x2c; // text length (16 bits)
|
||||||
|
memset(&expected[3], 'a', CONTROL_MSG_TEXT_MAX_LENGTH);
|
||||||
|
|
||||||
|
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_serialize_inject_mouse_event(void) {
|
||||||
|
struct control_msg msg = {
|
||||||
|
.type = CONTROL_MSG_TYPE_INJECT_MOUSE_EVENT,
|
||||||
|
.inject_mouse_event = {
|
||||||
|
.action = AMOTION_EVENT_ACTION_DOWN,
|
||||||
|
.buttons = AMOTION_EVENT_BUTTON_PRIMARY,
|
||||||
|
.position = {
|
||||||
|
.point = {
|
||||||
|
.x = 260,
|
||||||
|
.y = 1026,
|
||||||
|
},
|
||||||
|
.screen_size = {
|
||||||
|
.width = 1080,
|
||||||
|
.height = 1920,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char buf[CONTROL_MSG_SERIALIZED_MAX_SIZE];
|
||||||
|
int size = control_msg_serialize(&msg, buf);
|
||||||
|
assert(size == 18);
|
||||||
|
|
||||||
|
const unsigned char expected[] = {
|
||||||
|
CONTROL_MSG_TYPE_INJECT_MOUSE_EVENT,
|
||||||
|
0x00, // AKEY_EVENT_ACTION_DOWN
|
||||||
|
0x00, 0x00, 0x00, 0x01, // AMOTION_EVENT_BUTTON_PRIMARY
|
||||||
|
0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x04, 0x02, // 260 1026
|
||||||
|
0x04, 0x38, 0x07, 0x80, // 1080 1920
|
||||||
|
};
|
||||||
|
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_serialize_inject_scroll_event(void) {
|
||||||
|
struct control_msg msg = {
|
||||||
|
.type = CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT,
|
||||||
|
.inject_scroll_event = {
|
||||||
|
.position = {
|
||||||
|
.point = {
|
||||||
|
.x = 260,
|
||||||
|
.y = 1026,
|
||||||
|
},
|
||||||
|
.screen_size = {
|
||||||
|
.width = 1080,
|
||||||
|
.height = 1920,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.hscroll = 1,
|
||||||
|
.vscroll = -1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char buf[CONTROL_MSG_SERIALIZED_MAX_SIZE];
|
||||||
|
int size = control_msg_serialize(&msg, buf);
|
||||||
|
assert(size == 21);
|
||||||
|
|
||||||
|
const unsigned char expected[] = {
|
||||||
|
CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT,
|
||||||
|
0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x04, 0x02, // 260 1026
|
||||||
|
0x04, 0x38, 0x07, 0x80, // 1080 1920
|
||||||
|
0x00, 0x00, 0x00, 0x01, // 1
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, // -1
|
||||||
|
};
|
||||||
|
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_serialize_back_or_screen_on(void) {
|
||||||
|
struct control_msg msg = {
|
||||||
|
.type = CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char buf[CONTROL_MSG_SERIALIZED_MAX_SIZE];
|
||||||
|
int size = control_msg_serialize(&msg, buf);
|
||||||
|
assert(size == 1);
|
||||||
|
|
||||||
|
const unsigned char expected[] = {
|
||||||
|
CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON,
|
||||||
|
};
|
||||||
|
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_serialize_expand_notification_panel(void) {
|
||||||
|
struct control_msg msg = {
|
||||||
|
.type = CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char buf[CONTROL_MSG_SERIALIZED_MAX_SIZE];
|
||||||
|
int size = control_msg_serialize(&msg, buf);
|
||||||
|
assert(size == 1);
|
||||||
|
|
||||||
|
const unsigned char expected[] = {
|
||||||
|
CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL,
|
||||||
|
};
|
||||||
|
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_serialize_collapse_notification_panel(void) {
|
||||||
|
struct control_msg msg = {
|
||||||
|
.type = CONTROL_MSG_TYPE_COLLAPSE_NOTIFICATION_PANEL,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char buf[CONTROL_MSG_SERIALIZED_MAX_SIZE];
|
||||||
|
int size = control_msg_serialize(&msg, buf);
|
||||||
|
assert(size == 1);
|
||||||
|
|
||||||
|
const unsigned char expected[] = {
|
||||||
|
CONTROL_MSG_TYPE_COLLAPSE_NOTIFICATION_PANEL,
|
||||||
|
};
|
||||||
|
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_serialize_get_clipboard(void) {
|
||||||
|
struct control_msg msg = {
|
||||||
|
.type = CONTROL_MSG_TYPE_GET_CLIPBOARD,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char buf[CONTROL_MSG_SERIALIZED_MAX_SIZE];
|
||||||
|
int size = control_msg_serialize(&msg, buf);
|
||||||
|
assert(size == 1);
|
||||||
|
|
||||||
|
const unsigned char expected[] = {
|
||||||
|
CONTROL_MSG_TYPE_GET_CLIPBOARD,
|
||||||
|
};
|
||||||
|
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_serialize_set_clipboard(void) {
|
||||||
|
struct control_msg msg = {
|
||||||
|
.type = CONTROL_MSG_TYPE_SET_CLIPBOARD,
|
||||||
|
.inject_text = {
|
||||||
|
.text = "hello, world!",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char buf[CONTROL_MSG_SERIALIZED_MAX_SIZE];
|
||||||
|
int size = control_msg_serialize(&msg, buf);
|
||||||
|
assert(size == 16);
|
||||||
|
|
||||||
|
const unsigned char expected[] = {
|
||||||
|
CONTROL_MSG_TYPE_SET_CLIPBOARD,
|
||||||
|
0x00, 0x0d, // text length
|
||||||
|
'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', // text
|
||||||
|
};
|
||||||
|
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
test_serialize_inject_keycode();
|
||||||
|
test_serialize_inject_text();
|
||||||
|
test_serialize_inject_text_long();
|
||||||
|
test_serialize_inject_mouse_event();
|
||||||
|
test_serialize_inject_scroll_event();
|
||||||
|
test_serialize_back_or_screen_on();
|
||||||
|
test_serialize_expand_notification_panel();
|
||||||
|
test_serialize_collapse_notification_panel();
|
||||||
|
test_serialize_get_clipboard();
|
||||||
|
test_serialize_set_clipboard();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -1,28 +0,0 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "device_event.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
static void test_deserialize_clipboard_event(void) {
|
|
||||||
const unsigned char input[] = {
|
|
||||||
0x00, // DEVICE_EVENT_TYPE_CLIPBOARD
|
|
||||||
0x00, 0x03, // text length
|
|
||||||
0x41, 0x42, 0x43, // "ABC"
|
|
||||||
};
|
|
||||||
|
|
||||||
struct device_event event;
|
|
||||||
ssize_t r = device_event_deserialize(input, sizeof(input), &event);
|
|
||||||
assert(r == 6);
|
|
||||||
|
|
||||||
assert(event.type == DEVICE_EVENT_TYPE_GET_CLIPBOARD);
|
|
||||||
assert(event.clipboard_event.text);
|
|
||||||
assert(!strcmp("ABC", event.clipboard_event.text));
|
|
||||||
|
|
||||||
device_event_destroy(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
test_deserialize_clipboard_event();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "device_msg.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
static void test_deserialize_clipboard(void) {
|
||||||
|
const unsigned char input[] = {
|
||||||
|
DEVICE_MSG_TYPE_CLIPBOARD,
|
||||||
|
0x00, 0x03, // text length
|
||||||
|
0x41, 0x42, 0x43, // "ABC"
|
||||||
|
};
|
||||||
|
|
||||||
|
struct device_msg msg;
|
||||||
|
ssize_t r = device_msg_deserialize(input, sizeof(input), &msg);
|
||||||
|
assert(r == 6);
|
||||||
|
|
||||||
|
assert(msg.type == DEVICE_MSG_TYPE_CLIPBOARD);
|
||||||
|
assert(msg.clipboard.text);
|
||||||
|
assert(!strcmp("ABC", msg.clipboard.text));
|
||||||
|
|
||||||
|
device_msg_destroy(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
test_deserialize_clipboard();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -1,27 +0,0 @@
|
|||||||
package com.genymobile.scrcpy;
|
|
||||||
|
|
||||||
public final class DeviceEvent {
|
|
||||||
|
|
||||||
public static final int TYPE_GET_CLIPBOARD = 0;
|
|
||||||
|
|
||||||
private int type;
|
|
||||||
private String text;
|
|
||||||
|
|
||||||
private DeviceEvent() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DeviceEvent createGetClipboardEvent(String text) {
|
|
||||||
DeviceEvent event = new DeviceEvent();
|
|
||||||
event.type = TYPE_GET_CLIPBOARD;
|
|
||||||
event.text = text;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getText() {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package com.genymobile.scrcpy;
|
||||||
|
|
||||||
|
public final class DeviceMessage {
|
||||||
|
|
||||||
|
public static final int TYPE_CLIPBOARD = 0;
|
||||||
|
|
||||||
|
private int type;
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
private DeviceMessage() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DeviceMessage createClipboard(String text) {
|
||||||
|
DeviceMessage event = new DeviceMessage();
|
||||||
|
event.type = TYPE_CLIPBOARD;
|
||||||
|
event.text = text;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in new issue