Skip to content

Commit a60f2db

Browse files
committed
[client,x11] remember available atoms in clipboard
Filter out supported but unavailable formats in x11 clipboard.
1 parent 6ab7018 commit a60f2db

1 file changed

Lines changed: 125 additions & 16 deletions

File tree

‎client/X11/xf_cliprdr.c‎

Lines changed: 125 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ struct xf_clipboard
137137

138138
CliprdrFileContext* file;
139139
BOOL isImageContent;
140+
Atom* clientAvailableFormatAtoms;
141+
size_t clientAvailableFormatAtomsCount;
140142

141143
wLog* log;
142144
};
@@ -380,8 +382,34 @@ static BOOL xf_cliprdr_formats_equal(const CLIPRDR_FORMAT* server, const xfClipr
380382
return FALSE;
381383
}
382384

383-
static const xfCliprdrFormat* xf_cliprdr_get_client_format_by_id(xfClipboard* clipboard,
384-
UINT32 formatId)
385+
WINPR_ATTR_NODISCARD
386+
static BOOL xf_cliprdr_is_atom_available(xfClipboard* clipboard, Atom atom)
387+
{
388+
WINPR_ASSERT(clipboard);
389+
390+
char* name = Safe_XGetAtomName(clipboard->log, clipboard->xfc->display, atom);
391+
for (size_t x = 0; x < clipboard->numClientFormats; x++)
392+
{
393+
WINPR_ASSERT(clipboard->clientAvailableFormatAtoms);
394+
395+
Atom cur = clipboard->clientAvailableFormatAtoms[x];
396+
if (cur == atom)
397+
{
398+
WLog_Print(clipboard->log, WLOG_DEBUG, "Atom [%s] available from local clipboard",
399+
name);
400+
free(name);
401+
return TRUE;
402+
}
403+
}
404+
405+
WLog_Print(clipboard->log, WLOG_DEBUG, "Atom [%s] NOT available from local clipboard", name);
406+
free(name);
407+
return FALSE;
408+
}
409+
410+
WINPR_ATTR_NODISCARD
411+
static const xfCliprdrFormat* xf_cliprdr_get_client_available_format_by_id(xfClipboard* clipboard,
412+
UINT32 formatId)
385413
{
386414
WINPR_ASSERT(clipboard);
387415

@@ -391,6 +419,9 @@ static const xfCliprdrFormat* xf_cliprdr_get_client_format_by_id(xfClipboard* cl
391419
{
392420
const xfCliprdrFormat* format = &(clipboard->clientFormats[index]);
393421

422+
if (!xf_cliprdr_is_atom_available(clipboard, format->atom))
423+
continue;
424+
394425
if (fetchImage && format->isImage)
395426
return format;
396427

@@ -697,7 +728,8 @@ static BOOL xf_cliprdr_should_add_format(const CLIPRDR_FORMAT* formats, size_t c
697728
}
698729

699730
static CLIPRDR_FORMAT* xf_cliprdr_get_formats_from_targets(xfClipboard* clipboard,
700-
UINT32* numFormats)
731+
UINT32* numFormats, Atom** atoms,
732+
size_t* atomsCount)
701733
{
702734
Atom atom = None;
703735
BYTE* data = nullptr;
@@ -713,6 +745,14 @@ static CLIPRDR_FORMAT* xf_cliprdr_get_formats_from_targets(xfClipboard* clipboar
713745
WINPR_ASSERT(xfc);
714746

715747
*numFormats = 0;
748+
if (atomsCount)
749+
*atomsCount = 0;
750+
if (atoms)
751+
{
752+
XFree(*atoms);
753+
*atoms = nullptr;
754+
}
755+
716756
LogDynAndXGetWindowProperty(clipboard->log, xfc->display, xfc->drawable,
717757
clipboard->property_atom, 0, 200, 0, XA_ATOM, &atom,
718758
&format_property, &proplength, &bytes_left, &data);
@@ -788,20 +828,34 @@ static CLIPRDR_FORMAT* xf_cliprdr_get_formats_from_targets(xfClipboard* clipboar
788828
}
789829
out:
790830

791-
if (data)
831+
if (data && !atoms)
792832
XFree(data);
833+
else if (atoms)
834+
{
835+
*atoms = (Atom*)data;
836+
if (atomsCount)
837+
*atomsCount = proplength;
838+
}
793839

794840
return formats;
795841
}
796842

797-
static CLIPRDR_FORMAT* xf_cliprdr_get_client_formats(xfClipboard* clipboard, UINT32* numFormats)
843+
static CLIPRDR_FORMAT* xf_cliprdr_get_client_formats(xfClipboard* clipboard, UINT32* numFormats,
844+
Atom** atoms, size_t* atomsCount)
798845
{
799846
CLIPRDR_FORMAT* formats = nullptr;
800847

801848
WINPR_ASSERT(clipboard);
802849
WINPR_ASSERT(numFormats);
803850

804851
*numFormats = 0;
852+
if (atoms)
853+
{
854+
XFree(*atoms);
855+
*atoms = nullptr;
856+
}
857+
if (atomsCount)
858+
*atomsCount = 0;
805859

806860
if (xf_cliprdr_is_raw_transfer_available(clipboard))
807861
{
@@ -811,7 +865,7 @@ static CLIPRDR_FORMAT* xf_cliprdr_get_client_formats(xfClipboard* clipboard, UIN
811865
if (*numFormats == 0)
812866
{
813867
xf_cliprdr_free_formats(formats, *numFormats);
814-
formats = xf_cliprdr_get_formats_from_targets(clipboard, numFormats);
868+
formats = xf_cliprdr_get_formats_from_targets(clipboard, numFormats, atoms, atomsCount);
815869
}
816870

817871
return formats;
@@ -846,8 +900,40 @@ static void xf_cliprdr_provide_server_format_list(xfClipboard* clipboard)
846900
Stream_Free(formats, TRUE);
847901
}
848902

903+
WINPR_ATTR_MALLOC(free, 1)
904+
static char* atomsToStringList(wLog* log, Display* display, const Atom* atoms, size_t count)
905+
{
906+
WINPR_ASSERT(atoms || (count == 0));
907+
908+
char* str = calloc(1, sizeof(char));
909+
if (!str)
910+
return str;
911+
size_t len = 0;
912+
for (size_t x = 0; x < count; x++)
913+
{
914+
Atom atom = atoms[x];
915+
char* name = Safe_XGetAtomName(log, display, atom);
916+
if (name)
917+
{
918+
char* tmp = nullptr;
919+
if (len > 0)
920+
winpr_asprintf(&tmp, &len, "%s,%s", str, name);
921+
else
922+
{
923+
tmp = name;
924+
name = nullptr;
925+
}
926+
free(str);
927+
str = tmp;
928+
}
929+
winpr_str_append(name, str, len, ",");
930+
free(name);
931+
}
932+
return str;
933+
}
934+
849935
static UINT xf_cliprdr_send_format_list(xfClipboard* clipboard, const CLIPRDR_FORMAT* formats,
850-
UINT32 numFormats)
936+
UINT32 numFormats, Atom* atoms, size_t atomsCount)
851937
{
852938
union
853939
{
@@ -877,6 +963,16 @@ static UINT xf_cliprdr_send_format_list(xfClipboard* clipboard, const CLIPRDR_FO
877963

878964
xf_cliprdr_clear_cached_data(clipboard);
879965

966+
if (WLog_IsLevelActive(clipboard->log, WLOG_DEBUG))
967+
{
968+
char* list = atomsToStringList(clipboard->log, clipboard->xfc->display, atoms, atomsCount);
969+
WLog_Print(clipboard->log, WLOG_DEBUG, "Updating available atoms[%" PRIuz "] : { %s }",
970+
atomsCount, list);
971+
free(list);
972+
}
973+
clipboard->clientAvailableFormatAtoms = atoms;
974+
clipboard->clientAvailableFormatAtomsCount = atomsCount;
975+
880976
ret = cliprdr_file_context_notify_new_client_format_list(clipboard->file);
881977
if (ret)
882978
return ret;
@@ -889,8 +985,11 @@ static UINT xf_cliprdr_send_format_list(xfClipboard* clipboard, const CLIPRDR_FO
889985
static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
890986
{
891987
UINT32 numFormats = 0;
892-
CLIPRDR_FORMAT* formats = xf_cliprdr_get_client_formats(clipboard, &numFormats);
893-
xf_cliprdr_send_format_list(clipboard, formats, numFormats);
988+
Atom* atoms = nullptr;
989+
size_t atomsCount = 0;
990+
CLIPRDR_FORMAT* formats =
991+
xf_cliprdr_get_client_formats(clipboard, &numFormats, &atoms, &atomsCount);
992+
xf_cliprdr_send_format_list(clipboard, formats, numFormats, atoms, atomsCount);
894993
xf_cliprdr_free_formats(formats, numFormats);
895994
}
896995

@@ -913,7 +1012,7 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
9131012
* this ensures on next event that the buffer is not reused. */
9141013
clipboard->incr_data_length = 0;
9151014

916-
format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId);
1015+
format = xf_cliprdr_get_client_available_format_by_id(clipboard, clipboard->requestedFormatId);
9171016

9181017
if (!hasData || !data || !format)
9191018
{
@@ -1050,7 +1149,7 @@ static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target)
10501149
WINPR_ASSERT(xfc);
10511150

10521151
const xfCliprdrFormat* format =
1053-
xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId);
1152+
xf_cliprdr_get_client_available_format_by_id(clipboard, clipboard->requestedFormatId);
10541153

10551154
if (!format || (format->atom != target))
10561155
{
@@ -1293,6 +1392,10 @@ void xf_cliprdr_clear_cached_data(xfClipboard* clipboard)
12931392
HashTable_Clear(clipboard->cachedData);
12941393
HashTable_Clear(clipboard->cachedRawData);
12951394

1395+
XFree(clipboard->clientAvailableFormatAtoms);
1396+
clipboard->clientAvailableFormatAtoms = nullptr;
1397+
clipboard->clientAvailableFormatAtomsCount = 0;
1398+
12961399
cliprdr_file_context_clear(clipboard->file);
12971400

12981401
xf_cliprdr_stop_incr(clipboard);
@@ -1740,7 +1843,8 @@ static BOOL xf_cliprdr_process_property_notify(xfClipboard* clipboard, const XPr
17401843
else if ((xevent->window == xfc->drawable) && (xevent->state == PropertyNewValue) &&
17411844
clipboard->incr_starts)
17421845
{
1743-
format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId);
1846+
format =
1847+
xf_cliprdr_get_client_available_format_by_id(clipboard, clipboard->requestedFormatId);
17441848

17451849
if (format)
17461850
xf_cliprdr_get_requested_data(clipboard, format->atom);
@@ -1860,9 +1964,12 @@ static UINT xf_cliprdr_send_client_format_list(xfClipboard* clipboard)
18601964
WINPR_ASSERT(xfc);
18611965

18621966
UINT32 numFormats = 0;
1863-
CLIPRDR_FORMAT* formats = xf_cliprdr_get_client_formats(clipboard, &numFormats);
1967+
Atom* atoms = nullptr;
1968+
size_t atomsCount = 0;
1969+
CLIPRDR_FORMAT* formats =
1970+
xf_cliprdr_get_client_formats(clipboard, &numFormats, &atoms, &atomsCount);
18641971

1865-
const UINT ret = xf_cliprdr_send_format_list(clipboard, formats, numFormats);
1972+
const UINT ret = xf_cliprdr_send_format_list(clipboard, formats, numFormats, atoms, atomsCount);
18661973

18671974
if (clipboard->owner && clipboard->owner != xfc->drawable)
18681975
{
@@ -2162,13 +2269,13 @@ xf_cliprdr_server_format_data_request(CliprdrClientContext* context,
21622269

21632270
if (rawTransfer)
21642271
{
2165-
format = xf_cliprdr_get_client_format_by_id(clipboard, CF_RAW);
2272+
format = xf_cliprdr_get_client_available_format_by_id(clipboard, CF_RAW);
21662273
LogDynAndXChangeProperty(clipboard->log, xfc->display, xfc->drawable,
21672274
clipboard->property_atom, XA_INTEGER, 32, PropModeReplace,
21682275
(const BYTE*)&formatId, 1);
21692276
}
21702277
else
2171-
format = xf_cliprdr_get_client_format_by_id(clipboard, formatId);
2278+
format = xf_cliprdr_get_client_available_format_by_id(clipboard, formatId);
21722279

21732280
clipboard->requestedFormatId = rawTransfer ? CF_RAW : formatId;
21742281
if (!format)
@@ -2804,6 +2911,8 @@ void xf_clipboard_free(xfClipboard* clipboard)
28042911

28052912
cliprdr_file_context_free(clipboard->file);
28062913

2914+
XFree(clipboard->clientAvailableFormatAtoms);
2915+
28072916
ClipboardDestroy(clipboard->system);
28082917
HashTable_Free(clipboard->cachedRawData);
28092918
HashTable_Free(clipboard->cachedData);

0 commit comments

Comments
 (0)