diff --git a/firefox.spec b/firefox.spec index 24b2e0d..aa7afe8 100644 --- a/firefox.spec +++ b/firefox.spec @@ -104,7 +104,7 @@ Summary: Mozilla Firefox Web browser Name: firefox Version: 81.0.1 -Release: 7%{?dist} +Release: 9%{?dist} URL: https://www.mozilla.org/firefox/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}%{?pre_version}/source/firefox-%{version}%{?pre_version}.source.tar.xz @@ -170,6 +170,9 @@ Patch408: mozilla-1663844.patch Patch409: mozilla-1640567.patch Patch410: mozilla-1661192.patch Patch411: mozilla-1668771.patch +Patch412: mozilla-1634404.patch +Patch413: mozilla-1669495.patch +Patch414: mozilla-1656727.patch # Wayland specific upstream patches Patch574: firefox-pipewire-0-2.patch @@ -378,6 +381,9 @@ This package contains results of tests executed during build. %patch409 -p1 -b .1640567 %patch410 -p1 -b .1661192 %patch411 -p1 -b .1668771 +%patch412 -p1 -b .1634404 +%patch413 -p1 -b .1669495 +%patch414 -p1 -b .1656727 # Wayland specific upstream patches %if 0%{?fedora} < 32 @@ -972,6 +978,12 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #--------------------------------------------------------------------- %changelog +* Thu Oct 8 2020 Martin Stransky - 81.0.1-9 +- Added an updated fix for mozbz#1656727 + +* Thu Oct 8 2020 Martin Stransky - 81.0.1-8 +- Added fixes for mozbz#1634404, mozbz#1669495 + * Thu Oct 8 2020 Martin Stransky - 81.0.1-7 - Removed mozbz#1656727 as it causes a regression rhbz#1886243 diff --git a/mozilla-1634404.patch b/mozilla-1634404.patch new file mode 100644 index 0000000..75ea8ce --- /dev/null +++ b/mozilla-1634404.patch @@ -0,0 +1,20 @@ +diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp +--- a/widget/gtk/nsWindow.cpp ++++ b/widget/gtk/nsWindow.cpp +@@ -1593,7 +1593,14 @@ + // Get anchor rectangle + LayoutDeviceIntRect anchorRect(0, 0, 0, 0); + nsMenuPopupFrame* popupFrame = GetMenuPopupFrame(GetFrame()); +- int32_t p2a = AppUnitsPerCSSPixel() / gfxPlatformGtk::GetFontScaleFactor(); ++ ++ int32_t p2a; ++ double devPixelsPerCSSPixel = StaticPrefs::layout_css_devPixelsPerPx(); ++ if (devPixelsPerCSSPixel > 0.0) { ++ p2a = AppUnitsPerCSSPixel() / devPixelsPerCSSPixel * GdkScaleFactor(); ++ } else { ++ p2a = AppUnitsPerCSSPixel() / gfxPlatformGtk::GetFontScaleFactor(); ++ } + if (popupFrame) { + #ifdef MOZ_WAYLAND + anchorRect = LayoutDeviceIntRect::FromAppUnitsToOutside( + diff --git a/mozilla-1656727.patch b/mozilla-1656727.patch new file mode 100644 index 0000000..3ec60ae --- /dev/null +++ b/mozilla-1656727.patch @@ -0,0 +1,228 @@ +changeset: 553676:ca48ea0dfb91 +tag: tip +parent: 553673:a42aa9514794 +user: stransky +date: Mon Oct 05 15:06:55 2020 +0200 +files: widget/gtk/WindowSurfaceWayland.cpp widget/gtk/WindowSurfaceWayland.h +description: +Bug 1656727 [Wayland] Track delayed commits globally, r?jhorak + +Track delayed commits in a global list and don't store them in actual wayland surfaces. +When a delayed commit is called, check that the associated wayland surface is still valid. + +Differential Revision: https://phabricator.services.mozilla.com/D92432 + + +diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp +--- a/widget/gtk/WindowSurfaceWayland.cpp ++++ b/widget/gtk/WindowSurfaceWayland.cpp +@@ -159,7 +159,6 @@ We allocate shared memory (shm) by mmap( + between us and wayland compositor. We draw our graphics data to the shm and + handle to wayland compositor by WindowBackBuffer/WindowSurfaceWayland + (wl_buffer/wl_surface). +- + */ + + #define EVENT_LOOP_DELAY (1000 / 240) +@@ -167,6 +166,44 @@ handle to wayland compositor by WindowBa + #define BUFFER_BPP 4 + gfx::SurfaceFormat WindowBackBuffer::mFormat = gfx::SurfaceFormat::B8G8R8A8; + ++static mozilla::Mutex* gDelayedCommitLock = nullptr; ++static GList* gDelayedCommits = nullptr; ++ ++static void DelayedCommitsEnsureMutext() { ++ if (!gDelayedCommitLock) { ++ gDelayedCommitLock = new mozilla::Mutex("DelayedCommit lock"); ++ } ++} ++ ++static bool DelayedCommitsCheckAndRemoveSurface( ++ WindowSurfaceWayland* aSurface) { ++ MutexAutoLock lock(*gDelayedCommitLock); ++ GList* foundCommit = g_list_find(gDelayedCommits, aSurface); ++ if (foundCommit) { ++ gDelayedCommits = g_list_delete_link(gDelayedCommits, foundCommit); ++ } ++ return foundCommit != nullptr; ++} ++ ++static bool DelayedCommitsCheckAndAddSurface(WindowSurfaceWayland* aSurface) { ++ MutexAutoLock lock(*gDelayedCommitLock); ++ GList* foundCommit = g_list_find(gDelayedCommits, aSurface); ++ if (!foundCommit) { ++ gDelayedCommits = g_list_prepend(gDelayedCommits, aSurface); ++ } ++ return foundCommit == nullptr; ++} ++ ++// When a new window is created we may not have a valid wl_surface ++// for drawing (Gtk haven't created it yet). All commits are queued ++// and CommitWaylandBuffer() is called by timer when wl_surface is ready ++// for drawing. ++static void WaylandBufferDelayCommitHandler(WindowSurfaceWayland* aSurface) { ++ if (DelayedCommitsCheckAndRemoveSurface(aSurface)) { ++ aSurface->CommitWaylandBuffer(); ++ } ++} ++ + RefPtr WindowBackBuffer::GetWaylandDisplay() { + return mWindowSurfaceWayland->GetWaylandDisplay(); + } +@@ -400,7 +437,6 @@ WindowSurfaceWayland::WindowSurfaceWayla + mWaylandFullscreenDamage(false), + mFrameCallback(nullptr), + mLastCommittedSurface(nullptr), +- mDelayedCommitHandle(nullptr), + mLastCommitTime(0), + mDrawToWaylandBufferDirectly(true), + mCanSwitchWaylandBuffer(true), +@@ -412,6 +448,7 @@ WindowSurfaceWayland::WindowSurfaceWayla + for (int i = 0; i < BACK_BUFFER_NUM; i++) { + mShmBackupBuffer[i] = nullptr; + } ++ DelayedCommitsEnsureMutext(); + } + + WindowSurfaceWayland::~WindowSurfaceWayland() { +@@ -419,12 +456,9 @@ WindowSurfaceWayland::~WindowSurfaceWayl + NS_WARNING("Deleted WindowSurfaceWayland with a pending commit!"); + } + +- if (mDelayedCommitHandle) { +- // Delete reference to this to prevent WaylandBufferDelayCommitHandler() +- // operate on released this. mDelayedCommitHandle itself will +- // be released at WaylandBufferDelayCommitHandler(). +- *mDelayedCommitHandle = nullptr; +- } ++ // Delete reference to this to prevent WaylandBufferDelayCommitHandler() ++ // operate on released this. ++ DelayedCommitsCheckAndRemoveSurface(this); + + if (mFrameCallback) { + wl_callback_destroy(mFrameCallback); +@@ -865,23 +899,11 @@ bool WindowSurfaceWayland::CommitImageCa + return true; + } + +-static void WaylandBufferDelayCommitHandler(WindowSurfaceWayland** aSurface) { +- if (*aSurface) { +- (*aSurface)->DelayedCommitHandler(); +- } else { +- // Referenced WindowSurfaceWayland is already deleted. +- // Do nothing but just release the mDelayedCommitHandle allocated at +- // WindowSurfaceWayland::CommitWaylandBuffer(). +- free(aSurface); +- } +-} +- + void WindowSurfaceWayland::CommitWaylandBuffer() { + LOGWAYLAND(("WindowSurfaceWayland::CommitWaylandBuffer [%p]\n", (void*)this)); + LOGWAYLAND( + (" mDrawToWaylandBufferDirectly = %d\n", mDrawToWaylandBufferDirectly)); + LOGWAYLAND((" mCanSwitchWaylandBuffer = %d\n", mCanSwitchWaylandBuffer)); +- LOGWAYLAND((" mDelayedCommitHandle = %p\n", mDelayedCommitHandle)); + LOGWAYLAND((" mFrameCallback = %p\n", mFrameCallback)); + LOGWAYLAND((" mLastCommittedSurface = %p\n", mLastCommittedSurface)); + LOGWAYLAND((" mBufferPendingCommit = %d\n", mBufferPendingCommit)); +@@ -917,16 +939,10 @@ void WindowSurfaceWayland::CommitWayland + MOZ_ASSERT(!mFrameCallback || waylandSurface != mLastCommittedSurface, + "Missing wayland surface at frame callback!"); + +- // Do nothing if there's already mDelayedCommitHandle pending. +- if (!mDelayedCommitHandle) { +- mDelayedCommitHandle = static_cast( +- moz_xmalloc(sizeof(*mDelayedCommitHandle))); +- *mDelayedCommitHandle = this; +- ++ if (DelayedCommitsCheckAndAddSurface(this)) { + MessageLoop::current()->PostDelayedTask( + NewRunnableFunction("WaylandBackBufferCommit", +- &WaylandBufferDelayCommitHandler, +- mDelayedCommitHandle), ++ &WaylandBufferDelayCommitHandler, this), + EVENT_LOOP_DELAY); + } + return; +@@ -1039,24 +1055,5 @@ void WindowSurfaceWayland::FrameCallback + CommitWaylandBuffer(); + } + +-void WindowSurfaceWayland::DelayedCommitHandler() { +- MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); +- MOZ_ASSERT(mDelayedCommitHandle != nullptr, "Missing mDelayedCommitHandle!"); +- +- LOGWAYLAND( +- ("WindowSurfaceWayland::DelayedCommitHandler [%p]\n", (void*)this)); +- +- if (!mDelayedCommitHandle) { +- LOGWAYLAND((" We're missing mDelayedCommitHandle!\n")); +- return; +- } +- +- *mDelayedCommitHandle = nullptr; +- free(mDelayedCommitHandle); +- mDelayedCommitHandle = nullptr; +- +- CommitWaylandBuffer(); +-} +- + } // namespace widget + } // namespace mozilla +diff --git a/widget/gtk/WindowSurfaceWayland.h b/widget/gtk/WindowSurfaceWayland.h +--- a/widget/gtk/WindowSurfaceWayland.h ++++ b/widget/gtk/WindowSurfaceWayland.h +@@ -161,7 +161,7 @@ class WindowSurfaceWayland : public Wind + // If we fail (wayland compositor is busy, + // wl_surface is not created yet) we queue the painting + // and we send it to wayland compositor in FrameCallbackHandler()/ +- // DelayedCommitHandler/CommitWaylandBuffer(). ++ // CommitWaylandBuffer(). + already_AddRefed Lock( + const LayoutDeviceIntRegion& aRegion) override; + void Commit(const LayoutDeviceIntRegion& aInvalidRegion) final; +@@ -171,12 +171,6 @@ class WindowSurfaceWayland : public Wind + // queued commits. + void FrameCallbackHandler(); + +- // When a new window is created we may not have a valid wl_surface +- // for drawing (Gtk haven't created it yet). All commits are queued +- // and DelayedCommitHandler() is called by timer when wl_surface is ready +- // for drawing. +- void DelayedCommitHandler(); +- + // Try to commit all queued drawings to Wayland compositor. This is usually + // called from other routines but can be used to explicitly flush + // all drawings as we do when wl_buffer is released +@@ -249,17 +243,14 @@ class WindowSurfaceWayland : public Wind + wl_callback* mFrameCallback; + wl_surface* mLastCommittedSurface; + +- // Registered reference to pending DelayedCommitHandler() call. +- WindowSurfaceWayland** mDelayedCommitHandle; +- + // Cached drawings. If we can't get WaylandBuffer (wl_buffer) at + // WindowSurfaceWayland::Lock() we direct gecko rendering to + // mImageSurface. + // If we can't get WaylandBuffer at WindowSurfaceWayland::Commit() + // time, mImageSurface is moved to mDelayedImageCommits which + // holds all cached drawings. +- // mDelayedImageCommits can be drawn by FrameCallbackHandler(), +- // DelayedCommitHandler() or when WaylandBuffer is detached. ++ // mDelayedImageCommits can be drawn by FrameCallbackHandler() ++ // or when WaylandBuffer is detached. + RefPtr mImageSurface; + AutoTArray mDelayedImageCommits; + +@@ -282,8 +273,8 @@ class WindowSurfaceWayland : public Wind + // We can't send WaylandBuffer (wl_buffer) to compositor when gecko + // is rendering into it (i.e. between WindowSurfaceWayland::Lock() / + // WindowSurfaceWayland::Commit()). +- // Thus we use mBufferCommitAllowed to disable commit by callbacks +- // (FrameCallbackHandler(), DelayedCommitHandler()) ++ // Thus we use mBufferCommitAllowed to disable commit by ++ // CommitWaylandBuffer(). + bool mBufferCommitAllowed; + + // We need to clear WaylandBuffer when entire transparent window is repainted. + diff --git a/mozilla-1669495.patch b/mozilla-1669495.patch new file mode 100644 index 0000000..3ef027c --- /dev/null +++ b/mozilla-1669495.patch @@ -0,0 +1,130 @@ +diff -up firefox-81.0.1/layout/xul/nsMenuPopupFrame.cpp.1669495 firefox-81.0.1/layout/xul/nsMenuPopupFrame.cpp +--- firefox-81.0.1/layout/xul/nsMenuPopupFrame.cpp.1669495 2020-10-08 10:09:23.765819989 +0200 ++++ firefox-81.0.1/layout/xul/nsMenuPopupFrame.cpp 2020-10-08 10:09:23.771820010 +0200 +@@ -533,6 +533,26 @@ void nsMenuPopupFrame::LayoutPopup(nsBox + } + prefSize = XULBoundsCheck(minSize, prefSize, maxSize); + ++#ifdef MOZ_WAYLAND ++ static bool inWayland = gdk_display_get_default() && ++ !GDK_IS_X11_DISPLAY(gdk_display_get_default()); ++#else ++ static bool inWayland = false; ++#endif ++ if (inWayland) { ++ // If prefSize it is not a whole number in css pixels we need round it up ++ // to avoid reflow of the tooltips/popups and putting the text on two lines ++ // (usually happens with 200% scale factor and font scale factor <> 1) ++ // because GTK thrown away the decimals. ++ int32_t appPerCSS = AppUnitsPerCSSPixel(); ++ if (prefSize.width % appPerCSS > 0) { ++ prefSize.width += appPerCSS; ++ } ++ if (prefSize.height % appPerCSS > 0) { ++ prefSize.height += appPerCSS; ++ } ++ } ++ + bool sizeChanged = (mPrefSize != prefSize); + // if the size changed then set the bounds to be the preferred size + if (sizeChanged) { +diff -up firefox-81.0.1/widget/gtk/nsWindow.cpp.1669495 firefox-81.0.1/widget/gtk/nsWindow.cpp +--- firefox-81.0.1/widget/gtk/nsWindow.cpp.1669495 2020-10-08 10:09:23.770820007 +0200 ++++ firefox-81.0.1/widget/gtk/nsWindow.cpp 2020-10-08 10:10:29.225052014 +0200 +@@ -1090,11 +1090,13 @@ void nsWindow::Show(bool aState) { + + void nsWindow::ResizeInt(int aX, int aY, int aWidth, int aHeight, bool aMove, + bool aRepaint) { +- LOG(("nsWindow::ResizeInt [%p] %d %d -> %d %d repaint %d\n", (void*)this, aX, +- aY, aWidth, aHeight, aRepaint)); ++ LOG(("nsWindow::ResizeInt [%p] x:%d y:%d -> w:%d h:%d repaint %d aMove %d\n", ++ (void*)this, aX, aY, aWidth, aHeight, aRepaint, aMove)); + + ConstrainSize(&aWidth, &aHeight); + ++ LOG((" ConstrainSize: w:%d h;%d\n", aWidth, aHeight)); ++ + if (aMove) { + mBounds.x = aX; + mBounds.y = aY; +@@ -1132,8 +1134,7 @@ void nsWindow::ResizeInt(int aX, int aY, + } + + void nsWindow::Resize(double aWidth, double aHeight, bool aRepaint) { +- LOG(("nsWindow::Resize [%p] %d %d\n", (void*)this, (int)aWidth, +- (int)aHeight)); ++ LOG(("nsWindow::Resize [%p] %f %f\n", (void*)this, aWidth, aHeight)); + + double scale = + BoundsUseDesktopPixels() ? GetDesktopToDeviceScale().scale : 1.0; +@@ -1145,8 +1146,8 @@ void nsWindow::Resize(double aWidth, dou + + void nsWindow::Resize(double aX, double aY, double aWidth, double aHeight, + bool aRepaint) { +- LOG(("nsWindow::Resize [%p] %d %d repaint %d\n", (void*)this, (int)aWidth, +- (int)aHeight, aRepaint)); ++ LOG(("nsWindow::Resize [%p] %f %f repaint %d\n", (void*)this, aWidth, aHeight, ++ aRepaint)); + + double scale = + BoundsUseDesktopPixels() ? GetDesktopToDeviceScale().scale : 1.0; +@@ -1469,14 +1470,15 @@ void nsWindow::NativeMoveResizeWaylandPo + + newBounds.x = GdkCoordToDevicePixels(newBounds.x); + newBounds.y = GdkCoordToDevicePixels(newBounds.y); +- LOG((" new mBounds x=%d y=%d width=%d height=%d\n", newBounds.x, +- newBounds.y, newBounds.width, newBounds.height)); + + double scale = + BoundsUseDesktopPixels() ? GetDesktopToDeviceScale().scale : 1.0; + int32_t newWidth = NSToIntRound(scale * newBounds.width); + int32_t newHeight = NSToIntRound(scale * newBounds.height); + ++ LOG((" new mBounds x=%d y=%d width=%d height=%d\n", newBounds.x, ++ newBounds.y, newWidth, newHeight)); ++ + bool needsPositionUpdate = + (newBounds.x != mBounds.x || newBounds.y != mBounds.y); + bool needsSizeUpdate = +@@ -1484,6 +1486,7 @@ void nsWindow::NativeMoveResizeWaylandPo + // Update view + + if (needsSizeUpdate) { ++ LOG((" needSizeUpdate\n")); + int32_t p2a = AppUnitsPerCSSPixel() / gfxPlatformGtk::GetFontScaleFactor(); + mPreferredPopupRect = nsRect(NSIntPixelsToAppUnits(newBounds.x, p2a), + NSIntPixelsToAppUnits(newBounds.y, p2a), +@@ -1502,6 +1505,7 @@ void nsWindow::NativeMoveResizeWaylandPo + } + + if (needsPositionUpdate) { ++ LOG((" needPositionUpdate\n")); + // The newBounds are in coordinates relative to the parent window/popup. + // The NotifyWindowMoved requires the coordinates relative to the toplevel. + // We use the gdk_window_get_origin to get correct coordinates. +@@ -4211,6 +4215,8 @@ nsresult nsWindow::Create(nsIWidget* aPa + + // save our bounds + mBounds = aRect; ++ LOG((" mBounds: x:%d y:%d w:%d h:%d\n", mBounds.x, mBounds.y, mBounds.width, ++ mBounds.height)); + + mPreferredPopupRectFlushed = false; + +@@ -5061,13 +5067,16 @@ void nsWindow::NativeShow(bool aAction) + } + } + ++ LOG((" calling gtk_widget_show(mShell)\n")); + gtk_widget_show(mShell); + if (!mIsX11Display) { + WaylandStartVsync(); + } + } else if (mContainer) { ++ LOG((" calling gtk_widget_show(mContainer)\n")); + gtk_widget_show(GTK_WIDGET(mContainer)); + } else if (mGdkWindow) { ++ LOG((" calling gdk_window_show_unraised\n")); + gdk_window_show_unraised(mGdkWindow); + } + } else {