<!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>