tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 54f7883222118556e73ff6db64f26c1ec3fae3cb
parent e1c7f82240bc979c762d31aa575f5e5e0856991f
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date:   Wed,  7 Jan 2026 20:15:11 +0000

Bug 2008913 - Remove some now unreachable codepaths in gtk theme drawing. r=lsalzman,gfx-reviewers

We only use this codepath to draw the window decorations in X11 now,
but we never paint directly with Moz2D to the screen on the main window
nowadays.

Differential Revision: https://phabricator.services.mozilla.com/D278189

Diffstat:
Mgfx/2d/BorrowedContext.h | 57---------------------------------------------------------
Mgfx/2d/DrawTargetCairo.cpp | 48------------------------------------------------
Mgfx/2d/DrawTargetCairo.h | 1-
Mwidget/gtk/nsNativeThemeGTK.cpp | 255++++++++++++-------------------------------------------------------------------
4 files changed, 39 insertions(+), 322 deletions(-)

diff --git a/gfx/2d/BorrowedContext.h b/gfx/2d/BorrowedContext.h @@ -18,63 +18,6 @@ namespace mozilla { namespace gfx { -#ifdef MOZ_X11 -/* This is a helper class that let's you borrow an Xlib drawable from - * a DrawTarget. This is used for drawing themed widgets. - * - * Callers should check the Xlib drawable after constructing the object - * to see if it succeeded. The DrawTarget should not be used while - * the drawable is borrowed. */ -class BorrowedXlibDrawable { - public: - BorrowedXlibDrawable() - : mDT(nullptr), - mDisplay(nullptr), - mDrawable(X11None), - mScreen(nullptr), - mVisual(nullptr) {} - - explicit BorrowedXlibDrawable(DrawTarget* aDT) - : mDT(nullptr), - mDisplay(nullptr), - mDrawable(X11None), - mScreen(nullptr), - mVisual(nullptr) { - Init(aDT); - } - - // We can optionally Init after construction in - // case we don't know what the DT will be at construction - // time. - bool Init(DrawTarget* aDT); - - // The caller needs to call Finish if drawable is non-zero when - // they are done with the context. This is currently explicit - // instead of happening implicitly in the destructor to make - // what's happening in the caller more clear. It also - // let's you resume using the DrawTarget in the same scope. - void Finish(); - - ~BorrowedXlibDrawable() { MOZ_ASSERT(!mDrawable); } - - Display* GetDisplay() const { return mDisplay; } - Drawable GetDrawable() const { return mDrawable; } - Screen* GetScreen() const { return mScreen; } - Visual* GetVisual() const { return mVisual; } - IntSize GetSize() const { return mSize; } - Point GetOffset() const { return mOffset; } - - private: - DrawTarget* mDT; - Display* mDisplay; - Drawable mDrawable; - Screen* mScreen; - Visual* mVisual; - IntSize mSize; - Point mOffset; -}; -#endif - #ifdef XP_DARWIN /* This is a helper class that let's you borrow a CGContextRef from a * DrawTargetCG. This is used for drawing themed widgets. diff --git a/gfx/2d/DrawTargetCairo.cpp b/gfx/2d/DrawTargetCairo.cpp @@ -2126,53 +2126,5 @@ Rect DrawTargetCairo::GetUserSpaceClip() const { clipY2 - clipY1); // Narrowing of doubles to floats } -#ifdef MOZ_X11 -bool BorrowedXlibDrawable::Init(DrawTarget* aDT) { - MOZ_ASSERT(aDT, "Caller should check for nullptr"); - MOZ_ASSERT(!mDT, "Can't initialize twice!"); - mDT = aDT; - mDrawable = X11None; - -# ifdef CAIRO_HAS_XLIB_SURFACE - if (aDT->GetBackendType() != BackendType::CAIRO || aDT->IsTiledDrawTarget()) { - return false; - } - - DrawTargetCairo* cairoDT = static_cast<DrawTargetCairo*>(aDT); - cairo_surface_t* surf = cairo_get_group_target(cairoDT->mContext); - if (cairo_surface_get_type(surf) != CAIRO_SURFACE_TYPE_XLIB) { - return false; - } - cairo_surface_flush(surf); - - cairoDT->WillChange(); - - mDisplay = cairo_xlib_surface_get_display(surf); - mDrawable = cairo_xlib_surface_get_drawable(surf); - mScreen = cairo_xlib_surface_get_screen(surf); - mVisual = cairo_xlib_surface_get_visual(surf); - mSize.width = cairo_xlib_surface_get_width(surf); - mSize.height = cairo_xlib_surface_get_height(surf); - - double x = 0, y = 0; - cairo_surface_get_device_offset(surf, &x, &y); - mOffset = Point(x, y); - - return true; -# else - return false; -# endif -} - -void BorrowedXlibDrawable::Finish() { - DrawTargetCairo* cairoDT = static_cast<DrawTargetCairo*>(mDT); - cairo_surface_t* surf = cairo_get_group_target(cairoDT->mContext); - cairo_surface_mark_dirty(surf); - if (mDrawable) { - mDrawable = X11None; - } -} -#endif - } // namespace gfx } // namespace mozilla diff --git a/gfx/2d/DrawTargetCairo.h b/gfx/2d/DrawTargetCairo.h @@ -48,7 +48,6 @@ class GradientStopsCairo : public GradientStops { class DrawTargetCairo final : public DrawTarget { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetCairo, override) - friend class BorrowedXlibDrawable; DrawTargetCairo(); virtual ~DrawTargetCairo(); diff --git a/widget/gtk/nsNativeThemeGTK.cpp b/widget/gtk/nsNativeThemeGTK.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsNativeThemeGTK.h" +#include "cairo.h" #include "nsDeviceContext.h" #include "gtk/gtk.h" #include "nsPresContext.h" @@ -16,12 +17,6 @@ #include "mozilla/gfx/PathHelpers.h" #include "mozilla/WidgetUtilsGtk.h" -#ifdef MOZ_X11 -# ifdef CAIRO_HAS_XLIB_SURFACE -# include "cairo-xlib.h" -# endif -#endif - #include <dlfcn.h> using namespace mozilla; @@ -61,70 +56,6 @@ static Maybe<GtkWidgets::Type> AppearanceToWidgetType( return {}; } -class SystemCairoClipper : public ClipExporter { - public: - explicit SystemCairoClipper(cairo_t* aContext, gint aScaleFactor = 1) - : mContext(aContext), mScaleFactor(aScaleFactor) {} - - void BeginClip(const Matrix& aTransform) override { - cairo_matrix_t mat; - GfxMatrixToCairoMatrix(aTransform, mat); - // We also need to remove the scale factor effect from the matrix - mat.y0 = mat.y0 / mScaleFactor; - mat.x0 = mat.x0 / mScaleFactor; - cairo_set_matrix(mContext, &mat); - - cairo_new_path(mContext); - } - - void MoveTo(const Point& aPoint) override { - cairo_move_to(mContext, aPoint.x / mScaleFactor, aPoint.y / mScaleFactor); - mBeginPoint = aPoint; - mCurrentPoint = aPoint; - } - - void LineTo(const Point& aPoint) override { - cairo_line_to(mContext, aPoint.x / mScaleFactor, aPoint.y / mScaleFactor); - mCurrentPoint = aPoint; - } - - void BezierTo(const Point& aCP1, const Point& aCP2, - const Point& aCP3) override { - cairo_curve_to(mContext, aCP1.x / mScaleFactor, aCP1.y / mScaleFactor, - aCP2.x / mScaleFactor, aCP2.y / mScaleFactor, - aCP3.x / mScaleFactor, aCP3.y / mScaleFactor); - mCurrentPoint = aCP3; - } - - void QuadraticBezierTo(const Point& aCP1, const Point& aCP2) override { - Point CP0 = CurrentPoint(); - Point CP1 = (CP0 + aCP1 * 2.0) / 3.0; - Point CP2 = (aCP2 + aCP1 * 2.0) / 3.0; - Point CP3 = aCP2; - cairo_curve_to(mContext, CP1.x / mScaleFactor, CP1.y / mScaleFactor, - CP2.x / mScaleFactor, CP2.y / mScaleFactor, - CP3.x / mScaleFactor, CP3.y / mScaleFactor); - mCurrentPoint = aCP2; - } - - void Arc(const Point& aOrigin, float aRadius, float aStartAngle, - float aEndAngle, bool aAntiClockwise) override { - ArcToBezier(this, aOrigin, Size(aRadius, aRadius), aStartAngle, aEndAngle, - aAntiClockwise); - } - - void Close() override { - cairo_close_path(mContext); - mCurrentPoint = mBeginPoint; - } - - void EndClip() override { cairo_clip(mContext); } - - private: - cairo_t* mContext; - gint mScaleFactor; -}; - static void DrawThemeWithCairo(gfxContext* aContext, DrawTarget* aDrawTarget, const GtkWidgets::DrawingParams& aParams, double aScaleFactor, bool aSnapped, @@ -136,162 +67,54 @@ static void DrawThemeWithCairo(gfxContext* aContext, DrawTarget* aDrawTarget, RTLD_DEFAULT, "cairo_surface_set_device_scale"); const bool useHiDPIWidgets = aScaleFactor != 1.0 && sCairoSurfaceSetDeviceScalePtr; - - Point drawOffsetScaled; - Point drawOffsetOriginal; - Matrix transform; - if (!aSnapped) { - // If we are not snapped, we depend on the DT for translation. - drawOffsetOriginal = aDrawOrigin; - drawOffsetScaled = useHiDPIWidgets ? drawOffsetOriginal / aScaleFactor - : drawOffsetOriginal; - transform = aDrawTarget->GetTransform().PreTranslate(drawOffsetScaled); - } else { - // Otherwise, we only need to take the device offset into account. - drawOffsetOriginal = aDrawOrigin - aContext->GetDeviceOffset(); - drawOffsetScaled = useHiDPIWidgets ? drawOffsetOriginal / aScaleFactor - : drawOffsetOriginal; - transform = Matrix::Translation(drawOffsetScaled); - } - - if (!useHiDPIWidgets && aScaleFactor != 1) { - transform.PreScale(aScaleFactor, aScaleFactor); + // If we are not snapped, we depend on the DT for translation. + // Otherwise, we only need to take the device offset into account. + const Point drawOffset = + aSnapped ? aDrawOrigin - aContext->GetDeviceOffset() : aDrawOrigin; + // If the widget has any transparency, make sure to choose an alpha format. + const SurfaceFormat format = aTransparency != nsITheme::eOpaque + ? SurfaceFormat::B8G8R8A8 + : aDrawTarget->GetFormat(); + // Create a temporary data surface to render the widget into. + RefPtr<DataSourceSurface> dataSurface = Factory::CreateDataSourceSurface( + aDrawSize, format, aTransparency != nsITheme::eOpaque); + if (!dataSurface) { + return; } - cairo_matrix_t mat; - GfxMatrixToCairoMatrix(transform, mat); - - Size clipSize((aDrawSize.width + aScaleFactor - 1) / aScaleFactor, - (aDrawSize.height + aScaleFactor - 1) / aScaleFactor); - - // A direct Cairo draw target is not available, so we need to create a - // temporary one. -#if defined(MOZ_X11) && defined(CAIRO_HAS_XLIB_SURFACE) - if (GdkIsX11Display()) { - // If using a Cairo xlib surface, then try to reuse it. - BorrowedXlibDrawable borrow(aDrawTarget); - if (Drawable drawable = borrow.GetDrawable()) { - nsIntSize size = borrow.GetSize(); - cairo_surface_t* surf = cairo_xlib_surface_create( - borrow.GetDisplay(), drawable, borrow.GetVisual(), size.width, - size.height); - if (!NS_WARN_IF(!surf)) { - Point offset = borrow.GetOffset(); - if (offset != Point()) { - cairo_surface_set_device_offset(surf, offset.x, offset.y); - } - cairo_t* cr = cairo_create(surf); - if (!NS_WARN_IF(!cr)) { - RefPtr<SystemCairoClipper> clipper = new SystemCairoClipper(cr); - aContext->ExportClip(*clipper); - - cairo_set_matrix(cr, &mat); - - cairo_new_path(cr); - cairo_rectangle(cr, 0, 0, clipSize.width, clipSize.height); - cairo_clip(cr); - - GtkWidgets::Draw(cr, &aParams); - - cairo_destroy(cr); - } - cairo_surface_destroy(surf); - } - borrow.Finish(); + { + DataSourceSurface::ScopedMap map(dataSurface, + DataSourceSurface::MapType::WRITE); + if (NS_WARN_IF(!map.IsMapped())) { return; } - } -#endif - - // Check if the widget requires complex masking that must be composited. - // Try to directly write to the draw target's pixels if possible. - uint8_t* data; - nsIntSize size; - int32_t stride; - SurfaceFormat format; - IntPoint origin; - if (aDrawTarget->LockBits(&data, &size, &stride, &format, &origin)) { - // Create a Cairo image surface context the device rectangle. + // Create a Cairo image surface wrapping the data surface. cairo_surface_t* surf = cairo_image_surface_create_for_data( - data, GfxFormatToCairoFormat(format), size.width, size.height, stride); - if (!NS_WARN_IF(!surf)) { - if (useHiDPIWidgets) { - sCairoSurfaceSetDeviceScalePtr(surf, aScaleFactor, aScaleFactor); - } - if (origin != IntPoint()) { - cairo_surface_set_device_offset(surf, -origin.x, -origin.y); - } - cairo_t* cr = cairo_create(surf); - if (!NS_WARN_IF(!cr)) { - RefPtr<SystemCairoClipper> clipper = - new SystemCairoClipper(cr, useHiDPIWidgets ? aScaleFactor : 1); - aContext->ExportClip(*clipper); - - cairo_set_matrix(cr, &mat); - - cairo_new_path(cr); - cairo_rectangle(cr, 0, 0, clipSize.width, clipSize.height); - cairo_clip(cr); - - GtkWidgets::Draw(cr, &aParams); - - cairo_destroy(cr); - } - cairo_surface_destroy(surf); + map.GetData(), GfxFormatToCairoFormat(format), aDrawSize.width, + aDrawSize.height, map.GetStride()); + if (NS_WARN_IF(!surf)) { + return; } - aDrawTarget->ReleaseBits(data); - } else { - // If the widget has any transparency, make sure to choose an alpha format. - format = aTransparency != nsITheme::eOpaque ? SurfaceFormat::B8G8R8A8 - : aDrawTarget->GetFormat(); - // Create a temporary data surface to render the widget into. - RefPtr<DataSourceSurface> dataSurface = Factory::CreateDataSourceSurface( - aDrawSize, format, aTransparency != nsITheme::eOpaque); - DataSourceSurface::MappedSurface map; - if (!NS_WARN_IF( - !(dataSurface && - dataSurface->Map(DataSourceSurface::MapType::WRITE, &map)))) { - // Create a Cairo image surface wrapping the data surface. - cairo_surface_t* surf = cairo_image_surface_create_for_data( - map.mData, GfxFormatToCairoFormat(format), aDrawSize.width, - aDrawSize.height, map.mStride); - cairo_t* cr = nullptr; - if (!NS_WARN_IF(!surf)) { - cr = cairo_create(surf); - if (!NS_WARN_IF(!cr)) { - if (aScaleFactor != 1) { - if (useHiDPIWidgets) { - sCairoSurfaceSetDeviceScalePtr(surf, aScaleFactor, aScaleFactor); - } else { - cairo_scale(cr, aScaleFactor, aScaleFactor); - } - } - - GtkWidgets::Draw(cr, &aParams); + if (cairo_t* cr = cairo_create(surf)) { + if (aScaleFactor != 1) { + if (useHiDPIWidgets) { + sCairoSurfaceSetDeviceScalePtr(surf, aScaleFactor, aScaleFactor); + } else { + cairo_scale(cr, aScaleFactor, aScaleFactor); } } - - // Unmap the surface before using it as a source - dataSurface->Unmap(); - - if (cr) { - // The widget either needs to be masked or has transparency, so use the - // slower drawing path. - aDrawTarget->DrawSurface( - dataSurface, - Rect(aSnapped ? drawOffsetOriginal - - aDrawTarget->GetTransform().GetTranslation() - : drawOffsetOriginal, - Size(aDrawSize)), - Rect(0, 0, aDrawSize.width, aDrawSize.height)); - cairo_destroy(cr); - } - - if (surf) { - cairo_surface_destroy(surf); - } + GtkWidgets::Draw(cr, &aParams); + cairo_destroy(cr); } + cairo_surface_destroy(surf); } + + aDrawTarget->DrawSurface( + dataSurface, + Rect(aSnapped ? drawOffset - aDrawTarget->GetTransform().GetTranslation() + : drawOffset, + Size(aDrawSize)), + Rect(0, 0, aDrawSize.width, aDrawSize.height)); } void nsNativeThemeGTK::DrawWidgetBackground(