2019-05-31 20:55:11 +08:00
|
|
|
#include "control_msg.h"
|
|
|
|
|
2019-11-28 04:11:40 +08:00
|
|
|
#include <assert.h>
|
2019-05-31 20:55:11 +08:00
|
|
|
#include <string.h>
|
|
|
|
|
2019-09-30 04:36:56 +08:00
|
|
|
#include "config.h"
|
2019-11-24 18:53:00 +08:00
|
|
|
#include "util/buffer_util.h"
|
|
|
|
#include "util/log.h"
|
|
|
|
#include "util/str_util.h"
|
2019-05-31 20:55:11 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-09-15 22:16:17 +08:00
|
|
|
static uint16_t
|
|
|
|
to_fixed_point_16(float f) {
|
2019-11-28 04:11:40 +08:00
|
|
|
assert(f >= 0.0f && f <= 1.0f);
|
2019-09-15 22:16:17 +08:00
|
|
|
uint32_t u = f * 0x1p16f; // 2^16
|
|
|
|
if (u >= 0xffff) {
|
|
|
|
u = 0xffff;
|
|
|
|
}
|
|
|
|
return (uint16_t) u;
|
|
|
|
}
|
|
|
|
|
2019-05-31 20:55:11 +08:00
|
|
|
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: {
|
2020-04-14 01:37:34 +08:00
|
|
|
size_t len =
|
|
|
|
write_string(msg->inject_text.text,
|
|
|
|
CONTROL_MSG_INJECT_TEXT_MAX_LENGTH, &buf[1]);
|
2019-05-31 20:55:11 +08:00
|
|
|
return 1 + len;
|
|
|
|
}
|
2019-09-15 22:16:17 +08:00
|
|
|
case CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT:
|
|
|
|
buf[1] = msg->inject_touch_event.action;
|
|
|
|
buffer_write64be(&buf[2], msg->inject_touch_event.pointer_id);
|
|
|
|
write_position(&buf[10], &msg->inject_touch_event.position);
|
|
|
|
uint16_t pressure =
|
|
|
|
to_fixed_point_16(msg->inject_touch_event.pressure);
|
|
|
|
buffer_write16be(&buf[22], pressure);
|
2019-10-04 02:14:12 +08:00
|
|
|
buffer_write32be(&buf[24], msg->inject_touch_event.buttons);
|
|
|
|
return 28;
|
2019-05-31 20:55:11 +08:00
|
|
|
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: {
|
2020-05-26 02:58:24 +08:00
|
|
|
buf[1] = !!msg->set_clipboard.paste;
|
2020-05-26 00:41:05 +08:00
|
|
|
size_t len = write_string(msg->set_clipboard.text,
|
2019-05-31 20:55:11 +08:00
|
|
|
CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH,
|
2020-05-26 02:58:24 +08:00
|
|
|
&buf[2]);
|
|
|
|
return 2 + len;
|
2019-05-31 20:55:11 +08:00
|
|
|
}
|
2019-03-16 03:23:30 +08:00
|
|
|
case CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE:
|
|
|
|
buf[1] = msg->set_screen_power_mode.mode;
|
|
|
|
return 2;
|
2019-05-31 20:55:11 +08:00
|
|
|
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:
|
2019-12-05 02:55:28 +08:00
|
|
|
case CONTROL_MSG_TYPE_ROTATE_DEVICE:
|
2019-05-31 20:55:11 +08:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|