Rename "event" to "message"
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.
This commit is contained in:
parent
f710d76c9e
commit
28980bbc90
28 changed files with 777 additions and 778 deletions
|
@ -1,12 +1,12 @@
|
||||||
src = [
|
src = [
|
||||||
'src/main.c',
|
'src/main.c',
|
||||||
'src/command.c',
|
'src/command.c',
|
||||||
'src/control_event.c',
|
'src/control_msg.c',
|
||||||
'src/controller.c',
|
'src/controller.c',
|
||||||
'src/convert.c',
|
'src/convert.c',
|
||||||
'src/decoder.c',
|
'src/decoder.c',
|
||||||
'src/device.c',
|
'src/device.c',
|
||||||
'src/device_event.c',
|
'src/device_msg.c',
|
||||||
'src/file_handler.c',
|
'src/file_handler.c',
|
||||||
'src/fps_counter.c',
|
'src/fps_counter.c',
|
||||||
'src/input_manager.c',
|
'src/input_manager.c',
|
||||||
|
@ -160,13 +160,13 @@ tests = [
|
||||||
'tests/test_cbuf.c',
|
'tests/test_cbuf.c',
|
||||||
]],
|
]],
|
||||||
['test_control_event_serialize', [
|
['test_control_event_serialize', [
|
||||||
'tests/test_control_event_serialize.c',
|
'tests/test_control_msg_serialize.c',
|
||||||
'src/control_event.c',
|
'src/control_msg.c',
|
||||||
'src/str_util.c'
|
'src/str_util.c'
|
||||||
]],
|
]],
|
||||||
['test_device_event_deserialize', [
|
['test_device_event_deserialize', [
|
||||||
'tests/test_device_event_deserialize.c',
|
'tests/test_device_msg_deserialize.c',
|
||||||
'src/device_event.c'
|
'src/device_msg.c'
|
||||||
]],
|
]],
|
||||||
['test_strutil', [
|
['test_strutil', [
|
||||||
'tests/test_strutil.c',
|
'tests/test_strutil.c',
|
||||||
|
|
|
@ -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
|
|
83
app/src/control_msg.c
Normal file
83
app/src/control_msg.c
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
64
app/src/control_msg.h
Normal file
64
app/src/control_msg.h
Normal file
|
@ -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
|
|
@ -19,7 +19,7 @@ controller_init(struct controller *controller, socket_t control_socket) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(controller->event_cond = SDL_CreateCond())) {
|
if (!(controller->msg_cond = SDL_CreateCond())) {
|
||||||
receiver_destroy(&controller->receiver);
|
receiver_destroy(&controller->receiver);
|
||||||
SDL_DestroyMutex(controller->mutex);
|
SDL_DestroyMutex(controller->mutex);
|
||||||
return false;
|
return false;
|
||||||
|
@ -33,39 +33,39 @@ controller_init(struct controller *controller, socket_t control_socket) {
|
||||||
|
|
||||||
void
|
void
|
||||||
controller_destroy(struct controller *controller) {
|
controller_destroy(struct controller *controller) {
|
||||||
SDL_DestroyCond(controller->event_cond);
|
SDL_DestroyCond(controller->msg_cond);
|
||||||
SDL_DestroyMutex(controller->mutex);
|
SDL_DestroyMutex(controller->mutex);
|
||||||
|
|
||||||
struct control_event event;
|
struct control_msg msg;
|
||||||
while (cbuf_take(&controller->queue, &event)) {
|
while (cbuf_take(&controller->queue, &msg)) {
|
||||||
control_event_destroy(&event);
|
control_msg_destroy(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
receiver_destroy(&controller->receiver);
|
receiver_destroy(&controller->receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
controller_push_event(struct controller *controller,
|
controller_push_msg(struct controller *controller,
|
||||||
const struct control_event *event) {
|
const struct control_msg *msg) {
|
||||||
mutex_lock(controller->mutex);
|
mutex_lock(controller->mutex);
|
||||||
bool was_empty = cbuf_is_empty(&controller->queue);
|
bool was_empty = cbuf_is_empty(&controller->queue);
|
||||||
bool res = cbuf_push(&controller->queue, *event);
|
bool res = cbuf_push(&controller->queue, *msg);
|
||||||
if (was_empty) {
|
if (was_empty) {
|
||||||
cond_signal(controller->event_cond);
|
cond_signal(controller->msg_cond);
|
||||||
}
|
}
|
||||||
mutex_unlock(controller->mutex);
|
mutex_unlock(controller->mutex);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
process_event(struct controller *controller,
|
process_msg(struct controller *controller,
|
||||||
const struct control_event *event) {
|
const struct control_msg *msg) {
|
||||||
unsigned char serialized_event[CONTROL_EVENT_SERIALIZED_MAX_SIZE];
|
unsigned char serialized_msg[CONTROL_MSG_SERIALIZED_MAX_SIZE];
|
||||||
int length = control_event_serialize(event, serialized_event);
|
int length = control_msg_serialize(msg, serialized_msg);
|
||||||
if (!length) {
|
if (!length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int w = net_send_all(controller->control_socket, serialized_event, length);
|
int w = net_send_all(controller->control_socket, serialized_msg, length);
|
||||||
return w == length;
|
return w == length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,22 +76,22 @@ run_controller(void *data) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
mutex_lock(controller->mutex);
|
mutex_lock(controller->mutex);
|
||||||
while (!controller->stopped && cbuf_is_empty(&controller->queue)) {
|
while (!controller->stopped && cbuf_is_empty(&controller->queue)) {
|
||||||
cond_wait(controller->event_cond, controller->mutex);
|
cond_wait(controller->msg_cond, controller->mutex);
|
||||||
}
|
}
|
||||||
if (controller->stopped) {
|
if (controller->stopped) {
|
||||||
// stop immediately, do not process further events
|
// stop immediately, do not process further msgs
|
||||||
mutex_unlock(controller->mutex);
|
mutex_unlock(controller->mutex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
struct control_event event;
|
struct control_msg msg;
|
||||||
bool non_empty = cbuf_take(&controller->queue, &event);
|
bool non_empty = cbuf_take(&controller->queue, &msg);
|
||||||
SDL_assert(non_empty);
|
SDL_assert(non_empty);
|
||||||
mutex_unlock(controller->mutex);
|
mutex_unlock(controller->mutex);
|
||||||
|
|
||||||
bool ok = process_event(controller, &event);
|
bool ok = process_msg(controller, &msg);
|
||||||
control_event_destroy(&event);
|
control_msg_destroy(&msg);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
LOGD("Cannot write event to socket");
|
LOGD("Cannot write msg to socket");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ void
|
||||||
controller_stop(struct controller *controller) {
|
controller_stop(struct controller *controller) {
|
||||||
mutex_lock(controller->mutex);
|
mutex_lock(controller->mutex);
|
||||||
controller->stopped = true;
|
controller->stopped = true;
|
||||||
cond_signal(controller->event_cond);
|
cond_signal(controller->msg_cond);
|
||||||
mutex_unlock(controller->mutex);
|
mutex_unlock(controller->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
#ifndef CONTROL_H
|
#ifndef CONTROLLER_H
|
||||||
#define CONTROL_H
|
#define CONTROLLER_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <SDL2/SDL_mutex.h>
|
#include <SDL2/SDL_mutex.h>
|
||||||
#include <SDL2/SDL_thread.h>
|
#include <SDL2/SDL_thread.h>
|
||||||
|
|
||||||
#include "cbuf.h"
|
#include "cbuf.h"
|
||||||
#include "control_event.h"
|
#include "control_msg.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "receiver.h"
|
#include "receiver.h"
|
||||||
|
|
||||||
struct control_event_queue CBUF(struct control_event, 64);
|
struct control_msg_queue CBUF(struct control_msg, 64);
|
||||||
|
|
||||||
struct controller {
|
struct controller {
|
||||||
socket_t control_socket;
|
socket_t control_socket;
|
||||||
SDL_Thread *thread;
|
SDL_Thread *thread;
|
||||||
SDL_mutex *mutex;
|
SDL_mutex *mutex;
|
||||||
SDL_cond *event_cond;
|
SDL_cond *msg_cond;
|
||||||
bool stopped;
|
bool stopped;
|
||||||
struct control_event_queue queue;
|
struct control_msg_queue queue;
|
||||||
struct receiver receiver;
|
struct receiver receiver;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ void
|
||||||
controller_join(struct controller *controller);
|
controller_join(struct controller *controller);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
controller_push_event(struct controller *controller,
|
controller_push_msg(struct controller *controller,
|
||||||
const struct control_event *event);
|
const struct control_msg *msg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -159,19 +159,19 @@ convert_mouse_buttons(uint32_t state) {
|
||||||
|
|
||||||
bool
|
bool
|
||||||
input_key_from_sdl_to_android(const SDL_KeyboardEvent *from,
|
input_key_from_sdl_to_android(const SDL_KeyboardEvent *from,
|
||||||
struct control_event *to) {
|
struct control_msg *to) {
|
||||||
to->type = CONTROL_EVENT_TYPE_KEYCODE;
|
to->type = CONTROL_MSG_TYPE_INJECT_KEYCODE;
|
||||||
|
|
||||||
if (!convert_keycode_action(from->type, &to->keycode_event.action)) {
|
if (!convert_keycode_action(from->type, &to->inject_keycode.action)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t mod = from->keysym.mod;
|
uint16_t mod = from->keysym.mod;
|
||||||
if (!convert_keycode(from->keysym.sym, &to->keycode_event.keycode, mod)) {
|
if (!convert_keycode(from->keysym.sym, &to->inject_keycode.keycode, mod)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
to->keycode_event.metastate = convert_meta_state(mod);
|
to->inject_keycode.metastate = convert_meta_state(mod);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -179,17 +179,18 @@ input_key_from_sdl_to_android(const SDL_KeyboardEvent *from,
|
||||||
bool
|
bool
|
||||||
mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from,
|
mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from,
|
||||||
struct size screen_size,
|
struct size screen_size,
|
||||||
struct control_event *to) {
|
struct control_msg *to) {
|
||||||
to->type = CONTROL_EVENT_TYPE_MOUSE;
|
to->type = CONTROL_MSG_TYPE_INJECT_MOUSE_EVENT;
|
||||||
|
|
||||||
if (!convert_mouse_action(from->type, &to->mouse_event.action)) {
|
if (!convert_mouse_action(from->type, &to->inject_mouse_event.action)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
to->mouse_event.buttons = convert_mouse_buttons(SDL_BUTTON(from->button));
|
to->inject_mouse_event.buttons =
|
||||||
to->mouse_event.position.screen_size = screen_size;
|
convert_mouse_buttons(SDL_BUTTON(from->button));
|
||||||
to->mouse_event.position.point.x = from->x;
|
to->inject_mouse_event.position.screen_size = screen_size;
|
||||||
to->mouse_event.position.point.y = from->y;
|
to->inject_mouse_event.position.point.x = from->x;
|
||||||
|
to->inject_mouse_event.position.point.y = from->y;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -197,13 +198,13 @@ mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from,
|
||||||
bool
|
bool
|
||||||
mouse_motion_from_sdl_to_android(const SDL_MouseMotionEvent *from,
|
mouse_motion_from_sdl_to_android(const SDL_MouseMotionEvent *from,
|
||||||
struct size screen_size,
|
struct size screen_size,
|
||||||
struct control_event *to) {
|
struct control_msg *to) {
|
||||||
to->type = CONTROL_EVENT_TYPE_MOUSE;
|
to->type = CONTROL_MSG_TYPE_INJECT_MOUSE_EVENT;
|
||||||
to->mouse_event.action = AMOTION_EVENT_ACTION_MOVE;
|
to->inject_mouse_event.action = AMOTION_EVENT_ACTION_MOVE;
|
||||||
to->mouse_event.buttons = convert_mouse_buttons(from->state);
|
to->inject_mouse_event.buttons = convert_mouse_buttons(from->state);
|
||||||
to->mouse_event.position.screen_size = screen_size;
|
to->inject_mouse_event.position.screen_size = screen_size;
|
||||||
to->mouse_event.position.point.x = from->x;
|
to->inject_mouse_event.position.point.x = from->x;
|
||||||
to->mouse_event.position.point.y = from->y;
|
to->inject_mouse_event.position.point.y = from->y;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -211,17 +212,17 @@ mouse_motion_from_sdl_to_android(const SDL_MouseMotionEvent *from,
|
||||||
bool
|
bool
|
||||||
mouse_wheel_from_sdl_to_android(const SDL_MouseWheelEvent *from,
|
mouse_wheel_from_sdl_to_android(const SDL_MouseWheelEvent *from,
|
||||||
struct position position,
|
struct position position,
|
||||||
struct control_event *to) {
|
struct control_msg *to) {
|
||||||
to->type = CONTROL_EVENT_TYPE_SCROLL;
|
to->type = CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT;
|
||||||
|
|
||||||
to->scroll_event.position = position;
|
to->inject_scroll_event.position = position;
|
||||||
|
|
||||||
int mul = from->direction == SDL_MOUSEWHEEL_NORMAL ? 1 : -1;
|
int mul = from->direction == SDL_MOUSEWHEEL_NORMAL ? 1 : -1;
|
||||||
// SDL behavior seems inconsistent between horizontal and vertical scrolling
|
// SDL behavior seems inconsistent between horizontal and vertical scrolling
|
||||||
// so reverse the horizontal
|
// so reverse the horizontal
|
||||||
// <https://wiki.libsdl.org/SDL_MouseWheelEvent#Remarks>
|
// <https://wiki.libsdl.org/SDL_MouseWheelEvent#Remarks>
|
||||||
to->scroll_event.hscroll = -mul * from->x;
|
to->inject_scroll_event.hscroll = -mul * from->x;
|
||||||
to->scroll_event.vscroll = mul * from->y;
|
to->inject_scroll_event.vscroll = mul * from->y;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <SDL2/SDL_events.h>
|
#include <SDL2/SDL_events.h>
|
||||||
|
|
||||||
#include "control_event.h"
|
#include "control_msg.h"
|
||||||
|
|
||||||
struct complete_mouse_motion_event {
|
struct complete_mouse_motion_event {
|
||||||
SDL_MouseMotionEvent *mouse_motion_event;
|
SDL_MouseMotionEvent *mouse_motion_event;
|
||||||
|
@ -18,24 +18,24 @@ struct complete_mouse_wheel_event {
|
||||||
|
|
||||||
bool
|
bool
|
||||||
input_key_from_sdl_to_android(const SDL_KeyboardEvent *from,
|
input_key_from_sdl_to_android(const SDL_KeyboardEvent *from,
|
||||||
struct control_event *to);
|
struct control_msg *to);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from,
|
mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from,
|
||||||
struct size screen_size,
|
struct size screen_size,
|
||||||
struct control_event *to);
|
struct control_msg *to);
|
||||||
|
|
||||||
// the video size may be different from the real device size, so we need the
|
// the video size may be different from the real device size, so we need the
|
||||||
// size to which the absolute position apply, to scale it accordingly
|
// size to which the absolute position apply, to scale it accordingly
|
||||||
bool
|
bool
|
||||||
mouse_motion_from_sdl_to_android(const SDL_MouseMotionEvent *from,
|
mouse_motion_from_sdl_to_android(const SDL_MouseMotionEvent *from,
|
||||||
struct size screen_size,
|
struct size screen_size,
|
||||||
struct control_event *to);
|
struct control_msg *to);
|
||||||
|
|
||||||
// on Android, a scroll event requires the current mouse position
|
// on Android, a scroll event requires the current mouse position
|
||||||
bool
|
bool
|
||||||
mouse_wheel_from_sdl_to_android(const SDL_MouseWheelEvent *from,
|
mouse_wheel_from_sdl_to_android(const SDL_MouseWheelEvent *from,
|
||||||
struct position position,
|
struct position position,
|
||||||
struct control_event *to);
|
struct control_msg *to);
|
||||||
|
|
||||||
#endif
|
#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
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "device_event.h"
|
#include "device_msg.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <SDL2/SDL_assert.h>
|
#include <SDL2/SDL_assert.h>
|
||||||
|
@ -7,16 +7,16 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
device_event_deserialize(const unsigned char *buf, size_t len,
|
device_msg_deserialize(const unsigned char *buf, size_t len,
|
||||||
struct device_event *event) {
|
struct device_msg *msg) {
|
||||||
if (len < 3) {
|
if (len < 3) {
|
||||||
// at least type + empty string length
|
// at least type + empty string length
|
||||||
return 0; // not available
|
return 0; // not available
|
||||||
}
|
}
|
||||||
|
|
||||||
event->type = buf[0];
|
msg->type = buf[0];
|
||||||
switch (event->type) {
|
switch (msg->type) {
|
||||||
case DEVICE_EVENT_TYPE_GET_CLIPBOARD: {
|
case DEVICE_MSG_TYPE_CLIPBOARD: {
|
||||||
uint16_t clipboard_len = buffer_read16be(&buf[1]);
|
uint16_t clipboard_len = buffer_read16be(&buf[1]);
|
||||||
if (clipboard_len > len - 3) {
|
if (clipboard_len > len - 3) {
|
||||||
return 0; // not available
|
return 0; // not available
|
||||||
|
@ -31,18 +31,18 @@ device_event_deserialize(const unsigned char *buf, size_t len,
|
||||||
}
|
}
|
||||||
text[clipboard_len] = '\0';
|
text[clipboard_len] = '\0';
|
||||||
|
|
||||||
event->clipboard_event.text = text;
|
msg->clipboard.text = text;
|
||||||
return 3 + clipboard_len;
|
return 3 + clipboard_len;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
LOGW("Unsupported device event type: %d", (int) event->type);
|
LOGW("Unknown device message type: %d", (int) msg->type);
|
||||||
return -1; // error, we cannot recover
|
return -1; // error, we cannot recover
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
device_event_destroy(struct device_event *event) {
|
device_msg_destroy(struct device_msg *msg) {
|
||||||
if (event->type == DEVICE_EVENT_TYPE_GET_CLIPBOARD) {
|
if (msg->type == DEVICE_MSG_TYPE_CLIPBOARD) {
|
||||||
SDL_free(event->clipboard_event.text);
|
SDL_free(msg->clipboard.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
32
app/src/device_msg.h
Normal file
32
app/src/device_msg.h
Normal file
|
@ -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
|
|
@ -39,23 +39,23 @@ static void
|
||||||
send_keycode(struct controller *controller, enum android_keycode keycode,
|
send_keycode(struct controller *controller, enum android_keycode keycode,
|
||||||
int actions, const char *name) {
|
int actions, const char *name) {
|
||||||
// send DOWN event
|
// send DOWN event
|
||||||
struct control_event control_event;
|
struct control_msg msg;
|
||||||
control_event.type = CONTROL_EVENT_TYPE_KEYCODE;
|
msg.type = CONTROL_MSG_TYPE_INJECT_KEYCODE;
|
||||||
control_event.keycode_event.keycode = keycode;
|
msg.inject_keycode.keycode = keycode;
|
||||||
control_event.keycode_event.metastate = 0;
|
msg.inject_keycode.metastate = 0;
|
||||||
|
|
||||||
if (actions & ACTION_DOWN) {
|
if (actions & ACTION_DOWN) {
|
||||||
control_event.keycode_event.action = AKEY_EVENT_ACTION_DOWN;
|
msg.inject_keycode.action = AKEY_EVENT_ACTION_DOWN;
|
||||||
if (!controller_push_event(controller, &control_event)) {
|
if (!controller_push_msg(controller, &msg)) {
|
||||||
LOGW("Cannot send %s (DOWN)", name);
|
LOGW("Cannot request 'inject %s (DOWN)'", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actions & ACTION_UP) {
|
if (actions & ACTION_UP) {
|
||||||
control_event.keycode_event.action = AKEY_EVENT_ACTION_UP;
|
msg.inject_keycode.action = AKEY_EVENT_ACTION_UP;
|
||||||
if (!controller_push_event(controller, &control_event)) {
|
if (!controller_push_msg(controller, &msg)) {
|
||||||
LOGW("Cannot send %s (UP)", name);
|
LOGW("Cannot request 'inject %s (UP)'", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,41 +98,41 @@ action_menu(struct controller *controller, int actions) {
|
||||||
// turn the screen on if it was off, press BACK otherwise
|
// turn the screen on if it was off, press BACK otherwise
|
||||||
static void
|
static void
|
||||||
press_back_or_turn_screen_on(struct controller *controller) {
|
press_back_or_turn_screen_on(struct controller *controller) {
|
||||||
struct control_event control_event;
|
struct control_msg msg;
|
||||||
control_event.type = CONTROL_EVENT_TYPE_BACK_OR_SCREEN_ON;
|
msg.type = CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON;
|
||||||
|
|
||||||
if (!controller_push_event(controller, &control_event)) {
|
if (!controller_push_msg(controller, &msg)) {
|
||||||
LOGW("Cannot turn screen on");
|
LOGW("Cannot request 'turn screen on'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
expand_notification_panel(struct controller *controller) {
|
expand_notification_panel(struct controller *controller) {
|
||||||
struct control_event control_event;
|
struct control_msg msg;
|
||||||
control_event.type = CONTROL_EVENT_TYPE_EXPAND_NOTIFICATION_PANEL;
|
msg.type = CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL;
|
||||||
|
|
||||||
if (!controller_push_event(controller, &control_event)) {
|
if (!controller_push_msg(controller, &msg)) {
|
||||||
LOGW("Cannot expand notification panel");
|
LOGW("Cannot request 'expand notification panel'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
collapse_notification_panel(struct controller *controller) {
|
collapse_notification_panel(struct controller *controller) {
|
||||||
struct control_event control_event;
|
struct control_msg msg;
|
||||||
control_event.type = CONTROL_EVENT_TYPE_COLLAPSE_NOTIFICATION_PANEL;
|
msg.type = CONTROL_MSG_TYPE_COLLAPSE_NOTIFICATION_PANEL;
|
||||||
|
|
||||||
if (!controller_push_event(controller, &control_event)) {
|
if (!controller_push_msg(controller, &msg)) {
|
||||||
LOGW("Cannot collapse notification panel");
|
LOGW("Cannot request 'collapse notification panel'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
request_device_clipboard(struct controller *controller) {
|
request_device_clipboard(struct controller *controller) {
|
||||||
struct control_event control_event;
|
struct control_msg msg;
|
||||||
control_event.type = CONTROL_EVENT_TYPE_GET_CLIPBOARD;
|
msg.type = CONTROL_MSG_TYPE_GET_CLIPBOARD;
|
||||||
|
|
||||||
if (!controller_push_event(controller, &control_event)) {
|
if (!controller_push_msg(controller, &msg)) {
|
||||||
LOGW("Cannot get device clipboard");
|
LOGW("Cannot request device clipboard");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,13 +149,13 @@ set_device_clipboard(struct controller *controller) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct control_event control_event;
|
struct control_msg msg;
|
||||||
control_event.type = CONTROL_EVENT_TYPE_SET_CLIPBOARD;
|
msg.type = CONTROL_MSG_TYPE_SET_CLIPBOARD;
|
||||||
control_event.set_clipboard_event.text = text;
|
msg.set_clipboard.text = text;
|
||||||
|
|
||||||
if (!controller_push_event(controller, &control_event)) {
|
if (!controller_push_msg(controller, &msg)) {
|
||||||
SDL_free(text);
|
SDL_free(text);
|
||||||
LOGW("Cannot send clipboard paste event");
|
LOGW("Cannot request 'set device clipboard'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,12 +185,12 @@ clipboard_paste(struct controller *controller) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct control_event control_event;
|
struct control_msg msg;
|
||||||
control_event.type = CONTROL_EVENT_TYPE_TEXT;
|
msg.type = CONTROL_MSG_TYPE_INJECT_TEXT;
|
||||||
control_event.text_event.text = text;
|
msg.inject_text.text = text;
|
||||||
if (!controller_push_event(controller, &control_event)) {
|
if (!controller_push_msg(controller, &msg)) {
|
||||||
SDL_free(text);
|
SDL_free(text);
|
||||||
LOGW("Cannot send clipboard paste event");
|
LOGW("Cannot request 'paste clipboard'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,16 +203,16 @@ input_manager_process_text_input(struct input_manager *input_manager,
|
||||||
// letters and space are handled as raw key event
|
// letters and space are handled as raw key event
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct control_event control_event;
|
struct control_msg msg;
|
||||||
control_event.type = CONTROL_EVENT_TYPE_TEXT;
|
msg.type = CONTROL_MSG_TYPE_INJECT_TEXT;
|
||||||
control_event.text_event.text = SDL_strdup(event->text);
|
msg.inject_text.text = SDL_strdup(event->text);
|
||||||
if (!control_event.text_event.text) {
|
if (!msg.inject_text.text) {
|
||||||
LOGW("Cannot strdup input text");
|
LOGW("Cannot strdup input text");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!controller_push_event(input_manager->controller, &control_event)) {
|
if (!controller_push_msg(input_manager->controller, &msg)) {
|
||||||
SDL_free(control_event.text_event.text);
|
SDL_free(msg.inject_text.text);
|
||||||
LOGW("Cannot send text event");
|
LOGW("Cannot request 'inject text'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,10 +344,10 @@ input_manager_process_key(struct input_manager *input_manager,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct control_event control_event;
|
struct control_msg msg;
|
||||||
if (input_key_from_sdl_to_android(event, &control_event)) {
|
if (input_key_from_sdl_to_android(event, &msg)) {
|
||||||
if (!controller_push_event(input_manager->controller, &control_event)) {
|
if (!controller_push_msg(input_manager->controller, &msg)) {
|
||||||
LOGW("Cannot send control event");
|
LOGW("Cannot request 'inject keycode'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -359,12 +359,12 @@ input_manager_process_mouse_motion(struct input_manager *input_manager,
|
||||||
// do not send motion events when no button is pressed
|
// do not send motion events when no button is pressed
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct control_event control_event;
|
struct control_msg msg;
|
||||||
if (mouse_motion_from_sdl_to_android(event,
|
if (mouse_motion_from_sdl_to_android(event,
|
||||||
input_manager->screen->frame_size,
|
input_manager->screen->frame_size,
|
||||||
&control_event)) {
|
&msg)) {
|
||||||
if (!controller_push_event(input_manager->controller, &control_event)) {
|
if (!controller_push_msg(input_manager->controller, &msg)) {
|
||||||
LOGW("Cannot send mouse motion event");
|
LOGW("Cannot request 'inject mouse motion event'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -391,9 +391,8 @@ input_manager_process_mouse_button(struct input_manager *input_manager,
|
||||||
}
|
}
|
||||||
// double-click on black borders resize to fit the device screen
|
// double-click on black borders resize to fit the device screen
|
||||||
if (event->button == SDL_BUTTON_LEFT && event->clicks == 2) {
|
if (event->button == SDL_BUTTON_LEFT && event->clicks == 2) {
|
||||||
bool outside = is_outside_device_screen(input_manager,
|
bool outside =
|
||||||
event->x,
|
is_outside_device_screen(input_manager, event->x, event->y);
|
||||||
event->y);
|
|
||||||
if (outside) {
|
if (outside) {
|
||||||
screen_resize_to_fit(input_manager->screen);
|
screen_resize_to_fit(input_manager->screen);
|
||||||
return;
|
return;
|
||||||
|
@ -406,12 +405,12 @@ input_manager_process_mouse_button(struct input_manager *input_manager,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct control_event control_event;
|
struct control_msg msg;
|
||||||
if (mouse_button_from_sdl_to_android(event,
|
if (mouse_button_from_sdl_to_android(event,
|
||||||
input_manager->screen->frame_size,
|
input_manager->screen->frame_size,
|
||||||
&control_event)) {
|
&msg)) {
|
||||||
if (!controller_push_event(input_manager->controller, &control_event)) {
|
if (!controller_push_msg(input_manager->controller, &msg)) {
|
||||||
LOGW("Cannot send mouse button event");
|
LOGW("Cannot request 'inject mouse button event'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -423,10 +422,10 @@ input_manager_process_mouse_wheel(struct input_manager *input_manager,
|
||||||
.screen_size = input_manager->screen->frame_size,
|
.screen_size = input_manager->screen->frame_size,
|
||||||
.point = get_mouse_point(input_manager->screen),
|
.point = get_mouse_point(input_manager->screen),
|
||||||
};
|
};
|
||||||
struct control_event control_event;
|
struct control_msg msg;
|
||||||
if (mouse_wheel_from_sdl_to_android(event, position, &control_event)) {
|
if (mouse_wheel_from_sdl_to_android(event, position, &msg)) {
|
||||||
if (!controller_push_event(input_manager->controller, &control_event)) {
|
if (!controller_push_msg(input_manager->controller, &msg)) {
|
||||||
LOGW("Cannot send mouse wheel event");
|
LOGW("Cannot request 'inject mouse wheel event'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
#include <SDL2/SDL_clipboard.h>
|
#include <SDL2/SDL_clipboard.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "device_event.h"
|
#include "device_msg.h"
|
||||||
#include "events.h"
|
|
||||||
#include "lock_util.h"
|
#include "lock_util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
@ -24,21 +23,20 @@ receiver_destroy(struct receiver *receiver) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_event(struct receiver *receiver, struct device_event *event) {
|
process_msg(struct receiver *receiver, struct device_msg *msg) {
|
||||||
switch (event->type) {
|
switch (msg->type) {
|
||||||
case DEVICE_EVENT_TYPE_GET_CLIPBOARD:
|
case DEVICE_MSG_TYPE_CLIPBOARD:
|
||||||
SDL_SetClipboardText(event->clipboard_event.text);
|
SDL_SetClipboardText(msg->clipboard.text);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
process_events(struct receiver *receiver, const unsigned char *buf,
|
process_msgs(struct receiver *receiver, const unsigned char *buf, size_t len) {
|
||||||
size_t len) {
|
|
||||||
size_t head = 0;
|
size_t head = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct device_event event;
|
struct device_msg msg;
|
||||||
ssize_t r = device_event_deserialize(&buf[head], len - head, &event);
|
ssize_t r = device_msg_deserialize(&buf[head], len - head, &msg);
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -46,8 +44,8 @@ process_events(struct receiver *receiver, const unsigned char *buf,
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_event(receiver, &event);
|
process_msg(receiver, &msg);
|
||||||
device_event_destroy(&event);
|
device_msg_destroy(&msg);
|
||||||
|
|
||||||
head += r;
|
head += r;
|
||||||
SDL_assert(head <= len);
|
SDL_assert(head <= len);
|
||||||
|
@ -61,19 +59,19 @@ static int
|
||||||
run_receiver(void *data) {
|
run_receiver(void *data) {
|
||||||
struct receiver *receiver = data;
|
struct receiver *receiver = data;
|
||||||
|
|
||||||
unsigned char buf[DEVICE_EVENT_SERIALIZED_MAX_SIZE];
|
unsigned char buf[DEVICE_MSG_SERIALIZED_MAX_SIZE];
|
||||||
size_t head = 0;
|
size_t head = 0;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
SDL_assert(head < DEVICE_EVENT_SERIALIZED_MAX_SIZE);
|
SDL_assert(head < DEVICE_MSG_SERIALIZED_MAX_SIZE);
|
||||||
ssize_t r = net_recv(receiver->control_socket, buf,
|
ssize_t r = net_recv(receiver->control_socket, buf,
|
||||||
DEVICE_EVENT_SERIALIZED_MAX_SIZE - head);
|
DEVICE_MSG_SERIALIZED_MAX_SIZE - head);
|
||||||
if (r <= 0) {
|
if (r <= 0) {
|
||||||
LOGD("Receiver stopped");
|
LOGD("Receiver stopped");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t consumed = process_events(receiver, buf, r);
|
ssize_t consumed = process_msgs(receiver, buf, r);
|
||||||
if (consumed == -1) {
|
if (consumed == -1) {
|
||||||
// an error occurred
|
// an error occurred
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
228
app/tests/test_control_msg_serialize.c
Normal file
228
app/tests/test_control_msg_serialize.c
Normal file
|
@ -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;
|
|
||||||
}
|
|
28
app/tests/test_device_msg_deserialize.c
Normal file
28
app/tests/test_device_msg_deserialize.c
Normal file
|
@ -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;
|
||||||
|
}
|
|
@ -3,12 +3,12 @@ package com.genymobile.scrcpy;
|
||||||
/**
|
/**
|
||||||
* Union of all supported event types, identified by their {@code type}.
|
* Union of all supported event types, identified by their {@code type}.
|
||||||
*/
|
*/
|
||||||
public final class ControlEvent {
|
public final class ControlMessage {
|
||||||
|
|
||||||
public static final int TYPE_KEYCODE = 0;
|
public static final int TYPE_INJECT_KEYCODE = 0;
|
||||||
public static final int TYPE_TEXT = 1;
|
public static final int TYPE_INJECT_TEXT = 1;
|
||||||
public static final int TYPE_MOUSE = 2;
|
public static final int TYPE_INJECT_MOUSE_EVENT = 2;
|
||||||
public static final int TYPE_SCROLL = 3;
|
public static final int TYPE_INJECT_SCROLL_EVENT = 3;
|
||||||
public static final int TYPE_BACK_OR_SCREEN_ON = 4;
|
public static final int TYPE_BACK_OR_SCREEN_ON = 4;
|
||||||
public static final int TYPE_EXPAND_NOTIFICATION_PANEL = 5;
|
public static final int TYPE_EXPAND_NOTIFICATION_PANEL = 5;
|
||||||
public static final int TYPE_COLLAPSE_NOTIFICATION_PANEL = 6;
|
public static final int TYPE_COLLAPSE_NOTIFICATION_PANEL = 6;
|
||||||
|
@ -25,52 +25,52 @@ public final class ControlEvent {
|
||||||
private int hScroll;
|
private int hScroll;
|
||||||
private int vScroll;
|
private int vScroll;
|
||||||
|
|
||||||
private ControlEvent() {
|
private ControlMessage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ControlEvent createKeycodeControlEvent(int action, int keycode, int metaState) {
|
public static ControlMessage createInjectKeycode(int action, int keycode, int metaState) {
|
||||||
ControlEvent event = new ControlEvent();
|
ControlMessage event = new ControlMessage();
|
||||||
event.type = TYPE_KEYCODE;
|
event.type = TYPE_INJECT_KEYCODE;
|
||||||
event.action = action;
|
event.action = action;
|
||||||
event.keycode = keycode;
|
event.keycode = keycode;
|
||||||
event.metaState = metaState;
|
event.metaState = metaState;
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ControlEvent createTextControlEvent(String text) {
|
public static ControlMessage createInjectText(String text) {
|
||||||
ControlEvent event = new ControlEvent();
|
ControlMessage event = new ControlMessage();
|
||||||
event.type = TYPE_TEXT;
|
event.type = TYPE_INJECT_TEXT;
|
||||||
event.text = text;
|
event.text = text;
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ControlEvent createMotionControlEvent(int action, int buttons, Position position) {
|
public static ControlMessage createInjectMouseEvent(int action, int buttons, Position position) {
|
||||||
ControlEvent event = new ControlEvent();
|
ControlMessage event = new ControlMessage();
|
||||||
event.type = TYPE_MOUSE;
|
event.type = TYPE_INJECT_MOUSE_EVENT;
|
||||||
event.action = action;
|
event.action = action;
|
||||||
event.buttons = buttons;
|
event.buttons = buttons;
|
||||||
event.position = position;
|
event.position = position;
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ControlEvent createScrollControlEvent(Position position, int hScroll, int vScroll) {
|
public static ControlMessage createInjectScrollEvent(Position position, int hScroll, int vScroll) {
|
||||||
ControlEvent event = new ControlEvent();
|
ControlMessage event = new ControlMessage();
|
||||||
event.type = TYPE_SCROLL;
|
event.type = TYPE_INJECT_SCROLL_EVENT;
|
||||||
event.position = position;
|
event.position = position;
|
||||||
event.hScroll = hScroll;
|
event.hScroll = hScroll;
|
||||||
event.vScroll = vScroll;
|
event.vScroll = vScroll;
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ControlEvent createSetClipboardControlEvent(String text) {
|
public static ControlMessage createSetClipboard(String text) {
|
||||||
ControlEvent event = new ControlEvent();
|
ControlMessage event = new ControlMessage();
|
||||||
event.type = TYPE_SET_CLIPBOARD;
|
event.type = TYPE_SET_CLIPBOARD;
|
||||||
event.text = text;
|
event.text = text;
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ControlEvent createSimpleControlEvent(int type) {
|
public static ControlMessage createEmpty(int type) {
|
||||||
ControlEvent event = new ControlEvent();
|
ControlMessage event = new ControlMessage();
|
||||||
event.type = type;
|
event.type = type;
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
|
@ -6,11 +6,11 @@ import java.io.InputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
public class ControlEventReader {
|
public class ControlMessageReader {
|
||||||
|
|
||||||
private static final int KEYCODE_PAYLOAD_LENGTH = 9;
|
private static final int INJECT_KEYCODE_PAYLOAD_LENGTH = 9;
|
||||||
private static final int MOUSE_PAYLOAD_LENGTH = 17;
|
private static final int INJECT_MOUSE_EVENT_PAYLOAD_LENGTH = 17;
|
||||||
private static final int SCROLL_PAYLOAD_LENGTH = 20;
|
private static final int INJECT_SCROLL_EVENT_PAYLOAD_LENGTH = 20;
|
||||||
|
|
||||||
public static final int TEXT_MAX_LENGTH = 300;
|
public static final int TEXT_MAX_LENGTH = 300;
|
||||||
public static final int CLIPBOARD_TEXT_MAX_LENGTH = 4093;
|
public static final int CLIPBOARD_TEXT_MAX_LENGTH = 4093;
|
||||||
|
@ -20,7 +20,7 @@ public class ControlEventReader {
|
||||||
private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer);
|
private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer);
|
||||||
private final byte[] textBuffer = new byte[CLIPBOARD_TEXT_MAX_LENGTH];
|
private final byte[] textBuffer = new byte[CLIPBOARD_TEXT_MAX_LENGTH];
|
||||||
|
|
||||||
public ControlEventReader() {
|
public ControlMessageReader() {
|
||||||
// invariant: the buffer is always in "get" mode
|
// invariant: the buffer is always in "get" mode
|
||||||
buffer.limit(0);
|
buffer.limit(0);
|
||||||
}
|
}
|
||||||
|
@ -37,63 +37,63 @@ public class ControlEventReader {
|
||||||
int head = buffer.position();
|
int head = buffer.position();
|
||||||
int r = input.read(rawBuffer, head, rawBuffer.length - head);
|
int r = input.read(rawBuffer, head, rawBuffer.length - head);
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
throw new EOFException("Event controller socket closed");
|
throw new EOFException("Controller socket closed");
|
||||||
}
|
}
|
||||||
buffer.position(head + r);
|
buffer.position(head + r);
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ControlEvent next() {
|
public ControlMessage next() {
|
||||||
if (!buffer.hasRemaining()) {
|
if (!buffer.hasRemaining()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
int savedPosition = buffer.position();
|
int savedPosition = buffer.position();
|
||||||
|
|
||||||
int type = buffer.get();
|
int type = buffer.get();
|
||||||
ControlEvent controlEvent;
|
ControlMessage msg;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ControlEvent.TYPE_KEYCODE:
|
case ControlMessage.TYPE_INJECT_KEYCODE:
|
||||||
controlEvent = parseKeycodeControlEvent();
|
msg = parseInjectKeycode();
|
||||||
break;
|
break;
|
||||||
case ControlEvent.TYPE_TEXT:
|
case ControlMessage.TYPE_INJECT_TEXT:
|
||||||
controlEvent = parseTextControlEvent();
|
msg = parseInjectText();
|
||||||
break;
|
break;
|
||||||
case ControlEvent.TYPE_MOUSE:
|
case ControlMessage.TYPE_INJECT_MOUSE_EVENT:
|
||||||
controlEvent = parseMouseControlEvent();
|
msg = parseInjectMouseEvent();
|
||||||
break;
|
break;
|
||||||
case ControlEvent.TYPE_SCROLL:
|
case ControlMessage.TYPE_INJECT_SCROLL_EVENT:
|
||||||
controlEvent = parseScrollControlEvent();
|
msg = parseInjectScrollEvent();
|
||||||
break;
|
break;
|
||||||
case ControlEvent.TYPE_SET_CLIPBOARD:
|
case ControlMessage.TYPE_SET_CLIPBOARD:
|
||||||
controlEvent = parseSetClipboardEvent();
|
msg = parseSetClipboard();
|
||||||
break;
|
break;
|
||||||
case ControlEvent.TYPE_BACK_OR_SCREEN_ON:
|
case ControlMessage.TYPE_BACK_OR_SCREEN_ON:
|
||||||
case ControlEvent.TYPE_EXPAND_NOTIFICATION_PANEL:
|
case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL:
|
||||||
case ControlEvent.TYPE_COLLAPSE_NOTIFICATION_PANEL:
|
case ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL:
|
||||||
case ControlEvent.TYPE_GET_CLIPBOARD:
|
case ControlMessage.TYPE_GET_CLIPBOARD:
|
||||||
controlEvent = ControlEvent.createSimpleControlEvent(type);
|
msg = ControlMessage.createEmpty(type);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Ln.w("Unknown event type: " + type);
|
Ln.w("Unknown event type: " + type);
|
||||||
controlEvent = null;
|
msg = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controlEvent == null) {
|
if (msg == null) {
|
||||||
// failure, reset savedPosition
|
// failure, reset savedPosition
|
||||||
buffer.position(savedPosition);
|
buffer.position(savedPosition);
|
||||||
}
|
}
|
||||||
return controlEvent;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ControlEvent parseKeycodeControlEvent() {
|
private ControlMessage parseInjectKeycode() {
|
||||||
if (buffer.remaining() < KEYCODE_PAYLOAD_LENGTH) {
|
if (buffer.remaining() < INJECT_KEYCODE_PAYLOAD_LENGTH) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
int action = toUnsigned(buffer.get());
|
int action = toUnsigned(buffer.get());
|
||||||
int keycode = buffer.getInt();
|
int keycode = buffer.getInt();
|
||||||
int metaState = buffer.getInt();
|
int metaState = buffer.getInt();
|
||||||
return ControlEvent.createKeycodeControlEvent(action, keycode, metaState);
|
return ControlMessage.createInjectKeycode(action, keycode, metaState);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String parseString() {
|
private String parseString() {
|
||||||
|
@ -108,40 +108,40 @@ public class ControlEventReader {
|
||||||
return new String(textBuffer, 0, len, StandardCharsets.UTF_8);
|
return new String(textBuffer, 0, len, StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ControlEvent parseTextControlEvent() {
|
private ControlMessage parseInjectText() {
|
||||||
String text = parseString();
|
String text = parseString();
|
||||||
if (text == null) {
|
if (text == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return ControlEvent.createTextControlEvent(text);
|
return ControlMessage.createInjectText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ControlEvent parseMouseControlEvent() {
|
private ControlMessage parseInjectMouseEvent() {
|
||||||
if (buffer.remaining() < MOUSE_PAYLOAD_LENGTH) {
|
if (buffer.remaining() < INJECT_MOUSE_EVENT_PAYLOAD_LENGTH) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
int action = toUnsigned(buffer.get());
|
int action = toUnsigned(buffer.get());
|
||||||
int buttons = buffer.getInt();
|
int buttons = buffer.getInt();
|
||||||
Position position = readPosition(buffer);
|
Position position = readPosition(buffer);
|
||||||
return ControlEvent.createMotionControlEvent(action, buttons, position);
|
return ControlMessage.createInjectMouseEvent(action, buttons, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ControlEvent parseScrollControlEvent() {
|
private ControlMessage parseInjectScrollEvent() {
|
||||||
if (buffer.remaining() < SCROLL_PAYLOAD_LENGTH) {
|
if (buffer.remaining() < INJECT_SCROLL_EVENT_PAYLOAD_LENGTH) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Position position = readPosition(buffer);
|
Position position = readPosition(buffer);
|
||||||
int hScroll = buffer.getInt();
|
int hScroll = buffer.getInt();
|
||||||
int vScroll = buffer.getInt();
|
int vScroll = buffer.getInt();
|
||||||
return ControlEvent.createScrollControlEvent(position, hScroll, vScroll);
|
return ControlMessage.createInjectScrollEvent(position, hScroll, vScroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ControlEvent parseSetClipboardEvent() {
|
private ControlMessage parseSetClipboard() {
|
||||||
String text = parseString();
|
String text = parseString();
|
||||||
if (text == null) {
|
if (text == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return ControlEvent.createSetClipboardControlEvent(text);
|
return ControlMessage.createSetClipboard(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Position readPosition(ByteBuffer buffer) {
|
private static Position readPosition(ByteBuffer buffer) {
|
|
@ -11,11 +11,11 @@ import android.view.MotionEvent;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class EventController {
|
public class Controller {
|
||||||
|
|
||||||
private final Device device;
|
private final Device device;
|
||||||
private final DesktopConnection connection;
|
private final DesktopConnection connection;
|
||||||
private final EventSender sender;
|
private final DeviceMessageSender sender;
|
||||||
|
|
||||||
private final KeyCharacterMap charMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
|
private final KeyCharacterMap charMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
|
||||||
|
|
||||||
|
@ -23,11 +23,11 @@ public class EventController {
|
||||||
private final MotionEvent.PointerProperties[] pointerProperties = {new MotionEvent.PointerProperties()};
|
private final MotionEvent.PointerProperties[] pointerProperties = {new MotionEvent.PointerProperties()};
|
||||||
private final MotionEvent.PointerCoords[] pointerCoords = {new MotionEvent.PointerCoords()};
|
private final MotionEvent.PointerCoords[] pointerCoords = {new MotionEvent.PointerCoords()};
|
||||||
|
|
||||||
public EventController(Device device, DesktopConnection connection) {
|
public Controller(Device device, DesktopConnection connection) {
|
||||||
this.device = device;
|
this.device = device;
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
initPointer();
|
initPointer();
|
||||||
sender = new EventSender(connection);
|
sender = new DeviceMessageSender(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initPointer() {
|
private void initPointer() {
|
||||||
|
@ -62,40 +62,40 @@ public class EventController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventSender getSender() {
|
public DeviceMessageSender getSender() {
|
||||||
return sender;
|
return sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEvent() throws IOException {
|
private void handleEvent() throws IOException {
|
||||||
ControlEvent controlEvent = connection.receiveControlEvent();
|
ControlMessage msg = connection.receiveControlMessage();
|
||||||
switch (controlEvent.getType()) {
|
switch (msg.getType()) {
|
||||||
case ControlEvent.TYPE_KEYCODE:
|
case ControlMessage.TYPE_INJECT_KEYCODE:
|
||||||
injectKeycode(controlEvent.getAction(), controlEvent.getKeycode(), controlEvent.getMetaState());
|
injectKeycode(msg.getAction(), msg.getKeycode(), msg.getMetaState());
|
||||||
break;
|
break;
|
||||||
case ControlEvent.TYPE_TEXT:
|
case ControlMessage.TYPE_INJECT_TEXT:
|
||||||
injectText(controlEvent.getText());
|
injectText(msg.getText());
|
||||||
break;
|
break;
|
||||||
case ControlEvent.TYPE_MOUSE:
|
case ControlMessage.TYPE_INJECT_MOUSE_EVENT:
|
||||||
injectMouse(controlEvent.getAction(), controlEvent.getButtons(), controlEvent.getPosition());
|
injectMouse(msg.getAction(), msg.getButtons(), msg.getPosition());
|
||||||
break;
|
break;
|
||||||
case ControlEvent.TYPE_SCROLL:
|
case ControlMessage.TYPE_INJECT_SCROLL_EVENT:
|
||||||
injectScroll(controlEvent.getPosition(), controlEvent.getHScroll(), controlEvent.getVScroll());
|
injectScroll(msg.getPosition(), msg.getHScroll(), msg.getVScroll());
|
||||||
break;
|
break;
|
||||||
case ControlEvent.TYPE_BACK_OR_SCREEN_ON:
|
case ControlMessage.TYPE_BACK_OR_SCREEN_ON:
|
||||||
pressBackOrTurnScreenOn();
|
pressBackOrTurnScreenOn();
|
||||||
break;
|
break;
|
||||||
case ControlEvent.TYPE_EXPAND_NOTIFICATION_PANEL:
|
case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL:
|
||||||
device.expandNotificationPanel();
|
device.expandNotificationPanel();
|
||||||
break;
|
break;
|
||||||
case ControlEvent.TYPE_COLLAPSE_NOTIFICATION_PANEL:
|
case ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL:
|
||||||
device.collapsePanels();
|
device.collapsePanels();
|
||||||
break;
|
break;
|
||||||
case ControlEvent.TYPE_GET_CLIPBOARD:
|
case ControlMessage.TYPE_GET_CLIPBOARD:
|
||||||
String clipboardText = device.getClipboardText();
|
String clipboardText = device.getClipboardText();
|
||||||
sender.pushClipboardText(clipboardText);
|
sender.pushClipboardText(clipboardText);
|
||||||
break;
|
break;
|
||||||
case ControlEvent.TYPE_SET_CLIPBOARD:
|
case ControlMessage.TYPE_SET_CLIPBOARD:
|
||||||
device.setClipboardText(controlEvent.getText());
|
device.setClipboardText(msg.getText());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// do nothing
|
// do nothing
|
|
@ -24,8 +24,8 @@ public final class DesktopConnection implements Closeable {
|
||||||
private final InputStream controlInputStream;
|
private final InputStream controlInputStream;
|
||||||
private final OutputStream controlOutputStream;
|
private final OutputStream controlOutputStream;
|
||||||
|
|
||||||
private final ControlEventReader reader = new ControlEventReader();
|
private final ControlMessageReader reader = new ControlMessageReader();
|
||||||
private final DeviceEventWriter writer = new DeviceEventWriter();
|
private final DeviceMessageWriter writer = new DeviceMessageWriter();
|
||||||
|
|
||||||
private DesktopConnection(LocalSocket videoSocket, LocalSocket controlSocket) throws IOException {
|
private DesktopConnection(LocalSocket videoSocket, LocalSocket controlSocket) throws IOException {
|
||||||
this.videoSocket = videoSocket;
|
this.videoSocket = videoSocket;
|
||||||
|
@ -104,16 +104,16 @@ public final class DesktopConnection implements Closeable {
|
||||||
return videoFd;
|
return videoFd;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ControlEvent receiveControlEvent() throws IOException {
|
public ControlMessage receiveControlMessage() throws IOException {
|
||||||
ControlEvent event = reader.next();
|
ControlMessage msg = reader.next();
|
||||||
while (event == null) {
|
while (msg == null) {
|
||||||
reader.readFrom(controlInputStream);
|
reader.readFrom(controlInputStream);
|
||||||
event = reader.next();
|
msg = reader.next();
|
||||||
}
|
}
|
||||||
return event;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendDeviceEvent(DeviceEvent event) throws IOException {
|
public void sendDeviceMessage(DeviceMessage msg) throws IOException {
|
||||||
writer.writeTo(event, controlOutputStream);
|
writer.writeTo(msg, controlOutputStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,13 +2,13 @@ package com.genymobile.scrcpy;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public final class EventSender {
|
public final class DeviceMessageSender {
|
||||||
|
|
||||||
private final DesktopConnection connection;
|
private final DesktopConnection connection;
|
||||||
|
|
||||||
private String clipboardText;
|
private String clipboardText;
|
||||||
|
|
||||||
public EventSender(DesktopConnection connection) {
|
public DeviceMessageSender(DesktopConnection connection) {
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ public final class EventSender {
|
||||||
text = clipboardText;
|
text = clipboardText;
|
||||||
clipboardText = null;
|
clipboardText = null;
|
||||||
}
|
}
|
||||||
DeviceEvent event = DeviceEvent.createGetClipboardEvent(text);
|
DeviceMessage event = DeviceMessage.createClipboard(text);
|
||||||
connection.sendDeviceEvent(event);
|
connection.sendDeviceMessage(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@ import java.io.OutputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
public class DeviceEventWriter {
|
public class DeviceMessageWriter {
|
||||||
|
|
||||||
public static final int CLIPBOARD_TEXT_MAX_LENGTH = 4093;
|
public static final int CLIPBOARD_TEXT_MAX_LENGTH = 4093;
|
||||||
private static final int MAX_EVENT_SIZE = CLIPBOARD_TEXT_MAX_LENGTH + 3;
|
private static final int MAX_EVENT_SIZE = CLIPBOARD_TEXT_MAX_LENGTH + 3;
|
||||||
|
@ -14,12 +14,12 @@ public class DeviceEventWriter {
|
||||||
private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer);
|
private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer);
|
||||||
|
|
||||||
@SuppressWarnings("checkstyle:MagicNumber")
|
@SuppressWarnings("checkstyle:MagicNumber")
|
||||||
public void writeTo(DeviceEvent event, OutputStream output) throws IOException {
|
public void writeTo(DeviceMessage msg, OutputStream output) throws IOException {
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
buffer.put((byte) DeviceEvent.TYPE_GET_CLIPBOARD);
|
buffer.put((byte) DeviceMessage.TYPE_CLIPBOARD);
|
||||||
switch (event.getType()) {
|
switch (msg.getType()) {
|
||||||
case DeviceEvent.TYPE_GET_CLIPBOARD:
|
case DeviceMessage.TYPE_CLIPBOARD:
|
||||||
String text = event.getText();
|
String text = msg.getText();
|
||||||
byte[] raw = text.getBytes(StandardCharsets.UTF_8);
|
byte[] raw = text.getBytes(StandardCharsets.UTF_8);
|
||||||
int len = StringUtils.getUtf8TruncationIndex(raw, CLIPBOARD_TEXT_MAX_LENGTH);
|
int len = StringUtils.getUtf8TruncationIndex(raw, CLIPBOARD_TEXT_MAX_LENGTH);
|
||||||
buffer.putShort((short) len);
|
buffer.putShort((short) len);
|
||||||
|
@ -27,7 +27,7 @@ public class DeviceEventWriter {
|
||||||
output.write(rawBuffer, 0, buffer.position());
|
output.write(rawBuffer, 0, buffer.position());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Ln.w("Unknown device event: " + event.getType());
|
Ln.w("Unknown device message: " + msg.getType());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,11 +19,11 @@ public final class Server {
|
||||||
try (DesktopConnection connection = DesktopConnection.open(device, tunnelForward)) {
|
try (DesktopConnection connection = DesktopConnection.open(device, tunnelForward)) {
|
||||||
ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate());
|
ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate());
|
||||||
|
|
||||||
EventController controller = new EventController(device, connection);
|
Controller controller = new Controller(device, connection);
|
||||||
|
|
||||||
// asynchronous
|
// asynchronous
|
||||||
startEventController(controller);
|
startController(controller);
|
||||||
startEventSender(controller.getSender());
|
startDeviceMessageSender(controller.getSender());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// synchronous
|
// synchronous
|
||||||
|
@ -35,7 +35,7 @@ public final class Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void startEventController(final EventController controller) {
|
private static void startController(final Controller controller) {
|
||||||
new Thread(new Runnable() {
|
new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -43,13 +43,13 @@ public final class Server {
|
||||||
controller.control();
|
controller.control();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// this is expected on close
|
// this is expected on close
|
||||||
Ln.d("Event controller stopped");
|
Ln.d("Controller stopped");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void startEventSender(final EventSender sender) {
|
private static void startDeviceMessageSender(final DeviceMessageSender sender) {
|
||||||
new Thread(new Runnable() {
|
new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -57,7 +57,7 @@ public final class Server {
|
||||||
sender.loop();
|
sender.loop();
|
||||||
} catch (IOException | InterruptedException e) {
|
} catch (IOException | InterruptedException e) {
|
||||||
// this is expected on close
|
// this is expected on close
|
||||||
Ln.d("Event sender stopped");
|
Ln.d("Device message sender stopped");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
|
|
|
@ -14,24 +14,24 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
|
||||||
public class ControlEventReaderTest {
|
public class ControlMessageReaderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseKeycodeEvent() throws IOException {
|
public void testParseKeycodeEvent() throws IOException {
|
||||||
ControlEventReader reader = new ControlEventReader();
|
ControlMessageReader reader = new ControlMessageReader();
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
dos.writeByte(ControlEvent.TYPE_KEYCODE);
|
dos.writeByte(ControlMessage.TYPE_INJECT_KEYCODE);
|
||||||
dos.writeByte(KeyEvent.ACTION_UP);
|
dos.writeByte(KeyEvent.ACTION_UP);
|
||||||
dos.writeInt(KeyEvent.KEYCODE_ENTER);
|
dos.writeInt(KeyEvent.KEYCODE_ENTER);
|
||||||
dos.writeInt(KeyEvent.META_CTRL_ON);
|
dos.writeInt(KeyEvent.META_CTRL_ON);
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
|
|
||||||
reader.readFrom(new ByteArrayInputStream(packet));
|
reader.readFrom(new ByteArrayInputStream(packet));
|
||||||
ControlEvent event = reader.next();
|
ControlMessage event = reader.next();
|
||||||
|
|
||||||
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
|
Assert.assertEquals(ControlMessage.TYPE_INJECT_KEYCODE, event.getType());
|
||||||
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
|
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
|
||||||
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
|
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
|
||||||
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
||||||
|
@ -39,59 +39,59 @@ public class ControlEventReaderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseTextEvent() throws IOException {
|
public void testParseTextEvent() throws IOException {
|
||||||
ControlEventReader reader = new ControlEventReader();
|
ControlMessageReader reader = new ControlMessageReader();
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
dos.writeByte(ControlEvent.TYPE_TEXT);
|
dos.writeByte(ControlMessage.TYPE_INJECT_TEXT);
|
||||||
byte[] text = "testé".getBytes(StandardCharsets.UTF_8);
|
byte[] text = "testé".getBytes(StandardCharsets.UTF_8);
|
||||||
dos.writeShort(text.length);
|
dos.writeShort(text.length);
|
||||||
dos.write(text);
|
dos.write(text);
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
|
|
||||||
reader.readFrom(new ByteArrayInputStream(packet));
|
reader.readFrom(new ByteArrayInputStream(packet));
|
||||||
ControlEvent event = reader.next();
|
ControlMessage event = reader.next();
|
||||||
|
|
||||||
Assert.assertEquals(ControlEvent.TYPE_TEXT, event.getType());
|
Assert.assertEquals(ControlMessage.TYPE_INJECT_TEXT, event.getType());
|
||||||
Assert.assertEquals("testé", event.getText());
|
Assert.assertEquals("testé", event.getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseLongTextEvent() throws IOException {
|
public void testParseLongTextEvent() throws IOException {
|
||||||
ControlEventReader reader = new ControlEventReader();
|
ControlMessageReader reader = new ControlMessageReader();
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
dos.writeByte(ControlEvent.TYPE_TEXT);
|
dos.writeByte(ControlMessage.TYPE_INJECT_TEXT);
|
||||||
byte[] text = new byte[ControlEventReader.TEXT_MAX_LENGTH];
|
byte[] text = new byte[ControlMessageReader.TEXT_MAX_LENGTH];
|
||||||
Arrays.fill(text, (byte) 'a');
|
Arrays.fill(text, (byte) 'a');
|
||||||
dos.writeShort(text.length);
|
dos.writeShort(text.length);
|
||||||
dos.write(text);
|
dos.write(text);
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
|
|
||||||
reader.readFrom(new ByteArrayInputStream(packet));
|
reader.readFrom(new ByteArrayInputStream(packet));
|
||||||
ControlEvent event = reader.next();
|
ControlMessage event = reader.next();
|
||||||
|
|
||||||
Assert.assertEquals(ControlEvent.TYPE_TEXT, event.getType());
|
Assert.assertEquals(ControlMessage.TYPE_INJECT_TEXT, event.getType());
|
||||||
Assert.assertEquals(new String(text, StandardCharsets.US_ASCII), event.getText());
|
Assert.assertEquals(new String(text, StandardCharsets.US_ASCII), event.getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseMouseEvent() throws IOException {
|
public void testParseMouseEvent() throws IOException {
|
||||||
ControlEventReader reader = new ControlEventReader();
|
ControlMessageReader reader = new ControlMessageReader();
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
dos.writeByte(ControlEvent.TYPE_KEYCODE);
|
dos.writeByte(ControlMessage.TYPE_INJECT_KEYCODE);
|
||||||
dos.writeByte(MotionEvent.ACTION_DOWN);
|
dos.writeByte(MotionEvent.ACTION_DOWN);
|
||||||
dos.writeInt(MotionEvent.BUTTON_PRIMARY);
|
dos.writeInt(MotionEvent.BUTTON_PRIMARY);
|
||||||
dos.writeInt(KeyEvent.META_CTRL_ON);
|
dos.writeInt(KeyEvent.META_CTRL_ON);
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
|
|
||||||
reader.readFrom(new ByteArrayInputStream(packet));
|
reader.readFrom(new ByteArrayInputStream(packet));
|
||||||
ControlEvent event = reader.next();
|
ControlMessage event = reader.next();
|
||||||
|
|
||||||
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
|
Assert.assertEquals(ControlMessage.TYPE_INJECT_KEYCODE, event.getType());
|
||||||
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
|
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
|
||||||
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getKeycode());
|
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getKeycode());
|
||||||
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
||||||
|
@ -100,11 +100,11 @@ public class ControlEventReaderTest {
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("checkstyle:MagicNumber")
|
@SuppressWarnings("checkstyle:MagicNumber")
|
||||||
public void testParseScrollEvent() throws IOException {
|
public void testParseScrollEvent() throws IOException {
|
||||||
ControlEventReader reader = new ControlEventReader();
|
ControlMessageReader reader = new ControlMessageReader();
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
dos.writeByte(ControlEvent.TYPE_SCROLL);
|
dos.writeByte(ControlMessage.TYPE_INJECT_SCROLL_EVENT);
|
||||||
dos.writeInt(260);
|
dos.writeInt(260);
|
||||||
dos.writeInt(1026);
|
dos.writeInt(1026);
|
||||||
dos.writeShort(1080);
|
dos.writeShort(1080);
|
||||||
|
@ -115,9 +115,9 @@ public class ControlEventReaderTest {
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
|
|
||||||
reader.readFrom(new ByteArrayInputStream(packet));
|
reader.readFrom(new ByteArrayInputStream(packet));
|
||||||
ControlEvent event = reader.next();
|
ControlMessage event = reader.next();
|
||||||
|
|
||||||
Assert.assertEquals(ControlEvent.TYPE_SCROLL, event.getType());
|
Assert.assertEquals(ControlMessage.TYPE_INJECT_SCROLL_EVENT, event.getType());
|
||||||
Assert.assertEquals(260, event.getPosition().getPoint().getX());
|
Assert.assertEquals(260, event.getPosition().getPoint().getX());
|
||||||
Assert.assertEquals(1026, event.getPosition().getPoint().getY());
|
Assert.assertEquals(1026, event.getPosition().getPoint().getY());
|
||||||
Assert.assertEquals(1080, event.getPosition().getScreenSize().getWidth());
|
Assert.assertEquals(1080, event.getPosition().getScreenSize().getWidth());
|
||||||
|
@ -128,75 +128,75 @@ public class ControlEventReaderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseBackOrScreenOnEvent() throws IOException {
|
public void testParseBackOrScreenOnEvent() throws IOException {
|
||||||
ControlEventReader reader = new ControlEventReader();
|
ControlMessageReader reader = new ControlMessageReader();
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
dos.writeByte(ControlEvent.TYPE_BACK_OR_SCREEN_ON);
|
dos.writeByte(ControlMessage.TYPE_BACK_OR_SCREEN_ON);
|
||||||
|
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
|
|
||||||
reader.readFrom(new ByteArrayInputStream(packet));
|
reader.readFrom(new ByteArrayInputStream(packet));
|
||||||
ControlEvent event = reader.next();
|
ControlMessage event = reader.next();
|
||||||
|
|
||||||
Assert.assertEquals(ControlEvent.TYPE_BACK_OR_SCREEN_ON, event.getType());
|
Assert.assertEquals(ControlMessage.TYPE_BACK_OR_SCREEN_ON, event.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseExpandNotificationPanelEvent() throws IOException {
|
public void testParseExpandNotificationPanelEvent() throws IOException {
|
||||||
ControlEventReader reader = new ControlEventReader();
|
ControlMessageReader reader = new ControlMessageReader();
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
dos.writeByte(ControlEvent.TYPE_EXPAND_NOTIFICATION_PANEL);
|
dos.writeByte(ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL);
|
||||||
|
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
|
|
||||||
reader.readFrom(new ByteArrayInputStream(packet));
|
reader.readFrom(new ByteArrayInputStream(packet));
|
||||||
ControlEvent event = reader.next();
|
ControlMessage event = reader.next();
|
||||||
|
|
||||||
Assert.assertEquals(ControlEvent.TYPE_EXPAND_NOTIFICATION_PANEL, event.getType());
|
Assert.assertEquals(ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL, event.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseCollapseNotificationPanelEvent() throws IOException {
|
public void testParseCollapseNotificationPanelEvent() throws IOException {
|
||||||
ControlEventReader reader = new ControlEventReader();
|
ControlMessageReader reader = new ControlMessageReader();
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
dos.writeByte(ControlEvent.TYPE_COLLAPSE_NOTIFICATION_PANEL);
|
dos.writeByte(ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL);
|
||||||
|
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
|
|
||||||
reader.readFrom(new ByteArrayInputStream(packet));
|
reader.readFrom(new ByteArrayInputStream(packet));
|
||||||
ControlEvent event = reader.next();
|
ControlMessage event = reader.next();
|
||||||
|
|
||||||
Assert.assertEquals(ControlEvent.TYPE_COLLAPSE_NOTIFICATION_PANEL, event.getType());
|
Assert.assertEquals(ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL, event.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseGetClipboardEvent() throws IOException {
|
public void testParseGetClipboardEvent() throws IOException {
|
||||||
ControlEventReader reader = new ControlEventReader();
|
ControlMessageReader reader = new ControlMessageReader();
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
dos.writeByte(ControlEvent.TYPE_GET_CLIPBOARD);
|
dos.writeByte(ControlMessage.TYPE_GET_CLIPBOARD);
|
||||||
|
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
|
|
||||||
reader.readFrom(new ByteArrayInputStream(packet));
|
reader.readFrom(new ByteArrayInputStream(packet));
|
||||||
ControlEvent event = reader.next();
|
ControlMessage event = reader.next();
|
||||||
|
|
||||||
Assert.assertEquals(ControlEvent.TYPE_GET_CLIPBOARD, event.getType());
|
Assert.assertEquals(ControlMessage.TYPE_GET_CLIPBOARD, event.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseSetClipboardEvent() throws IOException {
|
public void testParseSetClipboardEvent() throws IOException {
|
||||||
ControlEventReader reader = new ControlEventReader();
|
ControlMessageReader reader = new ControlMessageReader();
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
dos.writeByte(ControlEvent.TYPE_SET_CLIPBOARD);
|
dos.writeByte(ControlMessage.TYPE_SET_CLIPBOARD);
|
||||||
byte[] text = "testé".getBytes(StandardCharsets.UTF_8);
|
byte[] text = "testé".getBytes(StandardCharsets.UTF_8);
|
||||||
dos.writeShort(text.length);
|
dos.writeShort(text.length);
|
||||||
dos.write(text);
|
dos.write(text);
|
||||||
|
@ -204,25 +204,25 @@ public class ControlEventReaderTest {
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
|
|
||||||
reader.readFrom(new ByteArrayInputStream(packet));
|
reader.readFrom(new ByteArrayInputStream(packet));
|
||||||
ControlEvent event = reader.next();
|
ControlMessage event = reader.next();
|
||||||
|
|
||||||
Assert.assertEquals(ControlEvent.TYPE_SET_CLIPBOARD, event.getType());
|
Assert.assertEquals(ControlMessage.TYPE_SET_CLIPBOARD, event.getType());
|
||||||
Assert.assertEquals("testé", event.getText());
|
Assert.assertEquals("testé", event.getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultiEvents() throws IOException {
|
public void testMultiEvents() throws IOException {
|
||||||
ControlEventReader reader = new ControlEventReader();
|
ControlMessageReader reader = new ControlMessageReader();
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
|
|
||||||
dos.writeByte(ControlEvent.TYPE_KEYCODE);
|
dos.writeByte(ControlMessage.TYPE_INJECT_KEYCODE);
|
||||||
dos.writeByte(KeyEvent.ACTION_UP);
|
dos.writeByte(KeyEvent.ACTION_UP);
|
||||||
dos.writeInt(KeyEvent.KEYCODE_ENTER);
|
dos.writeInt(KeyEvent.KEYCODE_ENTER);
|
||||||
dos.writeInt(KeyEvent.META_CTRL_ON);
|
dos.writeInt(KeyEvent.META_CTRL_ON);
|
||||||
|
|
||||||
dos.writeByte(ControlEvent.TYPE_KEYCODE);
|
dos.writeByte(ControlMessage.TYPE_INJECT_KEYCODE);
|
||||||
dos.writeByte(MotionEvent.ACTION_DOWN);
|
dos.writeByte(MotionEvent.ACTION_DOWN);
|
||||||
dos.writeInt(MotionEvent.BUTTON_PRIMARY);
|
dos.writeInt(MotionEvent.BUTTON_PRIMARY);
|
||||||
dos.writeInt(KeyEvent.META_CTRL_ON);
|
dos.writeInt(KeyEvent.META_CTRL_ON);
|
||||||
|
@ -230,14 +230,14 @@ public class ControlEventReaderTest {
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
reader.readFrom(new ByteArrayInputStream(packet));
|
reader.readFrom(new ByteArrayInputStream(packet));
|
||||||
|
|
||||||
ControlEvent event = reader.next();
|
ControlMessage event = reader.next();
|
||||||
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
|
Assert.assertEquals(ControlMessage.TYPE_INJECT_KEYCODE, event.getType());
|
||||||
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
|
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
|
||||||
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
|
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
|
||||||
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
||||||
|
|
||||||
event = reader.next();
|
event = reader.next();
|
||||||
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
|
Assert.assertEquals(ControlMessage.TYPE_INJECT_KEYCODE, event.getType());
|
||||||
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
|
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
|
||||||
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getKeycode());
|
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getKeycode());
|
||||||
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
||||||
|
@ -245,24 +245,24 @@ public class ControlEventReaderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPartialEvents() throws IOException {
|
public void testPartialEvents() throws IOException {
|
||||||
ControlEventReader reader = new ControlEventReader();
|
ControlMessageReader reader = new ControlMessageReader();
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
|
|
||||||
dos.writeByte(ControlEvent.TYPE_KEYCODE);
|
dos.writeByte(ControlMessage.TYPE_INJECT_KEYCODE);
|
||||||
dos.writeByte(KeyEvent.ACTION_UP);
|
dos.writeByte(KeyEvent.ACTION_UP);
|
||||||
dos.writeInt(KeyEvent.KEYCODE_ENTER);
|
dos.writeInt(KeyEvent.KEYCODE_ENTER);
|
||||||
dos.writeInt(KeyEvent.META_CTRL_ON);
|
dos.writeInt(KeyEvent.META_CTRL_ON);
|
||||||
|
|
||||||
dos.writeByte(ControlEvent.TYPE_KEYCODE);
|
dos.writeByte(ControlMessage.TYPE_INJECT_KEYCODE);
|
||||||
dos.writeByte(MotionEvent.ACTION_DOWN);
|
dos.writeByte(MotionEvent.ACTION_DOWN);
|
||||||
|
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
reader.readFrom(new ByteArrayInputStream(packet));
|
reader.readFrom(new ByteArrayInputStream(packet));
|
||||||
|
|
||||||
ControlEvent event = reader.next();
|
ControlMessage event = reader.next();
|
||||||
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
|
Assert.assertEquals(ControlMessage.TYPE_INJECT_KEYCODE, event.getType());
|
||||||
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
|
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
|
||||||
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
|
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
|
||||||
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
||||||
|
@ -278,7 +278,7 @@ public class ControlEventReaderTest {
|
||||||
|
|
||||||
// the event is now complete
|
// the event is now complete
|
||||||
event = reader.next();
|
event = reader.next();
|
||||||
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
|
Assert.assertEquals(ControlMessage.TYPE_INJECT_KEYCODE, event.getType());
|
||||||
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
|
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
|
||||||
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getKeycode());
|
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getKeycode());
|
||||||
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
Loading…
Reference in a new issue