<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p>Yeah, that's what I'm seeing, it happens on all kinds of actions,
none of which are triggering a resize that requires layout (like
opening/closing a TitledPane or resizing the whole Window).</p>
<p>--John<br>
</p>
<div class="moz-cite-prefix">On 23/04/2025 16:45, Andy Goryachev
wrote:<br>
</div>
<blockquote type="cite"
cite="mid:BYAPR10MB3013A52952E19794119E63BEE5BA2@BYAPR10MB3013.namprd10.prod.outlook.com">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="Generator"
content="Microsoft Word 15 (filtered medium)">
<style>@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}@font-face
{font-family:"Yu Gothic";
panose-1:2 11 4 0 0 0 0 0 0 0;}@font-face
{font-family:Aptos;
panose-1:2 11 0 4 2 2 2 2 2 4;}@font-face
{font-family:"Iosevka Fixed SS16";
panose-1:2 0 5 9 3 0 0 0 0 4;}@font-face
{font-family:"Times New Roman \(Body CS\)";
panose-1:2 11 6 4 2 2 2 2 2 4;}@font-face
{font-family:"\@Yu Gothic";
panose-1:2 11 4 0 0 0 0 0 0 0;}p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
font-size:10.0pt;
font-family:"Aptos",sans-serif;}a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}span.EmailStyle19
{mso-style-type:personal-reply;
font-family:"Iosevka Fixed SS16";
color:windowtext;}.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;
mso-ligatures:none;}div.WordSection1
{page:WordSection1;}</style>
<div class="WordSection1">
<p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">Possibly
related:
<a href="https://bugs.openjdk.org/browse/JDK-8089992"
moz-do-not-send="true" class="moz-txt-link-freetext">https://bugs.openjdk.org/browse/JDK-8089992</a><o:p></o:p></span></p>
<p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">-andy<o:p></o:p></span></p>
<p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<div id="mail-editor-reference-message-container">
<div>
<div>
<div
style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span
style="font-size:12.0pt;color:black">From:
</span></b><span
style="font-size:12.0pt;color:black">John Hendrikx
<a class="moz-txt-link-rfc2396E" href="mailto:john.hendrikx@gmail.com"><john.hendrikx@gmail.com></a><br>
<b>Date: </b>Wednesday, April 16, 2025 at 16:13<br>
<b>To: </b>Nir Lisker <a class="moz-txt-link-rfc2396E" href="mailto:nlisker@gmail.com"><nlisker@gmail.com></a>,
Andy Goryachev <a class="moz-txt-link-rfc2396E" href="mailto:andy.goryachev@oracle.com"><andy.goryachev@oracle.com></a><br>
<b>Cc: </b><a class="moz-txt-link-abbreviated" href="mailto:openjfx-dev@openjdk.org">openjfx-dev@openjdk.org</a>
<a class="moz-txt-link-rfc2396E" href="mailto:openjfx-dev@openjdk.org"><openjfx-dev@openjdk.org></a><br>
<b>Subject: </b>[External] : Re: Unnecessary
layouts; TLDR; new method "requestLocalLayout"<o:p></o:p></span></p>
</div>
<p>I tested this with several controls that were
triggering layouts (like on cursor movements), and I saw
no adverse effects. Basically, any time you interact
with a control and it triggers a full layout but its
bounds didn't change (ie. nothing in the UI changed
position or size) the full layout was unnecessary.<o:p></o:p></p>
<p>Most Skins/Controls do the simple thing of registering
listeners on any properties that may change their
appearance and calling requestLayout, while calling
requestLayout should really be reserved for things that
change their computeMin/Pref/Max values. If there were
no changes in any of those, then the parent layout won't
have changes either (and so on) so the final layout
result will be the exact same as before, yet tens of
thousands of calculations will have been done. Because
of how say HBox calculates its size, it also queries any
siblings, which in turn may be containers...<o:p></o:p></p>
<p>The only things "stopping" layout propagation are
things like scroll panes. This is why TextArea is a lot
less likely to trigger a layout all the way to the root
vs TextField.<o:p></o:p></p>
<p>--John<o:p></o:p></p>
<div>
<p class="MsoNormal"><span style="font-size:12.0pt">On
16/04/2025 17:04, Nir Lisker wrote:<o:p></o:p></span></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span style="font-size:12.0pt">Sounds
good. Have you tried a prototype implementation
for a built-in JavaFX control/Pane, just to see
how well it works?<o:p></o:p></span></p>
</div>
<p class="MsoNormal"><span style="font-size:12.0pt"><o:p> </o:p></span></p>
<div>
<div>
<p class="MsoNormal"><span style="font-size:12.0pt">On
Wed, Apr 16, 2025 at 5:50</span><span
style="font-size:12.0pt;font-family:"Arial",sans-serif"> </span><span
style="font-size:12.0pt">PM Andy Goryachev <<a
href="mailto:andy.goryachev@oracle.com"
moz-do-not-send="true"
class="moz-txt-link-freetext">andy.goryachev@oracle.com</a>>
wrote:<o:p></o:p></span></p>
</div>
<blockquote
style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<div>
<div>
<div>
<p class="MsoNormal"
style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">This
might be a good idea from an API
perspective, but please be careful - this
optimization might break the behavior. For
instance, the scroll bar might change as a
result of a key event in the TextArea, so
the text layout is still needed, however
expensive.</span><span
style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"
style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span
style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"
style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">(and
I like Michael's suggestion of naming the
method requestLayoutChildren())</span><span
style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"
style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span
style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"
style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">-andy</span><span
style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"
style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span
style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"
style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span
style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"
style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span
style="font-size:12.0pt"><o:p></o:p></span></p>
<div
id="m_-1880730255040356136mail-editor-reference-message-container">
<div>
<div>
<div
style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"
style="mso-margin-top-alt:auto;margin-bottom:12.0pt"><b><span
style="font-size:12.0pt;color:black">From:
</span></b><span
style="font-size:12.0pt;color:black">openjfx-dev <<a
href="mailto:openjfx-dev-retn@openjdk.org" target="_blank"
moz-do-not-send="true"
class="moz-txt-link-freetext">openjfx-dev-retn@openjdk.org</a>>
on behalf of John Hendrikx <<a
href="mailto:john.hendrikx@gmail.com" target="_blank"
moz-do-not-send="true"
class="moz-txt-link-freetext">john.hendrikx@gmail.com</a>><br>
<b>Date: </b>Monday, April 14,
2025 at 08:56<br>
<b>To: </b><a
href="mailto:openjfx-dev@openjdk.org" target="_blank"
moz-do-not-send="true"
class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>
<<a
href="mailto:openjfx-dev@openjdk.org" target="_blank"
moz-do-not-send="true"
class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>><br>
<b>Subject: </b>Unnecessary
layouts; TLDR; new method
"requestLocalLayout"</span><span
style="font-size:12.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"
style="mso-margin-top-alt:auto;margin-bottom:12.0pt"><span
style="font-size:11.0pt">I've been
writing a container that does
layout, and I've been using it<br>
extensively in my latest project.<br>
<br>
I noticed that many skins and
controls will call
requestLayout(), not<br>
realizing that this will mark the
current node + all parent nodes
with<br>
`NEEDS_LAYOUT`. This causes all
those containers to call `compute`<br>
methods and execute their
`layoutChildren`, even though your
control may<br>
only have changed something that
does NOT change its layout bounds
(like<br>
a color, background, alignment or
even things like a cursor shape or<br>
position). These computations are
expensive, involving querying of
all<br>
children of each container to find
out their min/pref/max sizes, do<br>
content bias calculations,
splitting space over each control
and many<br>
many snapXYZ calls -- all leading
to no visual layout change...<br>
<br>
For example, a TextArea or
TextField will call requestLayout
on every<br>
character typed, every cursor
movement, and every text content
change. <br>
None of those affects their bounds
(at least, in my experience, these<br>
controls are not continuously
resizing themselves when I scroll
or type<br>
things...). TextField will even
change its cursor shape every time
its<br>
value is updated, even if that
value is simply bound to a Slider
and the<br>
field doesn't have focus at all --
this field will then trigger
layout<br>
on itself and all its ancestors
even if it is in a completely
unrelated<br>
area of the UI (not close to the
slider).<br>
<br>
It seems that in many cases these
controls and skins just want their<br>
layoutChildren method to be
called, as their main layout logic
is<br>
located there -- duplicating this
logic partially for every minor<br>
property change that doesn't
affect its bounds is error prone,
so I can<br>
completely follow this reasoning.
However, using requestLayout to
get<br>
layoutChildren called is very
expensive.<br>
<br>
There is a better way: call
setNeedsLayout(true) -- this is a
protected<br>
method that any Node has access
to, and basically will only call<br>
layoutChildren on your own Node.
It marks all the parent nodes as<br>
`DIRTY_BRANCH`, which means that
on a layout pass it will traverse
down<br>
to see which nodes actually needs
layout (it won't call
layoutChildren<br>
for each ancestor, which is a big
win).<br>
<br>
Because of its protected nature
(and its required parameter which
must<br>
be true), it is a bit hard to
use. I'm thinking it might be a
good idea<br>
to introduce a new method here, a
request layout call that schedules
a<br>
Node for layout without forcing
all ancestors to do the same. This
way<br>
Skin and Control designers can
clearly see the two options and
choose<br>
what is required:<br>
<br>
requestLayout -- my bounds
likely have changed (font change,<br>
border/padding change, spacing
change), so please call compute
methods<br>
and redo the entire layout<br>
<br>
requestLocalLayout -- my
bounds have not changed (color
changes,<br>
background changes, content
changes within a ScrollPane,
cursor changes,<br>
cursor position changes, alignment
changes)<br>
<br>
What do you think?<br>
<br>
--John<br>
<br>
</span><span
style="font-size:12.0pt"><o:p></o:p></span></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</blockquote>
</body>
</html>