On Thu, 10 Sep 2026 01:13:52 GMT, Michael Strauß <[email protected]> wrote:
> This PR formalizes render scale and snapping policy as an inheritable layout > context. I've chosen the term "layout context" because it establishes > additional inputs to the layout algorithm that need to be accounted for, but > are not part of the geometric definition of the nodes in the scene graph > themselves. > > For example, consider a `VBox` with a spacing of 0.6: the gaps snap to 1.0 at > render scale 1, but to 0.5 at render scale 2. Even though the size of the > `VBox` and all of its inputs remain exactly the same, its children still need > to move a little bit. This is especially relevant for layout containers that > cache measurements or layout results (of which there are some), and makes it > necessary that we have a way to invalidate those containers when the render > scale or effective snapping policy changes. > > For this purpose, the following new APIs are added: > 1. `Parent.isSnappedToPixel()` returns the effective pixel-snapping policy, > which is only `true` if the node itself and all of its ancestors have their > `snapToPixel` property set. All snapping methods use this method (instead of > the `snapToPixel` property) to determine whether values should be snapped. > 2. `Parent.layoutContextInvalidated()` will be called whenever the render > scale or the effective pixel-snapping policy changes. This method can be > overridden by subclasses to clear their cached measurements. > > Since we now have a way to invalidate the layout context, we can also cache > render scales in each node instead of chasing pointers back to `Window` for > every individual snapping operation. Interestingly, `Region` already cached > the render scales, but in a useless way that accomplished almost nothing. > > Additionally, the snapping methods and the `snapToPixel` property are moved > from `Region` to `Parent`, as I think having them on `Region` was always > incorrect. Layout is a mechanism introduced by `Parent` (the > `layoutChildren()` method is defined on `Parent`), and pixel-snapping > intrinsically belongs to layout. Think about it: there can be subclasses of > `Parent` that can lay out nodes, so they must also have access to > pixel-snapping APIs. One such example is `Group`, which resizes its children > to their preferred sizes, but is itself not a `Region`. > > Moving methods to a superclass is a binary- and source-compatible change. > > --------- > - [x] I confirm that I make this contribution in accordance with the [OpenJDK > Interim AI Policy](https://openjdk.org/legal/ai). At a high level this sounds like a useful thing to do. It will take some time to go through it all, but I like the direction. modules/javafx.graphics/src/main/java/javafx/scene/Parent.java line 1080: > 1078: */ > 1079: @Deprecated(since = "9", forRemoval = true) > 1080: protected final double snapSpace(double value) { Since these are deprecated for removal, can they stay in Region? They could simply delegate to snapSpaceX (which is proposed to move to Parent). ------------- PR Review: https://git.openjdk.org/jfx/pull/2309#pullrequestreview-5172324097 PR Review Comment: https://git.openjdk.org/jfx/pull/2309#discussion_r3983540015
