From 4b3e37c749c12650f61d4af92934dc8621701cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= Date: Wed, 29 Jun 2016 14:33:08 +0100 Subject: [PATCH] Resolves: rhbz#1350478 better wayland c-n-p selection loss detection --- ...26304-cannot-detect-loss-of-wayland-.patch | 204 ++++++++++-------- 1 file changed, 120 insertions(+), 84 deletions(-) diff --git a/0001-Resolves-rhbz-1326304-cannot-detect-loss-of-wayland-.patch b/0001-Resolves-rhbz-1326304-cannot-detect-loss-of-wayland-.patch index 3e1bb6e..eefb5f4 100644 --- a/0001-Resolves-rhbz-1326304-cannot-detect-loss-of-wayland-.patch +++ b/0001-Resolves-rhbz-1326304-cannot-detect-loss-of-wayland-.patch @@ -1,8 +1,11 @@ -From 88cd9dd591d7921e5bce33c170b457ae5aa871bb Mon Sep 17 00:00:00 2001 +From 3af38da4f0cb6b6341efad280c73a7733de42bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= Date: Fri, 24 Jun 2016 15:06:36 +0100 Subject: [PATCH] Resolves: rhbz#1326304 cannot detect loss of wayland clipboard ownership +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit gtk_clipboard_get_owner always returns what you set with gtk_clipboard_set_with_owner and that doesn't change if some other @@ -21,12 +24,32 @@ its "paste"->m_aSystemContents->gtk->"copy"->m_aOurContents Undoubtedly something else will break now Change-Id: I32f2e1a2cc3310687f61a094fdfa940fa0cfcc39 + +Resolves: rhbz#1350478 identify that we own the selection with a unique target + +so we can tell that we own the selection in the absence of reliable selection +ownership notifications under wayland + +Note that gnome#768177 means that requests for CLIPBOARD targets after +requests for PRIMARY targets can time out, which is why my attempts at +doing this before giving up with + +commit 88cd9dd591d7921e5bce33c170b457ae5aa871bb +Author: Caolán McNamara +Date: Fri Jun 24 15:06:36 2016 +0100 + + Resolves: rhbz#1326304 cannot detect loss of wayland clipboard ownership + +didn't work. + +Change-Id: I1154899e478b6e0cc6f70aa0c90c26663299072c +(cherry picked from commit 88f7aae022bedd61588424a11bbc033217ba4e43) --- - vcl/unx/gtk3/gtk3gtkinst.cxx | 113 ++++++++----------------------------------- - 1 file changed, 19 insertions(+), 94 deletions(-) + vcl/unx/gtk3/gtk3gtkinst.cxx | 124 ++++++++++++++++++++++--------------------- + 1 file changed, 63 insertions(+), 61 deletions(-) diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx -index ed64ded..262478f 100644 +index ed64ded..8b01166 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -238,47 +238,6 @@ public: @@ -77,66 +100,98 @@ index ed64ded..262478f 100644 class VclGtkClipboard : public cppu::WeakComponentImplHelper< datatransfer::clipboard::XSystemClipboard, -@@ -287,9 +246,8 @@ class VclGtkClipboard : +@@ -287,7 +246,6 @@ class VclGtkClipboard : { GdkAtom m_nSelection; osl::Mutex m_aMutex; - ClipboardOwner* m_pOwner; -- gulong m_nOwnerChangedSignalId; -- Reference m_aContents; -+ Reference m_aOurContents; -+ Reference m_aSystemContents; + gulong m_nOwnerChangedSignalId; + Reference m_aContents; Reference m_aOwner; - std::list< Reference > m_aListeners; - std::vector m_aGtkTargets; -@@ -349,7 +307,6 @@ public: +@@ -349,7 +307,7 @@ public: void ClipboardGet(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info); void ClipboardClear(GtkClipboard *clipboard); - void OwnerChanged(GtkClipboard *clipboard, GdkEvent *event); ++ void OwnerPossiblyChanged(GtkClipboard *clipboard, GdkEvent *event); }; OUString VclGtkClipboard::getImplementationName() throw( RuntimeException, std::exception ) -@@ -370,33 +327,17 @@ sal_Bool VclGtkClipboard::supportsService( const OUString& ServiceName ) throw( +@@ -370,13 +328,13 @@ sal_Bool VclGtkClipboard::supportsService( const OUString& ServiceName ) throw( Reference< css::datatransfer::XTransferable > VclGtkClipboard::getContents() throw( RuntimeException, std::exception ) { - if (G_OBJECT(m_pOwner) != gtk_clipboard_get_owner(gtk_clipboard_get(m_nSelection)) && - !m_aContents.is()) -- { -- //tdf#93887 This is the system clipboard/selection. We fetch it when we are not -- //the owner of the clipboard and have not already fetched it. -- m_aContents = new GtkClipboardTransferable(m_nSelection); -- } -- return m_aContents; -+ if (!m_aSystemContents.is()) -+ m_aSystemContents= new GtkClipboardTransferable(m_nSelection); -+ return m_aSystemContents; ++ if (!m_aContents.is()) + { + //tdf#93887 This is the system clipboard/selection. We fetch it when we are not + //the owner of the clipboard and have not already fetched it. + m_aContents = new GtkClipboardTransferable(m_nSelection); + } ++ + return m_aContents; } - void VclGtkClipboard::ClipboardGet(GtkClipboard* /*clipboard*/, GtkSelectionData *selection_data, - guint info) - { -- if (!m_aContents.is()) -+ if (!m_aOurContents.is()) - return; -- m_aConversionHelper.setSelectionData(m_aContents, selection_data, info); --} -- --void VclGtkClipboard::OwnerChanged(GtkClipboard* clipboard, GdkEvent* /*event*/) --{ -- if (G_OBJECT(m_pOwner) != gtk_clipboard_get_owner(clipboard)) -- { -- //null out m_aContents to return control to the system-one which -- //will be retrieved if getContents is called again -- setContents(Reference(), -- Reference()); -- } -+ m_aConversionHelper.setSelectionData(m_aOurContents, selection_data, info); +@@ -388,9 +346,55 @@ void VclGtkClipboard::ClipboardGet(GtkClipboard* /*clipboard*/, GtkSelectionData + m_aConversionHelper.setSelectionData(m_aContents, selection_data, info); } - void VclGtkClipboard::ClipboardClear(GtkClipboard * /*clipboard*/) -@@ -488,21 +429,15 @@ namespace +-void VclGtkClipboard::OwnerChanged(GtkClipboard* clipboard, GdkEvent* /*event*/) ++namespace ++{ ++ const OString& getPID() ++ { ++ static OString sPID; ++ if (!sPID.getLength()) ++ { ++ oslProcessIdentifier aProcessId = 0; ++ oslProcessInfo info; ++ info.Size = sizeof (oslProcessInfo); ++ if (osl_getProcessInfo(nullptr, osl_Process_IDENTIFIER, &info) == osl_Process_E_None) ++ aProcessId = info.Ident; ++ sPID = OString::number(aProcessId); ++ } ++ return sPID; ++ } ++} ++ ++void VclGtkClipboard::OwnerPossiblyChanged(GtkClipboard* clipboard, GdkEvent* /*event*/) + { +- if (G_OBJECT(m_pOwner) != gtk_clipboard_get_owner(clipboard)) ++ if (!m_aContents.is()) ++ return; ++ ++ //if gdk_display_supports_selection_notification is not supported, e.g. like ++ //right now under wayland, then you only get owner-changed nofications at ++ //opportune times when the selection might have changed. So here ++ //we see if the selection supports a dummy selection type identifying ++ //our pid, in which case it's us. ++ bool bSelf = false; ++ ++ OString sTunnel = "application/x-libreoffice-internal-id-" + getPID(); ++ GdkAtom *targets; ++ gint n_targets; ++ if (gtk_clipboard_wait_for_targets(clipboard, &targets, &n_targets)) ++ { ++ for (gint i = 0; i < n_targets && !bSelf; ++i) ++ { ++ gchar* pName = gdk_atom_name(targets[i]); ++ if (strcmp(pName, sTunnel.getStr()) == 0) ++ { ++ bSelf = true; ++ } ++ g_free(pName); ++ } ++ ++ g_free(targets); ++ } ++ ++ if (!bSelf) + { + //null out m_aContents to return control to the system-one which + //will be retrieved if getContents is called again +@@ -488,20 +492,20 @@ namespace guint info, gpointer user_data_or_owner) { @@ -151,65 +206,46 @@ index ed64ded..262478f 100644 + VclGtkClipboard* pThis = reinterpret_cast(user_data_or_owner); pThis->ClipboardClear(clipboard); } -- -- void handle_owner_change(GtkClipboard *clipboard, GdkEvent *event, gpointer user_data) -- { -- VclGtkClipboard* pThis = static_cast(user_data); + + void handle_owner_change(GtkClipboard *clipboard, GdkEvent *event, gpointer user_data) + { + VclGtkClipboard* pThis = static_cast(user_data); - pThis->OwnerChanged(clipboard, event); -- } ++ pThis->OwnerPossiblyChanged(clipboard, event); + } } - VclGtkClipboard::VclGtkClipboard(GdkAtom nSelection) -@@ -511,11 +446,6 @@ VclGtkClipboard::VclGtkClipboard(GdkAtom nSelection) - (m_aMutex) - , m_nSelection(nSelection) - { -- GtkClipboard* clipboard = gtk_clipboard_get(m_nSelection); -- m_nOwnerChangedSignalId = g_signal_connect(clipboard, "owner-change", -- G_CALLBACK(handle_owner_change), this); +@@ -514,8 +518,6 @@ VclGtkClipboard::VclGtkClipboard(GdkAtom nSelection) + GtkClipboard* clipboard = gtk_clipboard_get(m_nSelection); + m_nOwnerChangedSignalId = g_signal_connect(clipboard, "owner-change", + G_CALLBACK(handle_owner_change), this); - m_pOwner = CLIPBOARD_OWNER(g_object_new(CLIPBOARD_OWNER_OBJECT, nullptr)); - m_pOwner->m_pThis = this; } void VclGtkClipboard::flushClipboard() -@@ -532,9 +462,6 @@ void VclGtkClipboard::flushClipboard() - - VclGtkClipboard::~VclGtkClipboard() +@@ -534,7 +536,6 @@ VclGtkClipboard::~VclGtkClipboard() { -- GtkClipboard* clipboard = gtk_clipboard_get(m_nSelection); -- g_signal_handler_disconnect(clipboard, m_nOwnerChangedSignalId); + GtkClipboard* clipboard = gtk_clipboard_get(m_nSelection); + g_signal_handler_disconnect(clipboard, m_nOwnerChangedSignalId); - g_object_unref(m_pOwner); ClipboardClear(nullptr); } -@@ -586,28 +513,26 @@ void VclGtkClipboard::setContents( - { - osl::ClearableMutexGuard aGuard( m_aMutex ); - Reference< datatransfer::clipboard::XClipboardOwner > xOldOwner( m_aOwner ); -- Reference< datatransfer::XTransferable > xOldContents( m_aContents ); -- m_aContents = xTrans; -+ Reference< datatransfer::XTransferable > xOldContents(m_aOurContents); -+ m_aOurContents = xTrans; - m_aOwner = xClipboardOwner; - - std::list< Reference< datatransfer::clipboard::XClipboardListener > > aListeners( m_aListeners ); - datatransfer::clipboard::ClipboardEvent aEv; - -- if (m_aContents.is()) -+ //if there was a previous gtk_clipboard_set_with_data call then -+ //ClipboardClearFunc will be called now -+ GtkClipboard* clipboard = gtk_clipboard_get(m_nSelection); -+ gtk_clipboard_clear(clipboard); -+ -+ if (m_aOurContents.is()) - { - css::uno::Sequence aFormats = xTrans->getTransferDataFlavors(); +@@ -599,15 +600,16 @@ void VclGtkClipboard::setContents( std::vector aGtkTargets(m_aConversionHelper.FormatsToGtk(aFormats)); if (!aGtkTargets.empty()) { - //if there was a previous gtk_clipboard_set_with_data call then - //ClipboardClearFunc will be called now -- GtkClipboard* clipboard = gtk_clipboard_get(m_nSelection); ++ GtkTargetEntry aEntry; ++ OString sTunnel = "application/x-libreoffice-internal-id-" + getPID(); ++ aEntry.target = g_strdup(sTunnel.getStr()); ++ aEntry.flags = 0; ++ aEntry.info = 0; ++ aGtkTargets.push_back(aEntry); ++ + GtkClipboard* clipboard = gtk_clipboard_get(m_nSelection); - if(G_OBJECT(m_pOwner) == gtk_clipboard_get_owner(clipboard)) - gtk_clipboard_clear(clipboard); - //use with_owner with m_pOwner so we can distinguish in handle_owner_change