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

Johan Vos jvos at openjdk.org
Tue Oct 28 08:28:22 UTC 2025


On Tue, 28 Oct 2025 07:28:25 GMT, John Hendrikx <jhendrikx at openjdk.org> wrote:

> It is starting to look like there may be more code relying on double layouts than I thought, even though most controls work absolutely fine. I think that it is still worth pursuing eliminating the need for these (as you can temporarily see the "wrong" positions), but it may take longer as each of these will need an investigation.
> 
> I remain convinced though that the original fix in https://bugs.openjdk.org/browse/JDK-8137252 was applied too hastily, and only worked because it, unintentionally, simply always allowed double layouts.

That is very well possible, but it is what it is. I believe the main goal of the layout phase in a pulse is to make sure that "ultimately", all direct/indirect requests are handled. The secondary goal is that it should be done as efficient as possible, e.g. do not require 2 (or more) passes unless absolutely needed. 
The issue is, though, that there are a huge amount of possible scenarios, leading to situations that can not be dealt with by a single, optimized flow. I started documenting and analyzing scenarios, and even a very basic 2 node case poses issues that can go wrong.
Looking at it with our openjfx glasses, some of these scenarios are really bad. However, developers without internal knowledge often have no idea how and why it can go wrong. Adding bindings/listeners between siblings is a very common pattern, and when looking at my old code, I made tons of "mistakes" by having too much bindings that asked the layout phase to solve an almost impossible job. 
At least the layout system in JavaFX gives developers lots of freedom, and it promises to handle all edge cases. That fulfills the main goal (correct rendering, perhaps after a number of pulses, leading to flickering), but it makes the second goal (top-efficiency) really hard.

To make it harder (but very understandable), the layout phase spans a number of classes, where different concepts/choices are made (e.g. both Parent and Node have internal state that is used to determine whether to initiate a new pulse). That makes it really hard to come up with a system that would typically be used in these situations: use an algorithm that always works (although maybe less performant), and use optimizations in specific cases (e.g. no bindings in properties of children in a chontainer -> use this branch).

Something I've been thinking about every now and then is to introduce runtime warnings (ideally compiler *errors*, but that would require lots of upfront analysis), where the layout subsystem can warn that "a pretty complex situation occurred", e.g. when it is running into cyclic conditions that are not trivial to resolve without performance degradation. But that would be a major effort and conceptual change.

TLDR: I feel your pain and it can be very frustrating having to deal with non-optimal but valid code, deployed in the wild.

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

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


More information about the openjfx-dev mailing list