mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-25 06:47:19 +00:00
[client] wayland: better self-copy detection
This new implementation uses a special mimetype to tag data copied from the guest, instead of using flags. This should make it easier to implement asynchronous transfers in the future. Also, it's simpler to understand and less error-prone. The pid is included in the mimetype in order to distinguish between different instances of looking glass: you might want to copy between two different VMs, for example.
This commit is contained in:
parent
0c9ecdfcb5
commit
a450e0f8f5
@ -117,8 +117,8 @@ struct WCBState
|
|||||||
char * stashedMimetype;
|
char * stashedMimetype;
|
||||||
uint8_t * stashedContents;
|
uint8_t * stashedContents;
|
||||||
ssize_t stashedSize;
|
ssize_t stashedSize;
|
||||||
bool isReceiving;
|
|
||||||
bool isSelfCopy;
|
bool isSelfCopy;
|
||||||
|
char lgMimetype[64];
|
||||||
|
|
||||||
bool haveRequest;
|
bool haveRequest;
|
||||||
LG_ClipboardData type;
|
LG_ClipboardData type;
|
||||||
@ -1005,6 +1005,9 @@ static void dataOfferHandleOffer(void * data, struct wl_data_offer * offer,
|
|||||||
free(wcb.stashedMimetype);
|
free(wcb.stashedMimetype);
|
||||||
wcb.stashedMimetype = strdup(mimetype);
|
wcb.stashedMimetype = strdup(mimetype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(mimetype, wcb.lgMimetype))
|
||||||
|
wcb.isSelfCopy = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dataOfferHandleSourceActions(void * data,
|
static void dataOfferHandleSourceActions(void * data,
|
||||||
@ -1029,13 +1032,14 @@ static void dataDeviceHandleDataOffer(void * data,
|
|||||||
struct wl_data_device * dataDevice, struct wl_data_offer * offer)
|
struct wl_data_device * dataDevice, struct wl_data_offer * offer)
|
||||||
{
|
{
|
||||||
wcb.stashedType = LG_CLIPBOARD_DATA_NONE;
|
wcb.stashedType = LG_CLIPBOARD_DATA_NONE;
|
||||||
|
wcb.isSelfCopy = false;
|
||||||
wl_data_offer_add_listener(offer, &dataOfferListener, NULL);
|
wl_data_offer_add_listener(offer, &dataOfferListener, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dataDeviceHandleSelection(void * data,
|
static void dataDeviceHandleSelection(void * data,
|
||||||
struct wl_data_device * dataDevice, struct wl_data_offer * offer)
|
struct wl_data_device * dataDevice, struct wl_data_offer * offer)
|
||||||
{
|
{
|
||||||
if (wcb.stashedType == LG_CLIPBOARD_DATA_NONE || !offer)
|
if (wcb.stashedType == LG_CLIPBOARD_DATA_NONE || wcb.isSelfCopy || !offer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int fds[2];
|
int fds[2];
|
||||||
@ -1045,8 +1049,6 @@ static void dataDeviceHandleSelection(void * data,
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
wcb.isReceiving = true;
|
|
||||||
wcb.isSelfCopy = false;
|
|
||||||
wl_data_offer_receive(offer, wcb.stashedMimetype, fds[1]);
|
wl_data_offer_receive(offer, wcb.stashedMimetype, fds[1]);
|
||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
free(wcb.stashedMimetype);
|
free(wcb.stashedMimetype);
|
||||||
@ -1093,13 +1095,10 @@ static void dataDeviceHandleSelection(void * data,
|
|||||||
|
|
||||||
wcb.stashedSize = numRead;
|
wcb.stashedSize = numRead;
|
||||||
wcb.stashedContents = buf;
|
wcb.stashedContents = buf;
|
||||||
wcb.isReceiving = false;
|
|
||||||
|
|
||||||
close(fds[0]);
|
close(fds[0]);
|
||||||
wl_data_offer_destroy(offer);
|
wl_data_offer_destroy(offer);
|
||||||
|
app_clipboardNotify(wcb.stashedType, 0);
|
||||||
if (!wcb.isSelfCopy)
|
|
||||||
app_clipboardNotify(wcb.stashedType, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_data_device_listener dataDeviceListener = {
|
static const struct wl_data_device_listener dataDeviceListener = {
|
||||||
@ -1121,6 +1120,9 @@ static bool waylandCBInit(void)
|
|||||||
wcb.stashedType = LG_CLIPBOARD_DATA_NONE;
|
wcb.stashedType = LG_CLIPBOARD_DATA_NONE;
|
||||||
wl_data_device_add_listener(wm.dataDevice, &dataDeviceListener, NULL);
|
wl_data_device_add_listener(wm.dataDevice, &dataDeviceListener, NULL);
|
||||||
|
|
||||||
|
snprintf(wcb.lgMimetype, sizeof(wcb.lgMimetype),
|
||||||
|
"application/x-looking-glass-copy;pid=%d", getpid());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1128,9 +1130,7 @@ static void dataSourceHandleSend(void * data, struct wl_data_source * source,
|
|||||||
const char * mimetype, int fd)
|
const char * mimetype, int fd)
|
||||||
{
|
{
|
||||||
struct WCBTransfer * transfer = (struct WCBTransfer *) data;
|
struct WCBTransfer * transfer = (struct WCBTransfer *) data;
|
||||||
if (wcb.isReceiving)
|
if (containsMimetype(transfer->mimetypes, mimetype))
|
||||||
wcb.isSelfCopy = true;
|
|
||||||
else if (containsMimetype(transfer->mimetypes, mimetype))
|
|
||||||
{
|
{
|
||||||
// Consider making this do non-blocking sends to not stall the Wayland
|
// Consider making this do non-blocking sends to not stall the Wayland
|
||||||
// event loop if it becomes a problem. This is "fine" in the sense that
|
// event loop if it becomes a problem. This is "fine" in the sense that
|
||||||
@ -1187,6 +1187,7 @@ static void waylandCBReplyFn(void * opaque, LG_ClipboardData type,
|
|||||||
wl_data_source_add_listener(source, &dataSourceListener, transfer);
|
wl_data_source_add_listener(source, &dataSourceListener, transfer);
|
||||||
for (const char ** mimetype = transfer->mimetypes; *mimetype; mimetype++)
|
for (const char ** mimetype = transfer->mimetypes; *mimetype; mimetype++)
|
||||||
wl_data_source_offer(source, *mimetype);
|
wl_data_source_offer(source, *mimetype);
|
||||||
|
wl_data_source_offer(source, wcb.lgMimetype);
|
||||||
|
|
||||||
wl_data_device_set_selection(wm.dataDevice, source,
|
wl_data_device_set_selection(wm.dataDevice, source,
|
||||||
wm.keyboardEnterSerial);
|
wm.keyboardEnterSerial);
|
||||||
|
Loading…
Reference in New Issue
Block a user