tor-browser

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

commit 0f2aaec1be54619203d398febf4921c5eba06213
parent 0ae81b46738fd8c776bb8b2c6d139ae4a8aa1193
Author: stransky <stransky@redhat.com>
Date:   Mon, 24 Nov 2025 18:53:47 +0000

Bug 1999838 [Linux] Always get window margin and check if it's actually changed before resize/move r=emilio

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

Diffstat:
Mwidget/gtk/nsWindow.cpp | 61+++++++++++++++++++++++++++++++------------------------------
Mwidget/gtk/nsWindow.h | 15++++-----------
2 files changed, 35 insertions(+), 41 deletions(-)

diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp @@ -426,7 +426,6 @@ nsWindow::nsWindow() mHasMappedToplevel(false), mPanInProgress(false), mPendingBoundsChange(false), - mPendingBoundsChangeMayChangeCsdMargin(false), mTitlebarBackdropState(false), mAlwaysOnTop(false), mIsTransparent(false), @@ -3361,8 +3360,8 @@ LayoutDeviceIntCoord GetXWindowBorder(GdkWindow* aWin) { top corner, so matches CSD size - (40,40). */ #ifdef MOZ_X11 -void nsWindow::RecomputeBoundsX11(bool aMayChangeCsdMargin) { - LOG("RecomputeBoundsX11(%d)", aMayChangeCsdMargin); +void nsWindow::RecomputeBoundsX11() { + LOGVERBOSE("RecomputeBoundsX11()"); auto* toplevel = GetToplevelGdkWindow(); @@ -3370,6 +3369,10 @@ void nsWindow::RecomputeBoundsX11(bool aMayChangeCsdMargin) { auto GetFrameTitlebarBounds = [&](GdkWindow* aWin) { GdkRectangle b{0}; gdk_window_get_frame_extents(aWin, &b); + LOGVERBOSE( + " GetFrameTitlebarBounds(): gdk_window_get_frame_extents() [%d,%d] -> " + "[%d x %d]", + b.x, b.y, b.width, b.height); if (gtk_check_version(3, 24, 35) && gdk_window_get_window_type(aWin) == GDK_WINDOW_TEMP) { // Workaround for https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/4820 @@ -3402,11 +3405,15 @@ void nsWindow::RecomputeBoundsX11(bool aMayChangeCsdMargin) { // event size, to avoid spurious resizes on e.g. sizemode changes. gdk_window_get_geometry(aWin, nullptr, nullptr, &b.width, &b.height); gdk_window_get_origin(aWin, &b.x, &b.y); + LOGVERBOSE(" GetBounds(): toplevel [%d,%d] -> [%d x %d]", b.x, b.y, + b.width, b.height); return DesktopIntRect(b.x, b.y, b.width, b.height); } gdk_window_get_position(aWin, &b.x, &b.y); b.width = gdk_window_get_width(aWin); b.height = gdk_window_get_height(aWin); + LOGVERBOSE(" GetBounds(): popup [%d,%d] -> [%d x %d]", b.x, b.y, b.width, + b.height); return DesktopIntRect(b.x, b.y, b.width, b.height); }; @@ -3429,7 +3436,7 @@ void nsWindow::RecomputeBoundsX11(bool aMayChangeCsdMargin) { IsTopLevelWidget() && mSizeMode != nsSizeMode_Fullscreen && !mUndecorated; if (!decorated) { mClientMargin = {}; - } else if (aMayChangeCsdMargin) { + } else { // TODO: Do we really need so complex margin calculation on X11? const DesktopIntRect clientRectRelativeToFrame = [&] { auto topLevelBoundsRelativeToFrame = toplevelBounds; @@ -3450,8 +3457,6 @@ void nsWindow::RecomputeBoundsX11(bool aMayChangeCsdMargin) { mClientMargin = DesktopIntRect(DesktopIntPoint(), finalBounds.Size()) - clientRectRelativeToFrame; mClientMargin.EnsureAtLeast(DesktopIntMargin()); - } else { - // Assume the client margin remains the same. } mClientArea = finalBounds; @@ -3459,7 +3464,7 @@ void nsWindow::RecomputeBoundsX11(bool aMayChangeCsdMargin) { } #endif #ifdef MOZ_WAYLAND -void nsWindow::RecomputeBoundsWayland(bool aMayChangeCsdMargin) { +void nsWindow::RecomputeBoundsWayland() { auto GetBounds = [&](GdkWindow* aWin) { GdkRectangle b{0}; gdk_window_get_position(aWin, &b.x, &b.y); @@ -3471,11 +3476,11 @@ void nsWindow::RecomputeBoundsWayland(bool aMayChangeCsdMargin) { const auto toplevelBounds = GetBounds(GetToplevelGdkWindow()); mClientArea = GetBounds(mGdkWindow); - LOG("RecomputeBoundsWayland(%d) GetBounds(mGdkWindow) [%d,%d] -> [%d x %d] " + LOG("RecomputeBoundsWayland() GetBounds(mGdkWindow) [%d,%d] -> [%d x %d] " "GetBounds(mShell) [%d,%d] -> [%d x %d]", - aMayChangeCsdMargin, mClientArea.x, mClientArea.y, mClientArea.width, - mClientArea.height, toplevelBounds.x, toplevelBounds.y, - toplevelBounds.width, toplevelBounds.height); + mClientArea.x, mClientArea.y, mClientArea.width, mClientArea.height, + toplevelBounds.x, toplevelBounds.y, toplevelBounds.width, + toplevelBounds.height); if (mClientArea.X() < 0 || mClientArea.Y() < 0 || mClientArea.Width() <= 1 || mClientArea.Height() <= 1) { @@ -3487,22 +3492,18 @@ void nsWindow::RecomputeBoundsWayland(bool aMayChangeCsdMargin) { IsTopLevelWidget() && mSizeMode != nsSizeMode_Fullscreen && !mUndecorated; if (!decorated) { mClientMargin = {}; - } else if (aMayChangeCsdMargin) { + } else { mClientMargin = DesktopIntRect(DesktopIntPoint(), toplevelBounds.Size()) - mClientArea; mClientMargin.EnsureAtLeast(DesktopIntMargin()); - } else { - // Assume the client margin remains the same. } } #endif -void nsWindow::RecomputeBounds(bool aMayChangeCsdMargin, bool aScaleChange) { - LOG("RecomputeBounds() margin %d scale change %d", aMayChangeCsdMargin, - aScaleChange); +void nsWindow::RecomputeBounds(bool aScaleChange) { + LOG("RecomputeBounds() scale change %d", aScaleChange); mPendingBoundsChange = false; - mPendingBoundsChangeMayChangeCsdMargin = false; auto* toplevel = GetToplevelGdkWindow(); if (!toplevel || mIsDestroyed) { @@ -3514,15 +3515,17 @@ void nsWindow::RecomputeBounds(bool aMayChangeCsdMargin, bool aScaleChange) { #ifdef MOZ_X11 if (GdkIsX11Display()) { - RecomputeBoundsX11(aMayChangeCsdMargin); + RecomputeBoundsX11(); } #endif #ifdef MOZ_WAYLAND if (GdkIsWaylandDisplay()) { - RecomputeBoundsWayland(aMayChangeCsdMargin); + RecomputeBoundsWayland(); } #endif + bool marginChanged = (oldMargin != mClientMargin); + #ifdef MOZ_LOGGING if (LOG_ENABLED()) { if (mHasReceivedSizeAllocate) { @@ -3574,9 +3577,9 @@ void nsWindow::RecomputeBounds(bool aMayChangeCsdMargin, bool aScaleChange) { // We need to send WindowMoved even if only the client margins changed // so that BrowserParent picks up the new offsets. - const bool moved = aScaleChange || aMayChangeCsdMargin || + const bool moved = aScaleChange || marginChanged || oldClientArea.TopLeft() != mClientArea.TopLeft(); - const bool resized = aScaleChange || aMayChangeCsdMargin || + const bool resized = aScaleChange || marginChanged || oldClientArea.Size() != mClientArea.Size(); if (moved) { @@ -3592,7 +3595,7 @@ gboolean nsWindow::OnPropertyNotifyEvent(GtkWidget* aWidget, GdkEventProperty* aEvent) { if (aEvent->atom == gdk_atom_intern("_NET_FRAME_EXTENTS", FALSE)) { LOG("OnPropertyNotifyEvent(_NET_FRAME_EXTENTS)"); - SchedulePendingBounds(MayChangeCsdMargin::Yes); + SchedulePendingBounds(); return FALSE; } if (!mGdkWindow) { @@ -4278,7 +4281,7 @@ gboolean nsWindow::OnShellConfigureEvent(GdkEventConfigure* aEvent) { // X11 calc bounds from outer window while Wayland uses // container size after container allocation event. if (GdkIsX11Display()) { - SchedulePendingBounds(MayChangeCsdMargin::No); + SchedulePendingBounds(); } return FALSE; } @@ -4301,7 +4304,7 @@ void nsWindow::OnContainerSizeAllocate(GtkAllocation* aAllocation) { // Also, this runs for both top level size_allocate and MozContainer size // allocate, so even if the client bounds are the same, we need to recompute // the bounds because the client margin might not. - SchedulePendingBounds(MayChangeCsdMargin::Yes); + SchedulePendingBounds(); // Invalidate the new part of the window now for the pending paint to // minimize background flashes (GDK does not do this for external @@ -4323,9 +4326,7 @@ void nsWindow::OnContainerSizeAllocate(GtkAllocation* aAllocation) { } } -void nsWindow::SchedulePendingBounds(MayChangeCsdMargin aMayChangeCsdMargin) { - mPendingBoundsChangeMayChangeCsdMargin |= - aMayChangeCsdMargin == MayChangeCsdMargin::Yes; +void nsWindow::SchedulePendingBounds() { if (mPendingBoundsChange) { return; } @@ -4337,7 +4338,7 @@ void nsWindow::SchedulePendingBounds(MayChangeCsdMargin aMayChangeCsdMargin) { void nsWindow::MaybeRecomputeBounds() { LOG("MaybeRecomputeBounds %d", mPendingBoundsChange); if (mPendingBoundsChange) { - RecomputeBounds(mPendingBoundsChangeMayChangeCsdMargin); + RecomputeBounds(); } } @@ -5721,7 +5722,7 @@ void nsWindow::RefreshScale(bool aRefreshScreen, bool aForceRefresh) { return; } - RecomputeBounds(/* MayChangeCsdMargin */ true, /* ScaleChanged*/ true); + RecomputeBounds(/* ScaleChanged*/ true); if (PresShell* presShell = GetPresShell()) { presShell->BackingScaleFactorChanged(); diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h @@ -216,15 +216,14 @@ class nsWindow final : public nsIWidget { // Recomputes the bounds according to our current window position. Dispatches // move / resizes as needed. - void RecomputeBounds(bool aMayChangeCsdMargin, bool aScaleChange = false); + void RecomputeBounds(bool aScaleChange = false); #ifdef MOZ_X11 - void RecomputeBoundsX11(bool aMayChangeCsdMargin); + void RecomputeBoundsX11(); #endif #ifdef MOZ_WAYLAND - void RecomputeBoundsWayland(bool aMayChangeCsdMargin); + void RecomputeBoundsWayland(); #endif - enum class MayChangeCsdMargin : bool { No = false, Yes }; - void SchedulePendingBounds(MayChangeCsdMargin); + void SchedulePendingBounds(); void MaybeRecomputeBounds(); void SetCursor(const Cursor&) override; @@ -730,12 +729,6 @@ class nsWindow final : public nsIWidget { bool mHasMappedToplevel : 1; bool mPanInProgress : 1; bool mPendingBoundsChange : 1; - // Whether our pending bounds change event might change the window CSD margin. - // This is needed because we might get two configures (one for mShell, one - // for mContainer's window) in quick succession, which might cause us to send - // spurious sequences of resizes if we don't do this on some compositors - // (older mutter at least). - bool mPendingBoundsChangeMayChangeCsdMargin : 1; // Draw titlebar with :backdrop css state (inactive/unfocused). bool mTitlebarBackdropState : 1; bool mAlwaysOnTop : 1;