Form resizing reflow

Hi,

Resizing a sizeable popup form is choppy on older hardware. By using Chrome DevTools trace on a project, I've discovered that there's intense layout thrashing even when it shouldn't really be needed.

The form has zero controls with Align or Anchors set and the layout is entirely CSS driven, so all of that work computes a realignment that has nothing to realign since the browser would reflow the content correctly on its own.

The analysis shows this series of events:

ResizeObserver (Forms.pas:3736) → HandleObserver (Forms.pas:2224) → TCustomForm.Resize (Forms.pas:1560), unthrottled, once per animation frame. Resize then does AlignControl(Self) (1595) plus Controls[i].UpdateAnchoring for the whole tree (1606).

1. AlignControls recurses into every child unconditionally — Controls.pas:1720

for j := 0 to ControlCount - 1 do
    Controls[j].AlignControl(Controls[j]);

So AlignControl runs for all 166+ controls on my form, including elements with Align = alNone and no children.

2. AlignControl writes, then reads the same element — Controls.pas:2314 → 2319

// write: invalidates style
  AControl.GetElementStyle.setProperty('overflow', 'hidden');   

  ...
// read: forces recalc + reflow
  r := GetClientRect;

Classic layout thrashing, once per control. The overflow values are then written back at 2395–2397 (three more writes). Line 2380 (scrollHeight > clientHeight) adds another forced reflow per control.

3. GetClientRect calls getComputedStyle just to read the border width — Controls.pas:3590 → GetStyle → Controls.pas:3405. This is what's taking the most time in my project.

4. GetWidth/GetHeight hit getBoundingClientRect unless WidthStyle = ssAbsolute — Controls.pas:3799 / 3820.
But ssAbsolute is incompatible with a CSS-framework layout: to let Bootstrap size our controls everything must be ssAuto. So in any Bootstrap app every GetWidth call is a forced reflow.

5. UpdateAnchoring reads the parent's bounds before checking whether it needs them — Controls.pas:5336 vs 5364

With the default Anchors = [akLeft, akTop], r is computed and never used. One forced reflow per control per frame, for nothing.

6. Same pattern in SetBoundsInt — Controls.pas:3100


  if (X <> Left) or (Y <> Top) or ((AWidth <> Width) and (WidthStyle = ssAbsolute)) or ...

Width is evaluated before the WidthStyle test that makes it irrelevant. Swapping the operands to (WidthStyle = ssAbsolute) and (AWidth <> Width) removes a forced reflow at zero risk.

In summary:

1. Reorder two tests (Controls.pas:3100 and 5336/5364): check WidthStyle/Anchors before reading geometry. Two-line change, removes a large share of the reflows for any app that doesn't use anchors.

2. Skip the realign when there's nothing to realign. A flag per container, maintained by the Align/Anchors/Center setters, recording "no child needs alignment". If clear, AlignControls (1581) and UpdateAnchoring (5313) return immediately. For CSS-framework-based apps (such as mine) this eliminates essentially 100% of the cost.

3. Optionally, throttle/coalesce the ResizeObserver callback (Forms.pas:3736), or expose a LiveResize property so the developer can choose "realign at drag end" instead of "realign every frame".

As a temporary workaround, I've disconnected the FResizeObserver and replaced it with a debounced one that calls HandleObserver 100 ms after the last size change. Resize becomes perfectly smooth: the browser resizes the popup element natively, Bootstrap reflows the children, the RTL stays out of it during the drag. But it relies on a private field and javascript injections, so I'd much prefer a supported solution.

Is there an official way to disable the RTL realign for forms whose layout is entirely CSS-driven?

Thank you in advance.

A possible solution with the current TMS WEB Core release is to add an override of HandleObserver in your form where this handling is not needed, i.e.

TMyForm = class(TWebForm)
protected
   function HandleObserver: boolean; override;
end;

function TMyForm.HandleObserver: boolean;
begin
  Result := true;
end;