[client] clipboard: add support for Caja

This commit is contained in:
Geoffrey McRae
2026-08-15 20:29:08 +10:00
parent 946e0f4945
commit 52d9ab10a0
3 changed files with 57 additions and 18 deletions

View File

@@ -79,6 +79,7 @@ static const char * jpegMimetypes[] =
static const char * fileMimetypes[] = static const char * fileMimetypes[] =
{ {
"x-special/gnome-copied-files", "x-special/gnome-copied-files",
"x-special/mate-copied-files",
"text/uri-list", "text/uri-list",
"application/x-kde-cutselection", "application/x-kde-cutselection",
NULL, NULL,
@@ -153,6 +154,7 @@ static bool isTextMimetype(const char * mimetype)
static enum LG_ClipboardData mimetypeToCbType(const char * mimetype) static enum LG_ClipboardData mimetypeToCbType(const char * mimetype)
{ {
if (!strcmp(mimetype, "x-special/gnome-copied-files") || if (!strcmp(mimetype, "x-special/gnome-copied-files") ||
!strcmp(mimetype, "x-special/mate-copied-files" ) ||
!strcmp(mimetype, "text/uri-list")) !strcmp(mimetype, "text/uri-list"))
return LG_CLIPBOARD_DATA_FILES; 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 || if (type != LG_CLIPBOARD_DATA_FILES ||
strcmp(mimetype, "x-special/gnome-copied-files") || strcmp(mimetype, "x-special/gnome-copied-files") ||
!strcmp(data->mimetypes[type], strcmp(mimetype, "x-special/mate-copied-files") ||
"x-special/gnome-copied-files")) !strcmp(data->mimetypes[type], "x-special/gnome-copied-files") ||
!strcmp(data->mimetypes[type], "x-special/mate-copied-files"))
return; return;
free(data->mimetypes[type]); free(data->mimetypes[type]);
} }
@@ -1295,7 +1298,9 @@ static bool fileTransferPayload(const struct WCBTransfer * transfer,
*data = transfer->fileUri; *data = transfer->fileUri;
*size = transfer->fileUriSize; *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; *data = transfer->fileGnome;
*size = transfer->fileGnomeSize; *size = transfer->fileGnomeSize;
@@ -1409,8 +1414,11 @@ static void dataSourceHandleSend(void * data, struct wl_data_source * source,
{ {
const char * payload; const char * payload;
size_t size; size_t size;
const bool deliversUri = !strcmp(mimetype, "text/uri-list") || const bool deliversUri =
!strcmp(mimetype, "x-special/gnome-copied-files"); !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) && if (fileTransferPayload(transfer, mimetype, &payload, &size) &&
clipboardFileWriteStart(fd, payload, size, clipboardFileWriteStart(fd, payload, size,
transfer, deliversUri)) transfer, deliversUri))
@@ -1538,6 +1546,9 @@ static bool waylandCBPublish(LG_ClipboardData type)
!clipboardFiles_getRemotePresentation(transfer->filePresentation, !clipboardFiles_getRemotePresentation(transfer->filePresentation,
"x-special/gnome-copied-files", "x-special/gnome-copied-files",
&transfer->fileGnome, &transfer->fileGnomeSize) || &transfer->fileGnome, &transfer->fileGnomeSize) ||
!clipboardFiles_getRemotePresentation(transfer->filePresentation,
"x-special/mate-copied-files",
&transfer->fileGnome, &transfer->fileGnomeSize) ||
!clipboardFiles_getRemotePresentation(transfer->filePresentation, !clipboardFiles_getRemotePresentation(transfer->filePresentation,
"application/x-kde-cutselection", "application/x-kde-cutselection",
&transfer->fileKde, &transfer->fileKdeSize))) &transfer->fileKde, &transfer->fileKdeSize)))

View File

@@ -92,6 +92,7 @@ struct X11ClipboardState
Atom aCurSelection; Atom aCurSelection;
Atom aTypes[LG_CLIPBOARD_DATA_NONE]; Atom aTypes[LG_CLIPBOARD_DATA_NONE];
Atom aFileGnome; Atom aFileGnome;
Atom aFileMate;
Atom aFileKde; Atom aFileKde;
Window targetsWindow; Window targetsWindow;
LG_ClipboardData type; LG_ClipboardData type;
@@ -114,8 +115,9 @@ static const char * atomTypes[] =
}; };
static const char fileGnomeMime[] = "x-special/gnome-copied-files"; static const char fileGnomeMime[] = "x-special/gnome-copied-files";
static const char fileKdeMime[] = "application/x-kde-cutselection"; static const char fileMateMime [] = "x-special/mate-copied-files";
static const char fileUriMime[] = "text/uri-list"; static const char fileKdeMime [] = "application/x-kde-cutselection";
static const char fileUriMime [] = "text/uri-list";
static struct X11ClipboardState x11cb; static struct X11ClipboardState x11cb;
@@ -143,6 +145,8 @@ static const char * fileMimeForAtom(Atom atom)
return fileUriMime; return fileUriMime;
if (atom == x11cb.aFileGnome) if (atom == x11cb.aFileGnome)
return fileGnomeMime; return fileGnomeMime;
if (atom == x11cb.aFileMate)
return fileMateMime;
if (atom == x11cb.aFileKde) if (atom == x11cb.aFileKde)
return fileKdeMime; return fileKdeMime;
return NULL; return NULL;
@@ -285,8 +289,11 @@ bool x11CBInit(void)
} }
x11cb.aFileGnome = XInternAtom(x11.display, fileGnomeMime, False); x11cb.aFileGnome = XInternAtom(x11.display, fileGnomeMime, False);
x11cb.aFileKde = XInternAtom(x11.display, fileKdeMime, False); x11cb.aFileMate = XInternAtom(x11.display, fileMateMime , False);
if (x11cb.aFileGnome == BadAlloc || x11cb.aFileGnome == BadValue || 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) x11cb.aFileKde == BadAlloc || x11cb.aFileKde == BadValue)
{ {
DEBUG_ERROR("failed to get clipboard file atoms"); DEBUG_ERROR("failed to get clipboard file atoms");
@@ -480,13 +487,14 @@ static void x11CBSelectionRequest(const XSelectionRequestEvent e)
// target list requested // target list requested
if (e.target == x11atoms.TARGETS) if (e.target == x11atoms.TARGETS)
{ {
Atom targets[4]; Atom targets[5];
targets[0] = x11atoms.TARGETS; targets[0] = x11atoms.TARGETS;
targets[1] = x11cb.aTypes[requestType]; targets[1] = x11cb.aTypes[requestType];
int count = 2; int count = 2;
if (requestType == LG_CLIPBOARD_DATA_FILES) if (requestType == LG_CLIPBOARD_DATA_FILES)
{ {
targets[count++] = x11cb.aFileGnome; targets[count++] = x11cb.aFileGnome;
targets[count++] = x11cb.aFileMate;
targets[count++] = x11cb.aFileKde; targets[count++] = x11cb.aFileKde;
} }
@@ -1406,11 +1414,19 @@ static void x11CBSelectionNotify(const XSelectionEvent e)
const Atom * targets = (const Atom *)data; const Atom * targets = (const Atom *)data;
Atom fileTarget = None; Atom fileTarget = None;
for (unsigned long i = 0; i < itemCount; ++i) for (unsigned long i = 0; i < itemCount; ++i)
{
if (targets[i] == x11cb.aFileGnome) if (targets[i] == x11cb.aFileGnome)
{ {
fileTarget = x11cb.aFileGnome; fileTarget = x11cb.aFileGnome;
break; break;
} }
if (targets[i] == x11cb.aFileMate)
{
fileTarget = x11cb.aFileMate;
break;
}
}
if (fileTarget == None) if (fileTarget == None)
for (unsigned long i = 0; i < itemCount; ++i) for (unsigned long i = 0; i < itemCount; ++i)
if (targets[i] == x11cb.aTypes[LG_CLIPBOARD_DATA_FILES]) if (targets[i] == x11cb.aTypes[LG_CLIPBOARD_DATA_FILES])

View File

@@ -59,6 +59,7 @@
#define FILE_DELIVERY_GRACE_MAX 4U #define FILE_DELIVERY_GRACE_MAX 4U
#define FILE_URI_PREFIX "file://" #define FILE_URI_PREFIX "file://"
#define FILE_GNOME_MIME "x-special/gnome-copied-files" #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_URI_MIME "text/uri-list"
#define FILE_KDE_CUT_MIME "application/x-kde-cutselection" #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, bool clipboardFiles_setLocal(const char * mime,
const void * data, size_t size) const void * data, size_t size)
{ {
if (!mime || (!data && size) || if (!mime || (!data && size))
(strcmp(mime, FILE_URI_MIME) && strcmp(mime, FILE_GNOME_MIME)))
return false; 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; const char * text = data;
size_t offset = 0; size_t offset = 0;
if (!strcmp(mime, FILE_GNOME_MIME)) if (gnome_or_mate)
{ {
const char * newline = size ? memchr(text, '\n', size) : NULL; const char * newline = size ? memchr(text, '\n', size) : NULL;
if (!newline) if (!newline)
@@ -2158,14 +2166,18 @@ static bool getRemoteDatasetNL(struct RemoteDataset * dataset,
*size = *data ? 1U : 0U; *size = *data ? 1U : 0U;
return *data != NULL; 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; return false;
const bool gnome = !strcmp(mime, FILE_GNOME_MIME);
char * result = NULL; char * result = NULL;
size_t used = 0; size_t used = 0;
size_t capacity = 0; size_t capacity = 0;
if (gnome) if (gnome_or_mate)
{ {
if (!grow((void **)&result, &capacity, 5U)) if (!grow((void **)&result, &capacity, 5U))
return false; return false;
@@ -2195,7 +2207,7 @@ static bool getRemoteDatasetNL(struct RemoteDataset * dataset,
goto error; goto error;
} }
if (gnome) if (gnome_or_mate)
used += (size_t)snprintf(result + used, capacity - used, used += (size_t)snprintf(result + used, capacity - used,
"\n" FILE_URI_PREFIX "%s", encoded); "\n" FILE_URI_PREFIX "%s", encoded);
else else