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