From 52d9ab10a0c6c5f50d061847ffd40b34117caeae Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Sat, 15 Aug 2026 20:29:08 +1000 Subject: [PATCH] [client] clipboard: add support for Caja --- client/displayservers/Wayland/clipboard.c | 21 +++++++++++++---- client/displayservers/X11/clipboard.c | 28 ++++++++++++++++++----- client/src/clipboard_files.c | 26 +++++++++++++++------ 3 files changed, 57 insertions(+), 18 deletions(-) diff --git a/client/displayservers/Wayland/clipboard.c b/client/displayservers/Wayland/clipboard.c index 98176987..c22b97b8 100644 --- a/client/displayservers/Wayland/clipboard.c +++ b/client/displayservers/Wayland/clipboard.c @@ -79,6 +79,7 @@ static const char * jpegMimetypes[] = static const char * fileMimetypes[] = { "x-special/gnome-copied-files", + "x-special/mate-copied-files", "text/uri-list", "application/x-kde-cutselection", NULL, @@ -153,6 +154,7 @@ static bool isTextMimetype(const char * mimetype) static enum LG_ClipboardData mimetypeToCbType(const char * mimetype) { if (!strcmp(mimetype, "x-special/gnome-copied-files") || + !strcmp(mimetype, "x-special/mate-copied-files" ) || !strcmp(mimetype, "text/uri-list")) return LG_CLIPBOARD_DATA_FILES; @@ -435,8 +437,9 @@ static void dataOfferHandleOffer(void * opaque, struct wl_data_offer * offer, { if (type != LG_CLIPBOARD_DATA_FILES || strcmp(mimetype, "x-special/gnome-copied-files") || - !strcmp(data->mimetypes[type], - "x-special/gnome-copied-files")) + strcmp(mimetype, "x-special/mate-copied-files") || + !strcmp(data->mimetypes[type], "x-special/gnome-copied-files") || + !strcmp(data->mimetypes[type], "x-special/mate-copied-files")) return; free(data->mimetypes[type]); } @@ -1295,7 +1298,9 @@ static bool fileTransferPayload(const struct WCBTransfer * transfer, *data = transfer->fileUri; *size = transfer->fileUriSize; } - else if (!strcmp(mime, "x-special/gnome-copied-files")) + else if ( + !strcmp(mime, "x-special/gnome-copied-files") || + !strcmp(mime, "x-special/mate-copied-files" )) { *data = transfer->fileGnome; *size = transfer->fileGnomeSize; @@ -1409,8 +1414,11 @@ static void dataSourceHandleSend(void * data, struct wl_data_source * source, { const char * payload; size_t size; - const bool deliversUri = !strcmp(mimetype, "text/uri-list") || - !strcmp(mimetype, "x-special/gnome-copied-files"); + const bool deliversUri = + !strcmp(mimetype, "text/uri-list" ) || + !strcmp(mimetype, "x-special/gnome-copied-files") || + !strcmp(mimetype, "x-special/mate-copied-files" ); + if (fileTransferPayload(transfer, mimetype, &payload, &size) && clipboardFileWriteStart(fd, payload, size, transfer, deliversUri)) @@ -1538,6 +1546,9 @@ static bool waylandCBPublish(LG_ClipboardData type) !clipboardFiles_getRemotePresentation(transfer->filePresentation, "x-special/gnome-copied-files", &transfer->fileGnome, &transfer->fileGnomeSize) || + !clipboardFiles_getRemotePresentation(transfer->filePresentation, + "x-special/mate-copied-files", + &transfer->fileGnome, &transfer->fileGnomeSize) || !clipboardFiles_getRemotePresentation(transfer->filePresentation, "application/x-kde-cutselection", &transfer->fileKde, &transfer->fileKdeSize))) diff --git a/client/displayservers/X11/clipboard.c b/client/displayservers/X11/clipboard.c index 7a89eed2..207882e4 100644 --- a/client/displayservers/X11/clipboard.c +++ b/client/displayservers/X11/clipboard.c @@ -92,6 +92,7 @@ struct X11ClipboardState Atom aCurSelection; Atom aTypes[LG_CLIPBOARD_DATA_NONE]; Atom aFileGnome; + Atom aFileMate; Atom aFileKde; Window targetsWindow; LG_ClipboardData type; @@ -114,8 +115,9 @@ static const char * atomTypes[] = }; static const char fileGnomeMime[] = "x-special/gnome-copied-files"; -static const char fileKdeMime[] = "application/x-kde-cutselection"; -static const char fileUriMime[] = "text/uri-list"; +static const char fileMateMime [] = "x-special/mate-copied-files"; +static const char fileKdeMime [] = "application/x-kde-cutselection"; +static const char fileUriMime [] = "text/uri-list"; static struct X11ClipboardState x11cb; @@ -143,6 +145,8 @@ static const char * fileMimeForAtom(Atom atom) return fileUriMime; if (atom == x11cb.aFileGnome) return fileGnomeMime; + if (atom == x11cb.aFileMate) + return fileMateMime; if (atom == x11cb.aFileKde) return fileKdeMime; return NULL; @@ -285,9 +289,12 @@ bool x11CBInit(void) } x11cb.aFileGnome = XInternAtom(x11.display, fileGnomeMime, False); - x11cb.aFileKde = XInternAtom(x11.display, fileKdeMime, False); - if (x11cb.aFileGnome == BadAlloc || x11cb.aFileGnome == BadValue || - x11cb.aFileKde == BadAlloc || x11cb.aFileKde == BadValue) + x11cb.aFileMate = XInternAtom(x11.display, fileMateMime , False); + x11cb.aFileKde = XInternAtom(x11.display, fileKdeMime , False); + if ( + x11cb.aFileGnome == BadAlloc || x11cb.aFileGnome == BadValue || + x11cb.aFileMate == BadAlloc || x11cb.aFileMate == BadValue || + x11cb.aFileKde == BadAlloc || x11cb.aFileKde == BadValue) { DEBUG_ERROR("failed to get clipboard file atoms"); return false; @@ -480,13 +487,14 @@ static void x11CBSelectionRequest(const XSelectionRequestEvent e) // target list requested if (e.target == x11atoms.TARGETS) { - Atom targets[4]; + Atom targets[5]; targets[0] = x11atoms.TARGETS; targets[1] = x11cb.aTypes[requestType]; int count = 2; if (requestType == LG_CLIPBOARD_DATA_FILES) { targets[count++] = x11cb.aFileGnome; + targets[count++] = x11cb.aFileMate; targets[count++] = x11cb.aFileKde; } @@ -1406,11 +1414,19 @@ static void x11CBSelectionNotify(const XSelectionEvent e) const Atom * targets = (const Atom *)data; Atom fileTarget = None; for (unsigned long i = 0; i < itemCount; ++i) + { if (targets[i] == x11cb.aFileGnome) { fileTarget = x11cb.aFileGnome; break; } + + if (targets[i] == x11cb.aFileMate) + { + fileTarget = x11cb.aFileMate; + break; + } + } if (fileTarget == None) for (unsigned long i = 0; i < itemCount; ++i) if (targets[i] == x11cb.aTypes[LG_CLIPBOARD_DATA_FILES]) diff --git a/client/src/clipboard_files.c b/client/src/clipboard_files.c index a4f98c17..941b2135 100644 --- a/client/src/clipboard_files.c +++ b/client/src/clipboard_files.c @@ -59,6 +59,7 @@ #define FILE_DELIVERY_GRACE_MAX 4U #define FILE_URI_PREFIX "file://" #define FILE_GNOME_MIME "x-special/gnome-copied-files" +#define FILE_MATE_MIME "x-special/mate-copied-files" #define FILE_URI_MIME "text/uri-list" #define FILE_KDE_CUT_MIME "application/x-kde-cutselection" @@ -2022,12 +2023,19 @@ static struct LocalNode * addLocalNode(struct LocalDataset * dataset, bool clipboardFiles_setLocal(const char * mime, const void * data, size_t size) { - if (!mime || (!data && size) || - (strcmp(mime, FILE_URI_MIME) && strcmp(mime, FILE_GNOME_MIME))) + if (!mime || (!data && size)) return false; + + const bool gnome_or_mate = + !strcmp(mime, FILE_GNOME_MIME) || + !strcmp(mime, FILE_MATE_MIME ); + + if (strcmp(mime, FILE_URI_MIME) && !gnome_or_mate) + return false; + const char * text = data; size_t offset = 0; - if (!strcmp(mime, FILE_GNOME_MIME)) + if (gnome_or_mate) { const char * newline = size ? memchr(text, '\n', size) : NULL; if (!newline) @@ -2158,14 +2166,18 @@ static bool getRemoteDatasetNL(struct RemoteDataset * dataset, *size = *data ? 1U : 0U; return *data != NULL; } - if (strcmp(mime, FILE_URI_MIME) && strcmp(mime, FILE_GNOME_MIME)) + + const bool gnome_or_mate = + !strcmp(mime, FILE_GNOME_MIME) || + !strcmp(mime, FILE_MATE_MIME ); + + if (strcmp(mime, FILE_URI_MIME) && !gnome_or_mate) return false; - const bool gnome = !strcmp(mime, FILE_GNOME_MIME); char * result = NULL; size_t used = 0; size_t capacity = 0; - if (gnome) + if (gnome_or_mate) { if (!grow((void **)&result, &capacity, 5U)) return false; @@ -2195,7 +2207,7 @@ static bool getRemoteDatasetNL(struct RemoteDataset * dataset, goto error; } - if (gnome) + if (gnome_or_mate) used += (size_t)snprintf(result + used, capacity - used, "\n" FILE_URI_PREFIX "%s", encoded); else