diff options
author | Caolán McNamara <caolanm@redhat.com> | 2020-11-05 10:48:30 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2020-11-06 10:40:25 +0100 |
commit | 057be6fd40fa32426a747f032b867be145797c6b (patch) | |
tree | cf4f3ecf812f2074be80605304369982b440d523 /vcl | |
parent | 23cb0b19060d0cdbc91f571f4797d1d07023048f (diff) |
Resolves: tdf#137181 set the clipboard asynchronously
because apparently hitting the wayland compositor repeatedly with
clipboard changes without a chance of reply triggers a "Lost connection
to Wayland compositor" failure, so make it happen on the next
event loop and have only one event pending
Related: tdf#137181 factor out the piece that triggers the problem
Change-Id: I24d22e70f5f614fa0c9d3d1672e064d9c57be57e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105340
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkinst.cxx | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index c8e8203cfa3e..828549ebe7d5 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -693,12 +693,14 @@ class VclGtkClipboard : GdkAtom m_nSelection; osl::Mutex m_aMutex; gulong m_nOwnerChangedSignalId; + ImplSVEvent* m_pSetClipboardEvent; Reference<css::datatransfer::XTransferable> m_aContents; Reference<css::datatransfer::clipboard::XClipboardOwner> m_aOwner; std::vector< Reference<css::datatransfer::clipboard::XClipboardListener> > m_aListeners; std::vector<GtkTargetEntry> m_aGtkTargets; VclToGtkHelper m_aConversionHelper; + DECL_LINK(AsyncSetGtkClipboard, void*, void); public: explicit VclGtkClipboard(GdkAtom nSelection); @@ -747,6 +749,7 @@ public: void ClipboardGet(GtkSelectionData *selection_data, guint info); void ClipboardClear(); void OwnerPossiblyChanged(GtkClipboard *clipboard); + void SetGtkClipboard(); }; } @@ -878,6 +881,11 @@ void VclGtkClipboard::OwnerPossiblyChanged(GtkClipboard* clipboard) void VclGtkClipboard::ClipboardClear() { + if (m_pSetClipboardEvent) + { + Application::RemoveUserEvent(m_pSetClipboardEvent); + m_pSetClipboardEvent = nullptr; + } for (auto &a : m_aGtkTargets) g_free(a.target); m_aGtkTargets.clear(); @@ -964,6 +972,7 @@ VclGtkClipboard::VclGtkClipboard(GdkAtom nSelection) datatransfer::clipboard::XFlushableClipboard, XServiceInfo> (m_aMutex) , m_nSelection(nSelection) + , m_pSetClipboardEvent(nullptr) { GtkClipboard* clipboard = gtk_clipboard_get(m_nSelection); m_nOwnerChangedSignalId = g_signal_connect(clipboard, "owner-change", @@ -990,6 +999,7 @@ VclGtkClipboard::~VclGtkClipboard() gtk_clipboard_clear(clipboard); ClipboardClear(); } + assert(!m_pSetClipboardEvent); assert(m_aGtkTargets.empty()); } @@ -1032,6 +1042,21 @@ std::vector<GtkTargetEntry> VclToGtkHelper::FormatsToGtk(const css::uno::Sequenc return aGtkTargets; } +IMPL_LINK_NOARG(VclGtkClipboard, AsyncSetGtkClipboard, void*, void) +{ + osl::ClearableMutexGuard aGuard( m_aMutex ); + m_pSetClipboardEvent = nullptr; + SetGtkClipboard(); +} + +void VclGtkClipboard::SetGtkClipboard() +{ + GtkClipboard* clipboard = gtk_clipboard_get(m_nSelection); + gtk_clipboard_set_with_data(clipboard, m_aGtkTargets.data(), m_aGtkTargets.size(), + ClipboardGetFunc, ClipboardClearFunc, this); + gtk_clipboard_set_can_store(clipboard, m_aGtkTargets.data(), m_aGtkTargets.size()); +} + void VclGtkClipboard::setContents( const Reference< css::datatransfer::XTransferable >& xTrans, const Reference< css::datatransfer::clipboard::XClipboardOwner >& xClipboardOwner ) @@ -1070,12 +1095,11 @@ void VclGtkClipboard::setContents( aEntry.info = 0; aGtkTargets.push_back(aEntry); - gtk_clipboard_set_with_data(clipboard, aGtkTargets.data(), aGtkTargets.size(), - ClipboardGetFunc, ClipboardClearFunc, this); - gtk_clipboard_set_can_store(clipboard, aGtkTargets.data(), aGtkTargets.size()); - } + m_aGtkTargets = aGtkTargets; - m_aGtkTargets = aGtkTargets; + if (!m_pSetClipboardEvent) + m_pSetClipboardEvent = Application::PostUserEvent(LINK(this, VclGtkClipboard, AsyncSetGtkClipboard)); + } } aEv.Contents = getContents(); |