191{
192 if (!_ctx || !_sync || ev.owner)
193 {
194 _last_timestamp = ev.timestamp;
195 if (!_current_mimetypes.empty())
196 {
197 _cache_data.clear();
198 auto rc =
199 SDL_SetClipboardData(sdlClip::ClipDataCb, sdlClip::ClipCleanCb, this, ev.mime_types,
200 WINPR_ASSERTING_INT_CAST(size_t, ev.num_mime_types));
201 _current_mimetypes.clear();
202 return rc;
203 }
204 return true;
205 }
206
207 if (ev.timestamp == _last_timestamp)
208 {
209 return true;
210 }
211
212 if (contains(ev.mime_types, ev.num_mime_types))
213 {
214 return true;
215 }
216
217 clearServerFormats();
218
219 const std::string mime_html = s_mime_html;
220
221 const std::vector<std::string> mime_bitmap = { BMP_MIME_LIST };
222 const std::string mime_webp = s_mime_webp;
223 const std::string mime_png = s_mime_png;
224 const std::string mime_jpeg = s_mime_jpg;
225 const std::string mime_tiff = s_mime_tiff;
226 const std::vector<std::string> mime_images = { mime_webp, mime_png, mime_jpeg,
227 mime_tiff, s_mime_avif, s_mime_jxl };
228
229 std::vector<std::string> clientFormatNames;
230 std::vector<CLIPRDR_FORMAT> clientFormats;
231
232 size_t nformats = WINPR_ASSERTING_INT_CAST(size_t, ev.num_mime_types);
233 const char** clipboard_mime_formats = ev.mime_types;
234
235 WLog_Print(_log, WLOG_TRACE, "SDL has %" PRIuz " formats", nformats);
236
237 bool textPushed = false;
238 bool imgPushed = false;
239 bool filePushed = false;
240
241 for (size_t i = 0; i < nformats; i++)
242 {
243 std::string local_mime = clipboard_mime_formats[i];
244 WLog_Print(_log, WLOG_TRACE, " - %s", local_mime.c_str());
245
246 if (std::find(s_mime_text().begin(), s_mime_text().end(), local_mime) !=
247 s_mime_text().end())
248 {
249
250 if (!textPushed)
251 {
252 clientFormats.push_back({ CF_TEXT, nullptr });
253 clientFormats.push_back({ CF_OEMTEXT, nullptr });
254 clientFormats.push_back({ CF_UNICODETEXT, nullptr });
255 textPushed = true;
256 }
257 }
258 else if (local_mime == mime_html)
259
260 clientFormatNames.emplace_back(s_type_HtmlFormat);
261 else if ((std::find(mime_bitmap.begin(), mime_bitmap.end(), local_mime) !=
262 mime_bitmap.end()) ||
263 (std::find(mime_images.begin(), mime_images.end(), local_mime) !=
264 mime_images.end()))
265 {
266
267 if (!imgPushed)
268 {
269 clientFormats.push_back({ CF_DIB, nullptr });
270#if defined(WINPR_UTILS_IMAGE_DIBv5)
271 clientFormats.push_back({ CF_DIBV5, nullptr });
272#endif
273
274 if (winpr_image_format_is_supported(WINPR_IMAGE_BITMAP))
275 {
276 for (auto& bmp : mime_bitmap)
277 clientFormatNames.push_back(bmp);
278 }
279
280 if (winpr_image_format_is_supported(WINPR_IMAGE_JPEG))
281 clientFormatNames.push_back(mime_jpeg);
282 if (winpr_image_format_is_supported(WINPR_IMAGE_WEBP))
283 clientFormatNames.push_back(mime_webp);
284 if (winpr_image_format_is_supported(WINPR_IMAGE_PNG))
285 clientFormatNames.push_back(mime_png);
286
287 clientFormatNames.emplace_back(s_type_HtmlFormat);
288 imgPushed = true;
289 }
290 clientFormatNames.push_back(local_mime);
291 }
292 else if (mime_is_file(local_mime))
293 {
294 if (!filePushed)
295 {
296 clientFormatNames.emplace_back(s_type_FileGroupDescriptorW);
297 filePushed = true;
298 }
299 }
300 }
301
302 std::sort(clientFormatNames.begin(), clientFormatNames.end());
303 clientFormatNames.erase(std::unique(clientFormatNames.begin(), clientFormatNames.end()),
304 clientFormatNames.end());
305
306 for (auto& name : clientFormatNames)
307 {
308 clientFormats.push_back({ ClipboardRegisterFormat(_system, name.c_str()), name.data() });
309 }
310
311 std::sort(clientFormats.begin(), clientFormats.end(),
312 [](const auto& a, const auto& b) { return a < b; });
313 auto u = std::unique(clientFormats.begin(), clientFormats.end());
314 clientFormats.erase(u, clientFormats.end());
315
317 { CB_FORMAT_LIST, 0, 0 },
318 static_cast<UINT32>(clientFormats.size()),
319 clientFormats.data(),
320 };
321
322 WLog_Print(_log, WLOG_TRACE,
323 "-------------- client format list [%" PRIu32 "] ------------------",
324 formatList.numFormats);
325 for (UINT32 x = 0; x < formatList.numFormats; x++)
326 {
327 auto format = &formatList.formats[x];
328 WLog_Print(_log, WLOG_TRACE, "client announces %" PRIu32 " [%s][%s]", format->formatId,
329 ClipboardGetFormatIdString(format->formatId), format->formatName);
330 }
331
332 if (cliprdr_file_context_notify_new_client_format_list(_file) != CHANNEL_RC_OK)
333 return false;
334
335 WINPR_ASSERT(_ctx);
336 WINPR_ASSERT(_ctx->ClientFormatList);
337 return _ctx->ClientFormatList(_ctx, &formatList) == CHANNEL_RC_OK;
338}