Resolves: rhbz#1350478 better wayland c-n-p selection loss detection

f41
Caolán McNamara 9 years ago
parent 3735f9fb51
commit 4b3e37c749

@ -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?= <caolanm@redhat.com>
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 <caolanm@redhat.com>
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<css::datatransfer::XTransferable> m_aContents;
+ Reference<css::datatransfer::XTransferable> m_aOurContents;
+ Reference<css::datatransfer::XTransferable> m_aSystemContents;
gulong m_nOwnerChangedSignalId;
Reference<css::datatransfer::XTransferable> m_aContents;
Reference<css::datatransfer::clipboard::XClipboardOwner> m_aOwner;
std::list< Reference<css::datatransfer::clipboard::XClipboardListener> > m_aListeners;
std::vector<GtkTargetEntry> 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<css::datatransfer::XTransferable>(),
- Reference<css::datatransfer::clipboard::XClipboardOwner>());
- }
+ 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<VclGtkClipboard*>(user_data_or_owner);
pThis->ClipboardClear(clipboard);
}
-
- void handle_owner_change(GtkClipboard *clipboard, GdkEvent *event, gpointer user_data)
- {
- VclGtkClipboard* pThis = static_cast<VclGtkClipboard*>(user_data);
void handle_owner_change(GtkClipboard *clipboard, GdkEvent *event, gpointer user_data)
{
VclGtkClipboard* pThis = static_cast<VclGtkClipboard*>(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<css::datatransfer::DataFlavor> aFormats = xTrans->getTransferDataFlavors();
@@ -599,15 +600,16 @@ void VclGtkClipboard::setContents(
std::vector<GtkTargetEntry> 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

Loading…
Cancel
Save