Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions evidence/held-layout-scroll-20261006/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Held layout requests during scrolling

Screen previously chose full layout whenever `_layout_widgets` was nonempty.
After a layout during a mutation, that same mapping intentionally retains
requests below the held roots. Compositor already preserves those roots' exact
committed geometry in both full and visible arrangement. Retained requests
therefore forced repeated full layout without being allowed to change their
subtree.

Screen now owns the existing hold classification in `_held_layout_requests`.
Scroll takes the original visible traversal when every pending member is held.
Requests outside the hold, including promoted auto-size ancestors, still force
full layout. The full-layout branch uses that same classification to retain
requests after arrangement. Release makes those requests actionable again.
An empty request mapping needs no mutation-root acquisition.

No placement, mutation-root, damage, callback, resize or renderer owner was
replaced. The original visible traversal still acquires retained reader paths;
Compositor still preserves exact held hit/paint geometry. No persistent state,
cache, timer, Toad change or publication exemption was added.

## Confirmation

The existing real App control now performs two scroll layouts while a mounted
child is held, verifies exact geometry/hits and pending requests, then admits an
outside request and verifies full layout. Original release applies the mount.
The original cut-cell, callback and overlap assertions remain. That control and
the inline/translucent controls passed: **3 passed in 0.57s**. The final empty
request shortcut was subsequently exercised by the source App below.

One original Toad sidebar source App completed with 508 widgets / 10 tabs,
exit zero and empty stderr. First-display medians were 35.1ms / 40.1ms, with a
112.1ms left maximum. This ordinary layout check does not measure the changed
held-scroll path or establish a reliable speed improvement.

Source: `before.json` parses native 249, Toad 288 and Core 324 modules with zero
omissions; `after.json` contains the native decision/consumer sites. Arbitrary
external dynamic mutation of private layout state remains outside this audit.

Raw App output and profiles remain under
`/home/ts/.cache/agent-scratch/held-layout-scroll-20261006/`.
The supplied live scroll profile identifies full/visible arrangement activity;
its transition groups do not establish call counts, CPU durations or which
pending layout requests caused any particular pass.

This is a source/native-framework qualification. Installed saved scrolling,
writer-gap reduction and overall smoothness remain unqualified. No provider,
package, artifact, public-owner or recorder operation occurred.
22 changes: 22 additions & 0 deletions evidence/held-layout-scroll-20261006/RESULT.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"source_head": "21e5620866fbf960ac7d39fd7f659bfa56c89fdd",
"controls": "3 passed in 0.57s",
"app": {
"exit": 0,
"stderr_bytes": 0,
"widgets": 508,
"tabs": 10,
"boundary": "source headless App _display, not terminal pixels or held-scroll latency"
},
"keepers": {
"src/textual/screen.py": "66ca0546457c22de6bdd9165a0e4c0a4b6a1294ad09ac5136f188a521729f6b2",
"tests/test_batch_paint_admission.py": "b002872170751bfea8cc99847574ac0df019c538191fe71c4f1fac71db745a0d",
"evidence/held-layout-scroll-20261006/before.json": "b17233b81c922f4a0f7652e603ee188d393f4a53421562a770cdac8f29ddeffa",
"evidence/held-layout-scroll-20261006/after.json": "9937a6bcc505cd48a2e5c0e1cbbe0c17272e9fd05d44bf438609202323e63466",
"evidence/held-layout-scroll-20261006/controls.log": "a2781fcf8f9c65bdb27d0edf589ab8df478ce510960a3dcee3c456a717c0f5ed",
"/home/ts/.cache/agent-scratch/held-layout-scroll-20261006/app.stdout.log": "518cc08803afbfecc92913c0e6953f19c9638d7c5ea57446ca58f3430fac1b8e",
"/home/ts/.cache/agent-scratch/held-layout-scroll-20261006/app.stderr.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"installed": false,
"reliable_latency_improvement": false
}
174 changes: 174 additions & 0 deletions evidence/held-layout-scroll-20261006/after.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
{
"modules": 249,
"omissions": [],
"sites": [
[
"src/textual/_compositor.py",
873,
"_layout_mutation_roots",
"Attribute"
],
[
"src/textual/_compositor.py",
1309,
"_layout_mutation_roots",
"Attribute"
],
[
"src/textual/_compositor.py",
1292,
"_layout_mutation_roots",
"Attribute"
],
[
"src/textual/app.py",
3850,
"_refresh_layout",
"Attribute"
],
[
"src/textual/layouts/stream.py",
58,
"_layout_widgets",
"Attribute"
],
[
"src/textual/screen.py",
1220,
"_layout_mutation_roots",
"FunctionDef"
],
[
"src/textual/screen.py",
1419,
"_held_layout_requests",
"FunctionDef"
],
[
"src/textual/screen.py",
1432,
"_refresh_layout",
"FunctionDef"
],
[
"src/textual/screen.py",
326,
"_layout_widgets",
"Attribute"
],
[
"src/textual/screen.py",
1421,
"_layout_widgets",
"Attribute"
],
[
"src/textual/screen.py",
1423,
"_layout_mutation_roots",
"Attribute"
],
[
"src/textual/screen.py",
1400,
"_layout_widgets",
"Attribute"
],
[
"src/textual/screen.py",
1485,
"_layout_widgets",
"Attribute"
],
[
"src/textual/screen.py",
1547,
"_layout_widgets",
"Attribute"
],
[
"src/textual/screen.py",
1549,
"_layout_widgets",
"Attribute"
],
[
"src/textual/screen.py",
1623,
"_refresh_layout",
"Attribute"
],
[
"src/textual/screen.py",
1704,
"_layout_widgets",
"Attribute"
],
[
"src/textual/screen.py",
1312,
"_refresh_layout",
"Attribute"
],
[
"src/textual/screen.py",
1445,
"_held_layout_requests",
"Attribute"
],
[
"src/textual/screen.py",
1485,
"_held_layout_requests",
"Attribute"
],
[
"src/textual/screen.py",
1548,
"_layout_widgets",
"Attribute"
],
[
"src/textual/screen.py",
1589,
"_layout_widgets",
"Attribute"
],
[
"src/textual/screen.py",
1642,
"_refresh_layout",
"Attribute"
],
[
"src/textual/screen.py",
1315,
"_refresh_layout",
"Attribute"
],
[
"src/textual/screen.py",
1591,
"_layout_widgets",
"Attribute"
],
[
"src/textual/screen.py",
1425,
"_layout_widgets",
"Attribute"
],
[
"src/textual/screen.py",
1550,
"_layout_widgets",
"Attribute"
],
[
"src/textual/screen.py",
1451,
"_layout_widgets",
"Attribute"
]
]
}
Loading
Loading