@@ -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
699730static 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 }
789829out :
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+
849935static 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
889985static 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