summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Stransky <stransky@redhat.com>2018-05-25 12:50:35 +0200
committerMartin Stransky <stransky@redhat.com>2018-05-25 12:50:35 +0200
commitdd0eb4d9d89c3b796044c7fac8397c8713c5cdeb (patch)
treea784b13aa5a0fb07ed8cc7c7f50ecdb3650c2e12
parentUpdate to 60.0.1 (diff)
downloadlibrewolf-fedora-ff-dd0eb4d9d89c3b796044c7fac8397c8713c5cdeb.tar.gz
librewolf-fedora-ff-dd0eb4d9d89c3b796044c7fac8397c8713c5cdeb.tar.bz2
librewolf-fedora-ff-dd0eb4d9d89c3b796044c7fac8397c8713c5cdeb.zip
Enable Wayland backend
-rw-r--r--firefox-wayland.desktop233
-rw-r--r--firefox.spec46
-rw-r--r--mozilla-1438131.patch1558
-rw-r--r--mozilla-1438136.patch34
-rw-r--r--mozilla-1460603.patch46
-rw-r--r--mozilla-1460605-1.patch40
-rw-r--r--mozilla-1460605-2.patch292
-rw-r--r--mozilla-1460810.patch30
-rw-r--r--mozilla-1461306.patch33
-rw-r--r--mozilla-1462622.patch36
-rw-r--r--mozilla-1462642.patch183
-rw-r--r--mozilla-1463753.patch127
-rw-r--r--rb244010.patch149
-rw-r--r--rb244012.patch44
-rw-r--r--rb246410.patch314
15 files changed, 3160 insertions, 5 deletions
diff --git a/firefox-wayland.desktop b/firefox-wayland.desktop
new file mode 100644
index 0000000..ad375b0
--- /dev/null
+++ b/firefox-wayland.desktop
@@ -0,0 +1,233 @@
+[Desktop Entry]
+Version=1.0
+Name=Firefox on Wayland
+GenericName=Web Browser
+Comment=Browse the Web
+Exec=firefox-wayland %u
+Icon=firefox
+Terminal=false
+Type=Application
+MimeType=text/html;text/xml;application/xhtml+xml;application/vnd.mozilla.xul+xml;text/mml;x-scheme-handler/http;x-scheme-handler/https;
+StartupNotify=true
+Categories=Network;WebBrowser;
+Keywords=web;browser;internet;
+Actions=new-window;new-private-window;
+
+[Desktop Action new-window]
+Name=Open a New Window
+Name[ach]=Dirica manyen
+Name[af]=Nuwe venster
+Name[an]=Nueva finestra
+Name[ar]=نافذة جديدة
+Name[as]=নতুন উইন্ডো
+Name[ast]=Ventana nueva
+Name[az]=Yeni Pəncərə
+Name[be]=Новае акно
+Name[bg]=Нов прозорец
+Name[bn-BD]=নতুন উইন্ডো (N)
+Name[bn-IN]=নতুন উইন্ডো
+Name[br]=Prenestr nevez
+Name[brx]=गोदान उइन्ड'(N)
+Name[bs]=Novi prozor
+Name[ca]=Finestra nova
+Name[cak]=K'ak'a' tzuwäch
+Name[cs]=Nové okno
+Name[cy]=Ffenestr Newydd
+Name[da]=Nyt vindue
+Name[de]=Neues Fenster
+Name[dsb]=Nowe wokno
+Name[el]=Νέο παράθυρο
+Name[en-GB]=New Window
+Name[en-US]=New Window
+Name[en-ZA]=New Window
+Name[eo]=Nova fenestro
+Name[es-AR]=Nueva ventana
+Name[es-CL]=Nueva ventana
+Name[es-ES]=Nueva ventana
+Name[es-MX]=Nueva ventana
+Name[et]=Uus aken
+Name[eu]=Leiho berria
+Name[fa]=پنجره جدید‌
+Name[ff]=Henorde Hesere
+Name[fi]=Uusi ikkuna
+Name[fr]=Nouvelle fenêtre
+Name[fy-NL]=Nij finster
+Name[ga-IE]=Fuinneog Nua
+Name[gd]=Uinneag ùr
+Name[gl]=Nova xanela
+Name[gn]=Ovetã pyahu
+Name[gu-IN]=નવી વિન્ડો
+Name[he]=חלון חדש
+Name[hi-IN]=नया विंडो
+Name[hr]=Novi prozor
+Name[hsb]=Nowe wokno
+Name[hu]=Új ablak
+Name[hy-AM]=Նոր Պատուհան
+Name[id]=Jendela Baru
+Name[is]=Nýr gluggi
+Name[it]=Nuova finestra
+Name[ja]=新しいウィンドウ
+Name[ja-JP-mac]=新規ウインドウ
+Name[ka]=ახალი ფანჯარა
+Name[kk]=Жаңа терезе
+Name[km]=បង្អួច​​​ថ្មី
+Name[kn]=ಹೊಸ ಕಿಟಕಿ
+Name[ko]=새 창
+Name[kok]=नवें जनेल
+Name[ks]=نئئ وِنڈو
+Name[lij]=Neuvo barcon
+Name[lo]=ຫນ້າຕ່າງໃຫມ່
+Name[lt]=Naujas langas
+Name[ltg]=Jauns lūgs
+Name[lv]=Jauns logs
+Name[mai]=नव विंडो
+Name[mk]=Нов прозорец
+Name[ml]=പുതിയ ജാലകം
+Name[mr]=नवीन पटल
+Name[ms]=Tetingkap Baru
+Name[my]=ဝင်းဒိုးအသစ်
+Name[nb-NO]=Nytt vindu
+Name[ne-NP]=नयाँ सञ्झ्याल
+Name[nl]=Nieuw venster
+Name[nn-NO]=Nytt vindauge
+Name[or]=ନୂତନ ୱିଣ୍ଡୋ
+Name[pa-IN]=ਨਵੀਂ ਵਿੰਡੋ
+Name[pl]=Nowe okno
+Name[pt-BR]=Nova janela
+Name[pt-PT]=Nova janela
+Name[rm]=Nova fanestra
+Name[ro]=Fereastră nouă
+Name[ru]=Новое окно
+Name[sat]=नावा विंडो (N)
+Name[si]=නව කවුළුවක්
+Name[sk]=Nové okno
+Name[sl]=Novo okno
+Name[son]=Zanfun taaga
+Name[sq]=Dritare e Re
+Name[sr]=Нови прозор
+Name[sv-SE]=Nytt fönster
+Name[ta]=புதிய சாளரம்
+Name[te]=కొత్త విండో
+Name[th]=หน้าต่างใหม่
+Name[tr]=Yeni pencere
+Name[tsz]=Eraatarakua jimpani
+Name[uk]=Нове вікно
+Name[ur]=نیا دریچہ
+Name[uz]=Yangi oyna
+Name[vi]=Cửa sổ mới
+Name[wo]=Palanteer bu bees
+Name[xh]=Ifestile entsha
+Name[zh-CN]=新建窗口
+Name[zh-TW]=開新視窗
+
+
+Exec=firefox-wayland %u
+
+[Desktop Action new-private-window]
+Name=Open a New Private Window
+Name[ach]=Dirica manyen me mung
+Name[af]=Nuwe privaatvenster
+Name[an]=Nueva finestra privada
+Name[ar]=نافذة خاصة جديدة
+Name[as]=নতুন ব্যক্তিগত উইন্ডো
+Name[ast]=Ventana privada nueva
+Name[az]=Yeni Məxfi Pəncərə
+Name[be]=Новае акно адасаблення
+Name[bg]=Нов прозорец за поверително сърфиране
+Name[bn-BD]=নতুন ব্যক্তিগত উইন্ডো
+Name[bn-IN]=নতুন ব্যক্তিগত উইন্ডো
+Name[br]=Prenestr merdeiñ prevez nevez
+Name[brx]=गोदान प्राइभेट उइन्ड'
+Name[bs]=Novi privatni prozor
+Name[ca]=Finestra privada nova
+Name[cak]=K'ak'a' ichinan tzuwäch
+Name[cs]=Nové anonymní okno
+Name[cy]=Ffenestr Breifat Newydd
+Name[da]=Nyt privat vindue
+Name[de]=Neues privates Fenster
+Name[dsb]=Nowe priwatne wokno
+Name[el]=Νέο παράθυρο ιδιωτικής περιήγησης
+Name[en-GB]=New Private Window
+Name[en-US]=New Private Window
+Name[en-ZA]=New Private Window
+Name[eo]=Nova privata fenestro
+Name[es-AR]=Nueva ventana privada
+Name[es-CL]=Nueva ventana privada
+Name[es-ES]=Nueva ventana privada
+Name[es-MX]=Nueva ventana privada
+Name[et]=Uus privaatne aken
+Name[eu]=Leiho pribatu berria
+Name[fa]=پنجره ناشناس جدید
+Name[ff]=Henorde Suturo Hesere
+Name[fi]=Uusi yksityinen ikkuna
+Name[fr]=Nouvelle fenêtre de navigation privée
+Name[fy-NL]=Nij priveefinster
+Name[ga-IE]=Fuinneog Nua Phríobháideach
+Name[gd]=Uinneag phrìobhaideach ùr
+Name[gl]=Nova xanela privada
+Name[gn]=Ovetã ñemi pyahu
+Name[gu-IN]=નવી ખાનગી વિન્ડો
+Name[he]=חלון פרטי חדש
+Name[hi-IN]=नयी निजी विंडो
+Name[hr]=Novi privatni prozor
+Name[hsb]=Nowe priwatne wokno
+Name[hu]=Új privát ablak
+Name[hy-AM]=Սկսել Գաղտնի դիտարկում
+Name[id]=Jendela Mode Pribadi Baru
+Name[is]=Nýr huliðsgluggi
+Name[it]=Nuova finestra anonima
+Name[ja]=新しいプライベートウィンドウ
+Name[ja-JP-mac]=新規プライベートウインドウ
+Name[ka]=ახალი პირადი ფანჯარა
+Name[kk]=Жаңа жекелік терезе
+Name[km]=បង្អួច​ឯកជន​ថ្មី
+Name[kn]=ಹೊಸ ಖಾಸಗಿ ಕಿಟಕಿ
+Name[ko]=새 사생활 보호 모드
+Name[kok]=नवो खाजगी विंडो
+Name[ks]=نْو پرایوٹ وینڈو&amp;
+Name[lij]=Neuvo barcon privou
+Name[lo]=ເປີດຫນ້າຕ່າງສວນຕົວຂື້ນມາໃຫມ່
+Name[lt]=Naujas privataus naršymo langas
+Name[ltg]=Jauns privatais lūgs
+Name[lv]=Jauns privātais logs
+Name[mai]=नया निज विंडो (W)
+Name[mk]=Нов приватен прозорец
+Name[ml]=പുതിയ സ്വകാര്യ ജാലകം
+Name[mr]=नवीन वैयक्तिक पटल
+Name[ms]=Tetingkap Persendirian Baharu
+Name[my]=New Private Window
+Name[nb-NO]=Nytt privat vindu
+Name[ne-NP]=नयाँ निजी सञ्झ्याल
+Name[nl]=Nieuw privévenster
+Name[nn-NO]=Nytt privat vindauge
+Name[or]=ନୂତନ ବ୍ୟକ୍ତିଗତ ୱିଣ୍ଡୋ
+Name[pa-IN]=ਨਵੀਂ ਪ੍ਰਾਈਵੇਟ ਵਿੰਡੋ
+Name[pl]=Nowe okno prywatne
+Name[pt-BR]=Nova janela privativa
+Name[pt-PT]=Nova janela privada
+Name[rm]=Nova fanestra privata
+Name[ro]=Fereastră privată nouă
+Name[ru]=Новое приватное окно
+Name[sat]=नावा निजेराक् विंडो (W )
+Name[si]=නව පුද්ගලික කවුළුව (W)
+Name[sk]=Nové okno v režime Súkromné prehliadanie
+Name[sl]=Novo zasebno okno
+Name[son]=Sutura zanfun taaga
+Name[sq]=Dritare e Re Private
+Name[sr]=Нови приватан прозор
+Name[sv-SE]=Nytt privat fönster
+Name[ta]=புதிய தனிப்பட்ட சாளரம்
+Name[te]=కొత్త ఆంతరంగిక విండో
+Name[th]=หน้าต่างส่วนตัวใหม่
+Name[tr]=Yeni gizli pencere
+Name[tsz]=Juchiiti eraatarakua jimpani
+Name[uk]=Приватне вікно
+Name[ur]=نیا نجی دریچہ
+Name[uz]=Yangi maxfiy oyna
+Name[vi]=Cửa sổ riêng tư mới
+Name[wo]=Panlanteeru biir bu bees
+Name[xh]=Ifestile yangasese entsha
+Name[zh-CN]=新建隐私浏览窗口
+Name[zh-TW]=新增隱私視窗
+Exec=firefox-wayland --private-window %u
+
diff --git a/firefox.spec b/firefox.spec
index 18b9d34..95aad1a 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -6,7 +6,7 @@
# for details.
#
# Build with Wayland Gtk+ backend?
-%global wayland_backend 0
+%global wayland_backend 1
# Use system hunspell?
%if 0%{?fedora} > 25
@@ -102,7 +102,7 @@
Summary: Mozilla Firefox Web browser
Name: firefox
Version: 60.0.1
-Release: 1%{?pre_tag}%{?dist}
+Release: 2%{?pre_tag}%{?dist}
URL: https://www.mozilla.org/firefox/
License: MPLv1.1 or GPLv2+ or LGPLv2+
Source0: https://hg.mozilla.org/releases/mozilla-release/archive/firefox-%{version}%{?pre_version}.source.tar.xz
@@ -119,6 +119,7 @@ Source25: firefox-symbolic.svg
Source26: distribution.ini
Source27: google-api-key
Source28: firefox-wayland.sh.in
+Source29: firefox-wayland.desktop
# Build patches
Patch3: mozilla-build-arm.patch
@@ -162,6 +163,21 @@ Patch417: bug1375074-save-restore-x28.patch
Patch421: complete-csd-window-offset-mozilla-1457691.patch
+# Wayland specific upstream patches
+Patch450: mozilla-1438131.patch
+Patch451: mozilla-1438136.patch
+Patch452: mozilla-1460603.patch
+Patch453: mozilla-1460605-1.patch
+Patch454: mozilla-1460605-2.patch
+Patch455: mozilla-1460810.patch
+Patch456: mozilla-1461306.patch
+Patch457: mozilla-1462622.patch
+Patch458: mozilla-1462642.patch
+Patch459: mozilla-1463753.patch
+Patch560: rb244010.patch
+Patch561: rb244012.patch
+Patch562: rb246410.patch
+
# Debian patches
Patch500: mozilla-440908.patch
@@ -339,6 +355,23 @@ This package contains results of tests executed during build.
%patch26 -p1 -b .icu
%endif
+# Wayland specific upstream patches
+%if %{?wayland_backend}
+%patch453 -p1 -b .mozilla-1460605-1
+%patch454 -p1 -b .mozilla-1460605-2
+%patch455 -p1 -b .mozilla-1460810
+%patch456 -p1 -b .mozilla-1461306
+%patch457 -p1 -b .mozilla-1462622
+%patch451 -p1 -b .mozilla-1438136
+%patch450 -p1 -b .mozilla-1438131
+%patch459 -p1 -b .mozilla-1463753
+%patch458 -p1 -b .mozilla-1462642
+%patch452 -p1 -b .mozilla-1460603
+%patch560 -p1 -b .rb244010
+%patch561 -p1 -b .rb244012
+%patch562 -p1 -b .rb246410
+%endif
+
%{__rm} -f .mozconfig
%{__cp} %{SOURCE10} .mozconfig
%if %{?wayland_backend}
@@ -596,6 +629,9 @@ DESTDIR=%{buildroot} make -C objdir install
%{__mkdir_p} %{buildroot}{%{_libdir},%{_bindir},%{_datadir}/applications}
desktop-file-install --dir %{buildroot}%{_datadir}/applications %{SOURCE20}
+%if %{?wayland_backend}
+desktop-file-install --dir %{buildroot}%{_datadir}/applications %{SOURCE29}
+%endif
# set up the firefox start script
%{__rm} -rf %{buildroot}%{_bindir}/firefox
@@ -744,9 +780,6 @@ sed -i -e "s/\[Crash Reporter\]/[Crash Reporter]\nEnabled=1/" %{buildroot}/%{moz
# Default
%{__cp} %{SOURCE12} %{buildroot}%{mozappdir}/browser/defaults/preferences
-%if %{?wayland_backend}
-echo 'pref("webgl.force-enabled",true);' >> %{buildroot}%{mozappdir}/browser/defaults/preferences
-%endif
# Copy over run-mozilla.sh
%{__cp} build/unix/run-mozilla.sh %{buildroot}%{mozappdir}
@@ -873,6 +906,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
#---------------------------------------------------------------------
%changelog
+* Fri May 25 2018 Martin Stransky <stransky@redhat.com> - 60.0.1-2
+- Enable Wayland backend.
+
* Wed May 23 2018 Jan Horak <jhorak@redhat.com> - 60.0.1-1
- Update to 60.0.1
diff --git a/mozilla-1438131.patch b/mozilla-1438131.patch
new file mode 100644
index 0000000..e77186d
--- /dev/null
+++ b/mozilla-1438131.patch
@@ -0,0 +1,1558 @@
+
+# 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
+
diff --git a/mozilla-1438136.patch b/mozilla-1438136.patch
new file mode 100644
index 0000000..6462a41
--- /dev/null
+++ b/mozilla-1438136.patch
@@ -0,0 +1,34 @@
+
+# HG changeset patch
+# User Evan Klitzke <evan@eklitzke.org>
+# Date 1526337180 -10800
+# Node ID 5c1d015760f220f5438ffa23a585140db7a9801d
+# Parent 505667081ae29ee0a66ef5ba19c3870570b08564
+Bug 1438136 - [Wayland/Clipboard] Null terminate text string returned by GetClipboardText(), r=stransky
+
+diff --git a/widget/gtk/nsClipboardWayland.cpp b/widget/gtk/nsClipboardWayland.cpp
+--- a/widget/gtk/nsClipboardWayland.cpp
++++ b/widget/gtk/nsClipboardWayland.cpp
+@@ -666,19 +666,20 @@ 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<char*>(
+- g_malloc(sizeof(char)*mClipboardDataLength));
++ 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,
+
diff --git a/mozilla-1460603.patch b/mozilla-1460603.patch
new file mode 100644
index 0000000..3e705b5
--- /dev/null
+++ b/mozilla-1460603.patch
@@ -0,0 +1,46 @@
+diff -up firefox-60.0.1/gfx/gl/GLLibraryEGL.cpp.mozilla-1460603 firefox-60.0.1/gfx/gl/GLLibraryEGL.cpp
+--- firefox-60.0.1/gfx/gl/GLLibraryEGL.cpp.mozilla-1460603 2018-05-16 07:38:30.000000000 +0200
++++ firefox-60.0.1/gfx/gl/GLLibraryEGL.cpp 2018-05-25 10:58:45.170047851 +0200
+@@ -31,6 +31,13 @@
+ #include "GLContextProvider.h"
+ #include "gfxPrefs.h"
+ #include "ScopedGLHelpers.h"
++#ifdef MOZ_WIDGET_GTK
++#include <gdk/gdk.h>
++#ifdef MOZ_WAYLAND
++#include <gdk/gdkwayland.h>
++#include <dlfcn.h>
++#endif // MOZ_WIDGET_GTK
++#endif // MOZ_WAYLAND
+
+ namespace mozilla {
+ namespace gl {
+@@ -566,7 +573,22 @@ GLLibraryEGL::EnsureInitialized(bool for
+ mIsWARP = true;
+ }
+ } else {
+- chosenDisplay = GetAndInitDisplay(*this, EGL_DEFAULT_DISPLAY);
++ void *nativeDisplay = EGL_DEFAULT_DISPLAY;
++#ifdef MOZ_WAYLAND
++ // Some drivers doesn't support EGL_DEFAULT_DISPLAY
++ GdkDisplay *gdkDisplay = gdk_display_get_default();
++ if (GDK_IS_WAYLAND_DISPLAY(gdkDisplay)) {
++ static auto sGdkWaylandDisplayGetWlDisplay =
++ (wl_display *(*)(GdkDisplay *))
++ dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display");
++ nativeDisplay = sGdkWaylandDisplayGetWlDisplay(gdkDisplay);
++ if (!nativeDisplay) {
++ NS_WARNING("Failed to get wl_display.");
++ return false;
++ }
++ }
++#endif
++ chosenDisplay = GetAndInitDisplay(*this, nativeDisplay);
+ }
+
+ if (!chosenDisplay) {
+@@ -872,4 +894,3 @@ AfterEGLCall(const char* glFunction)
+
+ } /* namespace gl */
+ } /* namespace mozilla */
+-
diff --git a/mozilla-1460605-1.patch b/mozilla-1460605-1.patch
new file mode 100644
index 0000000..70806bf
--- /dev/null
+++ b/mozilla-1460605-1.patch
@@ -0,0 +1,40 @@
+
+# HG changeset patch
+# User Martin Stransky <stransky@redhat.com>
+# Date 1525961643 -7200
+# Node ID c085f9360dfa4d0fc3d04d6db40d37e1369616b3
+# Parent acaaa40ebdf142fda38d5661f7631f029a2406c6
+Bug 1460605 - Use NS_NATIVE_EGL_WINDOW instead of NS_NATIVE_WINDOW on GTK r=lsalzman
+
+Original patch author is Takuro Ashie <ashie@clear-code.com>
+
+NS_NATIVE_EGL_WINDOW is exported by Gtk toolkit code and provides both X11 window
+handle for X11 Gtk backend and EGL window handle for Wayland backend.
+
+MozReview-Commit-ID: DEmlaLL7zGY
+
+diff --git a/gfx/gl/GLContextProviderEGL.cpp b/gfx/gl/GLContextProviderEGL.cpp
+--- a/gfx/gl/GLContextProviderEGL.cpp
++++ b/gfx/gl/GLContextProviderEGL.cpp
+@@ -1,18 +1,16 @@
+ /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ #if defined(MOZ_WIDGET_GTK)
+- #include <gdk/gdkx.h>
+- // we're using default display for now
+- #define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) ((EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow*)aWidget->GetNativeData(NS_NATIVE_WINDOW)))
+- #define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) ((EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow*)aWidget->RealWidget()->GetNativeData(NS_NATIVE_WINDOW)))
++ #define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_EGL_WINDOW))
++ #define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->RealWidget()->GetNativeData(NS_NATIVE_EGL_WINDOW))
+ #elif defined(MOZ_WIDGET_ANDROID)
+ #define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_JAVA_SURFACE))
+ #define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) (aWidget->AsAndroid()->GetEGLNativeWindow())
+ #elif defined(XP_WIN)
+ #define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
+ #define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->AsWindows()->GetHwnd())
+ #else
+ #define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
+
diff --git a/mozilla-1460605-2.patch b/mozilla-1460605-2.patch
new file mode 100644
index 0000000..157e2fd
--- /dev/null
+++ b/mozilla-1460605-2.patch
@@ -0,0 +1,292 @@
+
+# HG changeset patch
+# User Martin Stransky <stransky@redhat.com>
+# Date 1525961060 -7200
+# Node ID acaaa40ebdf142fda38d5661f7631f029a2406c6
+# Parent 5543294befe9494593370f33c40ba50c8239e0c6
+Bug 1460605 - Provide NS_NATIVE_EGL_WINDOW to get a native EGL window on Wayland, r=jhorak
+
+Original patch author is Takuro Ashie <ashie@clear-code.com>
+
+Provide ability to create native EGL window and provide it under NS_NATIVE_EGL_WINDOW
+to GL code. The native EGL window is owned/managed by mozcontainer.
+
+MozReview-Commit-ID: 4d0Kk6DRSaD
+
+diff --git a/config/system-headers.mozbuild b/config/system-headers.mozbuild
+--- a/config/system-headers.mozbuild
++++ b/config/system-headers.mozbuild
+@@ -1334,8 +1334,14 @@ if CONFIG['MOZ_SYSTEM_ICU']:
+ 'unicode/unistr.h',
+ 'unicode/unorm.h',
+ 'unicode/unum.h',
+ 'unicode/upluralrules.h',
+ 'unicode/ureldatefmt.h',
+ 'unicode/ustring.h',
+ 'unicode/utypes.h',
+ ]
++
++if CONFIG['MOZ_WAYLAND']:
++ system_headers += [
++ 'wayland-client.h',
++ 'wayland-egl.h',
++ ]
+diff --git a/widget/gtk/mozcontainer.cpp b/widget/gtk/mozcontainer.cpp
+--- a/widget/gtk/mozcontainer.cpp
++++ b/widget/gtk/mozcontainer.cpp
+@@ -5,16 +5,17 @@
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ #include "mozcontainer.h"
+ #include <gtk/gtk.h>
+ #ifdef MOZ_WAYLAND
+ #include <gdk/gdkx.h>
+ #include <gdk/gdkwayland.h>
++#include <wayland-egl.h>
+ #endif
+ #include <stdio.h>
+ #include <dlfcn.h>
+
+ #ifdef ACCESSIBILITY
+ #include <atk/atk.h>
+ #include "maiRedundantObjectFactory.h"
+ #endif
+@@ -202,16 +203,21 @@ void
+ moz_container_init (MozContainer *container)
+ {
+ gtk_widget_set_can_focus(GTK_WIDGET(container), TRUE);
+ gtk_container_set_resize_mode(GTK_CONTAINER(container), GTK_RESIZE_IMMEDIATE);
+ gtk_widget_set_redraw_on_allocate(GTK_WIDGET(container), FALSE);
+
+ #if defined(MOZ_WAYLAND)
+ {
++ container->subcompositor = nullptr;
++ container->surface = nullptr;
++ container->subsurface = nullptr;
++ container->eglwindow = nullptr;
++
+ GdkDisplay *gdk_display = gtk_widget_get_display(GTK_WIDGET(container));
+ if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) {
+ // Available as of GTK 3.8+
+ static auto sGdkWaylandDisplayGetWlDisplay =
+ (wl_display *(*)(GdkDisplay *))
+ dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display");
+
+ wl_display* display = sGdkWaylandDisplayGetWlDisplay(gdk_display);
+@@ -284,16 +290,17 @@ moz_container_map_surface(MozContainer *
+ wl_region_destroy(region);
+ }
+ return true;
+ }
+
+ static void
+ moz_container_unmap_surface(MozContainer *container)
+ {
++ g_clear_pointer(&container->eglwindow, wl_egl_window_destroy);
+ g_clear_pointer(&container->subsurface, wl_subsurface_destroy);
+ g_clear_pointer(&container->surface, wl_surface_destroy);
+ }
+
+ #endif
+
+ void
+ moz_container_map (GtkWidget *widget)
+@@ -429,16 +436,21 @@ moz_container_size_allocate (GtkWidget
+ // We need to position our subsurface according to GdkWindow
+ // when offset changes (GdkWindow is maximized for instance).
+ // see gtk-clutter-embed.c for reference.
+ if (container->subsurface) {
+ gint x, y;
+ gdk_window_get_position(gtk_widget_get_window(widget), &x, &y);
+ wl_subsurface_set_position(container->subsurface, x, y);
+ }
++ if (container->eglwindow) {
++ wl_egl_window_resize(container->eglwindow,
++ allocation->width, allocation->height,
++ 0, 0);
++ }
+ #endif
+ }
+
+ void
+ moz_container_remove (GtkContainer *container, GtkWidget *child_widget)
+ {
+ MozContainerChild *child;
+ MozContainer *moz_container;
+@@ -554,9 +566,32 @@ moz_container_get_wl_surface(MozContaine
+ if (!gdk_window_is_visible(window))
+ return nullptr;
+
+ moz_container_map_surface(container);
+ }
+
+ return container->surface;
+ }
++
++struct wl_egl_window *
++moz_container_get_wl_egl_window(MozContainer *container)
++{
++ if (!container->eglwindow) {
++ struct wl_surface *wlsurf = moz_container_get_wl_surface(container);
++ if (!wlsurf)
++ return nullptr;
++
++ GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(container));
++ container->eglwindow
++ = wl_egl_window_create(wlsurf,
++ gdk_window_get_width(window),
++ gdk_window_get_height(window));
++ }
++ return container->eglwindow;
++}
++
++gboolean
++moz_container_has_wl_egl_window(MozContainer *container)
++{
++ return container->eglwindow ? true : false;
++}
+ #endif
+diff --git a/widget/gtk/mozcontainer.h b/widget/gtk/mozcontainer.h
+--- a/widget/gtk/mozcontainer.h
++++ b/widget/gtk/mozcontainer.h
+@@ -67,16 +67,17 @@ struct _MozContainer
+ {
+ GtkContainer container;
+ GList *children;
+
+ #ifdef MOZ_WAYLAND
+ struct wl_subcompositor *subcompositor;
+ struct wl_surface *surface;
+ struct wl_subsurface *subsurface;
++ struct wl_egl_window *eglwindow;
+ #endif
+ };
+
+ struct _MozContainerClass
+ {
+ GtkContainerClass parent_class;
+ };
+
+@@ -90,11 +91,13 @@ void moz_container_move (
+ GtkWidget *child_widget,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+
+ #ifdef MOZ_WAYLAND
+ struct wl_surface* moz_container_get_wl_surface(MozContainer *container);
++struct wl_egl_window* moz_container_get_wl_egl_window(MozContainer *container);
++gboolean moz_container_has_wl_egl_window(MozContainer *container);
+ #endif
+
+ #endif /* __MOZ_CONTAINER_H__ */
+diff --git a/widget/gtk/mozwayland/mozwayland.c b/widget/gtk/mozwayland/mozwayland.c
+--- a/widget/gtk/mozwayland/mozwayland.c
++++ b/widget/gtk/mozwayland/mozwayland.c
+@@ -266,8 +266,26 @@ wl_display_read_events(struct wl_display
+ return -1;
+ }
+
+ MOZ_EXPORT void
+ wl_log_set_handler_client(wl_log_func_t handler)
+ {
+ }
+
++MOZ_EXPORT struct wl_egl_window *
++wl_egl_window_create(struct wl_surface *surface,
++ int width, int height)
++{
++ return NULL;
++}
++
++MOZ_EXPORT void
++wl_egl_window_destroy(struct wl_egl_window *egl_window)
++{
++}
++
++MOZ_EXPORT void
++wl_egl_window_resize(struct wl_egl_window *egl_window,
++ int width, int height,
++ int dx, int dy)
++{
++}
+diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
+--- a/widget/gtk/nsWindow.cpp
++++ b/widget/gtk/nsWindow.cpp
+@@ -1734,16 +1734,25 @@ nsWindow::GetNativeData(uint32_t aDataTy
+ return mIMContext.get();
+ }
+ case NS_NATIVE_OPENGL_CONTEXT:
+ return nullptr;
+ #ifdef MOZ_X11
+ case NS_NATIVE_COMPOSITOR_DISPLAY:
+ return gfxPlatformGtk::GetPlatform()->GetCompositorDisplay();
+ #endif // MOZ_X11
++ case NS_NATIVE_EGL_WINDOW: {
++ if (mIsX11Display)
++ return mGdkWindow ? (void*)GDK_WINDOW_XID(mGdkWindow) : nullptr;
++#ifdef MOZ_WAYLAND
++ if (mContainer)
++ return moz_container_get_wl_egl_window(mContainer);
++#endif
++ return nullptr;
++ }
+ default:
+ NS_WARNING("nsWindow::GetNativeData called with bad value");
+ return nullptr;
+ }
+ }
+
+ nsresult
+ nsWindow::SetTitle(const nsAString& aTitle)
+@@ -4303,16 +4312,26 @@ nsWindow::NativeShow(bool aAction)
+ else if (mContainer) {
+ gtk_widget_show(GTK_WIDGET(mContainer));
+ }
+ else if (mGdkWindow) {
+ gdk_window_show_unraised(mGdkWindow);
+ }
+ }
+ else {
++#ifdef MOZ_WAYLAND
++ if (mContainer && moz_container_has_wl_egl_window(mContainer)) {
++ // Because wl_egl_window is destroyed on moz_container_unmap(),
++ // the current compositor cannot use it anymore. To avoid crash,
++ // destroy the compositor & recreate a new compositor on next
++ // expose event.
++ DestroyLayerManager();
++ }
++#endif
++
+ if (mIsTopLevel) {
+ // Workaround window freezes on GTK versions before 3.21.2 by
+ // ensuring that configure events get dispatched to windows before
+ // they are unmapped. See bug 1225044.
+ if (gtk_check_version(3, 21, 2) != nullptr && mPendingConfigures > 0) {
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(GTK_WIDGET(mShell), &allocation);
+
+diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h
+--- a/widget/nsIWidget.h
++++ b/widget/nsIWidget.h
+@@ -138,16 +138,17 @@ typedef void* nsNativeWidget;
+ #define NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW 105
+ #endif
+ #if defined(MOZ_WIDGET_GTK)
+ // set/get nsPluginNativeWindowGtk, e10s specific
+ #define NS_NATIVE_PLUGIN_OBJECT_PTR 104
+ #ifdef MOZ_X11
+ #define NS_NATIVE_COMPOSITOR_DISPLAY 105
+ #endif // MOZ_X11
++#define NS_NATIVE_EGL_WINDOW 106
+ #endif
+ #ifdef MOZ_WIDGET_ANDROID
+ #define NS_JAVA_SURFACE 100
+ #define NS_PRESENTATION_WINDOW 101
+ #define NS_PRESENTATION_SURFACE 102
+ #endif
+
+ // Must be kept in sync with xpcom/rust/xpcom/src/interfaces/nonidl.rs
+
diff --git a/mozilla-1460810.patch b/mozilla-1460810.patch
new file mode 100644
index 0000000..016f75f
--- /dev/null
+++ b/mozilla-1460810.patch
@@ -0,0 +1,30 @@
+# HG changeset patch
+# User Evan Klitzke <evan@eklitzke.org>
+# Parent c5e0ee17388381f96d0acf4bdd9d163827719096
+Bug 1460810 - [Gtk/Wayland] Handle error value (-1) returned by gtk_section_data_get_length(), r=stransky
+
+diff --git a/widget/gtk/nsClipboardWayland.cpp b/widget/gtk/nsClipboardWayland.cpp
+--- a/widget/gtk/nsClipboardWayland.cpp
++++ b/widget/gtk/nsClipboardWayland.cpp
+@@ -662,18 +662,19 @@ wayland_clipboard_contents_received(GtkC
+ delete fastTrack;
+ }
+
+ void
+ nsRetrievalContextWayland::TransferFastTrackClipboard(
+ int aClipboardRequestNumber, GtkSelectionData *aSelectionData)
+ {
+ if (mClipboardRequestNumber == aClipboardRequestNumber) {
+- mClipboardDataLength = gtk_selection_data_get_length(aSelectionData);
+- if (mClipboardDataLength > 0) {
++ int dataLength = gtk_selection_data_get_length(aSelectionData);
++ if (dataLength > 0) {
++ mClipboardDataLength = dataLength;
+ mClipboardData = reinterpret_cast<char*>(
+ g_malloc(sizeof(char)*mClipboardDataLength));
+ memcpy(mClipboardData, gtk_selection_data_get_data(aSelectionData),
+ sizeof(char)*mClipboardDataLength);
+ }
+ } else {
+ NS_WARNING("Received obsoleted clipboard data!");
+ }
diff --git a/mozilla-1461306.patch b/mozilla-1461306.patch
new file mode 100644
index 0000000..84ee6c6
--- /dev/null
+++ b/mozilla-1461306.patch
@@ -0,0 +1,33 @@
+
+# HG changeset patch
+# User Martin Stransky <stransky@redhat.com>
+# Date 1526299286 -7200
+# Node ID 6495ae9d01e06109539413c538fd25ed942f6eb8
+# Parent 67553a1262de53d0ec85fdfcf1a2b55631eaca44
+Bug 1461306 - [Wayland] Don't use sizeof() to get mime type array size, r=jhorak
+
+MozReview-Commit-ID: GE5helkqoUt
+
+diff --git a/widget/gtk/nsClipboardWayland.cpp b/widget/gtk/nsClipboardWayland.cpp
+--- a/widget/gtk/nsClipboardWayland.cpp
++++ b/widget/gtk/nsClipboardWayland.cpp
+@@ -723,17 +723,17 @@ const char*
+ nsRetrievalContextWayland::GetClipboardText(int32_t aWhichClipboard)
+ {
+ GdkAtom selection = GetSelectionAtom(aWhichClipboard);
+ DataOffer* dataOffer = (selection == GDK_SELECTION_PRIMARY) ?
+ mPrimaryOffer : mClipboardOffer;
+ if (!dataOffer)
+ return nullptr;
+
+- for (unsigned int i = 0; i < sizeof(sTextMimeTypes); i++) {
++ for (unsigned int i = 0; i < TEXT_MIME_TYPES_NUM; i++) {
+ if (dataOffer->HasTarget(sTextMimeTypes[i])) {
+ uint32_t unused;
+ return GetClipboardData(sTextMimeTypes[i], aWhichClipboard,
+ &unused);
+ }
+ }
+ return nullptr;
+ }
+
diff --git a/mozilla-1462622.patch b/mozilla-1462622.patch
new file mode 100644
index 0000000..a1903dc
--- /dev/null
+++ b/mozilla-1462622.patch
@@ -0,0 +1,36 @@
+
+# HG changeset patch
+# User Martin Stransky <stransky@redhat.com>
+# Date 1526647470 -7200
+# Node ID d41fee41e38400fab5da0689c1f49e30f80e2d1b
+# Parent d2b91476bebc48f9e89f9d3e6c7b33decb2ae941
+Bug 1462622 - [Gtk/Linux] Don't use GLXVsyncSource() on non-X11 displays, r=lsalzman
+
+MozReview-Commit-ID: BBtnNLWqSiq
+
+diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp
+--- a/gfx/thebes/gfxPlatformGtk.cpp
++++ b/gfx/thebes/gfxPlatformGtk.cpp
+@@ -736,18 +736,20 @@ private:
+ };
+
+ already_AddRefed<gfx::VsyncSource>
+ gfxPlatformGtk::CreateHardwareVsyncSource()
+ {
+ // Only use GLX vsync when the OpenGL compositor is being used.
+ // The extra cost of initializing a GLX context while blocking the main
+ // thread is not worth it when using basic composition.
++ // Also don't use it on non-X11 displays.
+ if (gfxConfig::IsEnabled(Feature::HW_COMPOSITING)) {
+- if (gl::sGLXLibrary.SupportsVideoSync()) {
++ if (GDK_IS_X11_DISPLAY(gdk_display_get_default()) &&
++ gl::sGLXLibrary.SupportsVideoSync()) {
+ RefPtr<VsyncSource> vsyncSource = new GLXVsyncSource();
+ VsyncSource::Display& display = vsyncSource->GetGlobalDisplay();
+ if (!static_cast<GLXVsyncSource::GLXDisplay&>(display).Setup()) {
+ NS_WARNING("Failed to setup GLContext, falling back to software vsync.");
+ return gfxPlatform::CreateHardwareVsyncSource();
+ }
+ return vsyncSource.forget();
+ }
+
diff --git a/mozilla-1462642.patch b/mozilla-1462642.patch
new file mode 100644
index 0000000..9bd6ab8
--- /dev/null
+++ b/mozilla-1462642.patch
@@ -0,0 +1,183 @@
+diff -up firefox-60.0.1/gfx/gl/GLContextEGL.h.mozilla-1462642 firefox-60.0.1/gfx/gl/GLContextEGL.h
+--- firefox-60.0.1/gfx/gl/GLContextEGL.h.mozilla-1462642 2018-05-16 07:38:29.000000000 +0200
++++ firefox-60.0.1/gfx/gl/GLContextEGL.h 2018-05-25 10:54:09.271902218 +0200
+@@ -133,6 +133,10 @@ protected:
+ static EGLSurface CreatePBufferSurfaceTryingPowerOfTwo(EGLConfig config,
+ EGLenum bindToTextureFormat,
+ gfx::IntSize& pbsize);
++#if defined(MOZ_WAYLAND)
++ static EGLSurface CreateWaylandBufferSurface(EGLConfig config,
++ gfx::IntSize& pbsize);
++#endif
+ #if defined(MOZ_WIDGET_ANDROID)
+ public:
+ EGLSurface CreateCompatibleSurface(void* aWindow);
+diff -up firefox-60.0.1/gfx/gl/GLContextProviderEGL.cpp.mozilla-1462642 firefox-60.0.1/gfx/gl/GLContextProviderEGL.cpp
+--- firefox-60.0.1/gfx/gl/GLContextProviderEGL.cpp.mozilla-1462642 2018-05-25 10:54:09.258902265 +0200
++++ firefox-60.0.1/gfx/gl/GLContextProviderEGL.cpp 2018-05-25 10:55:57.634553279 +0200
+@@ -63,6 +63,17 @@
+ #include "ScopedGLHelpers.h"
+ #include "TextureImageEGL.h"
+
++#if defined(MOZ_WAYLAND)
++#include "nsAutoPtr.h"
++#include "nsDataHashtable.h"
++
++#include <gtk/gtk.h>
++#include <gdk/gdkx.h>
++#include <gdk/gdkwayland.h>
++#include <wayland-egl.h>
++#include <dlfcn.h>
++#endif
++
+ using namespace mozilla::gfx;
+
+ namespace mozilla {
+@@ -70,6 +81,35 @@ namespace gl {
+
+ using namespace mozilla::widget;
+
++#if defined(MOZ_WAYLAND)
++class WaylandGLSurface {
++public:
++ WaylandGLSurface(struct wl_surface *aWaylandSurface,
++ struct wl_egl_window *aEGLWindow);
++ ~WaylandGLSurface();
++private:
++ struct wl_surface *mWaylandSurface;
++ struct wl_egl_window *mEGLWindow;
++};
++
++static nsDataHashtable<nsPtrHashKey<void>, WaylandGLSurface*>
++ sWaylandGLSurface;
++
++void
++DeleteWaylandGLSurface(EGLSurface surface)
++{
++ // We're running on Wayland which means our EGLSurface may
++ // have attached Wayland backend data which must be released.
++ if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) {
++ auto entry = sWaylandGLSurface.Lookup(surface);
++ if (entry) {
++ delete entry.Data();
++ entry.Remove();
++ }
++ }
++}
++#endif
++
+ #define ADD_ATTR_2(_array, _k, _v) do { \
+ (_array).AppendElement(_k); \
+ (_array).AppendElement(_v); \
+@@ -125,6 +165,9 @@ DestroySurface(EGLSurface oldSurface) {
+ EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+ sEGLLibrary.fDestroySurface(EGL_DISPLAY(), oldSurface);
++#if defined(MOZ_WAYLAND)
++ DeleteWaylandGLSurface(oldSurface);
++#endif
+ }
+ }
+
+@@ -588,6 +631,52 @@ TRY_AGAIN_POWER_OF_TWO:
+ return surface;
+ }
+
++#if defined(MOZ_WAYLAND)
++WaylandGLSurface::WaylandGLSurface(struct wl_surface *aWaylandSurface,
++ struct wl_egl_window *aEGLWindow)
++ : mWaylandSurface(aWaylandSurface)
++ , mEGLWindow(aEGLWindow)
++{
++}
++
++WaylandGLSurface::~WaylandGLSurface()
++{
++ wl_egl_window_destroy(mEGLWindow);
++ wl_surface_destroy(mWaylandSurface);
++}
++
++EGLSurface
++GLContextEGL::CreateWaylandBufferSurface(EGLConfig config,
++ mozilla::gfx::IntSize& pbsize)
++{
++ // Available as of GTK 3.8+
++ static auto sGdkWaylandDisplayGetWlCompositor =
++ (wl_compositor *(*)(GdkDisplay *))
++ dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_compositor");
++
++ if (!sGdkWaylandDisplayGetWlCompositor)
++ return nullptr;
++
++ struct wl_compositor *compositor =
++ sGdkWaylandDisplayGetWlCompositor(gdk_display_get_default());
++ struct wl_surface *wlsurface = wl_compositor_create_surface(compositor);
++ struct wl_egl_window *eglwindow =
++ wl_egl_window_create(wlsurface, pbsize.width, pbsize.height);
++
++ EGLSurface surface =
++ sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config, eglwindow, 0);
++
++ if (surface) {
++ WaylandGLSurface* waylandData =
++ new WaylandGLSurface(wlsurface, eglwindow);
++ auto entry = sWaylandGLSurface.LookupForAdd(surface);
++ entry.OrInsert([&waylandData](){ return waylandData; });
++ }
++
++ return surface;
++}
++#endif
++
+ static const EGLint kEGLConfigAttribsOffscreenPBuffer[] = {
+ LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PBUFFER_BIT,
+ LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
+@@ -807,7 +896,17 @@ FillContextAttribs(bool alpha, bool dept
+ bool es3, nsTArray<EGLint>* out)
+ {
+ out->AppendElement(LOCAL_EGL_SURFACE_TYPE);
++#if defined(MOZ_WAYLAND)
++ if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) {
++ // Wayland on desktop does not support PBuffer or FBO.
++ // We create a dummy wl_egl_window instead.
++ out->AppendElement(LOCAL_EGL_WINDOW_BIT);
++ } else {
++ out->AppendElement(LOCAL_EGL_PBUFFER_BIT);
++ }
++#else
+ out->AppendElement(LOCAL_EGL_PBUFFER_BIT);
++#endif
+
+ out->AppendElement(LOCAL_EGL_RENDERABLE_TYPE);
+ if (es3) {
+@@ -926,9 +1025,17 @@ GLContextEGL::CreateEGLPBufferOffscreenC
+ }
+
+ mozilla::gfx::IntSize pbSize(size);
+- EGLSurface surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
+- LOCAL_EGL_NONE,
+- pbSize);
++ EGLSurface surface = nullptr;
++#if defined(MOZ_WAYLAND)
++ if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) {
++ surface = GLContextEGL::CreateWaylandBufferSurface(config, pbSize);
++ } else
++#endif
++ {
++ surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
++ LOCAL_EGL_NONE,
++ pbSize);
++ }
+ if (!surface) {
+ *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_POT");
+ NS_WARNING("Failed to create PBuffer for context!");
+@@ -941,6 +1048,9 @@ GLContextEGL::CreateEGLPBufferOffscreenC
+ if (!gl) {
+ NS_WARNING("Failed to create GLContext from PBuffer");
+ sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface);
++#if defined(MOZ_WAYLAND)
++ DeleteWaylandGLSurface(surface);
++#endif
+ return nullptr;
+ }
+
diff --git a/mozilla-1463753.patch b/mozilla-1463753.patch
new file mode 100644
index 0000000..4e83fd4
--- /dev/null
+++ b/mozilla-1463753.patch
@@ -0,0 +1,127 @@
+
+# HG changeset patch
+# User Martin Stransky <stransky@redhat.com>
+# Date 1527155477 -7200
+# Node ID 172827af80fa02953e0c7723c0dee915c411c286
+# Parent a5c04fe7278db916b3efd5f06a5f2a9da0d64ad2
+Bug 1463753 - [DragAndDrop] Update mTarget(Wayland)DragContext unconditionally and check its validity after that, r=jhorak
+
+MozReview-Commit-ID: KiNaPDDVvLu
+
+diff --git a/widget/gtk/nsDragService.cpp b/widget/gtk/nsDragService.cpp
+--- a/widget/gtk/nsDragService.cpp
++++ b/widget/gtk/nsDragService.cpp
+@@ -1043,21 +1043,21 @@ nsDragService::IsDataFlavorSupported(con
+ }
+
+ // check the target context vs. this flavor, one at a time
+ GList *tmp = nullptr;
+ if (mTargetDragContext) {
+ tmp = gdk_drag_context_list_targets(mTargetDragContext);
+ }
+ #ifdef MOZ_WAYLAND
+- else {
++ else if (mTargetWaylandDragContext) {
+ tmp = mTargetWaylandDragContext->GetTargets();
+ }
++ GList *tmp_head = tmp;
+ #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));
+@@ -1095,21 +1095,23 @@ nsDragService::IsDataFlavorSupported(con
+ 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);
+ }
+
++#ifdef MOZ_WAYLAND
+ // mTargetWaylandDragContext->GetTargets allocates the list
+ // so we need to free it here.
+- if (!mTargetDragContext) {
++ if (!mTargetDragContext && tmp_head) {
+ g_list_free(tmp_head);
+ }
++#endif
+
+ return NS_OK;
+ }
+
+ void
+ nsDragService::ReplyToDragMotion(GdkDragContext* aDragContext)
+ {
+ MOZ_LOG(sDragLm, LogLevel::Debug,
+@@ -2007,23 +2009,19 @@ 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();
+- if (mTargetDragContext) {
+- mTargetDragContext.steal(mPendingDragContext);
+- }
++ mTargetDragContext.steal(mPendingDragContext);
+ #ifdef MOZ_WAYLAND
+- else {
+- mTargetWaylandDragContext = mPendingWaylandDragContext.forget();
+- }
++ 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.
+@@ -2056,17 +2054,17 @@ nsDragService::RunScheduledTask()
+ #endif
+ } else {
+ // Reply to tell the source whether we can drop and what
+ // action would be taken.
+ if (mTargetDragContext) {
+ ReplyToDragMotion(mTargetDragContext);
+ }
+ #ifdef MOZ_WAYLAND
+- else {
++ else if (mTargetWaylandDragContext) {
+ ReplyToDragMotion(mTargetWaylandDragContext);
+ }
+ #endif
+ }
+ }
+ }
+
+ if (task == eDragTaskDrop) {
+@@ -2123,17 +2121,17 @@ nsDragService::UpdateDragAction()
+
+ // default is to do nothing
+ int action = nsIDragService::DRAGDROP_ACTION_NONE;
+ GdkDragAction gdkAction = GDK_ACTION_DEFAULT;
+ if (mTargetDragContext) {
+ gdkAction = gdk_drag_context_get_actions(mTargetDragContext);
+ }
+ #ifdef MOZ_WAYLAND
+- else {
++ else if (mTargetWaylandDragContext) {
+ // 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;
+
diff --git a/rb244010.patch b/rb244010.patch
new file mode 100644
index 0000000..0df8c3b
--- /dev/null
+++ b/rb244010.patch
@@ -0,0 +1,149 @@
+diff --git a/gfx/gl/GLContextProviderWayland.cpp b/gfx/gl/GLContextProviderWayland.cpp
+new file mode 100644
+--- /dev/null
++++ b/gfx/gl/GLContextProviderWayland.cpp
+@@ -0,0 +1,99 @@
++/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
++/* This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#ifdef MOZ_WIDGET_GTK
++#include <gdk/gdk.h>
++#include <gdk/gdkx.h>
++#endif
++
++#include "GLContextProvider.h"
++
++namespace mozilla {
++namespace gl {
++
++using namespace mozilla::gfx;
++using namespace mozilla::widget;
++
++static class GLContextProviderGLX sGLContextProviderGLX;
++static class GLContextProviderEGL sGLContextProviderEGL;
++
++already_AddRefed<GLContext>
++GLContextProviderWayland::CreateWrappingExisting(void* aContext, void* aSurface)
++{
++ if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
++ return sGLContextProviderGLX.CreateWrappingExisting(aContext, aSurface);
++ } else {
++ return sGLContextProviderEGL.CreateWrappingExisting(aContext, aSurface);
++ }
++}
++
++already_AddRefed<GLContext>
++GLContextProviderWayland::CreateForCompositorWidget(CompositorWidget* aCompositorWidget, bool aForceAccelerated)
++{
++ if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
++ return sGLContextProviderGLX.CreateForCompositorWidget(aCompositorWidget, aForceAccelerated);
++ } else {
++ return sGLContextProviderEGL.CreateForCompositorWidget(aCompositorWidget, aForceAccelerated);
++ }
++}
++
++already_AddRefed<GLContext>
++GLContextProviderWayland::CreateForWindow(nsIWidget* aWidget,
++ bool aWebRender,
++ bool aForceAccelerated)
++{
++ if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
++ return sGLContextProviderGLX.CreateForWindow(aWidget, aWebRender, aForceAccelerated);
++ } else {
++ return sGLContextProviderEGL.CreateForWindow(aWidget, aWebRender, aForceAccelerated);
++ }
++}
++
++/*static*/ already_AddRefed<GLContext>
++GLContextProviderWayland::CreateHeadless(CreateContextFlags flags,
++ nsACString* const out_failureId)
++{
++ if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
++ return sGLContextProviderGLX.CreateHeadless(flags, out_failureId);
++ } else {
++ return sGLContextProviderEGL.CreateHeadless(flags, out_failureId);
++ }
++}
++
++/*static*/ already_AddRefed<GLContext>
++GLContextProviderWayland::CreateOffscreen(const IntSize& size,
++ const SurfaceCaps& minCaps,
++ CreateContextFlags flags,
++ nsACString* const out_failureId)
++{
++ if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
++ return sGLContextProviderGLX.CreateOffscreen(size, minCaps, flags, out_failureId);
++ } else {
++ return sGLContextProviderEGL.CreateOffscreen(size, minCaps, flags, out_failureId);
++ }
++}
++
++/*static*/ GLContext*
++GLContextProviderWayland::GetGlobalContext()
++{
++ if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
++ return sGLContextProviderGLX.GetGlobalContext();
++ } else {
++ return sGLContextProviderEGL.GetGlobalContext();
++ }
++}
++
++/*static*/ void
++GLContextProviderWayland::Shutdown()
++{
++ if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
++ sGLContextProviderGLX.Shutdown();
++ } else {
++ sGLContextProviderEGL.Shutdown();
++ }
++}
++
++} /* namespace gl */
++} /* namespace mozilla */
+diff --git a/gfx/gl/moz.build b/gfx/gl/moz.build
+--- a/gfx/gl/moz.build
++++ b/gfx/gl/moz.build
+@@ -8,17 +8,17 @@ gl_provider = 'Null'
+
+ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
+ gl_provider = 'WGL'
+ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
+ gl_provider = 'CGL'
+ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit':
+ gl_provider = 'EAGL'
+ elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
+- if CONFIG['MOZ_EGL_XRENDER_COMPOSITE'] or CONFIG['MOZ_WAYLAND']:
++ if CONFIG['MOZ_EGL_XRENDER_COMPOSITE']:
+ gl_provider = 'EGL'
+ else:
+ gl_provider = 'GLX'
+ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
+ gl_provider = 'EGL'
+
+ if CONFIG['MOZ_GL_PROVIDER']:
+ gl_provider = CONFIG['MOZ_GL_PROVIDER']
+@@ -114,16 +114,21 @@ elif gl_provider == 'GLX':
+ SOURCES += [
+ 'GLContextProviderGLX.cpp',
+ 'SharedSurfaceGLX.cpp'
+ ]
+ EXPORTS += [
+ 'SharedSurfaceGLX.h'
+ ]
+
++if CONFIG['MOZ_WAYLAND']:
++ SOURCES += [
++ 'GLContextProviderWayland.cpp',
++ ]
++
+ UNIFIED_SOURCES += [
+ 'AndroidSurfaceTexture.cpp',
+ 'DecomposeIntoNoRepeatTriangles.cpp',
+ 'EGLUtils.cpp',
+ 'GfxTexturesReporter.cpp',
+ 'GLBlitHelper.cpp',
+ 'GLContext.cpp',
+ 'GLContextFeatures.cpp',
+
diff --git a/rb244012.patch b/rb244012.patch
new file mode 100644
index 0000000..a096b0e
--- /dev/null
+++ b/rb244012.patch
@@ -0,0 +1,44 @@
+diff --git a/gfx/gl/GLContextProvider.h b/gfx/gl/GLContextProvider.h
+--- a/gfx/gl/GLContextProvider.h
++++ b/gfx/gl/GLContextProvider.h
+@@ -36,30 +36,38 @@ namespace gl {
+
+ #ifdef XP_MACOSX
+ #define GL_CONTEXT_PROVIDER_NAME GLContextProviderCGL
+ #include "GLContextProviderImpl.h"
+ #undef GL_CONTEXT_PROVIDER_NAME
+ #define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderCGL
+ #endif
+
+-#if defined(MOZ_X11) && !defined(MOZ_WAYLAND)
++#if defined(MOZ_X11)
+ #define GL_CONTEXT_PROVIDER_NAME GLContextProviderGLX
+ #include "GLContextProviderImpl.h"
+ #undef GL_CONTEXT_PROVIDER_NAME
+ #define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderGLX
+ #endif
+
+ #define GL_CONTEXT_PROVIDER_NAME GLContextProviderEGL
+ #include "GLContextProviderImpl.h"
+ #undef GL_CONTEXT_PROVIDER_NAME
+ #ifndef GL_CONTEXT_PROVIDER_DEFAULT
+ #define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
+ #endif
+
++#if defined(MOZ_WAYLAND)
++ #define GL_CONTEXT_PROVIDER_NAME GLContextProviderWayland
++ #include "GLContextProviderImpl.h"
++ #undef GL_CONTEXT_PROVIDER_NAME
++ #undef GL_CONTEXT_PROVIDER_DEFAULT
++ #define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderWayland
++#endif
++
+ #if defined(MOZ_WIDGET_UIKIT)
+ #define GL_CONTEXT_PROVIDER_NAME GLContextProviderEAGL
+ #include "GLContextProviderImpl.h"
+ #undef GL_CONTEXT_PROVIDER_NAME
+ #ifndef GL_CONTEXT_PROVIDER_DEFAULT
+ #define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEAGL
+ #endif
+ #endif
+
diff --git a/rb246410.patch b/rb246410.patch
new file mode 100644
index 0000000..ef31278
--- /dev/null
+++ b/rb246410.patch
@@ -0,0 +1,314 @@
+diff -up firefox-60.0.1/gfx/gl/GLScreenBuffer.cpp.rb246410 firefox-60.0.1/gfx/gl/GLScreenBuffer.cpp
+--- firefox-60.0.1/gfx/gl/GLScreenBuffer.cpp.rb246410 2018-05-16 07:38:30.000000000 +0200
++++ firefox-60.0.1/gfx/gl/GLScreenBuffer.cpp 2018-05-25 11:50:38.260890405 +0200
+@@ -29,7 +29,7 @@
+ #include "SharedSurfaceIO.h"
+ #endif
+
+-#ifdef GL_PROVIDER_GLX
++#ifdef MOZ_X11
+ #include "GLXLibrary.h"
+ #include "SharedSurfaceGLX.h"
+ #endif
+@@ -83,7 +83,7 @@ GLScreenBuffer::CreateFactory(GLContext*
+ if (useGl) {
+ #if defined(XP_MACOSX)
+ factory = SurfaceFactory_IOSurface::Create(gl, caps, ipcChannel, flags);
+-#elif defined(GL_PROVIDER_GLX)
++#elif defined(MOZ_X11)
+ if (sGLXLibrary.UseTextureFromPixmap())
+ factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags);
+ #elif defined(MOZ_WIDGET_UIKIT)
+@@ -119,7 +119,7 @@ GLScreenBuffer::CreateFactory(GLContext*
+ #endif
+ }
+
+-#ifdef GL_PROVIDER_GLX
++#ifdef MOZ_X11
+ if (!factory && sGLXLibrary.UseTextureFromPixmap()) {
+ factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags);
+ }
+diff -up firefox-60.0.1/gfx/layers/client/TextureClient.cpp.rb246410 firefox-60.0.1/gfx/layers/client/TextureClient.cpp
+--- firefox-60.0.1/gfx/layers/client/TextureClient.cpp.rb246410 2018-05-16 07:38:30.000000000 +0200
++++ firefox-60.0.1/gfx/layers/client/TextureClient.cpp 2018-05-25 11:50:38.260890405 +0200
+@@ -45,10 +45,8 @@
+ #endif
+ #ifdef MOZ_X11
+ #include "mozilla/layers/TextureClientX11.h"
+-#ifdef GL_PROVIDER_GLX
+ #include "GLXLibrary.h"
+ #endif
+-#endif
+
+ #ifdef XP_MACOSX
+ #include "mozilla/layers/MacIOSurfaceTextureClientOGL.h"
+@@ -1122,7 +1120,6 @@ TextureClient::CreateForDrawing(TextureF
+ {
+ data = X11TextureData::Create(aSize, aFormat, aTextureFlags, aAllocator);
+ }
+-#ifdef GL_PROVIDER_GLX
+ if (!data && aLayersBackend == LayersBackend::LAYERS_OPENGL &&
+ type == gfxSurfaceType::Xlib &&
+ aFormat != SurfaceFormat::A8 &&
+@@ -1131,7 +1128,6 @@ TextureClient::CreateForDrawing(TextureF
+ data = X11TextureData::Create(aSize, aFormat, aTextureFlags, aAllocator);
+ }
+ #endif
+-#endif
+
+ #ifdef XP_MACOSX
+ if (!data && gfxPrefs::UseIOSurfaceTextures()) {
+diff -up firefox-60.0.1/gfx/layers/composite/X11TextureHost.cpp.rb246410 firefox-60.0.1/gfx/layers/composite/X11TextureHost.cpp
+--- firefox-60.0.1/gfx/layers/composite/X11TextureHost.cpp.rb246410 2018-05-16 07:38:29.000000000 +0200
++++ firefox-60.0.1/gfx/layers/composite/X11TextureHost.cpp 2018-05-25 11:50:38.260890405 +0200
+@@ -7,10 +7,8 @@
+ #include "X11TextureHost.h"
+ #include "mozilla/layers/BasicCompositor.h"
+ #include "mozilla/layers/X11TextureSourceBasic.h"
+-#ifdef GL_PROVIDER_GLX
+ #include "mozilla/layers/CompositorOGL.h"
+ #include "mozilla/layers/X11TextureSourceOGL.h"
+-#endif
+ #include "gfxXlibSurface.h"
+ #include "gfx2DGlue.h"
+
+@@ -43,12 +41,10 @@ X11TextureHost::Lock()
+ mTextureSource =
+ new X11TextureSourceBasic(mCompositor->AsBasicCompositor(), mSurface);
+ break;
+-#ifdef GL_PROVIDER_GLX
+ case LayersBackend::LAYERS_OPENGL:
+ mTextureSource =
+ new X11TextureSourceOGL(mCompositor->AsCompositorOGL(), mSurface);
+ break;
+-#endif
+ default:
+ return false;
+ }
+@@ -78,11 +74,9 @@ X11TextureHost::GetFormat() const
+ return SurfaceFormat::UNKNOWN;
+ }
+ gfxContentType type = mSurface->GetContentType();
+-#ifdef GL_PROVIDER_GLX
+ if (mCompositor->GetBackendType() == LayersBackend::LAYERS_OPENGL) {
+ return X11TextureSourceOGL::ContentTypeToSurfaceFormat(type);
+ }
+-#endif
+ return X11TextureSourceBasic::ContentTypeToSurfaceFormat(type);
+ }
+
+diff -up firefox-60.0.1/gfx/layers/ipc/ShadowLayerUtilsX11.cpp.rb246410 firefox-60.0.1/gfx/layers/ipc/ShadowLayerUtilsX11.cpp
+--- firefox-60.0.1/gfx/layers/ipc/ShadowLayerUtilsX11.cpp.rb246410 2018-05-16 07:38:30.000000000 +0200
++++ firefox-60.0.1/gfx/layers/ipc/ShadowLayerUtilsX11.cpp 2018-05-25 11:50:38.260890405 +0200
+@@ -74,11 +74,9 @@ SurfaceDescriptorX11::SurfaceDescriptorX
+ mFormat = cairo_xlib_surface_get_visual(aSurf->CairoSurface())->visualid;
+ }
+
+-#ifdef GL_PROVIDER_GLX
+ if (aForwardGLX) {
+ mGLXPixmap = aSurf->GetGLXPixmap();
+ }
+-#endif
+ }
+
+ SurfaceDescriptorX11::SurfaceDescriptorX11(Drawable aDrawable, XID aFormatID,
+@@ -109,10 +107,8 @@ SurfaceDescriptorX11::OpenForeign() cons
+ surf = new gfxXlibSurface(display, mId, visual, mSize);
+ }
+
+-#ifdef GL_PROVIDER_GLX
+ if (mGLXPixmap)
+ surf->BindGLXPixmap(mGLXPixmap);
+-#endif
+
+ return surf->CairoStatus() ? nullptr : surf.forget();
+ }
+diff -up firefox-60.0.1/gfx/layers/opengl/X11TextureSourceOGL.cpp.rb246410 firefox-60.0.1/gfx/layers/opengl/X11TextureSourceOGL.cpp
+--- firefox-60.0.1/gfx/layers/opengl/X11TextureSourceOGL.cpp.rb246410 2018-05-16 07:38:30.000000000 +0200
++++ firefox-60.0.1/gfx/layers/opengl/X11TextureSourceOGL.cpp 2018-05-25 11:50:38.260890405 +0200
+@@ -4,7 +4,7 @@
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+-#ifdef GL_PROVIDER_GLX
++#ifdef MOZ_X11
+
+ #include "X11TextureSourceOGL.h"
+ #include "gfxXlibSurface.h"
+diff -up firefox-60.0.1/gfx/layers/opengl/X11TextureSourceOGL.h.rb246410 firefox-60.0.1/gfx/layers/opengl/X11TextureSourceOGL.h
+--- firefox-60.0.1/gfx/layers/opengl/X11TextureSourceOGL.h.rb246410 2018-05-16 07:38:30.000000000 +0200
++++ firefox-60.0.1/gfx/layers/opengl/X11TextureSourceOGL.h 2018-05-25 11:50:38.260890405 +0200
+@@ -7,7 +7,7 @@
+ #ifndef MOZILLA_GFX_X11TEXTURESOURCEOGL__H
+ #define MOZILLA_GFX_X11TEXTURESOURCEOGL__H
+
+-#ifdef GL_PROVIDER_GLX
++#ifdef MOZ_X11
+
+ #include "mozilla/layers/CompositorOGL.h"
+ #include "mozilla/layers/TextureHostOGL.h"
+diff -up firefox-60.0.1/gfx/thebes/gfxPlatformGtk.cpp.rb246410 firefox-60.0.1/gfx/thebes/gfxPlatformGtk.cpp
+--- firefox-60.0.1/gfx/thebes/gfxPlatformGtk.cpp.rb246410 2018-05-25 11:50:38.250890430 +0200
++++ firefox-60.0.1/gfx/thebes/gfxPlatformGtk.cpp 2018-05-25 11:52:21.336628487 +0200
+@@ -41,11 +41,9 @@
+ #include "mozilla/Preferences.h"
+ #include "mozilla/X11Util.h"
+
+-#ifdef GL_PROVIDER_GLX
+ #include "GLContextProvider.h"
+ #include "GLContextGLX.h"
+ #include "GLXLibrary.h"
+-#endif
+
+ /* Undefine the Status from Xlib since it will conflict with system headers on OSX */
+ #if defined(__APPLE__) && defined(Status)
+@@ -528,7 +526,7 @@ gfxPlatformGtk::GetPlatformCMSOutputProf
+ }
+
+
+-#ifdef GL_PROVIDER_GLX
++#ifdef MOZ_X11
+
+ class GLXVsyncSource final : public VsyncSource
+ {
+diff -up firefox-60.0.1/gfx/thebes/gfxPlatformGtk.h.rb246410 firefox-60.0.1/gfx/thebes/gfxPlatformGtk.h
+--- firefox-60.0.1/gfx/thebes/gfxPlatformGtk.h.rb246410 2018-05-16 07:38:30.000000000 +0200
++++ firefox-60.0.1/gfx/thebes/gfxPlatformGtk.h 2018-05-25 11:50:38.260890405 +0200
+@@ -117,7 +117,7 @@ public:
+
+ bool AccelerateLayersByDefault() override;
+
+-#ifdef GL_PROVIDER_GLX
++#ifdef MOZ_X11
+ already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() override;
+ #endif
+
+diff -up firefox-60.0.1/gfx/thebes/gfxXlibSurface.cpp.rb246410 firefox-60.0.1/gfx/thebes/gfxXlibSurface.cpp
+--- firefox-60.0.1/gfx/thebes/gfxXlibSurface.cpp.rb246410 2018-05-16 07:38:30.000000000 +0200
++++ firefox-60.0.1/gfx/thebes/gfxXlibSurface.cpp 2018-05-25 11:51:59.741683360 +0200
+@@ -25,9 +25,7 @@ using namespace mozilla::gfx;
+
+ gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual)
+ : mPixmapTaken(false), mDisplay(dpy), mDrawable(drawable)
+-#if defined(GL_PROVIDER_GLX)
+ , mGLXPixmap(X11None)
+-#endif
+ {
+ const gfx::IntSize size = DoSizeQuery();
+ cairo_surface_t *surf = cairo_xlib_surface_create(dpy, drawable, visual, size.width, size.height);
+@@ -36,9 +34,7 @@ gfxXlibSurface::gfxXlibSurface(Display *
+
+ gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual, const gfx::IntSize& size)
+ : mPixmapTaken(false), mDisplay(dpy), mDrawable(drawable)
+-#if defined(GL_PROVIDER_GLX)
+ , mGLXPixmap(X11None)
+-#endif
+ {
+ NS_ASSERTION(Factory::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT),
+ "Bad size");
+@@ -51,9 +47,7 @@ gfxXlibSurface::gfxXlibSurface(Screen *s
+ const gfx::IntSize& size)
+ : mPixmapTaken(false), mDisplay(DisplayOfScreen(screen)),
+ mDrawable(drawable)
+-#if defined(GL_PROVIDER_GLX)
+- , mGLXPixmap(X11None)
+-#endif
++ , mGLXPixmap(X11None)
+ {
+ NS_ASSERTION(Factory::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT),
+ "Bad Size");
+@@ -67,9 +61,7 @@ gfxXlibSurface::gfxXlibSurface(Screen *s
+
+ gfxXlibSurface::gfxXlibSurface(cairo_surface_t *csurf)
+ : mPixmapTaken(false)
+-#if defined(GL_PROVIDER_GLX)
+- , mGLXPixmap(X11None)
+-#endif
++ , mGLXPixmap(X11None)
+ {
+ NS_PRECONDITION(cairo_surface_status(csurf) == 0,
+ "Not expecting an error surface");
+@@ -84,11 +76,9 @@ gfxXlibSurface::~gfxXlibSurface()
+ {
+ // gfxASurface's destructor calls RecordMemoryFreed().
+ if (mPixmapTaken) {
+-#if defined(GL_PROVIDER_GLX)
+ if (mGLXPixmap) {
+ gl::sGLXLibrary.DestroyPixmap(mDisplay, mGLXPixmap);
+ }
+-#endif
+ XFreePixmap (mDisplay, mDrawable);
+ }
+ }
+@@ -120,7 +110,7 @@ gfxXlibSurface::TakePixmap()
+ // The bit depth returned from Cairo is technically int, but this is
+ // the last place we'd be worried about that scenario.
+ unsigned int bitDepth = cairo_xlib_surface_get_depth(CairoSurface());
+- MOZ_ASSERT((bitDepth % 8) == 0, "Memory used not recorded correctly");
++ MOZ_ASSERT((bitDepth % 8) == 0, "Memory used not recorded correctly");
+
+ // Divide by 8 because surface_get_depth gives us the number of *bits* per
+ // pixel.
+@@ -272,7 +262,7 @@ gfxXlibSurface::CreateSimilarSurface(gfx
+ void
+ gfxXlibSurface::Finish()
+ {
+-#if defined(GL_PROVIDER_GLX)
++#if defined(MOZ_X11)
+ if (mPixmapTaken && mGLXPixmap) {
+ gl::sGLXLibrary.DestroyPixmap(mDisplay, mGLXPixmap);
+ mGLXPixmap = X11None;
+@@ -498,7 +488,7 @@ gfxXlibSurface::DepthOfVisual(const Scre
+ NS_ERROR("Visual not on Screen.");
+ return 0;
+ }
+-
++
+ /* static */
+ Visual*
+ gfxXlibSurface::FindVisual(Screen *screen, gfxImageFormat format)
+@@ -587,7 +577,7 @@ gfxXlibSurface::XRenderFormat()
+ return cairo_xlib_surface_get_xrender_format(CairoSurface());
+ }
+
+-#if defined(GL_PROVIDER_GLX)
++#if defined(MOZ_X11)
+ GLXPixmap
+ gfxXlibSurface::GetGLXPixmap()
+ {
+diff -up firefox-60.0.1/gfx/thebes/gfxXlibSurface.h.rb246410 firefox-60.0.1/gfx/thebes/gfxXlibSurface.h
+--- firefox-60.0.1/gfx/thebes/gfxXlibSurface.h.rb246410 2018-05-16 07:38:30.000000000 +0200
++++ firefox-60.0.1/gfx/thebes/gfxXlibSurface.h 2018-05-25 11:50:38.261890402 +0200
+@@ -12,9 +12,7 @@
+ #include <X11/Xlib.h>
+ #include "X11UndefineNone.h"
+
+-#if defined(GL_PROVIDER_GLX)
+ #include "GLXLibrary.h"
+-#endif
+
+ #include "nsSize.h"
+
+@@ -86,12 +84,10 @@ public:
+ // Find a visual and colormap pair suitable for rendering to this surface.
+ bool GetColormapAndVisual(Colormap* colormap, Visual **visual);
+
+-#if defined(GL_PROVIDER_GLX)
+ GLXPixmap GetGLXPixmap();
+ // Binds a GLXPixmap backed by this context's surface.
+ // Primarily for use in sharing surfaces.
+ void BindGLXPixmap(GLXPixmap aPixmap);
+-#endif
+
+ // Return true if cairo will take its slow path when this surface is used
+ // in a pattern with EXTEND_PAD. As a workaround for XRender's RepeatPad
+@@ -114,9 +110,7 @@ protected:
+
+ const mozilla::gfx::IntSize DoSizeQuery();
+
+-#if defined(GL_PROVIDER_GLX)
+ GLXPixmap mGLXPixmap;
+-#endif
+ };
+
+ #endif /* GFX_XLIBSURFACE_H */
bgstack15