From da21ac3792e5a49636df8ef69c00f2392932a21b Mon Sep 17 00:00:00 2001 From: akallabeth Date: Thu, 10 Apr 2025 13:24:51 +0200 Subject: [PATCH] [client,sdl] fix clipboard updates * Ignore updates for our own data (use a special clipboard format to identify these) --- client/SDL/SDL3/sdl_clip.cpp | 31 +++++++++++++++++++++++++++---- client/SDL/SDL3/sdl_clip.hpp | 1 + 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/client/SDL/SDL3/sdl_clip.cpp b/client/SDL/SDL3/sdl_clip.cpp index db4f2b0c8..e77a65aa9 100644 --- a/client/SDL/SDL3/sdl_clip.cpp +++ b/client/SDL/SDL3/sdl_clip.cpp @@ -90,6 +90,8 @@ static const std::vector& s_mime_image() static const char s_mime_gnome_copied_files[] = "x-special/gnome-copied-files"; static const char s_mime_mate_copied_files[] = "x-special/mate-copied-files"; +static const char s_mime_freerdp_update[] = "x-special/freerdp-clipboard-update"; + static const char* s_type_HtmlFormat = "HTML Format"; static const char* s_type_FileGroupDescriptorW = "FileGroupDescriptorW"; @@ -164,12 +166,23 @@ BOOL sdlClip::uninit(CliprdrClientContext* clip) return TRUE; } +static bool contains(const char** mime_types, Sint32 count) +{ + for (Sint32 x = 0; x < count; x++) + { + const auto mime = mime_types[x]; + if (mime && (strcmp(s_mime_freerdp_update, mime) == 0)) + return true; + } + return false; +} + bool sdlClip::handle_update(const SDL_ClipboardEvent& ev) { if (!_ctx || !_sync || ev.owner) { - /* TODO: Hack to identify our own updates */ - if (ev.owner && (ev.reserved == 0x42)) + _last_timestamp = ev.timestamp; + if (!_current_mimetypes.empty()) { _cache_data.clear(); auto rc = @@ -181,6 +194,16 @@ bool sdlClip::handle_update(const SDL_ClipboardEvent& ev) return true; } + if (ev.timestamp == _last_timestamp) + { + return true; + } + + if (contains(ev.mime_types, ev.num_mime_types)) + { + return true; + } + clearServerFormats(); std::string mime_html = s_mime_html; @@ -519,15 +542,15 @@ UINT sdlClip::ReceiveServerFormatList(CliprdrClientContext* context, clipboard->_current_mimetypes.push_back(s_mime_gnome_copied_files); clipboard->_current_mimetypes.push_back(s_mime_mate_copied_files); } + clipboard->_current_mimetypes.push_back(s_mime_freerdp_update); auto s = clipboard->_current_mimetypes.size(); SDL_Event ev = { SDL_EVENT_CLIPBOARD_UPDATE }; ev.clipboard.owner = true; + ev.clipboard.timestamp = SDL_GetTicksNS(); ev.clipboard.num_mime_types = WINPR_ASSERTING_INT_CAST(Sint32, s); ev.clipboard.mime_types = clipboard->_current_mimetypes.data(); - /* TODO: Hack to identify our own updates */ - ev.clipboard.reserved = 0x42; auto rc = (SDL_PushEvent(&ev) == 1); return clipboard->SendFormatListResponse(rc); } diff --git a/client/SDL/SDL3/sdl_clip.hpp b/client/SDL/SDL3/sdl_clip.hpp index 1119c840b..5df648cde 100644 --- a/client/SDL/SDL3/sdl_clip.hpp +++ b/client/SDL/SDL3/sdl_clip.hpp @@ -144,6 +144,7 @@ class sdlClip wClipboard* _system = nullptr; std::atomic _sync = false; HANDLE _event; + Uint64 _last_timestamp = 0; std::vector _serverFormats; CriticalSection _lock;