Set clipboard from the main thread

The clipboard changes from the device are received from a separate
thread, but it must be handled from the main thread.
This commit is contained in:
Romain Vimont 2024-09-06 23:08:08 +02:00
parent 87d9d68c07
commit c5ccae5538

View file

@ -6,6 +6,7 @@
#include <SDL2/SDL_clipboard.h> #include <SDL2/SDL_clipboard.h>
#include "device_msg.h" #include "device_msg.h"
#include "events.h"
#include "util/log.h" #include "util/log.h"
#include "util/str.h" #include "util/str.h"
@ -33,20 +34,38 @@ sc_receiver_destroy(struct sc_receiver *receiver) {
sc_mutex_destroy(&receiver->mutex); sc_mutex_destroy(&receiver->mutex);
} }
static void
task_set_clipboard(void *userdata) {
char *text = userdata;
char *current = SDL_GetClipboardText();
bool same = current && !strcmp(current, text);
SDL_free(current);
if (same) {
LOGD("Computer clipboard unchanged");
free(text);
return;
}
LOGI("Device clipboard copied");
SDL_SetClipboardText(text);
free(text);
}
static void static void
process_msg(struct sc_receiver *receiver, struct sc_device_msg *msg) { process_msg(struct sc_receiver *receiver, struct sc_device_msg *msg) {
switch (msg->type) { switch (msg->type) {
case DEVICE_MSG_TYPE_CLIPBOARD: { case DEVICE_MSG_TYPE_CLIPBOARD: {
char *current = SDL_GetClipboardText(); // Take ownership of the text (do not destroy the msg)
bool same = current && !strcmp(current, msg->clipboard.text); char *text = msg->clipboard.text;
SDL_free(current);
if (same) { bool ok = sc_post_to_main_thread(task_set_clipboard, text);
LOGD("Computer clipboard unchanged"); if (!ok) {
LOGW("Could not post clipboard to main thread");
free(text);
return; return;
} }
LOGI("Device clipboard copied");
SDL_SetClipboardText(msg->clipboard.text);
break; break;
} }
case DEVICE_MSG_TYPE_ACK_CLIPBOARD: case DEVICE_MSG_TYPE_ACK_CLIPBOARD:
@ -64,6 +83,7 @@ process_msg(struct sc_receiver *receiver, struct sc_device_msg *msg) {
} }
sc_acksync_ack(receiver->acksync, msg->ack_clipboard.sequence); sc_acksync_ack(receiver->acksync, msg->ack_clipboard.sequence);
// No allocation to free in the msg
break; break;
case DEVICE_MSG_TYPE_UHID_OUTPUT: case DEVICE_MSG_TYPE_UHID_OUTPUT:
if (sc_get_log_level() <= SC_LOG_LEVEL_VERBOSE) { if (sc_get_log_level() <= SC_LOG_LEVEL_VERBOSE) {
@ -86,6 +106,7 @@ process_msg(struct sc_receiver *receiver, struct sc_device_msg *msg) {
// Also check at runtime (do not trust the server) // Also check at runtime (do not trust the server)
if (!receiver->uhid_devices) { if (!receiver->uhid_devices) {
LOGE("Received unexpected HID output message"); LOGE("Received unexpected HID output message");
sc_device_msg_destroy(msg);
return; return;
} }
@ -99,6 +120,8 @@ process_msg(struct sc_receiver *receiver, struct sc_device_msg *msg) {
} else { } else {
LOGW("No UHID receiver for id %" PRIu16, msg->uhid_output.id); LOGW("No UHID receiver for id %" PRIu16, msg->uhid_output.id);
} }
sc_device_msg_destroy(msg);
break; break;
} }
} }
@ -117,7 +140,7 @@ process_msgs(struct sc_receiver *receiver, const uint8_t *buf, size_t len) {
} }
process_msg(receiver, &msg); process_msg(receiver, &msg);
sc_device_msg_destroy(&msg); // the device msg must be destroyed by process_msg()
head += r; head += r;
assert(head <= len); assert(head <= len);