summaryrefslogtreecommitdiff
path: root/mozilla-1438131.patch
diff options
context:
space:
mode:
Diffstat (limited to 'mozilla-1438131.patch')
-rw-r--r--mozilla-1438131.patch1558
1 files changed, 0 insertions, 1558 deletions
diff --git a/mozilla-1438131.patch b/mozilla-1438131.patch
deleted file mode 100644
index e77186d..0000000
--- a/mozilla-1438131.patch
+++ /dev/null
@@ -1,1558 +0,0 @@
-
-# HG changeset patch
-# User Martin Stransky <stransky@redhat.com>
-# Date 1522937803 -7200
-# Node ID 7e4166e13b3ec513ef3003527df601adf85f654b
-# Parent bf4962739d38ac21ba6ba216fa61f572e7976354
-Bug 1438131 - Implement Drop on Wayland, r=jhorak
-
-This patch implements Drop operation on Wayland/Gtk+. That's because drop operations are part
-of clipboard on Wayland and we use our own paste clipboard handler on Wayland (Bug 1282015).
-
-Wayland drop data are provided by wl_data_device_listener, it provides us drag and drop callbacks
-which we route to nsDragService module.
-
-MozReview-Commit-ID: 9uGYPg9YF6P
-
-diff --git a/widget/gtk/nsClipboardWayland.cpp b/widget/gtk/nsClipboardWayland.cpp
---- a/widget/gtk/nsClipboardWayland.cpp
-+++ b/widget/gtk/nsClipboardWayland.cpp
-@@ -18,16 +18,17 @@
- #include "nsPrimitiveHelpers.h"
- #include "nsIServiceManager.h"
- #include "nsImageToPixbuf.h"
- #include "nsStringStream.h"
- #include "nsIObserverService.h"
- #include "mozilla/Services.h"
- #include "mozilla/RefPtr.h"
- #include "mozilla/TimeStamp.h"
-+#include "nsDragService.h"
-
- #include "imgIContainer.h"
-
- #include <gtk/gtk.h>
- #include <poll.h>
- #include <sys/epoll.h>
- #include <stdlib.h>
- #include <string.h>
-@@ -41,16 +42,54 @@
- const char*
- nsRetrievalContextWayland::sTextMimeTypes[TEXT_MIME_TYPES_NUM] =
- {
- "text/plain;charset=utf-8",
- "UTF8_STRING",
- "COMPOUND_TEXT"
- };
-
-+static inline GdkDragAction
-+wl_to_gdk_actions(uint32_t dnd_actions)
-+{
-+ GdkDragAction actions = GdkDragAction(0);
-+
-+ if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
-+ actions = GdkDragAction(actions|GDK_ACTION_COPY);
-+ if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
-+ actions = GdkDragAction(actions|GDK_ACTION_MOVE);
-+
-+ return actions;
-+}
-+
-+static inline uint32_t
-+gdk_to_wl_actions(GdkDragAction action)
-+{
-+ uint32_t dnd_actions = 0;
-+
-+ if (action & (GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_PRIVATE))
-+ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
-+ if (action & GDK_ACTION_MOVE)
-+ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
-+
-+ return dnd_actions;
-+}
-+
-+static GtkWidget*
-+get_gtk_widget_for_wl_surface(struct wl_surface *surface)
-+{
-+ GdkWindow *gdkParentWindow =
-+ static_cast<GdkWindow*>(wl_surface_get_user_data(surface));
-+
-+ gpointer user_data = nullptr;
-+ gdk_window_get_user_data(gdkParentWindow, &user_data);
-+
-+ return GTK_WIDGET(user_data);
-+}
-+
- void
- DataOffer::AddMIMEType(const char *aMimeType)
- {
- GdkAtom atom = gdk_atom_intern(aMimeType, FALSE);
- mTargetMIMETypes.AppendElement(atom);
- }
-
- GdkAtom*
-@@ -150,44 +189,99 @@ WaylandDataOffer::RequestDataTransfer(co
- if (mWaylandDataOffer) {
- wl_data_offer_receive(mWaylandDataOffer, aMimeType, fd);
- return true;
- }
-
- return false;
- }
-
-+void
-+WaylandDataOffer::DragOfferAccept(const char* aMimeType, uint32_t aTime)
-+{
-+ wl_data_offer_accept(mWaylandDataOffer, aTime, aMimeType);
-+}
-+
-+/* We follow logic of gdk_wayland_drag_context_commit_status()/gdkdnd-wayland.c
-+ * here.
-+ */
-+void
-+WaylandDataOffer::SetDragStatus(GdkDragAction aAction, uint32_t aTime)
-+{
-+ uint32_t dnd_actions = gdk_to_wl_actions(aAction);
-+ uint32_t all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
-+ WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
-+
-+ wl_data_offer_set_actions(mWaylandDataOffer, all_actions, dnd_actions);
-+
-+ /* Workaround Wayland D&D architecture here. To get the data_device_drop()
-+ signal (which routes to nsDragService::GetData() call) we need to
-+ accept at least one mime type before data_device_leave().
-+
-+ Real wl_data_offer_accept() for actualy requested data mime type is
-+ called from nsDragService::GetData().
-+ */
-+ if (mTargetMIMETypes[0]) {
-+ wl_data_offer_accept(mWaylandDataOffer, aTime,
-+ gdk_atom_name(mTargetMIMETypes[0]));
-+ }
-+}
-+
-+void
-+WaylandDataOffer::SetSelectedDragAction(uint32_t aWaylandAction)
-+{
-+ mSelectedDragAction = aWaylandAction;
-+}
-+
-+GdkDragAction
-+WaylandDataOffer::GetSelectedDragAction()
-+{
-+ return wl_to_gdk_actions(mSelectedDragAction);
-+}
-+
- static void
- data_offer_offer (void *data,
- struct wl_data_offer *wl_data_offer,
- const char *type)
- {
- auto *offer = static_cast<DataOffer*>(data);
- offer->AddMIMEType(type);
- }
-
-+/* Advertise all available drag and drop actions from source.
-+ * We don't use that but follow gdk_wayland_drag_context_commit_status()
-+ * from gdkdnd-wayland.c here.
-+ */
- static void
- data_offer_source_actions(void *data,
- struct wl_data_offer *wl_data_offer,
- uint32_t source_actions)
- {
- }
-
-+/* Advertise recently selected drag and drop action by compositor, based
-+ * on source actions and user choice (key modifiers, etc.).
-+ */
- static void
- data_offer_action(void *data,
- struct wl_data_offer *wl_data_offer,
- uint32_t dnd_action)
- {
-+ auto *offer = static_cast<WaylandDataOffer*>(data);
-+ offer->SetSelectedDragAction(dnd_action);
- }
-
- /* wl_data_offer callback description:
- *
- * data_offer_offer - Is called for each MIME type available at wl_data_offer.
-- * data_offer_source_actions - Exposes all available D&D actions.
-- * data_offer_action - Expose one actually selected D&D action.
-+ * data_offer_source_actions - This event indicates the actions offered by
-+ * the data source.
-+ * data_offer_action - This event indicates the action selected by
-+ * the compositor after matching the source/destination
-+ * side actions.
- */
- static const struct wl_data_offer_listener data_offer_listener = {
- data_offer_offer,
- data_offer_source_actions,
- data_offer_action
- };
-
- WaylandDataOffer::WaylandDataOffer(wl_data_offer* aWaylandDataOffer)
-@@ -241,92 +335,203 @@ PrimaryDataOffer::PrimaryDataOffer(gtk_p
-
- PrimaryDataOffer::~PrimaryDataOffer(void)
- {
- if(mPrimaryDataOffer) {
- gtk_primary_selection_offer_destroy(mPrimaryDataOffer);
- }
- }
-
-+NS_IMPL_ISUPPORTS(nsWaylandDragContext, nsISupports);
-+
-+nsWaylandDragContext::nsWaylandDragContext(WaylandDataOffer* aDataOffer,
-+ wl_display *aDisplay)
-+ : mDataOffer(aDataOffer)
-+ , mDisplay(aDisplay)
-+ , mTime(0)
-+ , mGtkWidget(nullptr)
-+ , mX(0)
-+ , mY(0)
-+{
-+}
-+
- void
--nsRetrievalContextWayland::RegisterDataOffer(wl_data_offer *aWaylandDataOffer)
-+nsWaylandDragContext::DropDataEnter(GtkWidget* aGtkWidget, uint32_t aTime,
-+ nscoord aX, nscoord aY)
-+{
-+ mTime = aTime;
-+ mGtkWidget = aGtkWidget;
-+ mX = aX;
-+ mY = aY;
-+}
-+
-+void
-+nsWaylandDragContext::DropMotion(uint32_t aTime, nscoord aX, nscoord aY)
-+{
-+ mTime = aTime;
-+ mX = aX;
-+ mY = aY;
-+}
-+
-+void
-+nsWaylandDragContext::GetLastDropInfo(uint32_t *aTime, nscoord *aX, nscoord *aY)
-+{
-+ *aTime = mTime;
-+ *aX = mX;
-+ *aY = mY;
-+}
-+
-+void
-+nsWaylandDragContext::SetDragStatus(GdkDragAction aAction)
-+{
-+ mDataOffer->SetDragStatus(aAction, mTime);
-+}
-+
-+GdkDragAction
-+nsWaylandDragContext::GetSelectedDragAction()
-+{
-+ return mDataOffer->GetSelectedDragAction();
-+}
-+
-+GList*
-+nsWaylandDragContext::GetTargets()
-+{
-+ int targetNums;
-+ GdkAtom *atoms = mDataOffer->GetTargets(&targetNums);
-+
-+ GList* targetList = nullptr;
-+ for (int i = 0; i < targetNums; i++) {
-+ targetList = g_list_append(targetList, GDK_ATOM_TO_POINTER(atoms[i]));
-+ }
-+
-+ return targetList;
-+}
-+
-+char*
-+nsWaylandDragContext::GetData(const char* aMimeType, uint32_t* aContentLength)
-+{
-+ mDataOffer->DragOfferAccept(aMimeType, mTime);
-+ return mDataOffer->GetData(mDisplay, aMimeType, aContentLength);
-+}
-+
-+void
-+nsRetrievalContextWayland::RegisterNewDataOffer(wl_data_offer *aWaylandDataOffer)
- {
- DataOffer* dataOffer =
- static_cast<DataOffer*>(g_hash_table_lookup(mActiveOffers,
- aWaylandDataOffer));
-+ MOZ_ASSERT(dataOffer == nullptr,
-+ "Registered WaylandDataOffer already exists. Wayland protocol error?");
-+
- if (!dataOffer) {
- dataOffer = new WaylandDataOffer(aWaylandDataOffer);
- g_hash_table_insert(mActiveOffers, aWaylandDataOffer, dataOffer);
- }
- }
-
- void
--nsRetrievalContextWayland::RegisterDataOffer(
-+nsRetrievalContextWayland::RegisterNewDataOffer(
- gtk_primary_selection_offer *aPrimaryDataOffer)
- {
- DataOffer* dataOffer =
- static_cast<DataOffer*>(g_hash_table_lookup(mActiveOffers,
- aPrimaryDataOffer));
-+ MOZ_ASSERT(dataOffer == nullptr,
-+ "Registered PrimaryDataOffer already exists. Wayland protocol error?");
-+
- if (!dataOffer) {
- dataOffer = new PrimaryDataOffer(aPrimaryDataOffer);
- g_hash_table_insert(mActiveOffers, aPrimaryDataOffer, dataOffer);
- }
- }
-
- void
- nsRetrievalContextWayland::SetClipboardDataOffer(wl_data_offer *aWaylandDataOffer)
- {
-+ // Delete existing clipboard data offer
-+ mClipboardOffer = nullptr;
-+
- DataOffer* dataOffer =
- static_cast<DataOffer*>(g_hash_table_lookup(mActiveOffers,
- aWaylandDataOffer));
- NS_ASSERTION(dataOffer, "We're missing clipboard data offer!");
- if (dataOffer) {
- g_hash_table_remove(mActiveOffers, aWaylandDataOffer);
- mClipboardOffer = dataOffer;
- }
- }
-
- void
- nsRetrievalContextWayland::SetPrimaryDataOffer(
- gtk_primary_selection_offer *aPrimaryDataOffer)
- {
-- if (aPrimaryDataOffer == nullptr) {
-- // Release any primary offer we have.
-- mPrimaryOffer = nullptr;
-- } else {
-+ // Release any primary offer we have.
-+ mPrimaryOffer = nullptr;
-+
-+ // aPrimaryDataOffer can be null which means we lost
-+ // the mouse selection.
-+ if (aPrimaryDataOffer) {
- DataOffer* dataOffer =
- static_cast<DataOffer*>(g_hash_table_lookup(mActiveOffers,
- aPrimaryDataOffer));
- NS_ASSERTION(dataOffer, "We're missing primary data offer!");
- if (dataOffer) {
- g_hash_table_remove(mActiveOffers, aPrimaryDataOffer);
- mPrimaryOffer = dataOffer;
- }
- }
- }
-
- void
--nsRetrievalContextWayland::ClearDataOffers(void)
-+nsRetrievalContextWayland::AddDragAndDropDataOffer(wl_data_offer *aDropDataOffer)
-+{
-+ // Remove any existing D&D contexts.
-+ mDragContext = nullptr;
-+
-+ WaylandDataOffer* dataOffer =
-+ static_cast<WaylandDataOffer*>(g_hash_table_lookup(mActiveOffers,
-+ aDropDataOffer));
-+ NS_ASSERTION(dataOffer, "We're missing drag and drop data offer!");
-+ if (dataOffer) {
-+ g_hash_table_remove(mActiveOffers, aDropDataOffer);
-+ mDragContext = new nsWaylandDragContext(dataOffer, mDisplay);
-+ }
-+}
-+
-+nsWaylandDragContext*
-+nsRetrievalContextWayland::GetDragContext(void)
-+{
-+ return mDragContext;
-+}
-+
-+void
-+nsRetrievalContextWayland::ClearClipboardDataOffers(void)
- {
- if (mClipboardOffer)
- mClipboardOffer = nullptr;
- if (mPrimaryOffer)
- mPrimaryOffer = nullptr;
- }
-
-+void
-+nsRetrievalContextWayland::ClearDragAndDropDataOffer(void)
-+{
-+ mDragContext = nullptr;
-+}
-+
- // We have a new fresh data content.
- // We should attach listeners to it and save for further use.
- static void
- data_device_data_offer (void *data,
- struct wl_data_device *data_device,
- struct wl_data_offer *offer)
- {
- nsRetrievalContextWayland *context =
- static_cast<nsRetrievalContextWayland*>(data);
-- context->RegisterDataOffer(offer);
-+ context->RegisterNewDataOffer(offer);
- }
-
- // The new fresh data content is clipboard.
- static void
- data_device_selection (void *data,
- struct wl_data_device *wl_data_device,
- struct wl_data_offer *offer)
- {
-@@ -336,41 +541,88 @@ data_device_selection (void
- }
-
- // The new fresh wayland data content is drag and drop.
- static void
- data_device_enter (void *data,
- struct wl_data_device *data_device,
- uint32_t time,
- struct wl_surface *surface,
-- int32_t x,
-- int32_t y,
-+ int32_t x_fixed,
-+ int32_t y_fixed,
- struct wl_data_offer *offer)
- {
-+ nsRetrievalContextWayland *context =
-+ static_cast<nsRetrievalContextWayland*>(data);
-+ context->AddDragAndDropDataOffer(offer);
-+
-+ nsWaylandDragContext* dragContext = context->GetDragContext();
-+
-+ GtkWidget* gtkWidget = get_gtk_widget_for_wl_surface(surface);
-+ if (!gtkWidget) {
-+ NS_WARNING("DragAndDrop: Unable to get GtkWidget for wl_surface!");
-+ return;
-+ }
-+
-+ LOGDRAG(("nsWindow data_device_enter for GtkWidget %p\n",
-+ (void*)gtkWidget));
-+
-+ dragContext->DropDataEnter(gtkWidget, time,
-+ wl_fixed_to_int(x_fixed),
-+ wl_fixed_to_int(y_fixed));
- }
-
- static void
- data_device_leave (void *data,
- struct wl_data_device *data_device)
- {
-+ nsRetrievalContextWayland *context =
-+ static_cast<nsRetrievalContextWayland*>(data);
-+
-+ nsWaylandDragContext* dropContext = context->GetDragContext();
-+ WindowDragLeaveHandler(dropContext->GetWidget());
-+
-+ context->ClearDragAndDropDataOffer();
- }
-
- static void
- data_device_motion (void *data,
- struct wl_data_device *data_device,
- uint32_t time,
-- int32_t x,
-- int32_t y)
-+ int32_t x_fixed,
-+ int32_t y_fixed)
- {
-+ nsRetrievalContextWayland *context =
-+ static_cast<nsRetrievalContextWayland*>(data);
-+
-+ nsWaylandDragContext* dropContext = context->GetDragContext();
-+
-+ nscoord x = wl_fixed_to_int(x_fixed);
-+ nscoord y = wl_fixed_to_int(y_fixed);
-+ dropContext->DropMotion(time, x, y);
-+
-+ WindowDragMotionHandler(dropContext->GetWidget(), nullptr,
-+ dropContext, x, y, time);
- }
-
- static void
- data_device_drop (void *data,
- struct wl_data_device *data_device)
- {
-+ nsRetrievalContextWayland *context =
-+ static_cast<nsRetrievalContextWayland*>(data);
-+
-+ nsWaylandDragContext* dropContext = context->GetDragContext();
-+
-+ uint32_t time;
-+ nscoord x, y;
-+ dropContext->GetLastDropInfo(&time, &x, &y);
-+
-+ WindowDragDropHandler(dropContext->GetWidget(), nullptr, dropContext,
-+ x, y, time);
- }
-
- /* wl_data_device callback description:
- *
- * data_device_data_offer - It's called when there's a new wl_data_offer
- * available. We need to attach wl_data_offer_listener
- * to it to get available MIME types.
- *
-@@ -400,29 +652,41 @@ static const struct wl_data_device_liste
- static void
- primary_selection_data_offer (void *data,
- struct gtk_primary_selection_device *gtk_primary_selection_device,
- struct gtk_primary_selection_offer *gtk_primary_offer)
- {
- // create and add listener
- nsRetrievalContextWayland *context =
- static_cast<nsRetrievalContextWayland*>(data);
-- context->RegisterDataOffer(gtk_primary_offer);
-+ context->RegisterNewDataOffer(gtk_primary_offer);
- }
-
- static void
- primary_selection_selection (void *data,
- struct gtk_primary_selection_device *gtk_primary_selection_device,
- struct gtk_primary_selection_offer *gtk_primary_offer)
- {
- nsRetrievalContextWayland *context =
- static_cast<nsRetrievalContextWayland*>(data);
- context->SetPrimaryDataOffer(gtk_primary_offer);
- }
-
-+/* gtk_primary_selection_device callback description:
-+ *
-+ * primary_selection_data_offer - It's called when there's a new
-+ * gtk_primary_selection_offer available.
-+ * We need to attach gtk_primary_selection_offer_listener
-+ * to it to get available MIME types.
-+ *
-+ * primary_selection_selection - It's called when the new gtk_primary_selection_offer
-+ * is a primary selection content. It can be also called with
-+ * gtk_primary_selection_offer = null which means there's no
-+ * primary selection.
-+ */
- static const struct
- gtk_primary_selection_device_listener primary_selection_device_listener = {
- primary_selection_data_offer,
- primary_selection_selection,
- };
-
- bool
- nsRetrievalContextWayland::HasSelectionSupport(void)
-@@ -446,17 +710,17 @@ keyboard_handle_enter(void *data, struct
- static void
- keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
- uint32_t serial, struct wl_surface *surface)
- {
- // We lost focus so our clipboard data are outdated
- nsRetrievalContextWayland *context =
- static_cast<nsRetrievalContextWayland*>(data);
-
-- context->ClearDataOffers();
-+ context->ClearClipboardDataOffers();
- }
-
- static void
- keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
- uint32_t serial, uint32_t time, uint32_t key,
- uint32_t state)
- {
- }
-@@ -568,16 +832,17 @@ nsRetrievalContextWayland::nsRetrievalCo
- : mInitialized(false)
- , mSeat(nullptr)
- , mDataDeviceManager(nullptr)
- , mPrimarySelectionDataDeviceManager(nullptr)
- , mKeyboard(nullptr)
- , mActiveOffers(g_hash_table_new(NULL, NULL))
- , mClipboardOffer(nullptr)
- , mPrimaryOffer(nullptr)
-+ , mDragContext(nullptr)
- , mClipboardRequestNumber(0)
- , mClipboardData(nullptr)
- , mClipboardDataLength(0)
- {
- // Available as of GTK 3.8+
- static auto sGdkWaylandDisplayGetWlDisplay =
- (wl_display *(*)(GdkDisplay *))
- dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display");
-@@ -611,18 +876,31 @@ nsRetrievalContextWayland::nsRetrievalCo
- mSeat);
- gtk_primary_selection_device_add_listener(primaryDataDevice,
- &primary_selection_device_listener, this);
- }
-
- mInitialized = true;
- }
-
-+static gboolean
-+offer_hash_remove(gpointer wl_offer, gpointer aDataOffer, gpointer user_data)
-+{
-+#ifdef DEBUG
-+ nsPrintfCString msg("nsRetrievalContextWayland(): leaked nsDataOffer %p\n",
-+ aDataOffer);
-+ NS_WARNING(msg.get());
-+#endif
-+ delete static_cast<DataOffer*>(aDataOffer);
-+ return true;
-+}
-+
- nsRetrievalContextWayland::~nsRetrievalContextWayland(void)
- {
-+ g_hash_table_foreach_remove(mActiveOffers, offer_hash_remove, nullptr);
- g_hash_table_destroy(mActiveOffers);
- }
-
- GdkAtom*
- nsRetrievalContextWayland::GetTargets(int32_t aWhichClipboard,
- int* aTargetNum)
- {
- if (GetSelectionAtom(aWhichClipboard) == GDK_SELECTION_CLIPBOARD) {
-diff --git a/widget/gtk/nsClipboardWayland.h b/widget/gtk/nsClipboardWayland.h
---- a/widget/gtk/nsClipboardWayland.h
-+++ b/widget/gtk/nsClipboardWayland.h
-@@ -27,65 +27,108 @@ public:
-
- char* GetData(wl_display* aDisplay, const char* aMimeType,
- uint32_t* aContentLength);
-
- virtual ~DataOffer() {};
- private:
- virtual bool RequestDataTransfer(const char* aMimeType, int fd) = 0;
-
-+protected:
- nsTArray<GdkAtom> mTargetMIMETypes;
- };
-
- class WaylandDataOffer : public DataOffer
- {
- public:
- WaylandDataOffer(wl_data_offer* aWaylandDataOffer);
-
-+ void DragOfferAccept(const char* aMimeType, uint32_t aTime);
-+ void SetDragStatus(GdkDragAction aAction, uint32_t aTime);
-+
-+ GdkDragAction GetSelectedDragAction();
-+ void SetSelectedDragAction(uint32_t aWaylandAction);
-+
-+ void SetSourceDragActions(uint32_t aWaylandActions);
-+
-+ virtual ~WaylandDataOffer();
- private:
-- virtual ~WaylandDataOffer();
- bool RequestDataTransfer(const char* aMimeType, int fd) override;
-
- wl_data_offer* mWaylandDataOffer;
-+ uint32_t mSelectedDragAction;
- };
-
- class PrimaryDataOffer : public DataOffer
- {
- public:
- PrimaryDataOffer(gtk_primary_selection_offer* aPrimaryDataOffer);
-+ void SetAvailableDragActions(uint32_t aWaylandActions) {};
-
-+ virtual ~PrimaryDataOffer();
- private:
-- virtual ~PrimaryDataOffer();
- bool RequestDataTransfer(const char* aMimeType, int fd) override;
-
- gtk_primary_selection_offer* mPrimaryDataOffer;
- };
-
-+class nsWaylandDragContext : public nsISupports
-+{
-+ NS_DECL_ISUPPORTS
-+
-+public:
-+ nsWaylandDragContext(WaylandDataOffer* aWaylandDataOffer,
-+ wl_display *aDisplay);
-+
-+ void DropDataEnter(GtkWidget* aGtkWidget, uint32_t aTime,
-+ nscoord aX, nscoord aY);
-+ void DropMotion(uint32_t aTime, nscoord aX, nscoord aY);
-+ void GetLastDropInfo(uint32_t *aTime, nscoord *aX, nscoord *aY);
-+
-+ void SetDragStatus(GdkDragAction action);
-+ GdkDragAction GetSelectedDragAction();
-+
-+ GtkWidget* GetWidget() { return mGtkWidget; }
-+ GList* GetTargets();
-+ char* GetData(const char* aMimeType, uint32_t* aContentLength);
-+private:
-+ virtual ~nsWaylandDragContext() {};
-+
-+ nsAutoPtr<WaylandDataOffer> mDataOffer;
-+ wl_display* mDisplay;
-+ uint32_t mTime;
-+ GtkWidget* mGtkWidget;
-+ nscoord mX, mY;
-+};
-+
- class nsRetrievalContextWayland : public nsRetrievalContext
- {
- public:
- nsRetrievalContextWayland();
-
- virtual const char* GetClipboardData(const char* aMimeType,
- int32_t aWhichClipboard,
- uint32_t* aContentLength) override;
- virtual const char* GetClipboardText(int32_t aWhichClipboard) override;
- virtual void ReleaseClipboardData(const char* aClipboardData) override;
-
- virtual GdkAtom* GetTargets(int32_t aWhichClipboard,
- int* aTargetNum) override;
- virtual bool HasSelectionSupport(void) override;
-
-- void RegisterDataOffer(wl_data_offer *aWaylandDataOffer);
-- void RegisterDataOffer(gtk_primary_selection_offer *aPrimaryDataOffer);
-+ void RegisterNewDataOffer(wl_data_offer *aWaylandDataOffer);
-+ void RegisterNewDataOffer(gtk_primary_selection_offer *aPrimaryDataOffer);
-
- void SetClipboardDataOffer(wl_data_offer *aWaylandDataOffer);
- void SetPrimaryDataOffer(gtk_primary_selection_offer *aPrimaryDataOffer);
-+ void AddDragAndDropDataOffer(wl_data_offer *aWaylandDataOffer);
-+ nsWaylandDragContext* GetDragContext();
-
-- void ClearDataOffers();
-+ void ClearClipboardDataOffers();
-+ void ClearDragAndDropDataOffer();
-
- void ConfigureKeyboard(wl_seat_capability caps);
- void TransferFastTrackClipboard(int aClipboardRequestNumber,
- GtkSelectionData *aSelectionData);
-
- void InitDataDeviceManager(wl_registry *registry, uint32_t id, uint32_t version);
- void InitPrimarySelectionDataDeviceManager(wl_registry *registry, uint32_t id);
- void InitSeat(wl_registry *registry, uint32_t id, uint32_t version, void *data);
-@@ -98,16 +141,17 @@ private:
- wl_data_device_manager *mDataDeviceManager;
- gtk_primary_selection_device_manager *mPrimarySelectionDataDeviceManager;
- wl_keyboard *mKeyboard;
-
- // Data offers provided by Wayland data device
- GHashTable* mActiveOffers;
- nsAutoPtr<DataOffer> mClipboardOffer;
- nsAutoPtr<DataOffer> mPrimaryOffer;
-+ RefPtr<nsWaylandDragContext> mDragContext;
-
- int mClipboardRequestNumber;
- char* mClipboardData;
- uint32_t mClipboardDataLength;
-
- // Mime types used for text data at Gtk+, see request_text_received_func()
- // at gtkclipboard.c.
- #define TEXT_MIME_TYPES_NUM 3
-diff --git a/widget/gtk/nsDragService.cpp b/widget/gtk/nsDragService.cpp
---- a/widget/gtk/nsDragService.cpp
-+++ b/widget/gtk/nsDragService.cpp
-@@ -37,16 +37,19 @@
- #include "nsViewManager.h"
- #include "nsIFrame.h"
- #include "nsGtkUtils.h"
- #include "nsGtkKeyUtils.h"
- #include "mozilla/gfx/2D.h"
- #include "gfxPlatform.h"
- #include "ScreenHelperGTK.h"
- #include "nsArrayUtils.h"
-+#ifdef MOZ_WAYLAND
-+#include "nsClipboardWayland.h"
-+#endif
-
- using namespace mozilla;
- using namespace mozilla::gfx;
-
- // This sets how opaque the drag image is
- #define DRAG_IMAGE_ALPHA_LEVEL 0.5
-
- // These values are copied from GtkDragResult (rather than using GtkDragResult
-@@ -93,16 +96,20 @@ invisibleSourceDragDataGet(GtkWidget
- GtkSelectionData *aSelectionData,
- guint aInfo,
- guint32 aTime,
- gpointer aData);
-
- nsDragService::nsDragService()
- : mScheduledTask(eDragTaskNone)
- , mTaskSource(0)
-+#ifdef MOZ_WAYLAND
-+ , mPendingWaylandDragContext(nullptr)
-+ , mTargetWaylandDragContext(nullptr)
-+#endif
- {
- // We have to destroy the hidden widget before the event loop stops
- // running.
- nsCOMPtr<nsIObserverService> obsServ =
- mozilla::services::GetObserverService();
- obsServ->AddObserver(this, "quit-application", false);
-
- // our hidden source widget
-@@ -509,16 +516,19 @@ nsDragService::EndDragSession(bool aDone
- }
- }
-
- // unset our drag action
- SetDragAction(DRAGDROP_ACTION_NONE);
-
- // We're done with the drag context.
- mTargetDragContextForRemote = nullptr;
-+#ifdef MOZ_WAYLAND
-+ mTargetWaylandDragContextForRemote = nullptr;
-+#endif
-
- return nsBaseDragService::EndDragSession(aDoneDrag, aKeyModifiers);
- }
-
- // nsIDragSession
- NS_IMETHODIMP
- nsDragService::SetCanDrop(bool aCanDrop)
- {
-@@ -629,16 +639,24 @@ nsDragService::GetNumDropItems(uint32_t
- if (!mTargetWidget) {
- MOZ_LOG(sDragLm, LogLevel::Debug,
- ("*** warning: GetNumDropItems \
- called without a valid target widget!\n"));
- *aNumItems = 0;
- return NS_OK;
- }
-
-+#ifdef MOZ_WAYLAND
-+ // TODO: Wayland implementation of text/uri-list.
-+ if (!mTargetDragContext) {
-+ *aNumItems = 1;
-+ return NS_OK;
-+ }
-+#endif
-+
- bool isList = IsTargetContextList();
- if (isList)
- mSourceDataItems->GetLength(aNumItems);
- else {
- GdkAtom gdkFlavor = gdk_atom_intern(gTextUriListType, FALSE);
- GetTargetDragData(gdkFlavor);
- if (mTargetDragData) {
- const char *data = reinterpret_cast<char*>(mTargetDragData);
-@@ -1020,19 +1038,28 @@ nsDragService::IsDataFlavorSupported(con
- }
- }
- }
- }
- return NS_OK;
- }
-
- // check the target context vs. this flavor, one at a time
-- GList *tmp;
-- for (tmp = gdk_drag_context_list_targets(mTargetDragContext);
-- tmp; tmp = tmp->next) {
-+ GList *tmp = nullptr;
-+ if (mTargetDragContext) {
-+ tmp = gdk_drag_context_list_targets(mTargetDragContext);
-+ }
-+#ifdef MOZ_WAYLAND
-+ else {
-+ tmp = mTargetWaylandDragContext->GetTargets();
-+ }
-+#endif
-+ GList *tmp_head = tmp;
-+
-+ for (; tmp; tmp = tmp->next) {
- /* Bug 331198 */
- GdkAtom atom = GDK_POINTER_TO_ATOM(tmp->data);
- gchar *name = nullptr;
- name = gdk_atom_name(atom);
- MOZ_LOG(sDragLm, LogLevel::Debug,
- ("checking %s against %s\n", name, aDataFlavor));
- if (name && (strcmp(name, aDataFlavor) == 0)) {
- MOZ_LOG(sDragLm, LogLevel::Debug, ("good!\n"));
-@@ -1067,16 +1094,23 @@ nsDragService::IsDataFlavorSupported(con
- (strcmp(aDataFlavor, kFileMime) == 0))) {
- MOZ_LOG(sDragLm, LogLevel::Debug,
- ("good! ( it's text plain and we're checking \
- against text/unicode or application/x-moz-file)\n"));
- *_retval = true;
- }
- g_free(name);
- }
-+
-+ // mTargetWaylandDragContext->GetTargets allocates the list
-+ // so we need to free it here.
-+ if (!mTargetDragContext) {
-+ g_list_free(tmp_head);
-+ }
-+
- return NS_OK;
- }
-
- void
- nsDragService::ReplyToDragMotion(GdkDragContext* aDragContext)
- {
- MOZ_LOG(sDragLm, LogLevel::Debug,
- ("nsDragService::ReplyToDragMotion %d", mCanDrop));
-@@ -1098,16 +1132,46 @@ nsDragService::ReplyToDragMotion(GdkDrag
- action = GDK_ACTION_MOVE;
- break;
- }
- }
-
- gdk_drag_status(aDragContext, action, mTargetTime);
- }
-
-+#ifdef MOZ_WAYLAND
-+void
-+nsDragService::ReplyToDragMotion(nsWaylandDragContext* aDragContext)
-+{
-+ MOZ_LOG(sDragLm, LogLevel::Debug,
-+ ("nsDragService::ReplyToDragMotion %d", mCanDrop));
-+
-+ GdkDragAction action = (GdkDragAction)0;
-+ if (mCanDrop) {
-+ // notify the dragger if we can drop
-+ switch (mDragAction) {
-+ case DRAGDROP_ACTION_COPY:
-+ action = GDK_ACTION_COPY;
-+ break;
-+ case DRAGDROP_ACTION_LINK:
-+ action = GDK_ACTION_LINK;
-+ break;
-+ case DRAGDROP_ACTION_NONE:
-+ action = (GdkDragAction)0;
-+ break;
-+ default:
-+ action = GDK_ACTION_MOVE;
-+ break;
-+ }
-+ }
-+
-+ aDragContext->SetDragStatus(action);
-+}
-+#endif
-+
- void
- nsDragService::TargetDataReceived(GtkWidget *aWidget,
- GdkDragContext *aContext,
- gint aX,
- gint aY,
- GtkSelectionData *aSelectionData,
- guint aInfo,
- guint32 aTime)
-@@ -1129,16 +1193,22 @@ nsDragService::TargetDataReceived(GtkWid
- }
- }
-
- bool
- nsDragService::IsTargetContextList(void)
- {
- bool retval = false;
-
-+#ifdef MOZ_WAYLAND
-+ // TODO: We need a wayland implementation here.
-+ if (!mTargetDragContext)
-+ return retval;
-+#endif
-+
- // gMimeListType drags only work for drags within a single process. The
- // gtk_drag_get_source_widget() function will return nullptr if the source
- // of the drag is another app, so we use it to check if a gMimeListType
- // drop will work or not.
- if (gtk_drag_get_source_widget(mTargetDragContext) == nullptr)
- return retval;
-
- GList *tmp;
-@@ -1167,27 +1237,38 @@ void
- nsDragService::GetTargetDragData(GdkAtom aFlavor)
- {
- MOZ_LOG(sDragLm, LogLevel::Debug, ("getting data flavor %p\n", aFlavor));
- MOZ_LOG(sDragLm, LogLevel::Debug, ("mLastWidget is %p and mLastContext is %p\n",
- mTargetWidget.get(),
- mTargetDragContext.get()));
- // reset our target data areas
- TargetResetData();
-- gtk_drag_get_data(mTargetWidget, mTargetDragContext, aFlavor, mTargetTime);
-+
-+ if (mTargetDragContext) {
-+ gtk_drag_get_data(mTargetWidget, mTargetDragContext, aFlavor, mTargetTime);
-
-- MOZ_LOG(sDragLm, LogLevel::Debug, ("about to start inner iteration."));
-- PRTime entryTime = PR_Now();
-- while (!mTargetDragDataReceived && mDoingDrag) {
-- // check the number of iterations
-- MOZ_LOG(sDragLm, LogLevel::Debug, ("doing iteration...\n"));
-- PR_Sleep(20*PR_TicksPerSecond()/1000); /* sleep for 20 ms/iteration */
-- if (PR_Now()-entryTime > NS_DND_TIMEOUT) break;
-- gtk_main_iteration();
-+ MOZ_LOG(sDragLm, LogLevel::Debug, ("about to start inner iteration."));
-+ PRTime entryTime = PR_Now();
-+ while (!mTargetDragDataReceived && mDoingDrag) {
-+ // check the number of iterations
-+ MOZ_LOG(sDragLm, LogLevel::Debug, ("doing iteration...\n"));
-+ PR_Sleep(20*PR_TicksPerSecond()/1000); /* sleep for 20 ms/iteration */
-+ if (PR_Now()-entryTime > NS_DND_TIMEOUT) break;
-+ gtk_main_iteration();
-+ }
- }
-+#ifdef MOZ_WAYLAND
-+ else {
-+ mTargetDragData =
-+ mTargetWaylandDragContext->GetData(gdk_atom_name(aFlavor),
-+ &mTargetDragDataLen);
-+ mTargetDragDataReceived = true;
-+ }
-+#endif
- MOZ_LOG(sDragLm, LogLevel::Debug, ("finished inner iteration\n"));
- }
-
- void
- nsDragService::TargetResetData(void)
- {
- mTargetDragDataReceived = false;
- // make sure to free old data if we have to
-@@ -1428,17 +1509,17 @@ nsDragService::SourceEndDragSession(GdkD
- }
- }
-
- if (mDataTransfer) {
- mDataTransfer->SetDropEffectInt(dropEffect);
- }
-
- // Schedule the appropriate drag end dom events.
-- Schedule(eDragTaskSourceEnd, nullptr, nullptr, LayoutDeviceIntPoint(), 0);
-+ Schedule(eDragTaskSourceEnd, nullptr, nullptr, nullptr, LayoutDeviceIntPoint(), 0);
- }
-
- static void
- CreateUriList(nsIArray *items, gchar **text, gint *length)
- {
- uint32_t i, count;
- GString *uriList = g_string_new(nullptr);
-
-@@ -1778,64 +1859,68 @@ invisibleSourceDragEnd(GtkWidget
- //
- // No Gecko drag events are dispatched (during nested event loops) while other
- // Gecko drag events are in flight. This helps event handlers that may not
- // expect nested events, while accessing an event's dataTransfer for example.
-
- gboolean
- nsDragService::ScheduleMotionEvent(nsWindow *aWindow,
- GdkDragContext *aDragContext,
-+ nsWaylandDragContext *aWaylandDragContext,
- LayoutDeviceIntPoint aWindowPoint, guint aTime)
- {
-- if (mScheduledTask == eDragTaskMotion) {
-+ if (aDragContext && mScheduledTask == eDragTaskMotion) {
- // The drag source has sent another motion message before we've
- // replied to the previous. That shouldn't happen with Xdnd. The
- // spec for Motif drags is less clear, but we'll just update the
- // scheduled task with the new position reply only to the most
- // recent message.
- NS_WARNING("Drag Motion message received before previous reply was sent");
- }
-
- // Returning TRUE means we'll reply with a status message, unless we first
- // get a leave.
-- return Schedule(eDragTaskMotion, aWindow, aDragContext,
-+ return Schedule(eDragTaskMotion, aWindow, aDragContext, aWaylandDragContext,
- aWindowPoint, aTime);
- }
-
- void
- nsDragService::ScheduleLeaveEvent()
- {
- // We don't know at this stage whether a drop signal will immediately
- // follow. If the drop signal gets sent it will happen before we return
- // to the main loop and the scheduled leave task will be replaced.
-- if (!Schedule(eDragTaskLeave, nullptr, nullptr, LayoutDeviceIntPoint(), 0)) {
-+ if (!Schedule(eDragTaskLeave, nullptr, nullptr, nullptr,
-+ LayoutDeviceIntPoint(), 0)) {
- NS_WARNING("Drag leave after drop");
- }
- }
-
- gboolean
- nsDragService::ScheduleDropEvent(nsWindow *aWindow,
- GdkDragContext *aDragContext,
-+ nsWaylandDragContext *aWaylandDragContext,
- LayoutDeviceIntPoint aWindowPoint, guint aTime)
- {
- if (!Schedule(eDragTaskDrop, aWindow,
-- aDragContext, aWindowPoint, aTime)) {
-+ aDragContext, aWaylandDragContext, aWindowPoint, aTime)) {
- NS_WARNING("Additional drag drop ignored");
- return FALSE;
- }
-
- SetDragEndPoint(aWindowPoint + aWindow->WidgetToScreenOffset());
-
- // We'll reply with gtk_drag_finish().
- return TRUE;
- }
-
- gboolean
- nsDragService::Schedule(DragTask aTask, nsWindow *aWindow,
- GdkDragContext *aDragContext,
-+ nsWaylandDragContext *aWaylandDragContext,
- LayoutDeviceIntPoint aWindowPoint, guint aTime)
- {
- // If there is an existing leave or motion task scheduled, then that
- // will be replaced. When the new task is run, it will dispatch
- // any necessary leave or motion events.
-
- // If aTask is eDragTaskSourceEnd, then it will replace even a scheduled
- // drop event (which could happen if the drop event has not been processed
-@@ -1844,16 +1929,19 @@ nsDragService::Schedule(DragTask aTask,
- // drop.
- if (mScheduledTask == eDragTaskSourceEnd ||
- (mScheduledTask == eDragTaskDrop && aTask != eDragTaskSourceEnd))
- return FALSE;
-
- mScheduledTask = aTask;
- mPendingWindow = aWindow;
- mPendingDragContext = aDragContext;
-+#ifdef MOZ_WAYLAND
-+ mPendingWaylandDragContext = aWaylandDragContext;
-+#endif
- mPendingWindowPoint = aWindowPoint;
- mPendingTime = aTime;
-
- if (!mTaskSource) {
- // High priority is used here because the native events involved have
- // already waited at default priority. Perhaps a lower than default
- // priority could be used for motion tasks because there is a chance
- // that a leave or drop is waiting, but managing different priorities
-@@ -1919,17 +2007,24 @@ nsDragService::RunScheduledTask()
- // This may be the start of a destination drag session.
- StartDragSession();
-
- // mTargetWidget may be nullptr if the window has been destroyed.
- // (The leave event is not scheduled if a drop task is still scheduled.)
- // We still reply appropriately to indicate that the drop will or didn't
- // succeeed.
- mTargetWidget = mTargetWindow->GetMozContainerWidget();
-- mTargetDragContext.steal(mPendingDragContext);
-+ if (mTargetDragContext) {
-+ mTargetDragContext.steal(mPendingDragContext);
-+ }
-+#ifdef MOZ_WAYLAND
-+ else {
-+ mTargetWaylandDragContext = mPendingWaylandDragContext.forget();
-+ }
-+#endif
- mTargetTime = mPendingTime;
-
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#drag-and-drop-processing-model
- // (as at 27 December 2010) indicates that a "drop" event should only be
- // fired (at the current target element) if the current drag operation is
- // not none. The current drag operation will only be set to a non-none
- // value during a "dragover" event.
- //
-@@ -1951,44 +2046,59 @@ nsDragService::RunScheduledTask()
- // protocol is used.
- if (task == eDragTaskMotion || positionHasChanged) {
- UpdateDragAction();
- TakeDragEventDispatchedToChildProcess(); // Clear the old value.
- DispatchMotionEvents();
- if (task == eDragTaskMotion) {
- if (TakeDragEventDispatchedToChildProcess()) {
- mTargetDragContextForRemote = mTargetDragContext;
-+#ifdef MOZ_WAYLAND
-+ mTargetWaylandDragContextForRemote = mTargetWaylandDragContext;
-+#endif
- } else {
- // Reply to tell the source whether we can drop and what
- // action would be taken.
-- ReplyToDragMotion(mTargetDragContext);
-+ if (mTargetDragContext) {
-+ ReplyToDragMotion(mTargetDragContext);
-+ }
-+#ifdef MOZ_WAYLAND
-+ else {
-+ ReplyToDragMotion(mTargetWaylandDragContext);
-+ }
-+#endif
- }
- }
- }
-
- if (task == eDragTaskDrop) {
- gboolean success = DispatchDropEvent();
-
- // Perhaps we should set the del parameter to TRUE when the drag
- // action is move, but we don't know whether the data was successfully
- // transferred.
-- gtk_drag_finish(mTargetDragContext, success,
-- /* del = */ FALSE, mTargetTime);
-+ if (mTargetDragContext) {
-+ gtk_drag_finish(mTargetDragContext, success,
-+ /* del = */ FALSE, mTargetTime);
-+ }
-
- // This drag is over, so clear out our reference to the previous
- // window.
- mTargetWindow = nullptr;
- // Make sure to end the drag session. If this drag started in a
- // different app, we won't get a drag_end signal to end it from.
- EndDragSession(true, GetCurrentModifiers());
- }
-
- // We're done with the drag context.
- mTargetWidget = nullptr;
- mTargetDragContext = nullptr;
-+#ifdef MOZ_WAYLAND
-+ mTargetWaylandDragContext = nullptr;
-+#endif
-
- // If we got another drag signal while running the sheduled task, that
- // must have happened while running a nested event loop. Leave the task
- // source on the event loop.
- if (mScheduledTask != eDragTaskNone)
- return TRUE;
-
- // We have no task scheduled.
-@@ -2008,17 +2118,26 @@ nsDragService::UpdateDragAction()
- // nsContentUtils::SetDataTransferInEvent() to set the initial
- // dataTransfer.dropEffect, so GdkDragContext::suggested_action would be
- // more appropriate. GdkDragContext::actions should be used to set
- // dataTransfer.effectAllowed, which doesn't currently happen with
- // external sources.
-
- // default is to do nothing
- int action = nsIDragService::DRAGDROP_ACTION_NONE;
-- GdkDragAction gdkAction = gdk_drag_context_get_actions(mTargetDragContext);
-+ GdkDragAction gdkAction = GDK_ACTION_DEFAULT;
-+ if (mTargetDragContext) {
-+ gdkAction = gdk_drag_context_get_actions(mTargetDragContext);
-+ }
-+#ifdef MOZ_WAYLAND
-+ else {
-+ // We got the selected D&D action from compositor on Wayland.
-+ gdkAction = mTargetWaylandDragContext->GetSelectedDragAction();
-+ }
-+#endif
-
- // set the default just in case nothing matches below
- if (gdkAction & GDK_ACTION_DEFAULT)
- action = nsIDragService::DRAGDROP_ACTION_MOVE;
-
- // first check to see if move is set
- if (gdkAction & GDK_ACTION_MOVE)
- action = nsIDragService::DRAGDROP_ACTION_MOVE;
-@@ -2037,16 +2156,22 @@ nsDragService::UpdateDragAction()
-
- NS_IMETHODIMP
- nsDragService::UpdateDragEffect()
- {
- if (mTargetDragContextForRemote) {
- ReplyToDragMotion(mTargetDragContextForRemote);
- mTargetDragContextForRemote = nullptr;
- }
-+#ifdef MOZ_WAYLAND
-+ else if (mTargetWaylandDragContextForRemote) {
-+ ReplyToDragMotion(mTargetWaylandDragContextForRemote);
-+ mTargetWaylandDragContextForRemote = nullptr;
-+ }
-+#endif
- return NS_OK;
- }
-
- void
- nsDragService::DispatchMotionEvents()
- {
- mCanDrop = false;
-
-diff --git a/widget/gtk/nsDragService.h b/widget/gtk/nsDragService.h
---- a/widget/gtk/nsDragService.h
-+++ b/widget/gtk/nsDragService.h
-@@ -9,16 +9,17 @@
-
- #include "mozilla/RefPtr.h"
- #include "nsBaseDragService.h"
- #include "nsIObserver.h"
- #include "nsAutoRef.h"
- #include <gtk/gtk.h>
-
- class nsWindow;
-+class nsWaylandDragContext;
-
- namespace mozilla {
- namespace gfx {
- class SourceSurface;
- }
- }
-
- #ifndef HAVE_NSGOBJECTREFTRAITS
-@@ -93,21 +94,23 @@ public:
- gint aX,
- gint aY,
- GtkSelectionData *aSelection_data,
- guint aInfo,
- guint32 aTime);
-
- gboolean ScheduleMotionEvent(nsWindow *aWindow,
- GdkDragContext *aDragContext,
-+ nsWaylandDragContext* aPendingWaylandDragContext,
- mozilla::LayoutDeviceIntPoint aWindowPoint,
- guint aTime);
- void ScheduleLeaveEvent();
- gboolean ScheduleDropEvent(nsWindow *aWindow,
- GdkDragContext *aDragContext,
-+ nsWaylandDragContext* aPendingWaylandDragContext,
- mozilla::LayoutDeviceIntPoint aWindowPoint,
- guint aTime);
-
- nsWindow* GetMostRecentDestWindow()
- {
- return mScheduledTask == eDragTaskNone ? mTargetWindow
- : mPendingWindow;
- }
-@@ -153,30 +156,39 @@ private:
-
- // mPendingWindow, mPendingWindowPoint, mPendingDragContext, and
- // mPendingTime, carry information from the GTK signal that will be used
- // when the scheduled task is run. mPendingWindow and mPendingDragContext
- // will be nullptr if the scheduled task is eDragTaskLeave.
- RefPtr<nsWindow> mPendingWindow;
- mozilla::LayoutDeviceIntPoint mPendingWindowPoint;
- nsCountedRef<GdkDragContext> mPendingDragContext;
-+#ifdef MOZ_WAYLAND
-+ RefPtr<nsWaylandDragContext> mPendingWaylandDragContext;
-+#endif
- guint mPendingTime;
-
- // mTargetWindow and mTargetWindowPoint record the position of the last
- // eDragTaskMotion or eDragTaskDrop task that was run or is still running.
- // mTargetWindow is cleared once the drag has completed or left.
- RefPtr<nsWindow> mTargetWindow;
- mozilla::LayoutDeviceIntPoint mTargetWindowPoint;
- // mTargetWidget and mTargetDragContext are set only while dispatching
- // motion or drop events. mTime records the corresponding timestamp.
- nsCountedRef<GtkWidget> mTargetWidget;
- nsCountedRef<GdkDragContext> mTargetDragContext;
-+#ifdef MOZ_WAYLAND
-+ RefPtr<nsWaylandDragContext> mTargetWaylandDragContext;
-+#endif
- // mTargetDragContextForRemote is set while waiting for a reply from
- // a child process.
- nsCountedRef<GdkDragContext> mTargetDragContextForRemote;
-+#ifdef MOZ_WAYLAND
-+ RefPtr<nsWaylandDragContext> mTargetWaylandDragContextForRemote;
-+#endif
- guint mTargetTime;
-
- // is it OK to drop on us?
- bool mCanDrop;
-
- // have we received our drag data?
- bool mTargetDragDataReceived;
- // last data received and its length
-@@ -207,22 +219,25 @@ private:
- bool SetAlphaPixmap(SourceSurface *aPixbuf,
- GdkDragContext *aContext,
- int32_t aXOffset,
- int32_t aYOffset,
- const mozilla::LayoutDeviceIntRect &dragRect);
-
- gboolean Schedule(DragTask aTask, nsWindow *aWindow,
- GdkDragContext *aDragContext,
-+ nsWaylandDragContext* aPendingWaylandDragContext,
- mozilla::LayoutDeviceIntPoint aWindowPoint, guint aTime);
-
- // Callback for g_idle_add_full() to run mScheduledTask.
- static gboolean TaskDispatchCallback(gpointer data);
- gboolean RunScheduledTask();
- void UpdateDragAction();
- void DispatchMotionEvents();
- void ReplyToDragMotion(GdkDragContext* aDragContext);
-+#ifdef MOZ_WAYLAND
-+ void ReplyToDragMotion(nsWaylandDragContext* aDragContext);
-+#endif
- gboolean DispatchDropEvent();
- static uint32_t GetCurrentModifiers();
- };
-
- #endif // nsDragService_h__
--
-diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
---- a/widget/gtk/nsWindow.cpp
-+++ b/widget/gtk/nsWindow.cpp
-@@ -6081,23 +6081,23 @@ touch_event_cb(GtkWidget* aWidget, GdkEv
- void
- nsWindow::InitDragEvent(WidgetDragEvent &aEvent)
- {
- // set the keyboard modifiers
- guint modifierState = KeymapWrapper::GetCurrentModifierState();
- KeymapWrapper::InitInputEvent(aEvent, modifierState);
- }
-
--static gboolean
--drag_motion_event_cb(GtkWidget *aWidget,
-- GdkDragContext *aDragContext,
-- gint aX,
-- gint aY,
-- guint aTime,
-- gpointer aData)
-+gboolean
-+WindowDragMotionHandler(GtkWidget *aWidget,
-+ GdkDragContext *aDragContext,
-+ nsWaylandDragContext *aWaylandDragContext,
-+ gint aX,
-+ gint aY,
-+ guint aTime)
- {
- RefPtr<nsWindow> window = get_window_for_gtk_widget(aWidget);
- if (!window)
- return FALSE;
-
- // figure out which internal widget this drag motion actually happened on
- nscoord retx = 0;
- nscoord rety = 0;
-@@ -6112,25 +6112,34 @@ drag_motion_event_cb(GtkWidget *aWidget,
- }
-
- LOGDRAG(("nsWindow drag-motion signal for %p\n", (void*)innerMostWindow));
-
- LayoutDeviceIntPoint point = window->GdkPointToDevicePixels({ retx, rety });
-
- RefPtr<nsDragService> dragService = nsDragService::GetInstance();
- return dragService->
-- ScheduleMotionEvent(innerMostWindow, aDragContext,
-+ ScheduleMotionEvent(innerMostWindow, aDragContext, aWaylandDragContext,
- point, aTime);
- }
-
--static void
--drag_leave_event_cb(GtkWidget *aWidget,
-- GdkDragContext *aDragContext,
-- guint aTime,
-- gpointer aData)
-+static gboolean
-+drag_motion_event_cb(GtkWidget *aWidget,
-+ GdkDragContext *aDragContext,
-+ gint aX,
-+ gint aY,
-+ guint aTime,
-+ gpointer aData)
-+{
-+ return WindowDragMotionHandler(aWidget, aDragContext, nullptr,
-+ aX, aY, aTime);
-+}
-+
-+void
-+WindowDragLeaveHandler(GtkWidget *aWidget)
- {
- RefPtr<nsWindow> window = get_window_for_gtk_widget(aWidget);
- if (!window)
- return;
-
- RefPtr<nsDragService> dragService = nsDragService::GetInstance();
-
- nsWindow *mostRecentDragWindow = dragService->GetMostRecentDestWindow();
-@@ -6153,24 +6162,32 @@ drag_leave_event_cb(GtkWidget *aWidget,
- }
-
- LOGDRAG(("nsWindow drag-leave signal for %p\n",
- (void*)mostRecentDragWindow));
-
- dragService->ScheduleLeaveEvent();
- }
-
--
--static gboolean
--drag_drop_event_cb(GtkWidget *aWidget,
-- GdkDragContext *aDragContext,
-- gint aX,
-- gint aY,
-- guint aTime,
-- gpointer aData)
-+static void
-+drag_leave_event_cb(GtkWidget *aWidget,
-+ GdkDragContext *aDragContext,
-+ guint aTime,
-+ gpointer aData)
-+{
-+ WindowDragLeaveHandler(aWidget);
-+}
-+
-+gboolean
-+WindowDragDropHandler(GtkWidget *aWidget,
-+ GdkDragContext *aDragContext,
-+ nsWaylandDragContext *aWaylandDragContext,
-+ gint aX,
-+ gint aY,
-+ guint aTime)
- {
- RefPtr<nsWindow> window = get_window_for_gtk_widget(aWidget);
- if (!window)
- return FALSE;
-
- // figure out which internal widget this drag motion actually happened on
- nscoord retx = 0;
- nscoord rety = 0;
-@@ -6185,20 +6202,31 @@ drag_drop_event_cb(GtkWidget *aWidget,
- }
-
- LOGDRAG(("nsWindow drag-drop signal for %p\n", (void*)innerMostWindow));
-
- LayoutDeviceIntPoint point = window->GdkPointToDevicePixels({ retx, rety });
-
- RefPtr<nsDragService> dragService = nsDragService::GetInstance();
- return dragService->
-- ScheduleDropEvent(innerMostWindow, aDragContext,
-+ ScheduleDropEvent(innerMostWindow, aDragContext, aWaylandDragContext,
- point, aTime);
- }
-
-+static gboolean
-+drag_drop_event_cb(GtkWidget *aWidget,
-+ GdkDragContext *aDragContext,
-+ gint aX,
-+ gint aY,
-+ guint aTime,
-+ gpointer aData)
-+{
-+ return WindowDragDropHandler(aWidget, aDragContext, nullptr, aX, aY, aTime);
-+}
-+
- static void
- drag_data_received_event_cb(GtkWidget *aWidget,
- GdkDragContext *aDragContext,
- gint aX,
- gint aY,
- GtkSelectionData *aSelectionData,
- guint aInfo,
- guint aTime,
-diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h
---- a/widget/gtk/nsWindow.h
-+++ b/widget/gtk/nsWindow.h
-@@ -61,16 +61,31 @@ extern mozilla::LazyLogModule gWidgetDra
-
- #define LOG(args)
- #define LOGFOCUS(args)
- #define LOGDRAG(args)
- #define LOGDRAW(args)
-
- #endif /* MOZ_LOGGING */
-
-+#ifdef MOZ_WAYLAND
-+class nsWaylandDragContext;
-+
-+gboolean
-+WindowDragMotionHandler(GtkWidget *aWidget, GdkDragContext *aDragContext,
-+ nsWaylandDragContext *aWaylandDragContext,
-+ gint aX, gint aY, guint aTime);
-+gboolean
-+WindowDragDropHandler(GtkWidget *aWidget, GdkDragContext *aDragContext,
-+ nsWaylandDragContext *aWaylandDragContext, gint aX, gint aY,
-+ guint aTime);
-+void
-+WindowDragLeaveHandler(GtkWidget *aWidget);
-+#endif
-+
- class gfxPattern;
-
- namespace mozilla {
- class TimeStamp;
- class CurrentX11TimeGetter;
- }
-
- class nsWindow final : public nsBaseWidget
-
bgstack15