From f2b365008398396d60a97069edce2f19b6628a9c Mon Sep 17 00:00:00 2001 From: Narcis Beleuzu Date: Wed, 23 Dec 2020 12:50:06 +0200 Subject: [PATCH] Backed out changeset e8c18967320c (bug 1631061) for causing Bug 1683989 --- widget/gtk/nsClipboardWayland.cpp | 84 ++++++++++++++++++++++++------- widget/gtk/nsClipboardWayland.h | 6 +++ 2 files changed, 72 insertions(+), 18 deletions(-) diff --git a/widget/gtk/nsClipboardWayland.cpp b/widget/gtk/nsClipboardWayland.cpp index 91e177de0a57..f8e1031e9eea 100644 --- a/widget/gtk/nsClipboardWayland.cpp +++ b/widget/gtk/nsClipboardWayland.cpp @@ -749,6 +749,7 @@ nsRetrievalContextWayland::nsRetrievalContextWayland(void) mClipboardOffer(nullptr), mPrimaryOffer(nullptr), mDragContext(nullptr), + mClipboardRequestNumber(0), mClipboardData(nullptr), mClipboardDataLength(0) { wl_data_device* dataDevice = wl_data_device_manager_get_data_device( @@ -806,6 +807,42 @@ GdkAtom* nsRetrievalContextWayland::GetTargets(int32_t aWhichClipboard, return nullptr; } +struct FastTrackClipboard { + FastTrackClipboard(int aClipboardRequestNumber, + nsRetrievalContextWayland* aRetrievalContex) + : mClipboardRequestNumber(aClipboardRequestNumber), + mRetrievalContex(aRetrievalContex) {} + + int mClipboardRequestNumber; + nsRetrievalContextWayland* mRetrievalContex; +}; + +static void wayland_clipboard_contents_received( + GtkClipboard* clipboard, GtkSelectionData* selection_data, gpointer data) { + LOGCLIP(("wayland_clipboard_contents_received() callback\n")); + FastTrackClipboard* fastTrack = static_cast(data); + fastTrack->mRetrievalContex->TransferFastTrackClipboard( + fastTrack->mClipboardRequestNumber, selection_data); + delete fastTrack; +} + +void nsRetrievalContextWayland::TransferFastTrackClipboard( + int aClipboardRequestNumber, GtkSelectionData* aSelectionData) { + if (mClipboardRequestNumber == aClipboardRequestNumber) { + int dataLength = gtk_selection_data_get_length(aSelectionData); + if (dataLength > 0) { + mClipboardDataLength = dataLength; + mClipboardData = reinterpret_cast( + g_malloc(sizeof(char) * (mClipboardDataLength + 1))); + memcpy(mClipboardData, gtk_selection_data_get_data(aSelectionData), + sizeof(char) * mClipboardDataLength); + mClipboardData[mClipboardDataLength] = '\0'; + } + } else { + NS_WARNING("Received obsoleted clipboard data!"); + } +} + const char* nsRetrievalContextWayland::GetClipboardData( const char* aMimeType, int32_t aWhichClipboard, uint32_t* aContentLength) { NS_ASSERTION(mClipboardData == nullptr && mClipboardDataLength == 0, @@ -814,20 +851,33 @@ const char* nsRetrievalContextWayland::GetClipboardData( LOGCLIP(("nsRetrievalContextWayland::GetClipboardData [%p] mime %s\n", this, aMimeType)); - const auto& dataOffer = - (GetSelectionAtom(aWhichClipboard) == GDK_SELECTION_PRIMARY) - ? mPrimaryOffer - : mClipboardOffer; - if (!dataOffer) { - // Something went wrong. We're requested to provide clipboard data - // but we haven't got any from wayland. - NS_WARNING("Requested data without valid DataOffer!"); - if (mClipboardData) { - ReleaseClipboardData(mClipboardData); - } + /* If actual clipboard data is owned by us we don't need to go + * through Wayland but we ask Gtk+ to directly call data + * getter callback nsClipboard::SelectionGetEvent(). + * see gtk_selection_convert() at gtk+/gtkselection.c. + */ + GdkAtom selection = GetSelectionAtom(aWhichClipboard); + if (gdk_selection_owner_get(selection)) { + LOGCLIP((" Internal clipboard content\n")); + mClipboardRequestNumber++; + gtk_clipboard_request_contents( + gtk_clipboard_get(selection), gdk_atom_intern(aMimeType, FALSE), + wayland_clipboard_contents_received, + new FastTrackClipboard(mClipboardRequestNumber, this)); } else { - mClipboardData = dataOffer->GetData(mDisplay->GetDisplay(), aMimeType, - &mClipboardDataLength); + LOGCLIP((" Remote clipboard content\n")); + const auto& dataOffer = + (selection == GDK_SELECTION_PRIMARY) ? mPrimaryOffer : mClipboardOffer; + if (!dataOffer) { + // Something went wrong. We're requested to provide clipboard data + // but we haven't got any from wayland. + NS_WARNING("Requested data without valid DataOffer!"); + mClipboardData = nullptr; + mClipboardDataLength = 0; + } else { + mClipboardData = dataOffer->GetData(mDisplay->GetDisplay(), aMimeType, + &mClipboardDataLength); + } } *aContentLength = mClipboardDataLength; @@ -858,10 +908,8 @@ void nsRetrievalContextWayland::ReleaseClipboardData( NS_ASSERTION(aClipboardData == mClipboardData, "Releasing unknown clipboard data!"); + g_free((void*)aClipboardData); - if (mClipboardData) { - g_free((void*)aClipboardData); - mClipboardData = nullptr; - mClipboardDataLength = 0; - } + mClipboardData = nullptr; + mClipboardDataLength = 0; } diff --git a/widget/gtk/nsClipboardWayland.h b/widget/gtk/nsClipboardWayland.h index f9b857fea5e9..ddf5d40dc6dc 100644 --- a/widget/gtk/nsClipboardWayland.h +++ b/widget/gtk/nsClipboardWayland.h @@ -16,6 +16,8 @@ #include "nsClipboard.h" #include "nsWaylandDisplay.h" +struct FastTrackClipboard; + class DataOffer { public: void AddMIMEType(const char* aMimeType); @@ -132,6 +134,9 @@ class nsRetrievalContextWayland : public nsRetrievalContext { void ClearDragAndDropDataOffer(); + void TransferFastTrackClipboard(int aClipboardRequestNumber, + GtkSelectionData* aSelectionData); + virtual ~nsRetrievalContextWayland() override; private: @@ -144,6 +149,7 @@ class nsRetrievalContextWayland : public nsRetrievalContext { mozilla::UniquePtr mPrimaryOffer; RefPtr mDragContext; + int mClipboardRequestNumber; char* mClipboardData; uint32_t mClipboardDataLength;