Skip to content

linux: Draw shadows and rounded corners for frameless windows#4181

Open
aiddya wants to merge 1 commit into
chromiumembedded:masterfrom
aiddya:frameless-window-wayland
Open

linux: Draw shadows and rounded corners for frameless windows#4181
aiddya wants to merge 1 commit into
chromiumembedded:masterfrom
aiddya:frameless-window-wayland

Conversation

@aiddya

@aiddya aiddya commented May 27, 2026

Copy link
Copy Markdown

Introduce CaptionlessFrameViewLinux to draw shadows and rounded corners for frameless windows on Linux. This matches the behavior of frameless windows on macOS and Windows.

CaptionlessFrameViewLinux extends FrameViewLinux to suppress the titlebar and round all four corners. Corner radii propagate from the frame view to the client view, which rounds the hosted web contents. Overlay positioning is offset by the new frame border insets so overlays stay within the client area.

@magreenblatt

Copy link
Copy Markdown
Collaborator

Review Comments

Good approach overall — extending FrameViewLinux and FrameViewLayoutLinux is the right architecture, reusing upstream shadow drawing, resize handling, and layout while only overriding what's needed. A few items:

  1. static_cast to aura::WindowTreeHostPlatform* in the CaptionlessFrameViewLinux constructor is fragile. If the window tree host implementation changes, this crashes silently. Consider dynamic_cast with a null check, or moving this logic to the call site where the concrete type is known (similar to how DesktopWindowTreeHostLinux::CreateFrameView() does it).

  2. remove_standard_frame = true on Linux — this changes the guard from IS_WIN-only to IS_WIN || IS_LINUX and removes the X11 SetUseOSWindowFrame(x11window, false) call. The old comment warned this "will result in window resize artifacts" on Linux. The PR description and test instructions only cover Wayland — worth verifying this doesn't regress X11 frameless windows.

  3. UpdateWebViewRoundedCorners runs on every Layout() call — the recursive traversal looking for WebView instances could be expensive for complex view hierarchies. Also, the flush-detection epsilon (kEpsilon = 1.0f) seems generous; a comment explaining why 1.0f was chosen would help.

  4. Test only asserts on WaylandWindowFramelessClientBounds guards the inset assertions with IsRunningOnWayland(). A smoke test on X11 would help guard against the remove_standard_frame change causing regressions.

  5. Minor: SetPaintToLayer() in UpdateWindowRoundedCorners creates a compositing layer that's never removed when corners become square (e.g., maximized). Low impact but worth noting.

The overlay offset fix via ConvertPointToWidget is correct and clean.

@aiddya

aiddya commented May 28, 2026

Copy link
Copy Markdown
Author
  1. As CaptionlessFrameViewLinux is only used on Linux, GetHost() will always return DesktopWindowTreeHostLinux or a subclass if a consumer customizes it. DesktopWindowTreeHostLinux extends aura::WindowTreeHostPlatform, the static_cast is safe here. If the tree host classes are refactored, that line of code will have to change anyway. Chromium does not allow dynamic_cast, and the call site does not have access to the concrete type. DesktopWindowTreeHostLinux::CreateFrameView() is within the same class, so it doesn't face the same problem.
  2. I have tested this on XWayland and I've confirmed that this works the same way as on Wayland. I'm using translucent widgets now, which should avoid black bars in transparent areas. I've previously made changes to DesktopWindowTreeHostLinux to set opaque regions correctly as a part of FrameViewLinux work. This should resolve any persistent artifacts. As for transient artifacts during resize, that's an inherent X11 problem without any solution.
  3. a. It's important to run UpdateWebViewRoundedCorners on every Layout for correctness, as the web view instances could change. This operation is not very expensive, it's just a walk over all views and computing some rects. Setting the corner radii eventually calls NativeViewHostAura::ApplyRoundedCorners(), which caches the radii. If the values are the same, the operation completes pretty quickly.
    b. The epsilon is 1px to account for rounding errors. Chromium does not snap views to a grid, so with some fractional scaling factors, there could be 1px difference in overlapping views. See Frameless window on Wayland has a white line on top electron/electron#51457 for an example. There's already a 1-line comment about this, but I can elaborate if necessary. I misremembered the details of the issue. The mismatch shows up after converting DIPs to display pixels. I'll remove epsilon here, it's not necessary while calculating with DIPs.
  4. The asserts in WindowFramelessClientBounds are valid only for Wayland and X11 compositors that support transparency. I could include X11 in the test too, but I'll have to bring in some X11 dependencies in tests to check for transparency. Is that okay?
  5. The predominant Chromium pattern is to retain the layer when radii go to 0, as this would avoid the churn to recreate the layer when the window is moved back to "restored" state. See ContentsWebView for example.

Introduce CaptionlessFrameViewLinux to draw shadows and rounded corners
for frameless windows on Linux. This matches the behavior of frameless
windows on macOS and Windows.

CaptionlessFrameViewLinux extends FrameViewLinux to suppress the titlebar
and round all four corners. Corner radii propagate from the frame view to
the client view, which rounds the hosted web contents. Overlay positioning
is offset by the new frame border insets so overlays stay within the
client area.
@aiddya aiddya force-pushed the frameless-window-wayland branch from 6e06c31 to df67ebe Compare May 31, 2026 16:22
@aiddya

aiddya commented May 31, 2026

Copy link
Copy Markdown
Author

Removed epsilon and expanded tests to X11 with compositing support.

@aiddya

aiddya commented Jun 16, 2026

Copy link
Copy Markdown
Author

@magreenblatt Can you please take another look at this? I want to land this in 7871 if possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants