110 lines
7.1 KiB
Markdown
110 lines
7.1 KiB
Markdown
# Flat review in scrolling tables
|
||
|
||
Flat review captures the visible cells of selectable tables through AT-SPI
|
||
table coordinates and component hit testing. It does not enumerate the model's
|
||
offscreen rows. Visible column headers and compound cells remain available.
|
||
The first selected cell is retained as a focus anchor if horizontal scrolling
|
||
hides its column; its offscreen text does not enter review output.
|
||
|
||
New flat-review objects retain libatspi's event-maintained provider cache.
|
||
Clearing that cache forced redundant child-count requests even for known leaves,
|
||
which could abort capture when a provider was briefly unresponsive. Objects
|
||
already marked dirty in the owned tree still refresh their native snapshot.
|
||
|
||
Long text geometry queries are bounded to 128 characters per provider call.
|
||
Their rectangles are combined across every chunk, including interior bidi runs.
|
||
For partially clipped lines, offscreen chunks are rejected before querying
|
||
individual character rectangles. This preserves native offsets and visible text
|
||
without measuring thousands of characters in one synchronous request.
|
||
Exact range rectangles are reused only within one object's synchronous text
|
||
capture, including zero-area rectangles. This avoids querying the same 128-character
|
||
blocks once to combine line bounds and again to clip the line. The map is discarded
|
||
when that object's text capture returns; a changed viewport or later command does
|
||
not reuse it. Failed requests are not stored, and cancellation is checked before
|
||
using a saved rectangle. Individual glyph checks for clipped text remain intact.
|
||
|
||
In the live FastSMRW investigation, measuring an entire 3,424-character line took
|
||
about 0.9 seconds, exceeding the adapter's 0.8-second provider timeout. A later
|
||
child-count query then reported that the process appeared hung, masking the
|
||
earlier text-geometry timeout. The same read-only capture probe failed before
|
||
bounded measurement and completed after it. That is provider-capture evidence;
|
||
speech, keyboard response and physical Braille still require live acceptance.
|
||
Three subsequent read-only review-worker runs completed line, word, character,
|
||
window-start and window-end commands. Initial capture took roughly 4–6 seconds;
|
||
cached commands took about one millisecond. One earlier worker probe returned a
|
||
negative child count, which did not recur in those three runs. Negative-count
|
||
errors now include the same object metadata as provider-error responses so a
|
||
recurrence can be located. Initial-capture latency remains a live acceptance
|
||
concern.
|
||
|
||
Debug logs include one `flat review capture timing` record for each capture
|
||
attempt, including a timed-out attempt while a native call is still running.
|
||
It reports request-lock and GLib queue wait, root selection, cache preparation,
|
||
snapshot, geometry, visible-text, table-viewport, child-count, child-enumeration,
|
||
installation and reference-cleanup timings. Each stage has a total, invocation
|
||
count, and longest invocation with its bus/path/role. These are helper-stage
|
||
timings: a visible-text invocation can contain several native range queries.
|
||
`last_stage`, `stage_duration` and the object identity describe the stage at
|
||
completion or timeout; on timeout its elapsed portion is included in totals.
|
||
`root_scope` distinguishes a focused-window root from the desktop fallback.
|
||
Captured/pending object counts and text byte counts show traversal progress.
|
||
No names or text contents are added. Diagnostics allocate no per-capture trace
|
||
unless debug logging is enabled, and do not issue additional provider queries.
|
||
Late native completion cannot overwrite the timeout record.
|
||
|
||
A descendant which becomes defunct during capture is removed from its parent's
|
||
child list. A defunct root still fails capture. Other provider failures still
|
||
fail capture rather than presenting an old snapshot. Child-count errors include
|
||
the object's bus, path, role and the number of objects already captured, without
|
||
logging its name or text.
|
||
|
||
Run the native viewport regression on a private display and accessibility bus:
|
||
|
||
```sh
|
||
python3 tests/native_test_session.py env CTHULHU_NATIVE_REVIEW_TABLE=1 go test ./internal/atspi -run '^TestNativeFlatReviewLargeGTKTable$' -count=1 -timeout=150s -v
|
||
python3 tests/native_test_session.py env CTHULHU_NATIVE_REVIEW_CACHE=1 go test -race ./internal/atspi -run '^TestNativeFlatReviewPreservesProviderCache$' -count=1 -timeout=30s -v
|
||
python3 tests/native_test_session.py env CTHULHU_NATIVE_REVIEW_BOUNDS=1 go test -race ./internal/atspi -run '^TestNativeFlatReviewBoundsSlowLongRanges$' -count=1 -timeout=30s -v
|
||
python3 tests/native_atspi.py
|
||
```
|
||
|
||
The viewport test covers a 6,000-row GTK table scrolled to its middle, a changed
|
||
viewport and updated row text, a small table, an empty table with headers,
|
||
horizontal scrolling, and cells with multiple renderers. It checks that a small
|
||
viewport captures fewer than 100 objects. Before the change, the large case
|
||
captured 6,006 objects. The existing suite covers flat-review cursor movement,
|
||
text changes, terminal viewport capture, password exclusion, and ordinary
|
||
single/multiple GTK table selections.
|
||
|
||
The cache regression uses a GTK label whose initial cache reports zero children,
|
||
then arms a deliberately slow child-count getter. Before cache preservation,
|
||
capture failed on that redundant query. The test requires capture to succeed
|
||
without invoking the getter, then changes the label and checks that dirty text
|
||
is refreshed. The C fixture is compiled with the existing GTK development
|
||
dependencies during the test.
|
||
|
||
The long-range regression uses a horizontally clipped 3,424-character GTK label.
|
||
Its provider deliberately stalls when a range query exceeds 128 characters.
|
||
Capture must retain visible text and never trigger that large request. The fixture
|
||
also counts repeated native range requests: the original implementation repeats
|
||
36 requests, while capture-local reuse makes none. Unit
|
||
tests also cover Unicode offsets, offscreen query counts, interior bidi bounds,
|
||
zero-size chunks, cancellation and provider errors.
|
||
|
||
For live acceptance, use a user-started updated reader and:
|
||
|
||
1. In FastSMRW, review lines, words and characters in both directions, including
|
||
window start/end. Repeat after changing the selected post and after a timeline
|
||
update. Responses should complete without a long pause or a location error.
|
||
2. Scroll the table away from its original viewport. Review should contain the
|
||
currently visible rows. Check another GTK table, its column headers, and a
|
||
horizontally scrolled table.
|
||
3. Check ordinary Up/Down selection speech, menus, preferences notebooks and
|
||
terminal flat review. Semantic browser navigation and table speech should
|
||
continue to work because their captures retain the complete semantic tree.
|
||
4. Confirm audible output and physical Braille separately. Private native tests
|
||
do not establish these outcomes or prove that the live FastSMRW timeout is
|
||
resolved. Preserve fresh logs if a failure remains; the object metadata will
|
||
identify where capture stopped. Inspect `flat review capture timing` to
|
||
compare the failed initial capture with a successful retry, including root
|
||
scope, queue wait, stage totals and the slowest object in each stage.
|