-
Notifications
You must be signed in to change notification settings - Fork 542
8360940: Layout stops updating when using Parent#setNeedsLayout(true) due to incorrect state management #1879
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8360940: Layout stops updating when using Parent#setNeedsLayout(true) due to incorrect state management #1879
Conversation
|
👋 Welcome back jhendrikx! A progress list of the required criteria for merging this PR into |
|
@hjohn This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be: You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 37 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
Webrevs
|
|
/reviewers 2 |
|
@andy-goryachev-oracle |
|
The fix looks correct. Can you provide an automated test? |
|
I recommend removing |
kevinrushforth
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fix looks good. I confirm that the manual test program from the JBS bug fails without the fix and passes with the fix.
Would it be possible to turn it into an automated test?
|
@kevinrushforth I think I managed a suitable unit test. It fails without the fix, and passes with the fix. |
kevinrushforth
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I confirm that the new test fails without the fix and passes with the fix.
| * layout, while its ancestors are clean, which is an inconsistent state. | ||
| */ | ||
|
|
||
| p.requestLayout(forceParentLayout); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very, very minor suggestion to makes it more compact (it's ok to leave things as is):
// The forceParentLayout flag must be propagated to mark all ancestors
// as needing layout. Failure to do so while performingLayout is true
// would stop the propagation mid-tree. This leaves some nodes as needing
// layout, while its ancestors are clean, which is an inconsistent state.
p.requestLayout(forceParentLayout);
|
Thanks for the quick reviews @andy-goryachev-oracle @kevinrushforth |
|
sorry for the long delay... |
|
/integrate |
|
Going to push as commit 5682424.
Your commit was automatically rebased without conflicts. |
Ensures proper propagation of layout flags when using
forceParentLayout = true.This was the root cause of issue #1874
Note
Apparently it is still quite easy to mess up the layout flags. Basically, the layout flag tracked by Parent should always either be
CLEANfor any scene graph branch, or!CLEAN+ a layout pulse is scheduled on the correspondingScene.However, with careful use of the public API
requestLayoutone can get these flags in a bad state still:Let's say I have a branch
A (root node under Scene) -> B -> C, and a layout is in progress, and we're currently in thelayoutChildrenmethod ofC. The flagperformingLayoutwill betruefor all nodes in the branchA->B->C. Thelayoutmethod will set the layout flag toCLEANas its first action, so when we're atC::layoutChildren, all flags have been reset toCLEANalready. See theParent::layoutmethod for how all this works.Now, to mess up the flags, all you need to do is call
requestLayoutonBorCfrom thelayoutChildrenofC(or indirectly by changing something and something is listening to this and schedules a layout on something somewhere in this branch); note thatrequestLayoutis not documented to be illegal to call during layout, and some classes in FX will do so (ScrollPaneSkin, NumberAxis, etc..) risking the flags getting in a bad state... -- usually you get away with this, as there are many ways that layout is triggered, and eventually the flags will get overwritten and reset to a consistent state.The bad state occurs because this code path is followed (all code from
Parent):Calls to
markDirtyLayout(false, false):Before going into the
else(as none of the nodes is a layout root, andlocalwas set tofalse) it will do setLayoutFlag(LayoutFlags.NEEDS_LAYOUT) -- this will set a flag on some node; to eventually end up in a consistent state, it must mark all ancestors as well and schedule a pulse (withToolkit.getToolkit().requestNextPulse())... but:Here there is a guard
!p.isPerformingLayout, blocking propagation up the tree. As said, this flag istruefor all nodes during a layout of the same branch. The end result thus is that some nodes have their layout flag changed toNEEDS_LAYOUT, but it was not propagated, nor was a pulse scheduled...Progress
Issue
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jfx.git pull/1879/head:pull/1879$ git checkout pull/1879Update a local copy of the PR:
$ git checkout pull/1879$ git pull https://git.openjdk.org/jfx.git pull/1879/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 1879View PR using the GUI difftool:
$ git pr show -t 1879Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jfx/pull/1879.diff
Using Webrev
Link to Webrev Comment