To allow seamless copy-paste, on Ctrl+v, a SET_CLIPBOARD request is performed before injecting Ctrl+v. But when HID keyboard is enabled, the Ctrl+v injection is not sent on the same channel as the clipboard request, so they are not serialized, and may occur in any order. If Ctrl+v happens to be injected before the new clipboard content is set, then the old content is pasted instead, which is incorrect. To minimize the probability of occurrence of the wrong order, a delay of 2 milliseconds was added before injecting Ctrl+v. Then 5ms. But even with 5ms, the wrong behavior sometimes happens. To handle it properly, add an acknowledgement mechanism, so that Ctrl+v is injected over AOA only after the SET_CLIPBOARD request has been performed and acknowledged by the server. Refs e4163321f00bb3830c6049bdb6c1515e7cc668a0 Refs 45b0f8123a52f5c73a5860d616f4ceba2766ca6a PR #2814 <https://github.com/Genymobile/scrcpy/pull/2814>
70 lines
1.4 KiB
C
70 lines
1.4 KiB
C
#ifndef SC_AOA_HID_H
|
|
#define SC_AOA_HID_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#include <libusb-1.0/libusb.h>
|
|
|
|
#include "util/acksync.h"
|
|
#include "util/cbuf.h"
|
|
#include "util/thread.h"
|
|
#include "util/tick.h"
|
|
|
|
struct sc_hid_event {
|
|
uint16_t accessory_id;
|
|
unsigned char *buffer;
|
|
uint16_t size;
|
|
uint64_t ack_to_wait;
|
|
};
|
|
|
|
// Takes ownership of buffer
|
|
void
|
|
sc_hid_event_init(struct sc_hid_event *hid_event, uint16_t accessory_id,
|
|
unsigned char *buffer, uint16_t buffer_size);
|
|
|
|
void
|
|
sc_hid_event_destroy(struct sc_hid_event *hid_event);
|
|
|
|
struct sc_hid_event_queue CBUF(struct sc_hid_event, 64);
|
|
|
|
struct sc_aoa {
|
|
libusb_context *usb_context;
|
|
libusb_device *usb_device;
|
|
libusb_device_handle *usb_handle;
|
|
sc_thread thread;
|
|
sc_mutex mutex;
|
|
sc_cond event_cond;
|
|
bool stopped;
|
|
struct sc_hid_event_queue queue;
|
|
|
|
struct sc_acksync *acksync;
|
|
};
|
|
|
|
bool
|
|
sc_aoa_init(struct sc_aoa *aoa, const char *serial, struct sc_acksync *acksync);
|
|
|
|
void
|
|
sc_aoa_destroy(struct sc_aoa *aoa);
|
|
|
|
bool
|
|
sc_aoa_start(struct sc_aoa *aoa);
|
|
|
|
void
|
|
sc_aoa_stop(struct sc_aoa *aoa);
|
|
|
|
void
|
|
sc_aoa_join(struct sc_aoa *aoa);
|
|
|
|
bool
|
|
sc_aoa_setup_hid(struct sc_aoa *aoa, uint16_t accessory_id,
|
|
const unsigned char *report_desc, uint16_t report_desc_size);
|
|
|
|
bool
|
|
sc_aoa_unregister_hid(struct sc_aoa *aoa, uint16_t accessory_id);
|
|
|
|
bool
|
|
sc_aoa_push_hid_event(struct sc_aoa *aoa, const struct sc_hid_event *event);
|
|
|
|
#endif
|