summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Zoder <ozoder@redhat.com>2018-07-17 08:56:42 +0200
committerOndrej Zoder <ozoder@redhat.com>2018-07-17 08:56:42 +0200
commite963c8683d45c7702621537ebf76ced87f5219fd (patch)
treea72e6dc6a6957996577a4bf717158708c0fafc55
parentMerge branch 'master' into f27 (diff)
downloadlibrewolf-fedora-ff-e963c8683d45c7702621537ebf76ced87f5219fd.tar.gz
librewolf-fedora-ff-e963c8683d45c7702621537ebf76ced87f5219fd.tar.bz2
librewolf-fedora-ff-e963c8683d45c7702621537ebf76ced87f5219fd.zip
Added wayland patches
-rw-r--r--firefox.spec12
-rw-r--r--mozilla-1441743.patch336
-rw-r--r--mozilla-1444437.patch81
-rw-r--r--mozilla-1465371.patch59
-rw-r--r--mozilla-1467125.patch26
-rw-r--r--mozilla-1467128.patch359
-rw-r--r--mozilla-1468670.patch102
7 files changed, 975 insertions, 0 deletions
diff --git a/firefox.spec b/firefox.spec
index a6f8756..8879403 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -181,6 +181,12 @@ Patch563: rb245262.patch
Patch564: mozilla-1464808.patch
Patch565: mozilla-1464823.patch
Patch566: mozilla-1466473.patch
+Patch567: mozilla-1444437.patch
+Patch568: mozilla-1441743.patch
+Patch569: mozilla-1465371.patch
+Patch570: mozilla-1467125.patch
+Patch571: mozilla-1468670.patch
+Patch572: mozilla-1467128.patch
# Debian patches
Patch500: mozilla-440908.patch
@@ -389,6 +395,12 @@ This package contains results of tests executed during build.
%patch564 -p1 -b .mozilla-1464808
%patch565 -p1 -b .mozilla-1464823
%patch566 -p1 -b .mozilla-1466473
+%patch567 -p1 -b .mozilla-1444437
+%patch568 -p1 -b .mozilla-1441743
+%patch569 -p1 -b .mozilla-1465371
+%patch570 -p1 -b .mozilla-1467125
+%patch571 -p1 -b .mozilla-1468670
+%patch572 -p1 -b .mozilla-1467128
%endif
%{__rm} -f .mozconfig
diff --git a/mozilla-1441743.patch b/mozilla-1441743.patch
new file mode 100644
index 0000000..59018c7
--- /dev/null
+++ b/mozilla-1441743.patch
@@ -0,0 +1,336 @@
+diff --git a/widget/gtk/WindowSurfaceWayland.h b/widget/gtk/WindowSurfaceWayland.h
+--- a/widget/gtk/WindowSurfaceWayland.h
++++ b/widget/gtk/WindowSurfaceWayland.h
+@@ -3,16 +3,17 @@
+ * 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/. */
+
+ #ifndef _MOZILLA_WIDGET_GTK_WINDOW_SURFACE_WAYLAND_H
+ #define _MOZILLA_WIDGET_GTK_WINDOW_SURFACE_WAYLAND_H
+
+ #include <prthread.h>
++#include "mozilla/gfx/Types.h"
+
+ namespace mozilla {
+ namespace widget {
+
+ // Our general connection to Wayland display server,
+ // holds our display connection and runs event loop.
+ class nsWaylandDisplay : public nsISupports {
+ NS_DECL_THREADSAFE_ISUPPORTS
+@@ -61,17 +62,17 @@ private:
+ };
+
+ // Holds actual graphics data for wl_surface
+ class WindowBackBuffer {
+ public:
+ WindowBackBuffer(nsWaylandDisplay* aDisplay, int aWidth, int aHeight);
+ ~WindowBackBuffer();
+
+- already_AddRefed<gfx::DrawTarget> Lock(const LayoutDeviceIntRegion& aRegion);
++ already_AddRefed<gfx::DrawTarget> Lock();
+
+ void Attach(wl_surface* aSurface);
+ void Detach();
+ bool IsAttached() { return mAttached; }
+
+ bool Resize(int aWidth, int aHeight);
+ bool SetImageDataFromBackBuffer(class WindowBackBuffer* aSourceBuffer);
+
+@@ -107,27 +108,33 @@ public:
+ WindowSurfaceWayland(nsWindow *aWindow);
+ ~WindowSurfaceWayland();
+
+ already_AddRefed<gfx::DrawTarget> Lock(const LayoutDeviceIntRegion& aRegion) override;
+ void Commit(const LayoutDeviceIntRegion& aInvalidRegion) final;
+ void FrameCallbackHandler();
+
+ private:
+- WindowBackBuffer* GetBufferToDraw(int aWidth, int aHeight);
++ WindowBackBuffer* GetFrontBufferToDraw(int aWidth, int aHeight);
+ void UpdateScaleFactor();
+
++ already_AddRefed<gfx::DrawTarget> LockFrontBuffer(int aWidth, int aHeight);
++ already_AddRefed<gfx::DrawTarget> LockImageSurface(const gfx::IntSize& aLockSize);
++ bool CommitImageSurface(const LayoutDeviceIntRegion& aRegion);
++
+ // TODO: Do we need to hold a reference to nsWindow object?
+ nsWindow* mWindow;
+ nsWaylandDisplay* mWaylandDisplay;
+ WindowBackBuffer* mFrontBuffer;
+ WindowBackBuffer* mBackBuffer;
++ RefPtr<gfxImageSurface> mImageSurface;
+ wl_callback* mFrameCallback;
+ wl_surface* mFrameCallbackSurface;
+ MessageLoop* mDisplayThreadMessageLoop;
++ bool mDirectWlBufferDraw;
+ bool mDelayedCommit;
+ bool mFullScreenDamage;
+ bool mIsMainThread;
+ };
+
+ } // namespace widget
+ } // namespace mozilla
+
+
+diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp
+--- a/widget/gtk/WindowSurfaceWayland.cpp
++++ b/widget/gtk/WindowSurfaceWayland.cpp
+@@ -299,16 +299,17 @@ nsWaylandDisplay::Matches(wl_display *aD
+ }
+
+ NS_IMPL_ISUPPORTS(nsWaylandDisplay, nsISupports);
+
+ nsWaylandDisplay::nsWaylandDisplay(wl_display *aDisplay)
+ : mThreadId(PR_GetCurrentThread())
+ // gfx::SurfaceFormat::B8G8R8A8 is a basic Wayland format
+ // and is always present.
++ // TODO: Provide also format without alpha (Bug 1470126).
+ , mFormat(gfx::SurfaceFormat::B8G8R8A8)
+ , mShm(nullptr)
+ , mDisplay(aDisplay)
+ {
+ if (NS_IsMainThread()) {
+ // Use default event queue in main thread operated by Gtk+.
+ mEventQueue = nullptr;
+ } else {
+@@ -530,21 +531,19 @@ WindowBackBuffer::SetImageDataFromBackBu
+ }
+
+ mShmPool.SetImageDataFromPool(&aSourceBuffer->mShmPool,
+ aSourceBuffer->mWidth * aSourceBuffer->mHeight * BUFFER_BPP);
+ return true;
+ }
+
+ already_AddRefed<gfx::DrawTarget>
+-WindowBackBuffer::Lock(const LayoutDeviceIntRegion& aRegion)
++WindowBackBuffer::Lock()
+ {
+- gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect();
+- gfx::IntSize lockSize(bounds.XMost(), bounds.YMost());
+-
++ gfx::IntSize lockSize(mWidth, mHeight);
+ return gfxPlatform::CreateDrawTargetForData(static_cast<unsigned char*>(mShmPool.GetImageData()),
+ lockSize,
+ BUFFER_BPP * mWidth,
+ mWaylandDisplay->GetSurfaceFormat());
+ }
+
+ static void
+ frame_callback_handler(void *data, struct wl_callback *callback, uint32_t time)
+@@ -560,16 +559,17 @@ static const struct wl_callback_listener
+ WindowSurfaceWayland::WindowSurfaceWayland(nsWindow *aWindow)
+ : mWindow(aWindow)
+ , mWaylandDisplay(WaylandDisplayGet(aWindow->GetWaylandDisplay()))
+ , mFrontBuffer(nullptr)
+ , mBackBuffer(nullptr)
+ , mFrameCallback(nullptr)
+ , mFrameCallbackSurface(nullptr)
+ , mDisplayThreadMessageLoop(MessageLoop::current())
++ , mDirectWlBufferDraw(true)
+ , mDelayedCommit(false)
+ , mFullScreenDamage(false)
+ , mIsMainThread(NS_IsMainThread())
+ {
+ }
+
+ WindowSurfaceWayland::~WindowSurfaceWayland()
+ {
+@@ -598,17 +598,17 @@ WindowSurfaceWayland::UpdateScaleFactor(
+ {
+ wl_surface* waylandSurface = mWindow->GetWaylandSurface();
+ if (waylandSurface) {
+ wl_surface_set_buffer_scale(waylandSurface, mWindow->GdkScaleFactor());
+ }
+ }
+
+ WindowBackBuffer*
+-WindowSurfaceWayland::GetBufferToDraw(int aWidth, int aHeight)
++WindowSurfaceWayland::GetFrontBufferToDraw(int aWidth, int aHeight)
+ {
+ if (!mFrontBuffer) {
+ mFrontBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight);
+ mBackBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight);
+ return mFrontBuffer;
+ }
+
+ if (!mFrontBuffer->IsAttached()) {
+@@ -647,46 +647,149 @@ WindowSurfaceWayland::GetBufferToDraw(in
+ // the new buffer and leave gecko to render new whole content.
+ mFrontBuffer->Resize(aWidth, aHeight);
+ }
+
+ return mFrontBuffer;
+ }
+
+ already_AddRefed<gfx::DrawTarget>
++WindowSurfaceWayland::LockFrontBuffer(int aWidth, int aHeight)
++{
++ WindowBackBuffer* buffer = GetFrontBufferToDraw(aWidth, aHeight);
++ if (buffer) {
++ return buffer->Lock();
++ }
++
++ NS_WARNING("WindowSurfaceWayland::LockFrontBuffer(): No buffer available");
++ return nullptr;
++}
++
++already_AddRefed<gfx::DrawTarget>
++WindowSurfaceWayland::LockImageSurface(const gfx::IntSize& aLockSize)
++{
++ if (!mImageSurface || mImageSurface->CairoStatus() ||
++ !(aLockSize <= mImageSurface->GetSize())) {
++ mImageSurface = new gfxImageSurface(aLockSize,
++ SurfaceFormatToImageFormat(mWaylandDisplay->GetSurfaceFormat()));
++ if (mImageSurface->CairoStatus()) {
++ return nullptr;
++ }
++ }
++
++ return gfxPlatform::CreateDrawTargetForData(mImageSurface->Data(),
++ mImageSurface->GetSize(),
++ mImageSurface->Stride(),
++ mWaylandDisplay->GetSurfaceFormat());
++}
++
++/*
++ There are some situations which can happen here:
++
++ A) Lock() is called to whole surface. In that case we don't need
++ to clip/buffer the drawing and we can return wl_buffer directly
++ for drawing.
++ - mFrontBuffer is available - that's an ideal situation.
++ - mFrontBuffer is locked by compositor - flip buffers and draw.
++ - if we can't flip buffers - go B)
++
++ B) Lock() is requested for part(s) of screen. We need to provide temporary
++ surface to draw into and copy result (clipped) to target wl_surface.
++ */
++already_AddRefed<gfx::DrawTarget>
+ WindowSurfaceWayland::Lock(const LayoutDeviceIntRegion& aRegion)
+ {
+ MOZ_ASSERT(mIsMainThread == NS_IsMainThread());
+
+- // We allocate back buffer to widget size but return only
+- // portion requested by aRegion.
+- LayoutDeviceIntRect rect = mWindow->GetBounds();
+- WindowBackBuffer* buffer = GetBufferToDraw(rect.width,
+- rect.height);
+- if (!buffer) {
+- NS_WARNING("No drawing buffer available");
+- return nullptr;
++ LayoutDeviceIntRect screenRect = mWindow->GetBounds();
++ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect();
++ gfx::IntSize lockSize(bounds.XMost(), bounds.YMost());
++
++ // Are we asked for entire nsWindow to draw?
++ mDirectWlBufferDraw = (aRegion.GetNumRects() == 1 &&
++ bounds.x == 0 && bounds.y == 0 &&
++ lockSize.width == screenRect.width &&
++ lockSize.height == screenRect.height);
++
++ if (mDirectWlBufferDraw) {
++ RefPtr<gfx::DrawTarget> dt = LockFrontBuffer(screenRect.width,
++ screenRect.height);
++ if (dt) {
++ return dt.forget();
++ }
++
++ // We don't have any front buffer available. Try indirect drawing
++ // to mImageSurface which is mirrored to front buffer at commit.
++ mDirectWlBufferDraw = false;
+ }
+
+- return buffer->Lock(aRegion);
++ return LockImageSurface(lockSize);
++}
++
++bool
++WindowSurfaceWayland::CommitImageSurface(const LayoutDeviceIntRegion& aRegion)
++{
++ MOZ_ASSERT(!mDirectWlBufferDraw);
++
++ LayoutDeviceIntRect screenRect = mWindow->GetBounds();
++ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect();
++
++ gfx::Rect rect(bounds);
++ if (rect.IsEmpty()) {
++ return false;
++ }
++
++ RefPtr<gfx::DrawTarget> dt = LockFrontBuffer(screenRect.width,
++ screenRect.height);
++ RefPtr<gfx::SourceSurface> surf =
++ gfx::Factory::CreateSourceSurfaceForCairoSurface(mImageSurface->CairoSurface(),
++ mImageSurface->GetSize(),
++ mImageSurface->Format());
++ if (!dt || !surf) {
++ return false;
++ }
++
++ uint32_t numRects = aRegion.GetNumRects();
++ if (numRects != 1) {
++ AutoTArray<IntRect, 32> rects;
++ rects.SetCapacity(numRects);
++ for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
++ rects.AppendElement(iter.Get().ToUnknownRect());
++ }
++ dt->PushDeviceSpaceClipRects(rects.Elements(), rects.Length());
++ }
++
++ dt->DrawSurface(surf, rect, rect);
++
++ if (numRects != 1) {
++ dt->PopClip();
++ }
++
++ return true;
+ }
+
+ void
+ WindowSurfaceWayland::Commit(const LayoutDeviceIntRegion& aInvalidRegion)
+ {
+ MOZ_ASSERT(mIsMainThread == NS_IsMainThread());
+
+ wl_surface* waylandSurface = mWindow->GetWaylandSurface();
+ if (!waylandSurface) {
+ // Target window is already destroyed - don't bother to render there.
++ NS_WARNING("WindowSurfaceWayland::Commit(): parent wl_surface is already hidden/deleted.");
+ return;
+ }
+ wl_proxy_set_queue((struct wl_proxy *)waylandSurface,
+ mWaylandDisplay->GetEventQueue());
+
++ if (!mDirectWlBufferDraw) {
++ // We have new content at mImageSurface - copy data to mFrontBuffer first.
++ CommitImageSurface(aInvalidRegion);
++ }
++
+ if (mFullScreenDamage) {
+ LayoutDeviceIntRect rect = mWindow->GetBounds();
+ wl_surface_damage(waylandSurface, 0, 0, rect.width, rect.height);
+ mFullScreenDamage = false;
+ } else {
+ for (auto iter = aInvalidRegion.RectIter(); !iter.Done(); iter.Next()) {
+ const mozilla::LayoutDeviceIntRect &r = iter.Get();
+ wl_surface_damage(waylandSurface, r.x, r.y, r.width, r.height);
+@@ -730,17 +833,17 @@ WindowSurfaceWayland::FrameCallbackHandl
+ mFrameCallback = nullptr;
+ mFrameCallbackSurface = nullptr;
+ }
+
+ if (mDelayedCommit) {
+ wl_surface* waylandSurface = mWindow->GetWaylandSurface();
+ if (!waylandSurface) {
+ // Target window is already destroyed - don't bother to render there.
+- NS_WARNING("No drawing buffer available");
++ NS_WARNING("WindowSurfaceWayland::FrameCallbackHandler(): parent wl_surface is already hidden/deleted.");
+ return;
+ }
+ wl_proxy_set_queue((struct wl_proxy *)waylandSurface,
+ mWaylandDisplay->GetEventQueue());
+
+ // Send pending surface to compositor and register frame callback
+ // for possible subsequent drawing.
+ mFrameCallback = wl_surface_frame(waylandSurface);
diff --git a/mozilla-1444437.patch b/mozilla-1444437.patch
new file mode 100644
index 0000000..ed9e05a
--- /dev/null
+++ b/mozilla-1444437.patch
@@ -0,0 +1,81 @@
+diff -up firefox-61.0.1/widget/gtk/mozcontainer.cpp.mozilla-1444437 firefox-61.0.1/widget/gtk/mozcontainer.cpp
+--- firefox-61.0.1/widget/gtk/mozcontainer.cpp.mozilla-1444437 2018-07-16 16:38:36.059138061 +0200
++++ firefox-61.0.1/widget/gtk/mozcontainer.cpp 2018-07-16 17:04:10.127003844 +0200
+@@ -212,6 +212,7 @@ moz_container_init (MozContainer *contai
+ container->surface = nullptr;
+ container->subsurface = nullptr;
+ container->eglwindow = nullptr;
++ container->parent_surface_committed = false;
+
+ GdkDisplay *gdk_display = gtk_widget_get_display(GTK_WIDGET(container));
+ if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) {
+@@ -231,6 +232,15 @@ moz_container_init (MozContainer *contai
+ }
+
+ #if defined(MOZ_WAYLAND)
++static void
++moz_container_commited_handler(GdkFrameClock *clock, MozContainer *container)
++{
++ container->parent_surface_committed = true;
++ g_signal_handler_disconnect(clock,
++ container->parent_surface_committed_handler);
++ container->parent_surface_committed_handler = 0;
++}
++
+ /* We want to draw to GdkWindow owned by mContainer from Compositor thread but
+ * Gtk+ can be used in main thread only. So we create wayland wl_surface
+ * and attach it as an overlay to GdkWindow.
+@@ -256,6 +266,21 @@ moz_container_map_surface(MozContainer *
+ if (container->subsurface && container->surface)
+ return true;
+
++ if (!container->parent_surface_committed) {
++ if (!container->parent_surface_committed_handler) {
++ GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
++ static auto sGdkWindowGetFrameClock =
++ (GdkFrameClock *(*)(GdkWindow *))
++ dlsym(RTLD_DEFAULT, "gdk_window_get_frame_clock");
++ GdkFrameClock *clock = sGdkWindowGetFrameClock(window);
++ container->parent_surface_committed_handler =
++ g_signal_connect_after(clock, "after-paint",
++ G_CALLBACK(moz_container_commited_handler),
++ container);
++ }
++ return false;
++ }
++
+ if (!container->surface) {
+ struct wl_compositor *compositor;
+ compositor = sGdkWaylandDisplayGetWlCompositor(display);
+@@ -298,6 +323,19 @@ moz_container_unmap_surface(MozContainer
+ 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);
++
++ if (container->parent_surface_committed_handler) {
++ static auto sGdkWindowGetFrameClock =
++ (GdkFrameClock *(*)(GdkWindow *))
++ dlsym(RTLD_DEFAULT, "gdk_window_get_frame_clock");
++ GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
++ GdkFrameClock *clock = sGdkWindowGetFrameClock(window);
++
++ g_signal_handler_disconnect(clock,
++ container->parent_surface_committed_handler);
++ container->parent_surface_committed_handler = 0;
++ }
++ container->parent_surface_committed = false;
+ }
+
+ #endif
+diff -up firefox-61.0.1/widget/gtk/mozcontainer.h.mozilla-1444437 firefox-61.0.1/widget/gtk/mozcontainer.h
+--- firefox-61.0.1/widget/gtk/mozcontainer.h.mozilla-1444437 2018-07-16 16:38:36.059138061 +0200
++++ firefox-61.0.1/widget/gtk/mozcontainer.h 2018-07-16 16:38:36.105138588 +0200
+@@ -73,6 +73,8 @@ struct _MozContainer
+ struct wl_surface *surface;
+ struct wl_subsurface *subsurface;
+ struct wl_egl_window *eglwindow;
++ gboolean parent_surface_committed;
++ gulong parent_surface_committed_handler;
+ #endif
+ };
+
diff --git a/mozilla-1465371.patch b/mozilla-1465371.patch
new file mode 100644
index 0000000..8e4e8e1
--- /dev/null
+++ b/mozilla-1465371.patch
@@ -0,0 +1,59 @@
+diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
+--- a/toolkit/xre/nsAppRunner.cpp
++++ b/toolkit/xre/nsAppRunner.cpp
+@@ -1700,31 +1700,25 @@ ParseRemoteCommandLine(nsCString& progra
+
+ return REMOTE_FOUND;
+ }
+
+ static RemoteResult
+ StartRemoteClient(const char* aDesktopStartupID,
+ nsCString& program,
+ const char* profile,
+- const char* username,
+- bool aIsX11Display)
++ const char* username)
+ {
+ nsAutoPtr<nsRemoteClient> client;
+
+- if (aIsX11Display) {
+- client = new XRemoteClient();
+- } else {
+ #if defined(MOZ_ENABLE_DBUS) && defined(MOZ_WAYLAND)
+- client = new DBusRemoteClient();
++ client = new DBusRemoteClient();
+ #else
+- MOZ_ASSERT(false, "Missing remote implementation!");
+- return REMOTE_NOT_FOUND;
++ client = new XRemoteClient();
+ #endif
+- }
+
+ nsresult rv = client->Init();
+ if (NS_FAILED(rv))
+ return REMOTE_NOT_FOUND;
+
+ nsCString response;
+ bool success = false;
+ rv = client->SendCommandLine(program.get(), username, profile,
+@@ -4070,18 +4064,17 @@ XREMain::XRE_mainStartup(bool* aExitFlag
+ NS_WARNING("Cannot lock XRemote start mutex");
+ }
+ }
+
+ // Try to remote the entire command line. If this fails, start up normally.
+ const char* desktopStartupIDPtr =
+ mDesktopStartupID.IsEmpty() ? nullptr : mDesktopStartupID.get();
+
+- rr = StartRemoteClient(desktopStartupIDPtr, program, profile, username,
+- GDK_IS_X11_DISPLAY(mGdkDisplay));
++ rr = StartRemoteClient(desktopStartupIDPtr, program, profile, username);
+ if (rr == REMOTE_FOUND) {
+ *aExitFlag = true;
+ return 0;
+ }
+ if (rr == REMOTE_ARG_BAD) {
+ return 1;
+ }
+ }
+
diff --git a/mozilla-1467125.patch b/mozilla-1467125.patch
new file mode 100644
index 0000000..375ac49
--- /dev/null
+++ b/mozilla-1467125.patch
@@ -0,0 +1,26 @@
+diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp
+--- a/widget/gtk/WindowSurfaceWayland.cpp
++++ b/widget/gtk/WindowSurfaceWayland.cpp
+@@ -146,18 +146,19 @@ static StaticMutex gWaylandDisplaysMutex
+ //
+ // nsWaylandDisplay is our interface to wayland compositor. It provides wayland
+ // global objects as we need (wl_display, wl_shm) and operates wl_event_queue on
+ // compositor (not the main) thread.
+ static nsWaylandDisplay* WaylandDisplayGet(wl_display *aDisplay);
+ static void WaylandDisplayRelease(wl_display *aDisplay);
+ static void WaylandDisplayLoop(wl_display *aDisplay);
+
+-// TODO: is the 60pfs loop correct?
+-#define EVENT_LOOP_DELAY (1000/60)
++// TODO: Bug 1467125 - We need to integrate wl_display_dispatch_queue_pending() with
++// compositor event loop.
++#define EVENT_LOOP_DELAY (1000/240)
+
+ // Get WaylandDisplay for given wl_display and actual calling thread.
+ static nsWaylandDisplay*
+ WaylandDisplayGetLocked(wl_display *aDisplay, const StaticMutexAutoLock&)
+ {
+ nsWaylandDisplay* waylandDisplay = nullptr;
+
+ int len = gWaylandDisplays.Count();
+
diff --git a/mozilla-1467128.patch b/mozilla-1467128.patch
new file mode 100644
index 0000000..75cf92c
--- /dev/null
+++ b/mozilla-1467128.patch
@@ -0,0 +1,359 @@
+diff --git a/gfx/thebes/gfxPlatformGtk.h b/gfx/thebes/gfxPlatformGtk.h
+--- a/gfx/thebes/gfxPlatformGtk.h
++++ b/gfx/thebes/gfxPlatformGtk.h
+@@ -102,23 +102,42 @@ public:
+ #endif
+
+ #ifdef MOZ_X11
+ Display* GetCompositorDisplay() {
+ return mCompositorDisplay;
+ }
+ #endif // MOZ_X11
+
++#ifdef MOZ_WAYLAND
++ void SetWaylandLastVsync(uint32_t aVsyncTimestamp) {
++ mWaylandLastVsyncTimestamp = aVsyncTimestamp;
++ }
++ int64_t GetWaylandLastVsync() {
++ return mWaylandLastVsyncTimestamp;
++ }
++ void SetWaylandFrameDelay(int64_t aFrameDelay) {
++ mWaylandFrameDelay = aFrameDelay;
++ }
++ int64_t GetWaylandFrameDelay() {
++ return mWaylandFrameDelay;
++ }
++#endif
++
+ protected:
+ bool CheckVariationFontSupport() override;
+
+ int8_t mMaxGenericSubstitutions;
+
+ private:
+ virtual void GetPlatformCMSOutputProfile(void *&mem,
+ size_t &size) override;
+
+ #ifdef MOZ_X11
+ Display* mCompositorDisplay;
+ #endif
++#ifdef MOZ_WAYLAND
++ int64_t mWaylandLastVsyncTimestamp;
++ int64_t mWaylandFrameDelay;
++#endif
+ };
+
+ #endif /* GFX_PLATFORM_GTK_H */
+diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp
+--- a/gfx/thebes/gfxPlatformGtk.cpp
++++ b/gfx/thebes/gfxPlatformGtk.cpp
+@@ -46,16 +46,20 @@
+ #include "GLContextGLX.h"
+ #include "GLXLibrary.h"
+
+ /* Undefine the Status from Xlib since it will conflict with system headers on OSX */
+ #if defined(__APPLE__) && defined(Status)
+ #undef Status
+ #endif
+
++#ifdef MOZ_WAYLAND
++#include <gdk/gdkwayland.h>
++#endif
++
+ #endif /* MOZ_X11 */
+
+ #include <fontconfig/fontconfig.h>
+
+ #include "nsMathUtils.h"
+
+ #define GDK_PIXMAP_SIZE_MAX 32767
+
+@@ -89,16 +93,22 @@ gfxPlatformGtk::gfxPlatformGtk()
+ #ifdef MOZ_X11
+ if (gfxPlatform::IsHeadless() && GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
+ mCompositorDisplay = XOpenDisplay(nullptr);
+ MOZ_ASSERT(mCompositorDisplay, "Failed to create compositor display!");
+ } else {
+ mCompositorDisplay = nullptr;
+ }
+ #endif // MOZ_X11
++#ifdef MOZ_WAYLAND
++ // Wayland compositors use g_get_monotonic_time() to get timestamps.
++ mWaylandLastVsyncTimestamp = (g_get_monotonic_time() / 1000);
++ // Set default display fps to 60
++ mWaylandFrameDelay = 1000/60;
++#endif
+ }
+
+ gfxPlatformGtk::~gfxPlatformGtk()
+ {
+ #ifdef MOZ_X11
+ if (mCompositorDisplay) {
+ XCloseDisplay(mCompositorDisplay);
+ }
+@@ -505,26 +515,26 @@ gfxPlatformGtk::CheckVariationFontSuppor
+ // until at least 2.7.1.
+ FT_Int major, minor, patch;
+ FT_Library_Version(GetFTLibrary(), &major, &minor, &patch);
+ return major * 1000000 + minor * 1000 + patch >= 2007001;
+ }
+
+ #ifdef MOZ_X11
+
+-class GLXVsyncSource final : public VsyncSource
++class GtkVsyncSource final : public VsyncSource
+ {
+ public:
+- GLXVsyncSource()
++ GtkVsyncSource()
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+ mGlobalDisplay = new GLXDisplay();
+ }
+
+- virtual ~GLXVsyncSource()
++ virtual ~GtkVsyncSource()
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+ }
+
+ virtual Display& GetGlobalDisplay() override
+ {
+ return *mGlobalDisplay;
+ }
+@@ -536,39 +546,52 @@ public:
+ public:
+ GLXDisplay() : mGLContext(nullptr)
+ , mXDisplay(nullptr)
+ , mSetupLock("GLXVsyncSetupLock")
+ , mVsyncThread("GLXVsyncThread")
+ , mVsyncTask(nullptr)
+ , mVsyncEnabledLock("GLXVsyncEnabledLock")
+ , mVsyncEnabled(false)
++#ifdef MOZ_WAYLAND
++ , mIsWaylandDisplay(false)
++#endif
+ {
+ }
+
+ // Sets up the display's GL context on a worker thread.
+ // Required as GLContexts may only be used by the creating thread.
+ // Returns true if setup was a success.
+ bool Setup()
+ {
+ MonitorAutoLock lock(mSetupLock);
+ MOZ_ASSERT(NS_IsMainThread());
+ if (!mVsyncThread.Start())
+ return false;
+
+ RefPtr<Runnable> vsyncSetup =
+- NewRunnableMethod("GLXVsyncSource::GLXDisplay::SetupGLContext",
++ NewRunnableMethod("GtkVsyncSource::GLXDisplay::SetupGLContext",
+ this,
+ &GLXDisplay::SetupGLContext);
+ mVsyncThread.message_loop()->PostTask(vsyncSetup.forget());
+ // Wait until the setup has completed.
+ lock.Wait();
+ return mGLContext != nullptr;
+ }
+
++#ifdef MOZ_WAYLAND
++ bool SetupWayland()
++ {
++ MonitorAutoLock lock(mSetupLock);
++ MOZ_ASSERT(NS_IsMainThread());
++ mIsWaylandDisplay = true;
++ return mVsyncThread.Start();
++ }
++#endif
++
+ // Called on the Vsync thread to setup the GL context.
+ void SetupGLContext()
+ {
+ MonitorAutoLock lock(mSetupLock);
+ MOZ_ASSERT(!NS_IsMainThread());
+ MOZ_ASSERT(!mGLContext, "GLContext already setup!");
+
+ // Create video sync timer on a separate Display to prevent locking the
+@@ -613,29 +636,35 @@ public:
+ }
+
+ lock.NotifyAll();
+ }
+
+ virtual void EnableVsync() override
+ {
+ MOZ_ASSERT(NS_IsMainThread());
++#if !defined(MOZ_WAYLAND)
+ MOZ_ASSERT(mGLContext, "GLContext not setup!");
++#endif
+
+ MonitorAutoLock lock(mVsyncEnabledLock);
+ if (mVsyncEnabled) {
+ return;
+ }
+ mVsyncEnabled = true;
+
+ // If the task has not nulled itself out, it hasn't yet realized
+ // that vsync was disabled earlier, so continue its execution.
+ if (!mVsyncTask) {
+ mVsyncTask = NewRunnableMethod(
+- "GLXVsyncSource::GLXDisplay::RunVsync", this, &GLXDisplay::RunVsync);
++ "GtkVsyncSource::GLXDisplay::RunVsync", this,
++#if defined(MOZ_WAYLAND)
++ mIsWaylandDisplay ? &GLXDisplay::RunVsyncWayland :
++#endif
++ &GLXDisplay::RunVsync);
+ RefPtr<Runnable> addrefedTask = mVsyncTask;
+ mVsyncThread.message_loop()->PostTask(addrefedTask.forget());
+ }
+ }
+
+ virtual void DisableVsync() override
+ {
+ MonitorAutoLock lock(mVsyncEnabledLock);
+@@ -650,17 +679,17 @@ public:
+
+ virtual void Shutdown() override
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+ DisableVsync();
+
+ // Cleanup thread-specific resources before shutting down.
+ RefPtr<Runnable> shutdownTask = NewRunnableMethod(
+- "GLXVsyncSource::GLXDisplay::Cleanup", this, &GLXDisplay::Cleanup);
++ "GtkVsyncSource::GLXDisplay::Cleanup", this, &GLXDisplay::Cleanup);
+ mVsyncThread.message_loop()->PostTask(shutdownTask.forget());
+
+ // Stop, waiting for the cleanup task to finish execution.
+ mVsyncThread.Stop();
+ }
+
+ private:
+ virtual ~GLXDisplay()
+@@ -709,50 +738,96 @@ public:
+ }
+ }
+
+ lastVsync = TimeStamp::Now();
+ NotifyVsync(lastVsync);
+ }
+ }
+
++#ifdef MOZ_WAYLAND
++ /* VSync on Wayland is tricky as we can get only "last VSync" event signal.
++ * That means we should draw next frame at "last Vsync + frame delay" time.
++ */
++ void RunVsyncWayland()
++ {
++ MOZ_ASSERT(!NS_IsMainThread());
++
++ for (;;) {
++ {
++ MonitorAutoLock lock(mVsyncEnabledLock);
++ if (!mVsyncEnabled) {
++ mVsyncTask = nullptr;
++ return;
++ }
++ }
++
++ gint64 lastVsync = gfxPlatformGtk::GetPlatform()->GetWaylandLastVsync();
++ gint64 currTime = (g_get_monotonic_time() / 1000);
++
++ gint64 remaining = gfxPlatformGtk::GetPlatform()->GetWaylandFrameDelay() -
++ (currTime - lastVsync);
++ if (remaining > 0) {
++ PlatformThread::Sleep(remaining);
++ } else {
++ // Time from last HW Vsync is longer than our frame delay,
++ // use our approximation then.
++ gfxPlatformGtk::GetPlatform()->SetWaylandLastVsync(currTime);
++ }
++
++ NotifyVsync(TimeStamp::Now());
++ }
++ }
++#endif
++
+ void Cleanup() {
+ MOZ_ASSERT(!NS_IsMainThread());
+
+ mGLContext = nullptr;
+- XCloseDisplay(mXDisplay);
++ if (mXDisplay)
++ XCloseDisplay(mXDisplay);
+ }
+
+ // Owned by the vsync thread.
+ RefPtr<gl::GLContextGLX> mGLContext;
+ _XDisplay* mXDisplay;
+ Monitor mSetupLock;
+ base::Thread mVsyncThread;
+ RefPtr<Runnable> mVsyncTask;
+ Monitor mVsyncEnabledLock;
+ bool mVsyncEnabled;
++#ifdef MOZ_WAYLAND
++ bool mIsWaylandDisplay;
++#endif
+ };
+ private:
+ // We need a refcounted VsyncSource::Display to use chromium IPC runnables.
+ RefPtr<GLXDisplay> mGlobalDisplay;
+ };
+
+ already_AddRefed<gfx::VsyncSource>
+ gfxPlatformGtk::CreateHardwareVsyncSource()
+ {
++#ifdef MOZ_WAYLAND
++ if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) {
++ RefPtr<VsyncSource> vsyncSource = new GtkVsyncSource();
++ VsyncSource::Display& display = vsyncSource->GetGlobalDisplay();
++ static_cast<GtkVsyncSource::GLXDisplay&>(display).SetupWayland();
++ return vsyncSource.forget();
++ }
++#endif
++
+ // 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 (GDK_IS_X11_DISPLAY(gdk_display_get_default()) &&
+- gl::sGLXLibrary.SupportsVideoSync()) {
+- RefPtr<VsyncSource> vsyncSource = new GLXVsyncSource();
++ if (gl::sGLXLibrary.SupportsVideoSync()) {
++ RefPtr<VsyncSource> vsyncSource = new GtkVsyncSource();
+ VsyncSource::Display& display = vsyncSource->GetGlobalDisplay();
+- if (!static_cast<GLXVsyncSource::GLXDisplay&>(display).Setup()) {
++ if (!static_cast<GtkVsyncSource::GLXDisplay&>(display).Setup()) {
+ NS_WARNING("Failed to setup GLContext, falling back to software vsync.");
+ return gfxPlatform::CreateHardwareVsyncSource();
+ }
+ return vsyncSource.forget();
+ }
+ NS_WARNING("SGI_video_sync unsupported. Falling back to software vsync.");
+ }
+ return gfxPlatform::CreateHardwareVsyncSource();
+diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp
+--- a/widget/gtk/WindowSurfaceWayland.cpp
++++ b/widget/gtk/WindowSurfaceWayland.cpp
+@@ -546,16 +546,18 @@ WindowBackBuffer::Lock()
+ mWaylandDisplay->GetSurfaceFormat());
+ }
+
+ static void
+ frame_callback_handler(void *data, struct wl_callback *callback, uint32_t time)
+ {
+ auto surface = reinterpret_cast<WindowSurfaceWayland*>(data);
+ surface->FrameCallbackHandler();
++
++ gfxPlatformGtk::GetPlatform()->SetWaylandLastVsync(time);
+ }
+
+ static const struct wl_callback_listener frame_listener = {
+ frame_callback_handler
+ };
+
+ WindowSurfaceWayland::WindowSurfaceWayland(nsWindow *aWindow)
+ : mWindow(aWindow)
+
diff --git a/mozilla-1468670.patch b/mozilla-1468670.patch
new file mode 100644
index 0000000..42a05e2
--- /dev/null
+++ b/mozilla-1468670.patch
@@ -0,0 +1,102 @@
+diff --git a/widget/gtk/nsGtkKeyUtils.h b/widget/gtk/nsGtkKeyUtils.h
+--- a/widget/gtk/nsGtkKeyUtils.h
++++ b/widget/gtk/nsGtkKeyUtils.h
+@@ -169,17 +169,20 @@ protected:
+
+ bool mInitialized;
+
+ /**
+ * Initializing methods.
+ */
+ void Init();
+ void InitXKBExtension();
+- void InitBySystemSettings();
++ void InitBySystemSettingsX11();
++#ifdef MOZ_WAYLAND
++ void InitBySystemSettingsWayland();
++#endif
+
+ /**
+ * mModifierKeys stores each hardware key information.
+ */
+ struct ModifierKey {
+ guint mHardwareKeycode;
+ guint mMask;
+
+
+diff --git a/widget/gtk/nsGtkKeyUtils.cpp b/widget/gtk/nsGtkKeyUtils.cpp
+--- a/widget/gtk/nsGtkKeyUtils.cpp
++++ b/widget/gtk/nsGtkKeyUtils.cpp
+@@ -190,17 +190,21 @@ KeymapWrapper::Init()
+ MOZ_LOG(gKeymapWrapperLog, LogLevel::Info,
+ ("%p Init, mGdkKeymap=%p",
+ this, mGdkKeymap));
+
+ mModifierKeys.Clear();
+ memset(mModifierMasks, 0, sizeof(mModifierMasks));
+
+ if (GDK_IS_X11_DISPLAY(gdk_display_get_default()))
+- InitBySystemSettings();
++ InitBySystemSettingsX11();
++#ifdef MOZ_WAYLAND
++ else
++ InitBySystemSettingsWayland();
++#endif
+
+ gdk_window_add_filter(nullptr, FilterEvents, this);
+
+ MOZ_LOG(gKeymapWrapperLog, LogLevel::Info,
+ ("%p Init, CapsLock=0x%X, NumLock=0x%X, "
+ "ScrollLock=0x%X, Level3=0x%X, Level5=0x%X, "
+ "Shift=0x%X, Ctrl=0x%X, Alt=0x%X, Meta=0x%X, Super=0x%X, Hyper=0x%X",
+ this,
+@@ -270,20 +274,20 @@ KeymapWrapper::InitXKBExtension()
+ return;
+ }
+
+ MOZ_LOG(gKeymapWrapperLog, LogLevel::Info,
+ ("%p InitXKBExtension, Succeeded", this));
+ }
+
+ void
+-KeymapWrapper::InitBySystemSettings()
++KeymapWrapper::InitBySystemSettingsX11()
+ {
+ MOZ_LOG(gKeymapWrapperLog, LogLevel::Info,
+- ("%p InitBySystemSettings, mGdkKeymap=%p",
++ ("%p InitBySystemSettingsX11, mGdkKeymap=%p",
+ this, mGdkKeymap));
+
+ Display* display =
+ gdk_x11_display_get_xdisplay(gdk_display_get_default());
+
+ int min_keycode = 0;
+ int max_keycode = 0;
+ XDisplayKeycodes(display, &min_keycode, &max_keycode);
+@@ -434,16 +438,26 @@ KeymapWrapper::InitBySystemSettings()
+ }
+ }
+ }
+
+ XFreeModifiermap(xmodmap);
+ XFree(xkeymap);
+ }
+
++#ifdef MOZ_WAYLAND
++void
++KeymapWrapper::InitBySystemSettingsWayland()
++{
++ // Not implemented yet, but at least Alt modifier should be handled to save
++ // popular usage.
++ mModifierMasks[INDEX_ALT] = 1 << 3;
++}
++#endif
++
+ KeymapWrapper::~KeymapWrapper()
+ {
+ gdk_window_remove_filter(nullptr, FilterEvents, this);
+ g_signal_handlers_disconnect_by_func(mGdkKeymap,
+ FuncToGpointer(OnKeysChanged), this);
+ g_signal_handlers_disconnect_by_func(mGdkKeymap,
+ FuncToGpointer(OnDirectionChanged), this);
+ g_object_unref(mGdkKeymap);
bgstack15