diff options
author | Martin Stransky <stransky@redhat.com> | 2018-05-25 12:50:35 +0200 |
---|---|---|
committer | Martin Stransky <stransky@redhat.com> | 2018-05-25 12:50:35 +0200 |
commit | dd0eb4d9d89c3b796044c7fac8397c8713c5cdeb (patch) | |
tree | a784b13aa5a0fb07ed8cc7c7f50ecdb3650c2e12 | |
parent | Update to 60.0.1 (diff) | |
download | librewolf-fedora-ff-dd0eb4d9d89c3b796044c7fac8397c8713c5cdeb.tar.gz librewolf-fedora-ff-dd0eb4d9d89c3b796044c7fac8397c8713c5cdeb.tar.bz2 librewolf-fedora-ff-dd0eb4d9d89c3b796044c7fac8397c8713c5cdeb.zip |
Enable Wayland backend
-rw-r--r-- | firefox-wayland.desktop | 233 | ||||
-rw-r--r-- | firefox.spec | 46 | ||||
-rw-r--r-- | mozilla-1438131.patch | 1558 | ||||
-rw-r--r-- | mozilla-1438136.patch | 34 | ||||
-rw-r--r-- | mozilla-1460603.patch | 46 | ||||
-rw-r--r-- | mozilla-1460605-1.patch | 40 | ||||
-rw-r--r-- | mozilla-1460605-2.patch | 292 | ||||
-rw-r--r-- | mozilla-1460810.patch | 30 | ||||
-rw-r--r-- | mozilla-1461306.patch | 33 | ||||
-rw-r--r-- | mozilla-1462622.patch | 36 | ||||
-rw-r--r-- | mozilla-1462642.patch | 183 | ||||
-rw-r--r-- | mozilla-1463753.patch | 127 | ||||
-rw-r--r-- | rb244010.patch | 149 | ||||
-rw-r--r-- | rb244012.patch | 44 | ||||
-rw-r--r-- | rb246410.patch | 314 |
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]=نْو پرایوٹ وینڈو& +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 */ |