Skip to content

BrowserWindow.getBounds() includes transparent space taken up by shadows on Wayland #48589

@mitchchn

Description

@mitchchn

Preflight Checklist

Electron Version

38.3.0

What operating system(s) are you using?

Ubuntu

Operating System Version

Ubuntu 24.04

What arch are you using?

x64

Last Known Working Electron version

No response

Does the issue also appear in Chromium / Google Chrome?

No

Expected Behavior

BrowserWindow.getBounds() should return the bounds of the visible, physical window (contentBounds + titlebar). It should not include the transparent area which surrounds the window to support shadows.

Actual Behavior

This window will report bounds of 800x600 immediately after creation, but soon reports larger bounds of 844x822, even though the visible window is still 800x600.

const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  // Will be 844x822
  setTimeout(() => {
    console.log("Main window bounds after 1s:", mainWindow.getBounds());
  }, 1000);

The larger bounds are returned because the window is surrounded by a transparent client-drawn frame which paints shadows + the outer part of resize handle hit targets, but this is an implementation detail which is not relevant to the app.

This is an issue because if an app implements window bounds saving/restoration, windows will grow a little more each time they are created. (A bug for that specific manifestation of this issue may have been filed already.)

Isn't this what BrowserWindow.getContentBounds() is for?

No. BrowserWindow.getContentBounds() returns the web content bounds only, i.e. it subtracts the titlebar. An 800x600 window has these sets of bounds when drawn with CSD (ClientFrameViewLinux):

  • Total bounds including transparent shadow region: 844x644
  • Window bounds (visible window frame): 800x600
  • Content bounds: 800x532

That second value is the one which needs to be consistently respected by BrowserWindow.getBounds(), since it is supposed to be the same measurement as the value which is set on window creation. The total CSD bounds including external decorations do not need to be accessible from the JS layer.

Testcase Gist URL

https://gist.github.com/7487efc43b208a3624ba464cb156860d

Additional Information

Related to: #48588.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions