jfx icon indicating copy to clipboard operation
jfx copied to clipboard

8372415: Stage size should match visual window bounds

Open mstr2 opened this issue 1 month ago • 9 comments

On Windows, the Stage.width and Stage.height correspond to the window size as returned by GetWindowRect.

Up until Windows 10, the size of a window was identical to its visual borders. However, since Windows 10 has introduced thin visual window borders, the window manager adds an invisible border of a few pixels around the window to make it easier to resize the window. Since GetWindowRect returns the window size including these invisible borders, the location and size of a Stage isn't exactly what we'd expect.

For example, if we place a Stage at setX(0) and setY(0), the window appears with a small distance from the screen edge, and the window size extends a few pixels beyond its visual borders (in the following images, the screenshot size corresponds to the window size; note the invisible padding around the edges): window-size-1

What we actually want is to have the visual borders line up with the edges of the screen, and have the window size correspond to the visual borders: window-size-2

The implementation is quite simple: instead of GetWindowRect, we use DwmGetWindowAttribute(DWMA_EXTENDED_FRAME_BOUNDS). This gives us the bounds of the visual window borders. If this function fails, we fall back to GetWindowRect (now, I don't know why DwmGetWindowAttribute(DWMA_EXTENDED_FRAME_BOUNDS) would ever fail... maybe an old Windows version in a remote desktop scenario?).


Progress

  • [x] Change must not contain extraneous whitespace
  • [x] Commit message must refer to an issue
  • [ ] Change must be properly reviewed (2 reviews required, with at least 1 Reviewer, 1 Author)

Issue

  • JDK-8372415: Stage size should match visual window bounds (Bug - P4)

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jfx.git pull/1982/head:pull/1982
$ git checkout pull/1982

Update a local copy of the PR:
$ git checkout pull/1982
$ git pull https://git.openjdk.org/jfx.git pull/1982/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 1982

View PR using the GUI difftool:
$ git pr show -t 1982

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jfx/pull/1982.diff

Using Webrev

Link to Webrev Comment

mstr2 avatar Nov 24 '25 14:11 mstr2

/reviewers 2

mstr2 avatar Nov 24 '25 14:11 mstr2

:wave: Welcome back mstrauss! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

bridgekeeper[bot] avatar Nov 24 '25 14:11 bridgekeeper[bot]

❗ This change is not yet ready to be integrated. See the Progress checklist in the description for automated requirements.

openjdk[bot] avatar Nov 24 '25 14:11 openjdk[bot]

@mstr2 The total number of required reviews for this PR (including the jcheck configuration and the last /reviewers command) is now set to 2 (with at least 1 Reviewer, 1 Author).

openjdk[bot] avatar Nov 24 '25 14:11 openjdk[bot]

Webrevs

mlbridge[bot] avatar Nov 24 '25 14:11 mlbridge[bot]

I haven't uncovered any problems so far but it took me a while to get my bearings. You're working with two coordinate systems, the one used by JavaFX which doesn't include the invisible border and the one used by Windows which does. The naming convention is confusing since the "extended" rectangle is actually the smaller of the two. It would also be good to see some comments clarifying that m_insets, m_maxSize, and m_minSize are all specified in the JavaFX system.

beldenfox avatar Dec 02 '25 19:12 beldenfox

I haven't uncovered any problems so far but it took me a while to get my bearings. You're working with two coordinate systems, the one used by JavaFX which doesn't include the invisible border and the one used by Windows which does. The naming convention is confusing since the "extended" rectangle is actually the smaller of the two. It would also be good to see some comments clarifying that m_insets, m_maxSize, and m_minSize are all specified in the JavaFX system.

I don’t think it’s quite "two coordinate systems" (JavaFX vs Windows). Stage.width/height are intended to include the normal system decorations (title bar + borders), which historically also matches what people mean by "window size": it includes the non-client area, but not purely visual effects like drop shadows. The weirdness on Windows 10+ is that GetWindowRect started including an extra invisible resize border that’s not part of the visible frame, so the window ends up being reported a few pixels larger than it looks. Using DwmGetWindowAttribute(DWMA_EXTENDED_FRAME_BOUNDS) is basically a way to get the visually perceived bounds back.

mstr2 avatar Dec 02 '25 19:12 mstr2

I was thinking that JavaFX and Windows have different ideas of where the window origin (0, 0) lies; Windows thinks it's at the top left of drop shadow area and JavaFX thinks it's at the top left of the title bar (in this PR). But you're right, what's relevant is that there are two rectangles of different sizes. I still think it could be clearer that, say, m_insets applies to the smaller of the two (which is the extended one).

beldenfox avatar Dec 03 '25 00:12 beldenfox

I've added a comment to clarify that m_minSize, m_maxSize, and m_insets are specified with respect to the extended frame bounds.

mstr2 avatar Dec 03 '25 00:12 mstr2

With this fix applied, the problem described in JDK-8285983 disappears and the reported position and size of a full-screen window is as a sane person would expect it to be (position = 0,0 and size = visual bounds of the screen).

I suggest we re-open the bug (which was closed as "not an issue") and add it to this PR.

mstr2 avatar Dec 13 '25 04:12 mstr2

I've looked at every call to GetWindowRect and, where appropriate, replaced it with GetExtendedFrameBounds. In addition to that, I also tested the case when JavaFX is running in a DPI-unaware process. I've added code that detects this situation and applies the correct mapping from physical coordinates into virtualized coordinates.

mstr2 avatar Dec 15 '25 06:12 mstr2

/issue add JDK-8285983

mstr2 avatar Dec 15 '25 06:12 mstr2

@mstr2 Adding additional issue to issue list: 8285983: JavaFX reports maximized window size larger than the physical screen.

openjdk[bot] avatar Dec 15 '25 06:12 openjdk[bot]