fix: preserve transparency across setResizable toggles on Windows (#51175)

After #49428 made `NativeWindowViews::CanResize()` return `resizable_`
for frameless windows (instead of `resizable_ && thick_frame_`),
`HWNDMessageHandler::SizeConstraintsChanged()` started adding
`WS_THICKFRAME` to the window style whenever `CanResize()` reported true.
`WS_THICKFRAME` is incompatible with layered (translucent) windows and
destroys their transparency.

`SetContentSizeConstraints` already guards against this by skipping
`OnSizeConstraintsChanged()` when `!thick_frame_`. `SetResizable` did
not, so toggling resizability on a transparent window (e.g.
`setResizable(false)` then `setResizable(true)`) caused the Chromium
path to add `WS_THICKFRAME` and strip transparency.

Apply the same guard in `SetResizable`. Min/max constraints are still
enforced — Chromium reads them from the widget delegate on every
`WM_GETMINMAXINFO`, independent of `SizeConstraintsChanged()`.
This commit is contained in:
Shelley Vohr
2026-04-21 19:32:29 +02:00
committed by GitHub
parent 5ed6e4bf62
commit 2ba6d28c09

View File

@@ -966,10 +966,18 @@ void NativeWindowViews::SetResizable(bool resizable) {
gfx::Size window_size = GetSize();
SetSizeConstraints(extensions::SizeConstraints(window_size, window_size));
}
// Forcing OnSizeConstraintsChanged on Windows when !thick_frame_ would
// cause HWNDMessageHandler::SizeConstraintsChanged() to add WS_THICKFRAME
// based on CanResize(), which destroys transparency on layered windows.
// Min/max are still enforced through WM_GETMINMAXINFO directly from the
// widget delegate.
#if BUILDFLAG(IS_WIN)
if (thick_frame_ && widget() && widget()->widget_delegate())
widget()->OnSizeConstraintsChanged();
UpdateThickFrame();
#else
if (widget() && widget()->widget_delegate())
widget()->OnSizeConstraintsChanged();
#if BUILDFLAG(IS_WIN)
UpdateThickFrame();
#endif
}
}