[client] spice: handle clipboard request failures

This commit is contained in:
Geoffrey McRae
2026-07-28 13:05:40 +10:00
parent 67e2675afa
commit e73a3dec60
4 changed files with 32 additions and 11 deletions

View File

@@ -595,7 +595,8 @@ void waylandCBNotice(LG_ClipboardData type)
{ {
wlCb.haveRequest = true; wlCb.haveRequest = true;
wlCb.type = type; wlCb.type = type;
app_clipboardRequest(waylandCBReplyFn, NULL); if (!app_clipboardRequest(waylandCBReplyFn, NULL))
DEBUG_ERROR("Failed to request SPICE clipboard data");
} }
void waylandCBRelease(void) void waylandCBRelease(void)

View File

@@ -195,8 +195,9 @@ static void x11CBSelectionRequest(const XSelectionRequestEvent e)
if (x11cb.aTypes[i] == e.target && x11cb.type == i) if (x11cb.aTypes[i] == e.target && x11cb.type == i)
{ {
// request the data // request the data
app_clipboardRequest(x11CBReplyFn, s); if (app_clipboardRequest(x11CBReplyFn, s))
return; return;
goto nodata;
} }
nodata: nodata:

View File

@@ -151,7 +151,7 @@ void app_clipboardRelease(void);
void app_clipboardNotifyTypes(const LG_ClipboardData types[], int count); void app_clipboardNotifyTypes(const LG_ClipboardData types[], int count);
void app_clipboardNotifySize(const LG_ClipboardData type, size_t size); void app_clipboardNotifySize(const LG_ClipboardData type, size_t size);
void app_clipboardData(const LG_ClipboardData type, uint8_t * data, size_t size); void app_clipboardData(const LG_ClipboardData type, uint8_t * data, size_t size);
void app_clipboardRequest(const LG_ClipboardReplyFn replyFn, void * opaque); bool app_clipboardRequest(const LG_ClipboardReplyFn replyFn, void * opaque);
/** /**
* Show an alert on screen * Show an alert on screen

View File

@@ -348,24 +348,43 @@ void app_clipboardData(const LG_ClipboardData type, uint8_t * data, size_t size)
DEBUG_ERROR("Failed to send SPICE clipboard data"); DEBUG_ERROR("Failed to send SPICE clipboard data");
} }
void app_clipboardRequest(const LG_ClipboardReplyFn replyFn, void * opaque) bool app_clipboardRequest(const LG_ClipboardReplyFn replyFn, void * opaque)
{ {
if (!g_params.clipboardToLocal) if (!g_params.clipboardToLocal || !replyFn || !g_state.cbRequestList)
return; return false;
const PSDataType type = g_state.cbType;
struct CBRequest * cbr = malloc(sizeof(*cbr)); struct CBRequest * cbr = malloc(sizeof(*cbr));
if (!cbr) if (!cbr)
{ {
DEBUG_ERROR("out of memory"); DEBUG_ERROR("out of memory");
return; return false;
} }
cbr->type = g_state.cbType; cbr->type = type;
cbr->replyFn = replyFn; cbr->replyFn = replyFn;
cbr->opaque = opaque; cbr->opaque = opaque;
ll_push(g_state.cbRequestList, cbr);
purespice_clipboardRequest(g_state.cbType); if (!ll_push(g_state.cbRequestList, cbr))
{
free(cbr);
return false;
}
if (purespice_clipboardRequest(type))
return true;
/*
* Queue the callback before sending so a fast response cannot arrive before
* its request is visible. If another thread has already consumed it, the
* callback owns both cbr and opaque and the request completed successfully
* from the caller's perspective.
*/
if (!ll_removeData(g_state.cbRequestList, cbr))
return true;
free(cbr);
return false;
} }
static int mapSpiceToImGuiButton(uint32_t button) static int mapSpiceToImGuiButton(uint32_t button)