diff --git a/client/displayservers/Wayland/clipboard.c b/client/displayservers/Wayland/clipboard.c index 46079c36..c0bbbed3 100644 --- a/client/displayservers/Wayland/clipboard.c +++ b/client/displayservers/Wayland/clipboard.c @@ -210,6 +210,17 @@ static bool hasImageMimetype(char ** mimetypes) return false; } +static size_t getRepresentationTypes(char * const mimetypes[], + LG_ClipboardData types[]) +{ + size_t count = 0; + for (enum LG_ClipboardData type = 0; + type < LG_CLIPBOARD_DATA_NONE; ++type) + if (type != LG_CLIPBOARD_DATA_FILES && mimetypes[type]) + types[count++] = type; + return count; +} + enum ClipboardInvalidateMode { CLIPBOARD_INVALIDATE_CONDITIONAL, @@ -307,8 +318,10 @@ static void fileImportCleanup(void * opaque) static void fileImportCallback(uint32_t events, void * opaque) { struct ClipboardFileImport * import = opaque; - bool complete = false; - bool failed = (events & EPOLLERR) != 0; + LG_ClipboardData types[LG_CLIPBOARD_DATA_NONE]; + size_t typeCount = 0; + bool complete = false; + bool failed = (events & EPOLLERR) != 0; while (!failed) { if (import->size > SIZE_MAX - 4096U) @@ -337,6 +350,8 @@ static void fileImportCallback(uint32_t events, void * opaque) LG_LOCK(wlCb.lock); const bool current = wlCb.fileImport == import && wlCb.offer == import->offer; + if (current) + typeCount = getRepresentationTypes(wlCb.mimetypes, types); if (wlCb.fileImport == import) wlCb.fileImport = NULL; LG_UNLOCK(wlCb.lock); @@ -345,7 +360,7 @@ static void fileImportCallback(uint32_t events, void * opaque) import->data, import->size))) { clipboardFiles_clearLocal(); - clipboard_release(); + clipboard_notifyTypes(types, typeCount); } if (current) waylandPollUnregister(import->fd); @@ -516,11 +531,9 @@ static void dataDeviceHandleSelection(void * opaque, return; } - size_t idx = 0; enum LG_ClipboardData types[LG_CLIPBOARD_DATA_NONE]; - for (enum LG_ClipboardData i = 0; i < LG_CLIPBOARD_DATA_NONE; ++i) - if (extra->mimetypes[i]) - types[idx++] = i; + const size_t typeCount = + getRepresentationTypes(extra->mimetypes, types); char * oldMimetypes[LG_CLIPBOARD_DATA_NONE]; LG_LOCK(wlCb.lock); @@ -555,11 +568,11 @@ static void dataDeviceHandleSelection(void * opaque, if (!fileImportStart(offer, wlCb.mimetypes[LG_CLIPBOARD_DATA_FILES])) { clipboardFiles_clearLocal(); - clipboard_release(); + clipboard_notifyTypes(types, typeCount); } } else - clipboard_notifyTypes(types, idx); + clipboard_notifyTypes(types, typeCount); } static void dataDeviceHandleEnter(void * data, struct wl_data_device * device, diff --git a/client/displayservers/X11/clipboard.c b/client/displayservers/X11/clipboard.c index 207882e4..5e2a777b 100644 --- a/client/displayservers/X11/clipboard.c +++ b/client/displayservers/X11/clipboard.c @@ -76,14 +76,16 @@ struct X11ClipboardWrite struct X11ClipboardFileImport { - Window window; - Atom target; - const char * mime; - long propertyOffset; - uint8_t * data; - size_t size; - size_t capacity; - bool incremental; + Window window; + Atom target; + const char * mime; + long propertyOffset; + uint8_t * data; + size_t size; + size_t capacity; + bool incremental; + LG_ClipboardData types[LG_CLIPBOARD_DATA_NONE]; + size_t typeCount; }; struct X11ClipboardState @@ -858,7 +860,8 @@ static bool fileImportGrowNL(size_t wanted) return true; } -static bool startFileImport(Atom target) +static bool startFileImport(Atom target, + const LG_ClipboardData types[], size_t typeCount) { const char * mime = fileMimeForAtom(target); if (!mime) @@ -886,6 +889,8 @@ static bool startFileImport(Atom target) .target = target, .mime = mime, }; + memcpy(x11cb.fileImport.types, types, typeCount * sizeof(*types)); + x11cb.fileImport.typeCount = typeCount; XSelectInput(x11.display, window, PropertyChangeMask); XConvertSelection(x11.display, x11cb.aCurSelection, target, x11atoms.SEL_DATA, window, CurrentTime); @@ -900,11 +905,18 @@ static void finishFileImport(struct X11ClipboardFileImport import, if (!clipboardFiles_setLocal(import.mime, data, size)) { clipboardFiles_clearLocal(); - clipboard_release(); + clipboard_notifyTypes(import.types, import.typeCount); } free(import.data); } +static void failFileImport(struct X11ClipboardFileImport import) +{ + free(import.data); + clipboardFiles_clearLocal(); + clipboard_notifyTypes(import.types, import.typeCount); +} + static bool x11CBFileImportSelectionNotify(const XSelectionEvent e) { Atom type; @@ -930,8 +942,7 @@ static bool x11CBFileImportSelectionNotify(const XSelectionEvent e) LG_UNLOCK(x11cb.lock); if (data) XFree(data); - free(failed.data); - clipboard_release(); + failFileImport(failed); return true; } @@ -943,8 +954,7 @@ static bool x11CBFileImportSelectionNotify(const XSelectionEvent e) LG_UNLOCK(x11cb.lock); if (data) XFree(data); - free(failed.data); - clipboard_release(); + failFileImport(failed); return true; } x11cb.fileImport.incremental = true; @@ -960,10 +970,7 @@ static bool x11CBFileImportSelectionNotify(const XSelectionEvent e) if (valid) finishFileImport(import, data, itemCount); else - { - free(import.data); - clipboard_release(); - } + failFileImport(import); if (data) XFree(data); return true; @@ -1000,8 +1007,7 @@ readProperty: LG_UNLOCK(x11cb.lock); if (data) XFree(data); - free(failed.data); - clipboard_release(); + failFileImport(failed); return; } @@ -1026,8 +1032,7 @@ readProperty: { const struct X11ClipboardFileImport failed = takeFileImportNL(); LG_UNLOCK(x11cb.lock); - free(failed.data); - clipboard_release(); + failFileImport(failed); return; } x11cb.fileImport.propertyOffset += (long)units; @@ -1407,11 +1412,23 @@ static void x11CBSelectionNotify(const XSelectionEvent e) goto out; } - size_t typeCount = 0; + size_t typeCount = 0; LG_ClipboardData types[LG_CLIPBOARD_DATA_NONE]; // see if we support any of the targets listed const Atom * targets = (const Atom *)data; + for(int n = 0; n < LG_CLIPBOARD_DATA_NONE; ++n) + { + if (n == LG_CLIPBOARD_DATA_FILES) + continue; + for(unsigned long i = 0; i < itemCount; ++i) + if (x11cb.aTypes[n] == targets[i]) + { + types[typeCount++] = n; + break; + } + } + Atom fileTarget = None; for (unsigned long i = 0; i < itemCount; ++i) { @@ -1438,19 +1455,11 @@ static void x11CBSelectionNotify(const XSelectionEvent e) if (fileTarget != None) { clipboardFiles_clearLocal(); - if (!startFileImport(fileTarget)) - clipboard_release(); + if (!startFileImport(fileTarget, types, typeCount)) + clipboard_notifyTypes(types, typeCount); goto out; } - for(int n = 0; n < LG_CLIPBOARD_DATA_NONE; ++n) - for(unsigned long i = 0; i < itemCount; ++i) - if (x11cb.aTypes[n] == targets[i]) - { - types[typeCount++] = n; - break; - } - clipboard_notifyTypes(types, typeCount); goto out; }