You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libreoffice/0001-Resolves-rhbz-1326304-...

263 lines
9.9 KiB

9 years ago
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
application takes over the clipboard
The "owner-change" signal doesn't contain any useful data under wayland,
and doesn't fire when you'd expect either, just when the app becomes
active or gets focus or something like that. So you get it when you
do have the clipboard and when you don't, so that's no use either to
detect loss of clipboard ownership
So, forget about clipboard ownership, and always take the data to
be pasted from the system clipboard, so when we are pasting from ourselves
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)
---
9 years ago
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
9 years ago
index ed64ded..8b01166 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
9 years ago
@@ -238,47 +238,6 @@ public:
}
};
-//We want to use gtk_clipboard_get_owner own owner-change to distinguish between
-//us gaining the clipboard ownership vs losing it. To do that we need to use
-//gtk_clipboard_set_with_owner and to do that we need a GObject, so define
-//one here for that purpose and just give it a VclGtkClipboard* member
-class VclGtkClipboard;
-
9 years ago
-struct ClipboardOwner
-{
- GObject parent_instance;
-
- /* instance members */
- VclGtkClipboard* m_pThis;
-};
-
9 years ago
-struct ClipboardOwnerClass
-{
- GObjectClass parent_class;
-
- /* class members */
-};
-
-#define CLIPBOARD_OWNER_OBJECT (clipboard_owner_get_type ())
-#define CLIPBOARD_OWNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLIPBOARD_OWNER_OBJECT, ClipboardOwner))
-
-#ifdef __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-#endif
-G_DEFINE_TYPE(ClipboardOwner, clipboard_owner, G_TYPE_OBJECT);
-#ifdef __GNUC__
-#pragma GCC diagnostic pop
-#endif
-
-static void clipboard_owner_class_init (ClipboardOwnerClass *)
-{
-}
-
-static void clipboard_owner_init(ClipboardOwner *)
-{
-}
-
class VclGtkClipboard :
public cppu::WeakComponentImplHelper<
datatransfer::clipboard::XSystemClipboard,
9 years ago
@@ -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::clipboard::XClipboardOwner> m_aOwner;
9 years ago
@@ -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 )
9 years ago
@@ -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())
+ 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;
}
9 years ago
@@ -388,9 +346,55 @@ void VclGtkClipboard::ClipboardGet(GtkClipboard* /*clipboard*/, GtkSelectionData
m_aConversionHelper.setSelectionData(m_aContents, selection_data, info);
}
-void VclGtkClipboard::OwnerChanged(GtkClipboard* clipboard, GdkEvent* /*event*/)
+namespace
9 years ago
+{
+ 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*/)
9 years ago
{
- 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
9 years ago
@@ -488,20 +492,20 @@ namespace
guint info,
gpointer user_data_or_owner)
{
- VclGtkClipboard* pThis = CLIPBOARD_OWNER(user_data_or_owner)->m_pThis;
+ VclGtkClipboard* pThis = reinterpret_cast<VclGtkClipboard*>(user_data_or_owner);
pThis->ClipboardGet(clipboard, selection_data, info);
}
void ClipboardClearFunc(GtkClipboard *clipboard, gpointer user_data_or_owner)
{
- VclGtkClipboard* pThis = CLIPBOARD_OWNER(user_data_or_owner)->m_pThis;
+ 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);
- pThis->OwnerChanged(clipboard, event);
+ pThis->OwnerPossiblyChanged(clipboard, event);
}
}
9 years ago
@@ -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()
9 years ago
@@ -534,7 +536,6 @@ VclGtkClipboard::~VclGtkClipboard()
{
GtkClipboard* clipboard = gtk_clipboard_get(m_nSelection);
g_signal_handler_disconnect(clipboard, m_nOwnerChangedSignalId);
- g_object_unref(m_pOwner);
ClipboardClear(nullptr);
}
9 years ago
@@ -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
+ 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
- //if we have gained or lost ownership of the clipboard
- gtk_clipboard_set_with_owner(clipboard, aGtkTargets.data(), aGtkTargets.size(),
- ClipboardGetFunc, ClipboardClearFunc, G_OBJECT(m_pOwner));
+ gtk_clipboard_set_with_data(clipboard, aGtkTargets.data(), aGtkTargets.size(),
+ ClipboardGetFunc, ClipboardClearFunc, this);
gtk_clipboard_set_can_store(clipboard, aGtkTargets.data(), aGtkTargets.size());
}
--
2.7.4