summaryrefslogtreecommitdiffstats
path: root/widget/gtk/nsWindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'widget/gtk/nsWindow.cpp')
-rw-r--r--widget/gtk/nsWindow.cpp185
1 files changed, 93 insertions, 92 deletions
diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
index 0a78d0c8ec..2971497969 100644
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -389,8 +389,7 @@ static void GtkWindowSetTransientFor(GtkWindow* aWindow, GtkWindow* aParent) {
}
nsWindow::nsWindow()
- : mTitlebarRectMutex("nsWindow::mTitlebarRectMutex"),
- mWindowVisibilityMutex("nsWindow::mWindowVisibilityMutex"),
+ : mWindowVisibilityMutex("nsWindow::mWindowVisibilityMutex"),
mIsMapped(false),
mIsDestroyed(false),
mIsShown(false),
@@ -514,10 +513,6 @@ void nsWindow::MaybeDispatchResized() {
<< mBounds << " size state " << mSizeMode;
}
- if (IsTopLevelWindowType()) {
- UpdateTopLevelOpaqueRegion();
- }
-
// Notify the GtkCompositorWidget of a ClientSizeChange
if (mCompositorWidgetDelegate) {
mCompositorWidgetDelegate->NotifyClientSizeChanged(GetClientSize());
@@ -591,6 +586,7 @@ void nsWindow::Destroy() {
mWaylandVsyncSource = nullptr;
}
mWaylandVsyncDispatcher = nullptr;
+ UnlockNativePointer();
#endif
// dragService will be null after shutdown of the service manager.
@@ -3216,9 +3212,7 @@ LayoutDeviceIntRect nsWindow::GetScreenBounds() {
return rect;
}
-LayoutDeviceIntSize nsWindow::GetClientSize() {
- return LayoutDeviceIntSize(mBounds.width, mBounds.height);
-}
+LayoutDeviceIntSize nsWindow::GetClientSize() { return mBounds.Size(); }
LayoutDeviceIntRect nsWindow::GetClientBounds() {
// GetBounds returns a rect whose top left represents the top left of the
@@ -5379,8 +5373,6 @@ void nsWindow::OnWindowStateEvent(GtkWidget* aWidget,
} else {
ClearTransparencyBitmap();
}
- } else {
- SetTitlebarRect();
}
}
@@ -5391,7 +5383,6 @@ void nsWindow::OnDPIChanged() {
if (PresShell* presShell = mWidgetListener->GetPresShell()) {
presShell->BackingScaleFactorChanged();
}
- mWidgetListener->UIResolutionChanged();
}
NotifyAPZOfDPIChange();
}
@@ -6934,80 +6925,99 @@ LayoutDeviceIntCoord nsWindow::GetTitlebarRadius() {
return GdkCoordToDevicePixels(cssCoord);
}
+LayoutDeviceIntRegion nsWindow::GetOpaqueRegion() const {
+ AutoReadLock r(mOpaqueRegionLock);
+ return mOpaqueRegion;
+}
+
// See subtract_corners_from_region() at gtk/gtkwindow.c
// We need to subtract corners from toplevel window opaque region
// to draw transparent corners of default Gtk titlebar.
// Both implementations (cairo_region_t and wl_region) needs to be synced.
-static void SubtractTitlebarCorners(cairo_region_t* aRegion, int aX, int aY,
- int aWindowWidth, int aWindowHeight,
- int aTitlebarRadius) {
- if (!aTitlebarRadius) {
- return;
- }
- cairo_rectangle_int_t rect = {aX, aY, aTitlebarRadius, aTitlebarRadius};
- cairo_region_subtract_rectangle(aRegion, &rect);
- rect = {
- aX + aWindowWidth - aTitlebarRadius,
- aY,
- aTitlebarRadius,
- aTitlebarRadius,
- };
- cairo_region_subtract_rectangle(aRegion, &rect);
- rect = {
- aX,
- aY + aWindowHeight - aTitlebarRadius,
- aTitlebarRadius,
- aTitlebarRadius,
- };
- cairo_region_subtract_rectangle(aRegion, &rect);
- rect = {
- aX + aWindowWidth - aTitlebarRadius,
- aY + aWindowHeight - aTitlebarRadius,
- aTitlebarRadius,
- aTitlebarRadius,
- };
- cairo_region_subtract_rectangle(aRegion, &rect);
+static void SubtractTitlebarCorners(LayoutDeviceIntRegion& aRegion,
+ const LayoutDeviceIntRect& aRect,
+ LayoutDeviceIntCoord aRadius) {
+ if (!aRadius) {
+ return;
+ }
+ const LayoutDeviceIntSize size(aRadius, aRadius);
+ aRegion.SubOut(LayoutDeviceIntRect(aRect.TopLeft(), size));
+ aRegion.SubOut(LayoutDeviceIntRect(
+ aRect.TopRight() - LayoutDeviceIntPoint(aRadius, 0), size));
+ aRegion.SubOut(LayoutDeviceIntRect(
+ aRect.BottomLeft() - LayoutDeviceIntPoint(0, aRadius), size));
+ aRegion.SubOut(LayoutDeviceIntRect(
+ aRect.BottomRight() - LayoutDeviceIntPoint(aRadius, aRadius), size));
+}
+
+void nsWindow::UpdateOpaqueRegion(const LayoutDeviceIntRegion& aRegion) {
+ LayoutDeviceIntRegion region = aRegion;
+ SubtractTitlebarCorners(region, LayoutDeviceIntRect({}, mBounds.Size()),
+ GetTitlebarRadius());
+ {
+ AutoReadLock r(mOpaqueRegionLock);
+ if (mOpaqueRegion == region) {
+ return;
+ }
+ }
+ {
+ AutoWriteLock w(mOpaqueRegionLock);
+ mOpaqueRegion = region;
+ }
+ UpdateOpaqueRegionInternal();
}
-void nsWindow::UpdateTopLevelOpaqueRegion() {
+void nsWindow::UpdateOpaqueRegionInternal() {
if (!mCompositedScreen) {
return;
}
+ if (!IsTopLevelWindowType()) {
+ // We need to clear target buffer alpha values of popup windows as
+ // SW-WR paints with alpha blending (see Bug 1674473).
+ return;
+ }
+
GdkWindow* window = GetToplevelGdkWindow();
if (!window) {
return;
}
MOZ_ASSERT(gdk_window_get_window_type(window) == GDK_WINDOW_TOPLEVEL);
- int x = 0;
- int y = 0;
-
- gdk_window_get_position(mGdkWindow, &x, &y);
-
- int width = DevicePixelsToGdkCoordRoundDown(mBounds.width);
- int height = DevicePixelsToGdkCoordRoundDown(mBounds.height);
-
- cairo_region_t* region = cairo_region_create();
- cairo_rectangle_int_t rect = {x, y, width, height};
- cairo_region_union_rectangle(region, &rect);
-
- // TODO: We actually could get a proper opaque region from layout, see
- // nsIWidget::UpdateOpaqueRegion. This could simplify titlebar drawing.
- int radius = DoDrawTilebarCorners() ? int(GetTitlebarRadius()) : 0;
- SubtractTitlebarCorners(region, x, y, width, height, radius);
-
- gdk_window_set_opaque_region(window, region);
-
- cairo_region_destroy(region);
+ {
+ AutoReadLock lock(mOpaqueRegionLock);
+ cairo_region_t* region = nullptr;
+ if (!mOpaqueRegion.IsEmpty()) {
+ // NOTE(emilio): The opaque region is relative to our mContainer /
+ // mGdkWindow / inner window, but we're setting it on the top level
+ // GdkWindow / mShell.
+ //
+ // So we need to offset the rects by the position of mGdkWindow, in order
+ // for them to be in the right coordinate system.
+ GdkPoint offset{0, 0};
+ gdk_window_get_position(mGdkWindow, &offset.x, &offset.y);
+
+ region = cairo_region_create();
+
+ for (auto iter = mOpaqueRegion.RectIter(); !iter.Done(); iter.Next()) {
+ auto gdkRect = DevicePixelsToGdkRectRoundIn(iter.Get());
+ cairo_rectangle_int_t rect = {gdkRect.x + offset.x,
+ gdkRect.y + offset.y, gdkRect.width,
+ gdkRect.height};
+ cairo_region_union_rectangle(region, &rect);
+ }
+ }
+ gdk_window_set_opaque_region(window, region);
+ if (region) {
+ cairo_region_destroy(region);
+ }
+ }
#ifdef MOZ_WAYLAND
if (GdkIsWaylandDisplay()) {
- moz_container_wayland_update_opaque_region(mContainer, radius);
+ moz_container_wayland_update_opaque_region(mContainer);
}
#endif
-
- SetTitlebarRect();
}
bool nsWindow::IsChromeWindowTitlebar() {
@@ -7181,24 +7191,6 @@ nsresult nsWindow::UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect,
return NS_OK;
}
-#define TITLEBAR_HEIGHT 10
-
-void nsWindow::SetTitlebarRect() {
- MutexAutoLock lock(mTitlebarRectMutex);
-
- if (!mGdkWindow || !DoDrawTilebarCorners()) {
- mTitlebarRect = LayoutDeviceIntRect();
- return;
- }
- mTitlebarRect = LayoutDeviceIntRect(0, 0, mBounds.width,
- GdkCeiledScaleFactor() * TITLEBAR_HEIGHT);
-}
-
-LayoutDeviceIntRect nsWindow::GetTitlebarRect() {
- MutexAutoLock lock(mTitlebarRectMutex);
- return mTitlebarRect;
-}
-
void nsWindow::UpdateTitlebarTransparencyBitmap() {
NS_ASSERTION(mTransparencyBitmapForTitlebar,
"Transparency bitmap is already used to draw window shape");
@@ -8243,7 +8235,9 @@ static void toplevel_window_size_allocate_cb(GtkWidget* widget,
return;
}
- window->UpdateTopLevelOpaqueRegion();
+ // NOTE(emilio): We need to do this here to override GTK's own opaque region
+ // setting (which would clobber ours).
+ window->UpdateOpaqueRegionInternal();
}
static gboolean delete_event_cb(GtkWidget* widget, GdkEventAny* event) {
@@ -9180,9 +9174,11 @@ void nsWindow::SetDrawsInTitlebar(bool aState) {
} else {
ClearTransparencyBitmap();
}
- } else {
- SetTitlebarRect();
}
+
+ // 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);
}
GtkWindow* nsWindow::GetCurrentTopmostWindow() const {
@@ -9249,6 +9245,16 @@ GdkRectangle nsWindow::DevicePixelsToGdkRectRoundOut(
return {x, y, right - x, bottom - y};
}
+GdkRectangle nsWindow::DevicePixelsToGdkRectRoundIn(
+ const LayoutDeviceIntRect& aRect) {
+ double scale = FractionalScaleFactor();
+ int x = ceil(aRect.x / scale);
+ int y = ceil(aRect.y / scale);
+ int right = floor((aRect.x + aRect.width) / scale);
+ int bottom = floor((aRect.y + aRect.height) / scale);
+ return {x, y, std::max(right - x, 0), std::max(bottom - y, 0)};
+}
+
GdkRectangle nsWindow::DevicePixelsToGdkSizeRoundUp(
const LayoutDeviceIntSize& aSize) {
double scale = FractionalScaleFactor();
@@ -9843,9 +9849,7 @@ void nsWindow::LockNativePointer() {
return;
}
- if (mLockedPointer || mRelativePointer) {
- UnlockNativePointer();
- }
+ UnlockNativePointer();
mLockedPointer = zwp_pointer_constraints_v1_lock_pointer(
pointerConstraints, surface, pointer, nullptr,
@@ -9869,9 +9873,6 @@ void nsWindow::LockNativePointer() {
}
void nsWindow::UnlockNativePointer() {
- if (!GdkIsWaylandDisplay()) {
- return;
- }
if (mRelativePointer) {
zwp_relative_pointer_v1_destroy(mRelativePointer);
mRelativePointer = nullptr;