RFR: 8370498: Improve how Node detects whether a layout property change requires a new layout pass [v4]

Michael Strauß mstrauss at openjdk.org
Thu Jan 15 18:36:26 UTC 2026


On Wed, 7 Jan 2026 21:21:14 GMT, John Hendrikx <jhendrikx at openjdk.org> wrote:

> This is why IMHO any layout that relies on convergence is already broken; it just happens to broken in a way that eventually leads to a stable result...

A single top-down layout pass only works when the layout constraints are acyclic. However, JavaFX expressly supports cyclic constraints, so the layout system can't chicken out. As soon as there's a cyclic dependency (parent layout is constrained by child, child layout is constrained by parent), you've got a fixed-point problem and need to solve it in some form, for example with multiple layout phases or iteration.

Cyclic dependencies can appear in several situations:
* CSS/layout coupling: styling influences sizing, sizing influences styling
* Parent size depends on child size
* Child wraps based on parent width
* Baseline alignment
* ...

Looking at how other frameworks do this, we see that WPF and Android use two layout phases: a constraint-carrying measurement pass (given some available size constraint, how much space would each node like to have?), and a second arrange pass that authoritatively tells each node how much space it is given.

Such a system can break some cycles, especially the kind where parent and child sizes mutually constrain each other. It's not a catch-all solution; there can be higher-level cycles, for example with a scroll bar that, upon appearing, causes the layout to reflow, which then again influences the scroll bar. Android detects relayout requests during the layout phase, and will allow for one additional round of measure+layout in the same frame; if a second relayout request is encountered, it is deferred to the next frame.

In JavaFX, we don't have two phases of layout to break the easier cycles, and we don't have multiple rounds of layout. I think it is obvious that we need to do something about that, and pretending that cyclic constraints don't exist is not that.

What I believe can work for JavaFX is a layout system that basically does this for each frame:

while (!layoutClean) {
    doCssPass();
    doLayoutPass();
}

If this doesn't settle in a very small number of iterations (something like 3), we can do the remainder of the work in subsequent frames to prevent unresponsive applications. Maybe we can even detect oscillations (e.g. scroll bar flip-flop) and suspend layout in these cases.

-------------

PR Comment: https://git.openjdk.org/jfx/pull/1945#issuecomment-3756305694


More information about the openjfx-dev mailing list