On Mon, 15 Dec 2025 18:53:59 GMT, Andy Goryachev <[email protected]> wrote:
>> When a Window is created with a certain X/Y coordinate to place it on a >> specific screen, and is subsequently shown for the first time, one of the >> first things it does is size the window according to the size of the Scene. >> It does this based on the render scale of the *primary* screen as it has not >> moved the peer yet to the correct screen. After the scene has been sized, >> it is moved to the correct screen, triggering a change of render scale, but >> not a resizing of the Window (as this is only done once). >> >> The result of this is that due to slight difference in render scale, the >> size calculated for the scene may be a few pixels off. As the scene's >> preferred size is used for this calculation, even a few pixels too small can >> result in Labels being shown with ellipsis on the intended target screen >> with a different render scale. >> >> When observing the render scale X or Y property, one can observe a change >> from 1.0 (the default value) to 2.0 (the primary screen's render scale) to >> another value (depending on the target screen). However, the Window >> involved (being positioned by the user using setX()/setY() before it is >> shown) was never shown on the primary screen, yet the size calculation >> assumed it was. >> >> To solve this problem, the peer should be moved to the correct screen >> **before** asking the Scene for its preferred size to use as the initial >> Window size. Doing so (by adding an additional `applyBounds` call) also >> results in the render scale properties to only change once (or not at all) >> from their default value to the target screen's value (or not at all if the >> target screen is 1.0 scale). > > This fix introduces another issue in the monkey tester, breaking the layout > (see the screenshot below). The failure can be seen when the MT window > appears on the primary (scale=2) as well as on the secondary (scale=1) > monitor, running macOS 26.1. > > The layout gets fixed when the user resizes the window. > > Interestingly, moving the window to another screen with a different scale > **does not** fixes the issue. > > <img width="1380" height="623" alt="Screenshot 2025-12-15 at 10 47 46" > src="https://github.com/user-attachments/assets/0af65495-7e28-428d-9001-a94c68917833" > /> > > More observations: > - it does fixes the menu bar issue mentioned in > https://github.com/openjdk/jfx/pull/1945#pullrequestreview-3385140013 > - also tested in combination with #1945 , the layout issue is present in the > combined version @andy-goryachev-oracle Well, this is going a bit beyond what I'm trying to fix. I don't see any of the issues you're showing, not with test programs, nor with MonkeyTester. In fact, I saw several positive things after applying this fix (Windows are no longer sized with unused empty space when immediately shown on a different monitor). As this again seems to be Mac specific, I have very limited means to "fix" this further, so perhaps you could have a look yourself. I've added some debug output that will be helpful (you can share it here). Look specifically at what `setBounds` is called with. MonkeyTester is setting X/Y/width/height of its Window explicitly when it has some settings stored from a previous run. This means it generally follows a slightly different code path when the window is shown, since all the "explicit" flags for x, y, width and height will be true. Still, that doesn't explain how you get some unused empty space. Here's an example of the output on my system, where MonkeyTester is shown on the 1.0 monitor on the right side of a 1.5 monitor: Window/invalidationListener: shown changed to: true Window/invalidationListener: screen=javafx.stage.Screen@21e4df3b bounds:Rectangle2D [minX=0.0, minY=0.0, maxX=2560.0, maxY=1440.0, width=2560.0, height=1440.0] visualBounds:Rectangle2D [minX=0.0, minY=0.0, maxX=2560.0, maxY=1400.0, width=2560.0, height=1400.0] dpi:93.0 outputScale:(1.5,1.5) Window/peer: setBounds(2698.0, 61.0, true, true, winW:1463.0, 708.0, clientW:-1.0, -1.0, 0.0, 0.0, rsx:0.0, rsy:0.0) Window/invalidationListener: after applying bounds screen=javafx.stage.Screen@55e0e86c bounds:Rectangle2D [minX=2560.0, minY=-194.0, maxX=4480.0, maxY=1006.0, width=1920.0, height=1200.0] visualBounds:Rectangle2D [minX=2560.0, minY=-194.0, maxX=4480.0, maxY=1006.0, width=1920.0, height=1200.0] dpi:94.0 outputScale:(1.0,1.0) Window/invalidationListener: output scale used before sizing scene: 1.0 Window/invalidationListener: size from scene: 517.0x2646.0 Window/peer: setBounds(2698.0, 61.0, true, true, winW:1471.0, 727.0, clientW:-1.0, -1.0, 0.0, 0.0, rsx:1.0, rsy:1.0) Window/invalidationListener: exit invalidation listener What you see above here is that initially the window screen is still the primary screen (at minXY=0,0); after `applyBounds` this changes to the correct screen. The scene size code is then called with the correct values (render scale 1.0). The scene size is however a bit weird; it is very wide, probably because there are many controls in your Scene that have a wide preferred width. It's possible this is somehow the cause of that empty space -- still, on my system, those values are unused as MonkeyTester sets its own width/height, which you can see in the final `setBounds` call -- effectively, the scene sizing is ignored, and it should re-layout with the final size. Come to think of it, the scene size call is basically superfluous; if width/height is explicit, we could skip that completely. Anyway, let me know what you find. I'm not seeing any issues with the above outputs, but perhaps something odd pops up on your system that may point us in the right direction. ------------- PR Comment: https://git.openjdk.org/jfx/pull/2007#issuecomment-3659265912
