From f9d2d99166f2259f05cd348fcde019b9a314d780 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Thu, 30 May 2019 00:24:26 +0200 Subject: [PATCH] Add GET_CLIPBOARD device event Add the first device event, used to forward the device clipboard to the computer. --- app/meson.build | 5 ++ app/src/device_event.c | 48 +++++++++++++++++++ app/src/device_event.h | 33 +++++++++++++ app/tests/test_device_event_deserialize.c | 28 +++++++++++ .../com/genymobile/scrcpy/DeviceEvent.java | 27 +++++++++++ 5 files changed, 141 insertions(+) create mode 100644 app/src/device_event.c create mode 100644 app/src/device_event.h create mode 100644 app/tests/test_device_event_deserialize.c create mode 100644 server/src/main/java/com/genymobile/scrcpy/DeviceEvent.java diff --git a/app/meson.build b/app/meson.build index c6c91e71..326a6656 100644 --- a/app/meson.build +++ b/app/meson.build @@ -6,6 +6,7 @@ src = [ 'src/convert.c', 'src/decoder.c', 'src/device.c', + 'src/device_event.c', 'src/file_handler.c', 'src/fps_counter.c', 'src/input_manager.c', @@ -162,6 +163,10 @@ tests = [ 'src/control_event.c', 'src/str_util.c' ]], + ['test_device_event_deserialize', [ + 'tests/test_device_event_deserialize.c', + 'src/device_event.c' + ]], ['test_strutil', [ 'tests/test_strutil.c', 'src/str_util.c' diff --git a/app/src/device_event.c b/app/src/device_event.c new file mode 100644 index 00000000..5bc70d99 --- /dev/null +++ b/app/src/device_event.c @@ -0,0 +1,48 @@ +#include "device_event.h" + +#include +#include + +#include "buffer_util.h" +#include "log.h" + +ssize_t +device_event_deserialize(const unsigned char *buf, size_t len, + struct device_event *event) { + if (len < 3) { + // at least type + empty string length + return 0; // not available + } + + event->type = buf[0]; + switch (event->type) { + case DEVICE_EVENT_TYPE_GET_CLIPBOARD: { + uint16_t clipboard_len = buffer_read16be(&buf[1]); + if (clipboard_len > len - 3) { + return 0; // not available + } + char *text = SDL_malloc(clipboard_len + 1); + if (!text) { + LOGW("Could not allocate text for clipboard"); + return -1; + } + if (clipboard_len) { + memcpy(text, &buf[3], clipboard_len); + } + text[clipboard_len] = '\0'; + + event->clipboard_event.text = text; + return 3 + clipboard_len; + } + default: + LOGW("Unsupported device event type: %d", (int) event->type); + return -1; // error, we cannot recover + } +} + +void +device_event_destroy(struct device_event *event) { + if (event->type == DEVICE_EVENT_TYPE_GET_CLIPBOARD) { + SDL_free(event->clipboard_event.text); + } +} diff --git a/app/src/device_event.h b/app/src/device_event.h new file mode 100644 index 00000000..8e0e8e7f --- /dev/null +++ b/app/src/device_event.h @@ -0,0 +1,33 @@ +#ifndef DEVICEEVENT_H +#define DEVICEEVENT_H + +#include +#include +#include + +#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 diff --git a/app/tests/test_device_event_deserialize.c b/app/tests/test_device_event_deserialize.c new file mode 100644 index 00000000..83e5e02e --- /dev/null +++ b/app/tests/test_device_event_deserialize.c @@ -0,0 +1,28 @@ +#include +#include + +#include "device_event.h" + +#include +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; +} diff --git a/server/src/main/java/com/genymobile/scrcpy/DeviceEvent.java b/server/src/main/java/com/genymobile/scrcpy/DeviceEvent.java new file mode 100644 index 00000000..97bcbfc6 --- /dev/null +++ b/server/src/main/java/com/genymobile/scrcpy/DeviceEvent.java @@ -0,0 +1,27 @@ +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; + } +}