Bug 1913104 - Remove X11 mask code. r=stransky,desktop-theme-reviewers,dao

It's only used in non-compositing WMs, to implement popup transparency,
and it's completely untested.

Instead, do not draw shadows and rounded corners on those WMs.

Differential Revision: https://phabricator.services.mozilla.com/D219141
This commit is contained in:
Emilio Cobos Álvarez 2024-08-16 08:11:18 +00:00
Родитель 89fbad696d
Коммит 6073058701
18 изменённых файлов: 44 добавлений и 644 удалений

Просмотреть файл

@ -3187,7 +3187,6 @@ pref("network.psl.onUpdate_notify", false);
#ifdef MOZ_WIDGET_GTK
pref("widget.disable-workspace-management", false);
pref("widget.titlebar-x11-use-shape-mask", false);
#endif
// All the Geolocation preferences are here.

Просмотреть файл

@ -43,6 +43,12 @@ panel {
--panel-shadow-margin: 4px;
}
/* On some linux WMs we need to draw square menus because alpha is not available */
@media (-moz-platform: linux) and (not (-moz-gtk-csd-available)) {
--panel-shadow-margin: 0px !important;
--panel-border-radius: 0px !important;
}
@media (-moz-platform: macos) {
appearance: auto;
-moz-default-appearance: menupopup;

Просмотреть файл

@ -14,7 +14,8 @@ CompositorWidgetChild::CompositorWidgetChild(
RefPtr<CompositorVsyncDispatcher> aVsyncDispatcher,
RefPtr<CompositorWidgetVsyncObserver> aVsyncObserver,
const CompositorWidgetInitData&)
: mVsyncDispatcher(aVsyncDispatcher), mVsyncObserver(aVsyncObserver) {
: mVsyncDispatcher(std::move(aVsyncDispatcher)),
mVsyncObserver(std::move(aVsyncObserver)) {
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(!gfxPlatform::IsHeadless());
}
@ -42,9 +43,8 @@ void CompositorWidgetChild::CleanupResources() {
Unused << SendCleanupResources();
}
void CompositorWidgetChild::SetRenderingSurface(const uintptr_t aXWindow,
const bool aShaped) {
Unused << SendSetRenderingSurface(aXWindow, aShaped);
void CompositorWidgetChild::SetRenderingSurface(const uintptr_t aXWindow) {
Unused << SendSetRenderingSurface(aXWindow);
}
} // namespace widget

Просмотреть файл

@ -28,8 +28,7 @@ class CompositorWidgetChild final : public PCompositorWidgetChild,
void NotifyClientSizeChanged(const LayoutDeviceIntSize& aClientSize) override;
void CleanupResources() override;
void SetRenderingSurface(const uintptr_t aXWindow,
const bool aShaped) override;
void SetRenderingSurface(const uintptr_t aXWindow) override;
private:
RefPtr<CompositorVsyncDispatcher> mVsyncDispatcher;

Просмотреть файл

@ -46,8 +46,8 @@ mozilla::ipc::IPCResult CompositorWidgetParent::RecvCleanupResources() {
}
mozilla::ipc::IPCResult CompositorWidgetParent::RecvSetRenderingSurface(
const uintptr_t& aXWindow, const bool& aShaped) {
SetRenderingSurface(aXWindow, aShaped);
const uintptr_t& aXWindow) {
SetRenderingSurface(aXWindow);
return IPC_OK();
}

Просмотреть файл

@ -29,8 +29,8 @@ class CompositorWidgetParent final : public PCompositorWidgetParent,
const LayoutDeviceIntSize& aClientSize) override;
mozilla::ipc::IPCResult RecvCleanupResources() override;
mozilla::ipc::IPCResult RecvSetRenderingSurface(const uintptr_t& aXWindow,
const bool& aShaped) override;
mozilla::ipc::IPCResult RecvSetRenderingSurface(
const uintptr_t& aXWindow) override;
private:
RefPtr<VsyncObserver> mVsyncObserver;

Просмотреть файл

@ -6,9 +6,7 @@
#include "GtkCompositorWidget.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/WidgetUtilsGtk.h"
#include "mozilla/widget/InProcessCompositorWidget.h"
#include "mozilla/widget/PlatformWidgetTypes.h"
#include "nsWindow.h"
@ -40,7 +38,7 @@ GtkCompositorWidget::GtkCompositorWidget(
"GtkCompositorWidget::mClientSize") {
#if defined(MOZ_X11)
if (GdkIsX11Display()) {
ConfigureX11Backend((Window)aInitData.XWindow(), aInitData.Shaped());
ConfigureX11Backend((Window)aInitData.XWindow());
LOG("GtkCompositorWidget::GtkCompositorWidget() [%p] mXWindow %p\n",
(void*)mWidget.get(), (void*)aInitData.XWindow());
}
@ -176,19 +174,18 @@ void GtkCompositorWidget::ConfigureWaylandBackend() {
#endif
#if defined(MOZ_X11)
void GtkCompositorWidget::ConfigureX11Backend(Window aXWindow, bool aShaped) {
void GtkCompositorWidget::ConfigureX11Backend(Window aXWindow) {
// We don't have X window yet.
if (!aXWindow) {
mProvider.CleanupResources();
return;
}
// Initialize the window surface provider
mProvider.Initialize(aXWindow, aShaped);
mProvider.Initialize(aXWindow);
}
#endif
void GtkCompositorWidget::SetRenderingSurface(const uintptr_t aXWindow,
const bool aShaped) {
void GtkCompositorWidget::SetRenderingSurface(const uintptr_t aXWindow) {
LOG("GtkCompositorWidget::SetRenderingSurface() [%p]\n", mWidget.get());
#if defined(MOZ_WAYLAND)
@ -199,8 +196,8 @@ void GtkCompositorWidget::SetRenderingSurface(const uintptr_t aXWindow,
#endif
#if defined(MOZ_X11)
if (GdkIsX11Display()) {
LOG(" configure XWindow %p shaped %d\n", (void*)aXWindow, aShaped);
ConfigureX11Backend((Window)aXWindow, aShaped);
LOG(" configure XWindow %p\n", (void*)aXWindow);
ConfigureX11Backend((Window)aXWindow);
}
#endif
}

Просмотреть файл

@ -31,8 +31,7 @@ class PlatformCompositorWidgetDelegate : public CompositorWidgetDelegate {
virtual GtkCompositorWidget* AsGtkCompositorWidget() { return nullptr; };
virtual void CleanupResources() = 0;
virtual void SetRenderingSurface(const uintptr_t aXWindow,
const bool aShaped) = 0;
virtual void SetRenderingSurface(const uintptr_t aXWindow) = 0;
// CompositorWidgetDelegate Overrides
@ -79,8 +78,7 @@ class GtkCompositorWidget : public CompositorWidget,
void CleanupResources() override;
// Resume rendering with to given aXWindow (X11) or nsWindow (Wayland).
void SetRenderingSurface(const uintptr_t aXWindow,
const bool aShaped) override;
void SetRenderingSurface(const uintptr_t aXWindow) override;
// If we fail to set window size (due to different screen scale or so)
// we can't paint the frame by compositor.
@ -105,7 +103,7 @@ class GtkCompositorWidget : public CompositorWidget,
void ConfigureWaylandBackend();
#endif
#if defined(MOZ_X11)
void ConfigureX11Backend(Window aXWindow, bool aShaped);
void ConfigureX11Backend(Window aXWindow);
#endif
#ifdef MOZ_LOGGING
bool IsPopup();

Просмотреть файл

@ -171,10 +171,7 @@ void moz_container_realize(GtkWidget* widget) {
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.window_type = GDK_WINDOW_CHILD;
MozContainer* container = MOZ_CONTAINER(widget);
attributes.visual =
container->data.force_default_visual
? gdk_screen_get_system_visual(gtk_widget_get_screen(widget))
: gtk_widget_get_visual(widget);
attributes.visual = gtk_widget_get_visual(widget);
window = gdk_window_new(parent, &attributes, attributes_mask);
@ -228,10 +225,6 @@ void moz_container_size_allocate(GtkWidget* widget, GtkAllocation* allocation) {
}
}
void moz_container_force_default_visual(MozContainer* container) {
container->data.force_default_visual = true;
}
nsWindow* moz_container_get_nsWindow(MozContainer* container) {
gpointer user_data = g_object_get_data(G_OBJECT(container), "nsWindow");
return static_cast<nsWindow*>(user_data);

Просмотреть файл

@ -48,7 +48,6 @@ struct _MozContainer {
GtkContainer container;
gboolean destroyed;
struct Data {
gboolean force_default_visual = false;
#ifdef MOZ_WAYLAND
MozContainerWayland wl_container;
#endif
@ -64,7 +63,6 @@ GtkWidget* moz_container_new(void);
void moz_container_unmap(GtkWidget* widget);
void moz_container_put(MozContainer* container, GtkWidget* child_widget, gint x,
gint y);
void moz_container_force_default_visual(MozContainer* container);
void moz_container_class_init(MozContainerClass* klass);
class nsWindow;

Просмотреть файл

@ -23,7 +23,7 @@ parent:
async NotifyClientSizeChanged(LayoutDeviceIntSize aClientSize);
async CleanupResources();
async SetRenderingSurface(uintptr_t aXWindow, bool aShaped);
async SetRenderingSurface(uintptr_t aXWindow);
child:

Просмотреть файл

@ -17,7 +17,6 @@ struct GtkCompositorWidgetInitData
{
uintptr_t XWindow;
nsCString XDisplayString;
bool Shaped;
bool IsX11Display;
LayoutDeviceIntSize InitialClientSize;

Просмотреть файл

@ -46,7 +46,6 @@ WindowSurfaceProvider::WindowSurfaceProvider()
mWindowSurfaceValid(false)
#ifdef MOZ_X11
,
mIsShaped(false),
mXDepth(0),
mXWindow(0),
mXVisual(nullptr)
@ -78,7 +77,7 @@ bool WindowSurfaceProvider::Initialize(GtkCompositorWidget* aCompositorWidget) {
}
#endif
#ifdef MOZ_X11
bool WindowSurfaceProvider::Initialize(Window aWindow, bool aIsShaped) {
bool WindowSurfaceProvider::Initialize(Window aWindow) {
mWindowSurfaceValid = false;
// Grab the window's visual and depth
@ -91,7 +90,6 @@ bool WindowSurfaceProvider::Initialize(Window aWindow, bool aIsShaped) {
mXWindow = aWindow;
mXVisual = windowAttrs.visual;
mXDepth = windowAttrs.depth;
mIsShaped = aIsShaped;
return true;
}
#endif
@ -106,7 +104,6 @@ void WindowSurfaceProvider::CleanupResources() {
mXWindow = 0;
mXVisual = 0;
mXDepth = 0;
mIsShaped = false;
#endif
}
@ -130,7 +127,7 @@ RefPtr<WindowSurface> WindowSurfaceProvider::CreateWindowSurface() {
// 1. MIT-SHM
// 2. XPutImage
# ifdef MOZ_HAVE_SHMIMAGE
if (!mIsShaped && nsShmImage::UseShm()) {
if (nsShmImage::UseShm()) {
LOG(("Drawing to Window 0x%lx will use MIT-SHM\n", (Window)mXWindow));
return MakeRefPtr<WindowSurfaceX11SHM>(DefaultXDisplay(), mXWindow,
mXVisual, mXDepth);
@ -139,7 +136,7 @@ RefPtr<WindowSurface> WindowSurfaceProvider::CreateWindowSurface() {
LOG(("Drawing to Window 0x%lx will use XPutImage\n", (Window)mXWindow));
return MakeRefPtr<WindowSurfaceX11Image>(DefaultXDisplay(), mXWindow,
mXVisual, mXDepth, mIsShaped);
mXVisual, mXDepth);
}
#endif
MOZ_RELEASE_ASSERT(false);
@ -187,7 +184,7 @@ WindowSurfaceProvider::StartRemoteDrawingInRegion(
gfxWarningOnce()
<< "Failed to lock WindowSurface, falling back to XPutImage backend.";
mWindowSurface = MakeRefPtr<WindowSurfaceX11Image>(
DefaultXDisplay(), mXWindow, mXVisual, mXDepth, mIsShaped);
DefaultXDisplay(), mXWindow, mXVisual, mXDepth);
dt = mWindowSurface->Lock(aInvalidRegion);
}
#endif

Просмотреть файл

@ -49,7 +49,7 @@ class WindowSurfaceProvider final {
bool Initialize(GtkCompositorWidget* aCompositorWidget);
#endif
#ifdef MOZ_X11
bool Initialize(Window aWindow, bool aIsShaped);
bool Initialize(Window aWindow);
Window GetXWindow() const { return mXWindow; }
#endif
@ -89,7 +89,6 @@ class WindowSurfaceProvider final {
GtkCompositorWidget* mCompositorWidget = nullptr;
#endif
#ifdef MOZ_X11
bool mIsShaped;
int mXDepth;
// Make mXWindow atomic to allow it read from different threads
// and make tsan happy.

Просмотреть файл

@ -29,33 +29,10 @@ using namespace mozilla::gfx;
WindowSurfaceX11Image::WindowSurfaceX11Image(Display* aDisplay, Window aWindow,
Visual* aVisual,
unsigned int aDepth,
bool aIsShaped)
: WindowSurfaceX11(aDisplay, aWindow, aVisual, aDepth),
mTransparencyBitmap(nullptr),
mTransparencyBitmapWidth(0),
mTransparencyBitmapHeight(0),
mIsShaped(aIsShaped),
mWindowParent(0) {
if (!mIsShaped) {
return;
}
unsigned int aDepth)
: WindowSurfaceX11(aDisplay, aWindow, aVisual, aDepth) {}
Window root, *children = nullptr;
unsigned int childrenNum;
if (XQueryTree(mDisplay, mWindow, &root, &mWindowParent, &children,
&childrenNum)) {
if (children) {
XFree((char*)children);
}
}
}
WindowSurfaceX11Image::~WindowSurfaceX11Image() {
if (mTransparencyBitmap) {
delete[] mTransparencyBitmap;
}
}
WindowSurfaceX11Image::~WindowSurfaceX11Image() {}
already_AddRefed<gfx::DrawTarget> WindowSurfaceX11Image::Lock(
const LayoutDeviceIntRegion& aRegion) {
@ -78,13 +55,6 @@ already_AddRefed<gfx::DrawTarget> WindowSurfaceX11Image::Lock(
: gfx::SurfaceFormat::X8R8G8B8_UINT32;
}
// Use alpha image format for shaped window as we derive
// the shape bitmap from alpha channel. Must match SHAPED_IMAGE_SURFACE_BPP
// and SHAPED_IMAGE_SURFACE_ALPHA_INDEX.
if (mIsShaped) {
format = gfx::SurfaceFormat::A8R8G8B8_UINT32;
}
mImageSurface = new gfxImageSurface(size, format);
if (mImageSurface->CairoStatus()) {
return nullptr;
@ -112,122 +82,6 @@ already_AddRefed<gfx::DrawTarget> WindowSurfaceX11Image::Lock(
ImageFormatToSurfaceFormat(format));
}
// The transparency bitmap routines are derived form the ones at nsWindow.cpp.
// The difference here is that we compose to RGBA image and then create
// the shape mask from final image alpha channel.
static inline int32_t GetBitmapStride(int32_t width) { return (width + 7) / 8; }
static bool ChangedMaskBits(gchar* aMaskBits, int32_t aMaskWidth,
int32_t aMaskHeight, const nsIntRect& aRect,
uint8_t* aImageData) {
int32_t stride = aMaskWidth * SHAPED_IMAGE_SURFACE_BPP;
int32_t x, y, xMax = aRect.XMost(), yMax = aRect.YMost();
int32_t maskBytesPerRow = GetBitmapStride(aMaskWidth);
for (y = aRect.y; y < yMax; y++) {
gchar* maskBytes = aMaskBits + y * maskBytesPerRow;
uint8_t* alphas = aImageData;
for (x = aRect.x; x < xMax; x++) {
bool newBit = *(alphas + SHAPED_IMAGE_SURFACE_ALPHA_INDEX) > 0x7f;
alphas += SHAPED_IMAGE_SURFACE_BPP;
gchar maskByte = maskBytes[x >> 3];
bool maskBit = (maskByte & (1 << (x & 7))) != 0;
if (maskBit != newBit) {
return true;
}
}
aImageData += stride;
}
return false;
}
static void UpdateMaskBits(gchar* aMaskBits, int32_t aMaskWidth,
int32_t aMaskHeight, const nsIntRect& aRect,
uint8_t* aImageData) {
int32_t stride = aMaskWidth * SHAPED_IMAGE_SURFACE_BPP;
int32_t x, y, xMax = aRect.XMost(), yMax = aRect.YMost();
int32_t maskBytesPerRow = GetBitmapStride(aMaskWidth);
for (y = aRect.y; y < yMax; y++) {
gchar* maskBytes = aMaskBits + y * maskBytesPerRow;
uint8_t* alphas = aImageData;
for (x = aRect.x; x < xMax; x++) {
bool newBit = *(alphas + SHAPED_IMAGE_SURFACE_ALPHA_INDEX) > 0x7f;
alphas += SHAPED_IMAGE_SURFACE_BPP;
gchar mask = 1 << (x & 7);
gchar maskByte = maskBytes[x >> 3];
// Note: '-newBit' turns 0 into 00...00 and 1 into 11...11
maskBytes[x >> 3] = (maskByte & ~mask) | (-newBit & mask);
}
aImageData += stride;
}
}
void WindowSurfaceX11Image::ResizeTransparencyBitmap(int aWidth, int aHeight) {
int32_t actualSize =
GetBitmapStride(mTransparencyBitmapWidth) * mTransparencyBitmapHeight;
int32_t newSize = GetBitmapStride(aWidth) * aHeight;
if (actualSize < newSize) {
delete[] mTransparencyBitmap;
mTransparencyBitmap = new gchar[newSize];
}
mTransparencyBitmapWidth = aWidth;
mTransparencyBitmapHeight = aHeight;
}
void WindowSurfaceX11Image::ApplyTransparencyBitmap() {
gfx::IntSize size = mWindowSurface->GetSize();
bool maskChanged = true;
if (!mTransparencyBitmap) {
mTransparencyBitmapWidth = size.width;
mTransparencyBitmapHeight = size.height;
int32_t byteSize =
GetBitmapStride(mTransparencyBitmapWidth) * mTransparencyBitmapHeight;
mTransparencyBitmap = new gchar[byteSize];
} else {
bool sizeChanged = (size.width != mTransparencyBitmapWidth ||
size.height != mTransparencyBitmapHeight);
if (sizeChanged) {
ResizeTransparencyBitmap(size.width, size.height);
} else {
maskChanged = ChangedMaskBits(
mTransparencyBitmap, mTransparencyBitmapWidth,
mTransparencyBitmapHeight, nsIntRect(0, 0, size.width, size.height),
(uint8_t*)mImageSurface->Data());
}
}
if (maskChanged) {
UpdateMaskBits(mTransparencyBitmap, mTransparencyBitmapWidth,
mTransparencyBitmapHeight,
nsIntRect(0, 0, size.width, size.height),
(uint8_t*)mImageSurface->Data());
// We use X11 calls where possible, because GDK handles expose events
// for shaped windows in a way that's incompatible with us (Bug 635903).
// It doesn't occur when the shapes are set through X.
Display* xDisplay = mWindowSurface->XDisplay();
Window xDrawable = mWindowSurface->XDrawable();
Pixmap maskPixmap = XCreateBitmapFromData(
xDisplay, xDrawable, mTransparencyBitmap, mTransparencyBitmapWidth,
mTransparencyBitmapHeight);
XShapeCombineMask(xDisplay, xDrawable, ShapeBounding, 0, 0, maskPixmap,
ShapeSet);
if (mWindowParent) {
XShapeCombineMask(mDisplay, mWindowParent, ShapeBounding, 0, 0,
maskPixmap, ShapeSet);
}
XFreePixmap(xDisplay, maskPixmap);
}
}
void WindowSurfaceX11Image::Commit(
const LayoutDeviceIntRegion& aInvalidRegion) {
RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateDrawTargetForCairoSurface(
@ -245,10 +99,6 @@ void WindowSurfaceX11Image::Commit(
return;
}
if (mIsShaped) {
ApplyTransparencyBitmap();
}
uint32_t numRects = aInvalidRegion.GetNumRects();
if (numRects == 1) {
dt->CopySurface(surf, bounds, bounds.TopLeft());

Просмотреть файл

@ -20,7 +20,7 @@ namespace widget {
class WindowSurfaceX11Image : public WindowSurfaceX11 {
public:
WindowSurfaceX11Image(Display* aDisplay, Window aWindow, Visual* aVisual,
unsigned int aDepth, bool aIsShaped);
unsigned int aDepth);
~WindowSurfaceX11Image();
already_AddRefed<gfx::DrawTarget> Lock(
@ -29,17 +29,8 @@ class WindowSurfaceX11Image : public WindowSurfaceX11 {
bool IsFallback() const override { return true; }
private:
void ResizeTransparencyBitmap(int aWidth, int aHeight);
void ApplyTransparencyBitmap();
RefPtr<gfxXlibSurface> mWindowSurface;
RefPtr<gfxImageSurface> mImageSurface;
gchar* mTransparencyBitmap;
int32_t mTransparencyBitmapWidth;
int32_t mTransparencyBitmapHeight;
bool mIsShaped;
Window mWindowParent;
};
} // namespace widget

Просмотреть файл

@ -343,14 +343,6 @@ static GdkCursor* gCursorCache[eCursorCount];
// only the button state bits are used.
static guint gButtonState;
static inline int32_t GetBitmapStride(int32_t width) {
#if defined(MOZ_X11)
return (width + 7) / 8;
#else
return cairo_format_stride_for_width(CAIRO_FORMAT_A1, width);
#endif
}
static inline bool TimestampIsNewerThan(guint32 a, guint32 b) {
// Timestamps are just the least significant bits of a monotonically
// increasing function, and so the use of unsigned overflow arithmetic.
@ -415,7 +407,6 @@ nsWindow::nsWindow()
mPopupTrackInHierarchy(false),
mPopupTrackInHierarchyConfigured(false),
mHiddenPopupPositioned(false),
mTransparencyBitmapForTitlebar(false),
mHasAlphaVisual(false),
mPopupAnchored(false),
mPopupContextMenu(false),
@ -611,8 +602,6 @@ void nsWindow::Destroy() {
MOZ_ASSERT(!gtk_widget_get_mapped(mShell));
MOZ_ASSERT(!gtk_widget_get_mapped(GTK_WIDGET(mContainer)));
ClearTransparencyBitmap();
DestroyLayerManager();
// mSurfaceProvider holds reference to this nsWindow so we need to explicitly
@ -3888,27 +3877,6 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) {
// to the new bounds here. The region is relative to this
// window.
region.And(region, LayoutDeviceIntRect(0, 0, mBounds.width, mBounds.height));
bool shaped = false;
if (TransparencyMode::Transparent == GetTransparencyMode()) {
auto* window = static_cast<nsWindow*>(GetTopLevelWidget());
if (mTransparencyBitmapForTitlebar) {
if (mSizeMode == nsSizeMode_Normal) {
window->UpdateTitlebarTransparencyBitmap();
} else {
window->ClearTransparencyBitmap();
}
} else {
if (mHasAlphaVisual) {
// Remove possible shape mask from when window manger was not
// previously compositing.
window->ClearTransparencyBitmap();
} else {
shaped = true;
}
}
}
if (region.IsEmpty()) {
LOG("quit, region.IsEmpty()");
return TRUE;
@ -3944,28 +3912,8 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) {
}
#ifdef MOZ_X11
if (shaped) {
// Collapse update area to the bounding box. This is so we only have to
// call UpdateTranslucentWindowAlpha once. After we have dropped
// support for non-Thebes graphics, UpdateTranslucentWindowAlpha will be
// our private interface so we can rework things to avoid this.
dt->PushClipRect(Rect(boundsRect));
// The double buffering is done here to extract the shape mask.
// (The shape mask won't be necessary when a visual with an alpha
// channel is used on compositing window managers.)
layerBuffering = BufferMode::BUFFER_NONE;
RefPtr<DrawTarget> destDT =
dt->CreateSimilarDrawTarget(boundsRect.Size(), SurfaceFormat::B8G8R8A8);
if (!destDT || !destDT->IsValid()) {
return FALSE;
}
destDT->SetTransform(Matrix::Translation(-boundsRect.TopLeft()));
ctx.emplace(destDT, /* aPreserveTransform */ true);
} else {
gfxUtils::ClipToRegion(dt, region.ToUnknownRegion());
ctx.emplace(dt, /* aPreserveTransform */ true);
}
gfxUtils::ClipToRegion(dt, region.ToUnknownRegion());
ctx.emplace(dt, /* aPreserveTransform */ true);
# if 0
// NOTE: Paint flashing region would be wrong for cairo, since
@ -3980,7 +3928,6 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) {
#endif // MOZ_X11
bool painted = false;
{
if (renderer->GetBackendType() == LayersBackend::LAYERS_NONE) {
if (GetTransparencyMode() == TransparencyMode::Transparent &&
@ -3992,7 +3939,7 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) {
}
AutoLayerManagerSetup setupLayerManager(
this, ctx.isNothing() ? nullptr : &ctx.ref(), layerBuffering);
painted = listener->PaintWindow(this, region);
listener->PaintWindow(this, region);
// Re-get the listener since the will paint notification might have
// killed it.
@ -4004,26 +3951,8 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) {
}
#ifdef MOZ_X11
// PaintWindow can Destroy us (bug 378273), avoid doing any paint
// operations below if that happened - it will lead to XError and exit().
if (shaped) {
if (MOZ_LIKELY(!mIsDestroyed)) {
if (painted) {
RefPtr<SourceSurface> surf = ctx->GetDrawTarget()->Snapshot();
UpdateAlpha(surf, boundsRect);
dt->DrawSurface(surf, Rect(boundsRect),
Rect(0, 0, boundsRect.width, boundsRect.height),
DrawSurfaceOptions(SamplingFilter::POINT),
DrawOptions(1.0f, CompositionOp::OP_SOURCE));
}
}
}
ctx.reset();
dt->PopClip();
#endif // MOZ_X11
EndRemoteDrawingInRegion(dt, region);
@ -4043,33 +3972,6 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) {
return TRUE;
}
void nsWindow::UpdateAlpha(SourceSurface* aSourceSurface,
nsIntRect aBoundsRect) {
// We need to create our own buffer to force the stride to match the
// expected stride.
int32_t stride =
GetAlignedStride<4>(aBoundsRect.width, BytesPerPixel(SurfaceFormat::A8));
if (stride == 0) {
return;
}
int32_t bufferSize = stride * aBoundsRect.height;
auto imageBuffer = MakeUniqueFallible<uint8_t[]>(bufferSize);
{
RefPtr<DrawTarget> drawTarget = gfxPlatform::CreateDrawTargetForData(
imageBuffer.get(), aBoundsRect.Size(), stride, SurfaceFormat::A8);
if (drawTarget) {
drawTarget->DrawSurface(aSourceSurface,
Rect(0, 0, aBoundsRect.width, aBoundsRect.height),
Rect(0, 0, aSourceSurface->GetSize().width,
aSourceSurface->GetSize().height),
DrawSurfaceOptions(SamplingFilter::POINT),
DrawOptions(1.0f, CompositionOp::OP_SOURCE));
}
}
UpdateTranslucentWindowAlphaInternal(aBoundsRect, imageBuffer.get(), stride);
}
gboolean nsWindow::OnConfigureEvent(GtkWidget* aWidget,
GdkEventConfigure* aEvent) {
// These events are only received on toplevel windows.
@ -5400,14 +5302,6 @@ void nsWindow::OnWindowStateEvent(GtkWidget* aWidget,
if (mWidgetListener && mSizeMode != oldSizeMode) {
mWidgetListener->SizeModeChanged(mSizeMode);
}
if (mDrawInTitlebar && mTransparencyBitmapForTitlebar) {
if (mSizeMode == nsSizeMode_Normal && !mIsTiled) {
UpdateTitlebarTransparencyBitmap();
} else {
ClearTransparencyBitmap();
}
}
}
void nsWindow::OnDPIChanged() {
@ -5850,10 +5744,6 @@ void nsWindow::EnsureGdkWindow() {
}
}
bool nsWindow::GetShapedState() {
return mIsTransparent && !mHasAlphaVisual && !mTransparencyBitmapForTitlebar;
}
void nsWindow::ConfigureCompositor() {
MOZ_DIAGNOSTIC_ASSERT(mIsMapped);
MOZ_DIAGNOSTIC_ASSERT(mCompositorState == COMPOSITOR_ENABLED);
@ -6049,21 +5939,11 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
}
}
// Use X shape mask to draw round corners of Firefox titlebar.
// We don't use shape masks any more as we switched to ARGB visual
// by default and non-compositing screens use solid-csd decorations
// without round corners.
// Leave the shape mask code here as it can be used to draw round
// corners on EGL (https://gitlab.freedesktop.org/mesa/mesa/-/issues/149)
// or when custom titlebar theme is used.
mTransparencyBitmapForTitlebar = TitlebarUseShapeMask();
// We have a toplevel window with transparency.
// Calls to UpdateTitlebarTransparencyBitmap() from OnExposeEvent()
// occur before SetTransparencyMode() receives TransparencyMode::Transparent
// from layout, so set mIsTransparent here.
if (mWindowType == WindowType::TopLevel &&
(mHasAlphaVisual || mTransparencyBitmapForTitlebar)) {
if (mWindowType == WindowType::TopLevel && mHasAlphaVisual) {
mIsTransparent = true;
}
@ -6207,10 +6087,6 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
gtk_widget_set_app_paintable(
mShell, StaticPrefs::widget_transparent_windows_AtStartup());
if (mTransparencyBitmapForTitlebar) {
moz_container_force_default_visual(mContainer);
}
// If we draw to mContainer window then configure it now because
// gtk_container_add() realizes the child widget.
gtk_widget_set_has_window(container, true);
@ -6671,8 +6547,7 @@ void nsWindow::ResumeCompositorImpl() {
LOG("nsWindow::ResumeCompositorImpl()\n");
MOZ_DIAGNOSTIC_ASSERT(mCompositorWidgetDelegate);
mCompositorWidgetDelegate->SetRenderingSurface(GetX11Window(),
GetShapedState());
mCompositorWidgetDelegate->SetRenderingSurface(GetX11Window());
// As WaylandStartVsync needs mCompositorWidgetDelegate this is the right
// time to start it.
@ -6817,8 +6692,6 @@ void nsWindow::NativeShow(bool aAction) {
mPendingConfigures = 0;
}
gtk_widget_hide(mShell);
ClearTransparencyBitmap(); // Release some resources
}
}
}
@ -6861,7 +6734,7 @@ LayoutDeviceIntSize nsWindow::GetSafeWindowSize(LayoutDeviceIntSize aSize) {
}
void nsWindow::SetTransparencyMode(TransparencyMode aMode) {
bool isTransparent = aMode == TransparencyMode::Transparent;
const bool isTransparent = aMode == TransparencyMode::Transparent;
if (mIsTransparent == isTransparent) {
return;
@ -6878,11 +6751,6 @@ void nsWindow::SetTransparencyMode(TransparencyMode aMode) {
return;
}
if (!isTransparent) {
ClearTransparencyBitmap();
} // else the new default alpha values are "all 1", so we don't
// need to change anything yet
mIsTransparent = isTransparent;
if (!mHasAlphaVisual) {
@ -7068,247 +6936,6 @@ bool nsWindow::DoDrawTilebarCorners() {
!mIsTiled;
}
void nsWindow::ResizeTransparencyBitmap() {
if (!mTransparencyBitmap) {
return;
}
if (mBounds.width == mTransparencyBitmapWidth &&
mBounds.height == mTransparencyBitmapHeight) {
return;
}
int32_t newRowBytes = GetBitmapStride(mBounds.width);
int32_t newSize = newRowBytes * mBounds.height;
auto* newBits = new gchar[newSize];
// fill new mask with "transparent", first
memset(newBits, 0, newSize);
// Now copy the intersection of the old and new areas into the new mask
int32_t copyWidth = std::min(mBounds.width, mTransparencyBitmapWidth);
int32_t copyHeight = std::min(mBounds.height, mTransparencyBitmapHeight);
int32_t oldRowBytes = GetBitmapStride(mTransparencyBitmapWidth);
int32_t copyBytes = GetBitmapStride(copyWidth);
int32_t i;
gchar* fromPtr = mTransparencyBitmap;
gchar* toPtr = newBits;
for (i = 0; i < copyHeight; i++) {
memcpy(toPtr, fromPtr, copyBytes);
fromPtr += oldRowBytes;
toPtr += newRowBytes;
}
delete[] mTransparencyBitmap;
mTransparencyBitmap = newBits;
mTransparencyBitmapWidth = mBounds.width;
mTransparencyBitmapHeight = mBounds.height;
}
static bool ChangedMaskBits(gchar* aMaskBits, int32_t aMaskWidth,
int32_t aMaskHeight, const nsIntRect& aRect,
uint8_t* aAlphas, int32_t aStride) {
int32_t x, y, xMax = aRect.XMost(), yMax = aRect.YMost();
int32_t maskBytesPerRow = GetBitmapStride(aMaskWidth);
for (y = aRect.y; y < yMax; y++) {
gchar* maskBytes = aMaskBits + y * maskBytesPerRow;
uint8_t* alphas = aAlphas;
for (x = aRect.x; x < xMax; x++) {
bool newBit = *alphas > 0x7f;
alphas++;
gchar maskByte = maskBytes[x >> 3];
bool maskBit = (maskByte & (1 << (x & 7))) != 0;
if (maskBit != newBit) {
return true;
}
}
aAlphas += aStride;
}
return false;
}
static void UpdateMaskBits(gchar* aMaskBits, int32_t aMaskWidth,
int32_t aMaskHeight, const nsIntRect& aRect,
uint8_t* aAlphas, int32_t aStride) {
int32_t x, y, xMax = aRect.XMost(), yMax = aRect.YMost();
int32_t maskBytesPerRow = GetBitmapStride(aMaskWidth);
for (y = aRect.y; y < yMax; y++) {
gchar* maskBytes = aMaskBits + y * maskBytesPerRow;
uint8_t* alphas = aAlphas;
for (x = aRect.x; x < xMax; x++) {
bool newBit = *alphas > 0x7f;
alphas++;
gchar mask = 1 << (x & 7);
gchar maskByte = maskBytes[x >> 3];
// Note: '-newBit' turns 0 into 00...00 and 1 into 11...11
maskBytes[x >> 3] = (maskByte & ~mask) | (-newBit & mask);
}
aAlphas += aStride;
}
}
void nsWindow::ApplyTransparencyBitmap() {
#ifdef MOZ_X11
// We use X11 calls where possible, because GDK handles expose events
// for shaped windows in a way that's incompatible with us (Bug 635903).
// It doesn't occur when the shapes are set through X.
Display* xDisplay = GDK_WINDOW_XDISPLAY(mGdkWindow);
Window xDrawable = GDK_WINDOW_XID(mGdkWindow);
Pixmap maskPixmap = XCreateBitmapFromData(
xDisplay, xDrawable, mTransparencyBitmap, mTransparencyBitmapWidth,
mTransparencyBitmapHeight);
XShapeCombineMask(xDisplay, xDrawable, ShapeBounding, 0, 0, maskPixmap,
ShapeSet);
XFreePixmap(xDisplay, maskPixmap);
#endif // MOZ_X11
}
void nsWindow::ClearTransparencyBitmap() {
if (!mTransparencyBitmap) {
return;
}
delete[] mTransparencyBitmap;
mTransparencyBitmap = nullptr;
mTransparencyBitmapWidth = 0;
mTransparencyBitmapHeight = 0;
if (!mShell) {
return;
}
#ifdef MOZ_X11
if (MOZ_UNLIKELY(!mGdkWindow)) {
return;
}
Display* xDisplay = GDK_WINDOW_XDISPLAY(mGdkWindow);
Window xWindow = gdk_x11_window_get_xid(mGdkWindow);
XShapeCombineMask(xDisplay, xWindow, ShapeBounding, 0, 0, X11None, ShapeSet);
#endif
}
nsresult nsWindow::UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect,
uint8_t* aAlphas,
int32_t aStride) {
NS_ASSERTION(mIsTransparent, "Window is not transparent");
NS_ASSERTION(!mTransparencyBitmapForTitlebar,
"Transparency bitmap is already used for titlebar rendering");
if (mTransparencyBitmap == nullptr) {
int32_t size = GetBitmapStride(mBounds.width) * mBounds.height;
mTransparencyBitmap = new gchar[size];
memset(mTransparencyBitmap, 255, size);
mTransparencyBitmapWidth = mBounds.width;
mTransparencyBitmapHeight = mBounds.height;
} else {
ResizeTransparencyBitmap();
}
nsIntRect rect;
rect.IntersectRect(aRect, nsIntRect(0, 0, mBounds.width, mBounds.height));
if (!ChangedMaskBits(mTransparencyBitmap, mBounds.width, mBounds.height, rect,
aAlphas, aStride)) {
// skip the expensive stuff if the mask bits haven't changed; hopefully
// this is the common case
return NS_OK;
}
UpdateMaskBits(mTransparencyBitmap, mBounds.width, mBounds.height, rect,
aAlphas, aStride);
if (!mNeedsShow) {
ApplyTransparencyBitmap();
}
return NS_OK;
}
void nsWindow::UpdateTitlebarTransparencyBitmap() {
NS_ASSERTION(mTransparencyBitmapForTitlebar,
"Transparency bitmap is already used to draw window shape");
if (!mGdkWindow || !mDrawInTitlebar ||
(mBounds.width == mTransparencyBitmapWidth &&
mBounds.height == mTransparencyBitmapHeight)) {
return;
}
bool maskCreate =
!mTransparencyBitmap || mBounds.width > mTransparencyBitmapWidth;
bool maskUpdate =
!mTransparencyBitmap || mBounds.width != mTransparencyBitmapWidth;
LayoutDeviceIntCoord radius = GetTitlebarRadius();
if (maskCreate) {
delete[] mTransparencyBitmap;
int32_t size = GetBitmapStride(mBounds.width) * radius;
mTransparencyBitmap = new gchar[size];
mTransparencyBitmapWidth = mBounds.width;
} else {
mTransparencyBitmapWidth = mBounds.width;
}
mTransparencyBitmapHeight = mBounds.height;
if (maskUpdate) {
cairo_surface_t* surface = cairo_image_surface_create(
CAIRO_FORMAT_A8, mTransparencyBitmapWidth, radius);
if (!surface) {
return;
}
cairo_t* cr = cairo_create(surface);
GtkWidgetState state;
memset((void*)&state, 0, sizeof(state));
GdkRectangle rect = {0, 0, mTransparencyBitmapWidth, radius};
moz_gtk_widget_paint(MOZ_GTK_HEADER_BAR, cr, &rect, &state, 0,
GTK_TEXT_DIR_NONE);
cairo_destroy(cr);
cairo_surface_mark_dirty(surface);
cairo_surface_flush(surface);
UpdateMaskBits(mTransparencyBitmap, mTransparencyBitmapWidth, radius,
nsIntRect(0, 0, mTransparencyBitmapWidth, radius),
cairo_image_surface_get_data(surface),
cairo_format_stride_for_width(CAIRO_FORMAT_A8,
mTransparencyBitmapWidth));
cairo_surface_destroy(surface);
}
#ifdef MOZ_X11
if (!mNeedsShow) {
Display* xDisplay = GDK_WINDOW_XDISPLAY(mGdkWindow);
Window xDrawable = GDK_WINDOW_XID(mGdkWindow);
Pixmap maskPixmap =
XCreateBitmapFromData(xDisplay, xDrawable, mTransparencyBitmap,
mTransparencyBitmapWidth, radius);
XShapeCombineMask(xDisplay, xDrawable, ShapeBounding, 0, 0, maskPixmap,
ShapeSet);
if (mTransparencyBitmapHeight > radius) {
XRectangle rect = {0, 0, (unsigned short)mTransparencyBitmapWidth,
(unsigned short)(mTransparencyBitmapHeight - radius)};
XShapeCombineRectangles(xDisplay, xDrawable, ShapeBounding, 0, radius,
&rect, 1, ShapeUnion, 0);
}
XFreePixmap(xDisplay, maskPixmap);
}
#endif
}
GtkWidget* nsWindow::GetToplevelWidget() const { return mShell; }
GdkWindow* nsWindow::GetToplevelGdkWindow() const {
@ -9215,14 +8842,6 @@ void nsWindow::SetDrawsInTitlebar(bool aState) {
gtk_widget_destroy(tmpWindow);
}
if (mTransparencyBitmapForTitlebar) {
if (mDrawInTitlebar && mSizeMode == nsSizeMode_Normal && !mIsTiled) {
UpdateTitlebarTransparencyBitmap();
} else {
ClearTransparencyBitmap();
}
}
// Recompute the input region (which should generally be null, but this is
// enough to work around bug 1844497, which is probably a gtk bug).
SetInputRegion(mInputRegion);
@ -9685,24 +9304,6 @@ nsWindow::GtkWindowDecoration nsWindow::GetSystemGtkWindowDecoration() {
return sGtkWindowDecoration;
}
bool nsWindow::TitlebarUseShapeMask() {
static int useShapeMask = []() {
// Don't use titlebar shape mask on Wayland
if (!GdkIsX11Display()) {
return false;
}
// We can't use shape masks on Mutter/X.org as we can't resize Firefox
// window there (Bug 1530252).
if (IsGnomeDesktopEnvironment()) {
return false;
}
return Preferences::GetBool("widget.titlebar-x11-use-shape-mask", false);
}();
return useShapeMask;
}
int32_t nsWindow::RoundsWidgetCoordinatesTo() { return GdkCeiledScaleFactor(); }
void nsWindow::GetCompositorWidgetInitData(
@ -9723,8 +9324,7 @@ void nsWindow::GetCompositorWidgetInitData(
}
#endif
*aInitData = mozilla::widget::GtkCompositorWidgetInitData(
window, displayName, GetShapedState(), GdkIsX11Display(),
GetClientSize());
window, displayName, GdkIsX11Display(), GetClientSize());
#ifdef MOZ_X11
if (GdkIsX11Display()) {
@ -10083,7 +9683,7 @@ void nsWindow::OnMap() {
#ifdef MOZ_X11
if (GdkIsX11Display()) {
mSurfaceProvider.Initialize(GetX11Window(), GetShapedState());
mSurfaceProvider.Initialize(GetX11Window());
// Set window manager hint to keep fullscreen windows composited.
//

Просмотреть файл

@ -319,21 +319,11 @@ class nsWindow final : public nsBaseWidget {
const mozilla::WidgetKeyboardEvent& aEvent,
nsTArray<mozilla::CommandInt>& aCommands) override;
// These methods are for toplevel windows only.
void ResizeTransparencyBitmap();
void ApplyTransparencyBitmap();
void ClearTransparencyBitmap();
void SetTransparencyMode(TransparencyMode aMode) override;
TransparencyMode GetTransparencyMode() override;
void SetInputRegion(const InputRegion&) override;
nsresult UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect,
uint8_t* aAlphas,
int32_t aStride);
void ReparentNativeWidget(nsIWidget* aNewParent) override;
void UpdateTitlebarTransparencyBitmap();
nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
NativeMouseMessage aNativeMessage,
mozilla::MouseButton aButton,
@ -417,8 +407,7 @@ class nsWindow final : public nsBaseWidget {
*/
static GtkWindowDecoration GetSystemGtkWindowDecoration();
static bool TitlebarUseShapeMask();
bool IsRemoteContent() { return HasRemoteContent(); }
bool IsRemoteContent() const { return HasRemoteContent(); }
void NativeMoveResizeWaylandPopupCallback(const GdkRectangle* aFinalSize,
bool aFlippedX, bool aFlippedY);
static bool IsToplevelWindowTransparent();
@ -495,9 +484,6 @@ class nsWindow final : public nsBaseWidget {
mozilla::Atomic<int, mozilla::Relaxed> mCeiledScaleFactor{1};
double mFractionalScaleFactor = 0.0;
void UpdateAlpha(mozilla::gfx::SourceSurface* aSourceSurface,
nsIntRect aBoundsRect);
void NativeMoveResize(bool aMoved, bool aResized);
void NativeShow(bool aAction);
@ -519,7 +505,6 @@ class nsWindow final : public nsBaseWidget {
GtkWidget* GetToplevelWidget() const;
nsWindow* GetContainerWindow() const;
Window GetX11Window();
bool GetShapedState();
void EnsureGdkWindow();
void SetUrgencyHint(GtkWidget* top_window, bool state);
void SetDefaultIcon(void);
@ -729,10 +714,6 @@ class nsWindow final : public nsBaseWidget {
*/
bool mHiddenPopupPositioned : 1;
// The transparency bitmap is used instead of ARGB visual for toplevel
// window to draw titlebar.
bool mTransparencyBitmapForTitlebar : 1;
// True when we're on compositing window manager and this
// window is using visual with alpha channel.
bool mHasAlphaVisual : 1;
@ -795,13 +776,6 @@ class nsWindow final : public nsBaseWidget {
// Whether we need to retry capturing the mouse because we' re not mapped yet.
bool mNeedsToRetryCapturingMouse : 1;
// This bitmap tracks which pixels are transparent. We don't support
// full translucency at this time; each pixel is either fully opaque
// or fully transparent.
gchar* mTransparencyBitmap = nullptr;
int32_t mTransparencyBitmapWidth = 0;
int32_t mTransparencyBitmapHeight = 0;
// all of our DND stuff
void InitDragEvent(mozilla::WidgetDragEvent& aEvent);