5d17bcf1bc
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. Refse4163321f0
Refs45b0f8123a
PR #2814 <https://github.com/Genymobile/scrcpy/pull/2814>
66 lines
1.4 KiB
C
66 lines
1.4 KiB
C
#ifndef SC_ACK_SYNC_H
|
|
#define SC_ACK_SYNC_H
|
|
|
|
#include "common.h"
|
|
|
|
#include "thread.h"
|
|
|
|
#define SC_SEQUENCE_INVALID 0
|
|
|
|
/**
|
|
* Helper to wait for acknowledgments
|
|
*
|
|
* In practice, it is used to wait for device clipboard acknowledgement from the
|
|
* server before injecting Ctrl+v via AOA HID, in order to avoid pasting the
|
|
* content of the old device clipboard (if Ctrl+v was injected before the
|
|
* clipboard content was actually set).
|
|
*/
|
|
struct sc_acksync {
|
|
sc_mutex mutex;
|
|
sc_cond cond;
|
|
|
|
bool stopped;
|
|
|
|
// Last acked value, initially SC_SEQUENCE_INVALID
|
|
uint64_t ack;
|
|
};
|
|
|
|
enum sc_acksync_wait_result {
|
|
// Acknowledgment received
|
|
SC_ACKSYNC_WAIT_OK,
|
|
|
|
// Timeout expired
|
|
SC_ACKSYNC_WAIT_TIMEOUT,
|
|
|
|
// Interrupted from another thread by sc_acksync_interrupt()
|
|
SC_ACKSYNC_WAIT_INTR,
|
|
};
|
|
|
|
bool
|
|
sc_acksync_init(struct sc_acksync *as);
|
|
|
|
void
|
|
sc_acksync_destroy(struct sc_acksync *as);
|
|
|
|
/**
|
|
* Acknowledge `sequence`
|
|
*
|
|
* The `sequence` must be greater than (or equal to) any previous acknowledged
|
|
* sequence.
|
|
*/
|
|
void
|
|
sc_acksync_ack(struct sc_acksync *as, uint64_t sequence);
|
|
|
|
/**
|
|
* Wait for acknowledgment of sequence `ack` (or higher)
|
|
*/
|
|
enum sc_acksync_wait_result
|
|
sc_acksync_wait(struct sc_acksync *as, uint64_t ack, sc_tick deadline);
|
|
|
|
/**
|
|
* Interrupt any `sc_acksync_wait()`
|
|
*/
|
|
void
|
|
sc_acksync_interrupt(struct sc_acksync *as);
|
|
|
|
#endif
|