From 72ee195693a030990e9965ac93922c9aae32988d Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Fri, 6 Sep 2024 23:08:08 +0200 Subject: [PATCH] Set clipboard from the main thread The clipboard changes from the device are received from a separate thread, but they must be handled from the main thread. PR #5270 --- app/src/receiver.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/app/src/receiver.c b/app/src/receiver.c index 3e572067..2911f8b9 100644 --- a/app/src/receiver.c +++ b/app/src/receiver.c @@ -6,8 +6,10 @@ #include #include "device_msg.h" +#include "events.h" #include "util/log.h" #include "util/str.h" +#include "util/thread.h" bool sc_receiver_init(struct sc_receiver *receiver, sc_socket control_socket, @@ -33,20 +35,39 @@ sc_receiver_destroy(struct sc_receiver *receiver) { sc_mutex_destroy(&receiver->mutex); } +static void +task_set_clipboard(void *userdata) { + assert(sc_thread_get_id() == SC_MAIN_THREAD_ID); + + char *text = userdata; + + char *current = SDL_GetClipboardText(); + bool same = current && !strcmp(current, text); + SDL_free(current); + if (same) { + LOGD("Computer clipboard unchanged"); + } else { + LOGI("Device clipboard copied"); + SDL_SetClipboardText(text); + } + + free(text); +} + static void process_msg(struct sc_receiver *receiver, struct sc_device_msg *msg) { switch (msg->type) { case DEVICE_MSG_TYPE_CLIPBOARD: { - char *current = SDL_GetClipboardText(); - bool same = current && !strcmp(current, msg->clipboard.text); - SDL_free(current); - if (same) { - LOGD("Computer clipboard unchanged"); + // Take ownership of the text (do not destroy the msg) + char *text = msg->clipboard.text; + + bool ok = sc_post_to_main_thread(task_set_clipboard, text); + if (!ok) { + LOGW("Could not post clipboard to main thread"); + free(text); return; } - LOGI("Device clipboard copied"); - SDL_SetClipboardText(msg->clipboard.text); break; } case DEVICE_MSG_TYPE_ACK_CLIPBOARD: @@ -64,6 +85,7 @@ process_msg(struct sc_receiver *receiver, struct sc_device_msg *msg) { } sc_acksync_ack(receiver->acksync, msg->ack_clipboard.sequence); + // No allocation to free in the msg break; case DEVICE_MSG_TYPE_UHID_OUTPUT: if (sc_get_log_level() <= SC_LOG_LEVEL_VERBOSE) { @@ -86,6 +108,7 @@ process_msg(struct sc_receiver *receiver, struct sc_device_msg *msg) { // Also check at runtime (do not trust the server) if (!receiver->uhid_devices) { LOGE("Received unexpected HID output message"); + sc_device_msg_destroy(msg); return; } @@ -99,6 +122,8 @@ process_msg(struct sc_receiver *receiver, struct sc_device_msg *msg) { } else { LOGW("No UHID receiver for id %" PRIu16, msg->uhid_output.id); } + + sc_device_msg_destroy(msg); break; } } @@ -117,7 +142,7 @@ process_msgs(struct sc_receiver *receiver, const uint8_t *buf, size_t len) { } process_msg(receiver, &msg); - sc_device_msg_destroy(&msg); + // the device msg must be destroyed by process_msg() head += r; assert(head <= len);