7.1 KiB
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:
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:
- 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.
- 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.
- 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.
- 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 timingto compare the failed initial capture with a successful retry, including root scope, queue wait, stage totals and the slowest object in each stage.