Some checks failed
makepad-table / model (push) Has been cancelled
makepad-table / widget (push) Has been cancelled
makepad-table / hygiene (push) Has been cancelled
PDF engine / engine (push) Has been cancelled
PDF engine / makepad-integration (push) Has been cancelled
PDF engine / fuzz (push) Has been cancelled
Payment domain, storage, platform and UI / isolated-payment-tests (push) Has been cancelled
Payment domain, storage, platform and UI / payment-ui-tests (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
email / gates (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (push) Has been cancelled
nigig-build (CAD) / supply-chain (push) Has been cancelled
nigig-build (CAD) / cad-module (push) Has been cancelled
nigig-build (CAD) / full-crate-check (push) Has been cancelled
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
nigig-map / test (push) Has been cancelled
sms / gates (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
304 lines
20 KiB
Markdown
304 lines
20 KiB
Markdown
# Doc workspace device verification (Android/iOS)
|
||
|
||
The doc workspace logic that can be verified without hardware already
|
||
is: the real-`Cx` runtime harness (`tests.rs` in this folder) covers
|
||
event routing, selection/caret math, cell ranges, clipboard semantics,
|
||
gesture arbitration, and multi-line layout against stub areas. What it
|
||
cannot prove is anything the platform owns: the soft keyboard, the
|
||
native clipboard action menu, touch-event delivery and hit
|
||
transformation, scroll handoff to the parent `ScrollYView`, and actual
|
||
pixels. THIS runbook is the last-remaining checklist — every section
|
||
maps to a behavior the milestones deliberately deferred to hardware:
|
||
|
||
- IME opening deferred to device verification (mobile Edit/Done
|
||
milestone).
|
||
- Clipboard menu placement and keyboard-shift deferred (mobile
|
||
clipboard menu milestone; `cx.keyboard_shift` is passed straight
|
||
through to the platform).
|
||
- ScrollYView parent handoff is the one unchecked roadmap box.
|
||
- Painting/clipping visual pass was scoped here by the legacy
|
||
perf-box retirement (draw logic is harness-covered; pixels are not).
|
||
|
||
Execute the sections in order against BOTH the CRDT workspace
|
||
(`CrdtDocWorkspace`, active) and the legacy `DocWorkspace` (fallback)
|
||
where a section says BOTH; otherwise the CRDT workspace is the target.
|
||
Record each row PASS/FAIL/notes in section 10.
|
||
|
||
## 0. Prerequisites — build to device
|
||
|
||
The Makepad fork pinned in `Cargo.lock` ships `tools/cargo_makepad`;
|
||
install once from the checkout (or from a fetched copy):
|
||
|
||
```
|
||
cargo install --path <makepad-checkout>/tools/cargo_makepad
|
||
```
|
||
|
||
Android (device on USB, adb visible):
|
||
|
||
```
|
||
cargo makepad android install-toolchain
|
||
cargo makepad android run -p nigig-build
|
||
```
|
||
|
||
iOS (Xcode + device; provisioning per the tool's notes):
|
||
|
||
```
|
||
cargo makepad apple list # certificates/profiles/devices
|
||
cargo makepad apple ios run-device -p nigig-build --org=<ORG> --app=<APP>
|
||
```
|
||
|
||
Flag reference lives in the tool itself (`cargo makepad --help`;
|
||
`--package-name`, `--app-label`, `--abi`, `--sdk-path` on Android;
|
||
`--profile`, `--cert`, `--device` on iOS). Logs: `adb logcat` on
|
||
Android, Xcode devices console on iOS — filter for the app process.
|
||
|
||
Before starting, open the document workspace and set some content: at
|
||
least two paragraphs, one 2x2 table with cell text `a | bc` / `d | e`,
|
||
one cell edited through an external plain-text editor to hold
|
||
`x<newline>y` (paste the two-line string into the cell through the
|
||
system clipboard — see section 6; it round-trips verbatim by design).
|
||
|
||
## 1. Interaction mode: View ↔ Edit
|
||
|
||
Code anchors: first real `TouchUpdate` flips `interaction_mode` to
|
||
View (`crdt_widget.rs`, the `mobile_mode_initialized` arm); the mobile
|
||
toolbar's AdaptiveView button (`edit_mode_btn` in both workspaces)
|
||
calls `toggle_interaction_mode` and relabels Edit ↔ Done
|
||
(`widgets/workspace.rs`).
|
||
|
||
| # | Action | Expected |
|
||
|---|--------|----------|
|
||
| 1.1 | Cold-launch on device, tap inside the document once | Keyboard does NOT open (first touch dropped the session to View; the tap parks a passive cursor) |
|
||
| 1.2 | Drag vertically right after 1.1 | The page scrolls (View skips the editor's area hits entirely) |
|
||
| 1.3 | Tap the toolbar Edit button | Button relabels Done; a subsequent tap in text opens the IME (keyboard shows, caret blinks at the tap char boundary) |
|
||
| 1.4 | Tap Done | Keyboard closes; taps are passive again |
|
||
|
||
Fail criteria: IME opens in View mode; Edit/Done desynchronizes from
|
||
the label; a tap in Edit does not open the keyboard (see section 2's
|
||
frame-driven reassert before calling it a bug).
|
||
|
||
## 2. IME opening and text input
|
||
|
||
Code anchors: taps in Edit call `cx.show_text_ime(self.draw_bg.area(),
|
||
abs)`; a frame-driven reassert mirrors the request on backends that
|
||
honor it only after the focus area has been drawn (mobile milestone
|
||
note in `crdt_widget.rs`).
|
||
|
||
| # | Action | Expected |
|
||
|---|--------|----------|
|
||
| 2.1 | Edit mode: tap mid-word in a paragraph, type | Characters insert at the caret; the caret tracks |
|
||
| 2.2 | Tap inside a table cell, type | Characters insert at the char under the pointer (midpoint split); no whole-cell stomping |
|
||
| 2.3 | While typing in a cell, accept an autocorrect/autocomplete suggestion | The committed text lands as the cell content, once (whole-cell write path consumes the commit; composing text should not stack) |
|
||
| 2.4 | Tap an empty cell and type | Text appears; undo once restores the empty cell |
|
||
| 2.5 | Type a long word that passes the cell's right edge | Text visually overflows the cell (known single-line behavior — multi-character overflow is drawn, not wrapped; NOT a failure, note only) |
|
||
|
||
Fail criteria: doubled commits, keyboard opening but input dropping,
|
||
caret/IME disagreement (the IME anchor is the caret rect + its height;
|
||
a misplaced suggestion popup usually means the anchor rect is off).
|
||
|
||
## 3. Long-press selection, handles, clipboard menu
|
||
|
||
Code anchors: the gesture router arms long-press at 24 frames and
|
||
hands control to `SelectWord` (`mobile_gesture.rs`,
|
||
`long_press_frames: 24`); handles come from
|
||
`compute_selection_handles`; the menu is requested through
|
||
`cx.show_clipboard_actions(has_selection, rect, cx.keyboard_shift)`
|
||
with `rect` = the selection's handle union (text) or the pressed
|
||
cell's rect (cell range), mirrored in `widget.clipboard_menu`.
|
||
|
||
| # | Action | Expected |
|
||
|---|--------|----------|
|
||
| 3.1 | Edit mode: press and hold on a word WITHOUT moving for ~0.5s | Word selects, handles appear at its edges, the native menu floats near the selection with Copy/Cut (and Paste if the system clipboard is non-empty) |
|
||
| 3.2 | Repeat 3.1 with the keyboard OPEN | The menu floats clear of the keyboard area (platform places it from `keyboard_shift`) |
|
||
| 3.3 | Drag the START handle onto another word; drag the END handle | Selection follows the fingers; menu does NOT re-open WHILE dragging (initiating matches TextInput cadence) |
|
||
| 3.6 | Lift the finger after a handle drag | The native menu re-floats, anchored on the NEW selection span (not the stale word rect), with Copy/Cut offered for the copyable span. Only in Edit mode; in View the drag still adjusts the highlight but no menu appears |
|
||
| 3.4 | Long-press on empty space between paragraphs | Nothing arms; no menu |
|
||
| 3.5 | Long-press inside a table cell (not on a handle) | The cell range arms on the pressed cell; dragging expands the range rectangle; the menu offers the full action set (a range copies tabular text, so has_selection = true) |
|
||
|
||
Fail criteria: long-press fires while the finger has moved (should
|
||
have routed to scroll, section 5); the menu appears under the keyboard
|
||
or at stale coordinates; handles select inverted (start/end swapped).
|
||
|
||
## 4. Table gestures: ranges, merge/split, in-cell editing
|
||
|
||
Code anchors: long-press cell → `start_cell_range`; drag with a live
|
||
range → `extend_cell_range_to` (the touch-only spanning path; the
|
||
router idles in Selecting while a range is active); Merge/Split
|
||
toolbar buttons → `merge_selected_cells` / `split_cell_at_cursor`.
|
||
|
||
| # | Action | Expected |
|
||
|---|--------|----------|
|
||
| 4.1 | Long-press a cell, drag diagonally across four cells, release | 2x2 range highlighted (per-cell bands; covered cells draw under the anchor when merged) |
|
||
| 4.2 | With the range armed, tap Merge | Cells merge; my content keeps in the anchor; Undo reverses it in one step |
|
||
| 4.3 | Tap into the merged cell, tap Split | The merge splits back to individual cells |
|
||
| 4.4 | Long-press a cell, drag past the table edge mid-gesture | Range clamps at the table bounds; no wrap to other rows/columns |
|
||
| 4.5 | Insert a second table (toolbar +Table), tap its top-left cell, and Paste the range copied in 3.5/4.1 | The rectangle distributes one cell per tab stop; caret parks at the last written cell; one undo restores the pasted cells |
|
||
|
||
Fail criteria: ranges extending after lift-off; merge/undo splitting
|
||
into many undo steps; paste redistributing shifted (quoting covered in
|
||
section 6).
|
||
|
||
## 5. Scroll handoff to the parent ScrollYView — the open roadmap box
|
||
|
||
Code anchors: router `PendingLongPress` + move > 10 px before the
|
||
24-frame arm → `PassToScroll` and the drag is never claimed; in View
|
||
mode the area-hit match is skipped outright. Both workspaces embed the
|
||
editor in a `ScrollYView` (`crdt_body` for CRDT, `body_scroll` for
|
||
legacy `DocWorkspace`). Run BOTH editors through this section — the
|
||
legacy box on the roadmap names exactly this handoff.
|
||
|
||
| # | Action | Expected |
|
||
|---|--------|----------|
|
||
| 5.1 | CRDT workspace, View mode: drag up/down inside the document area | The page pans; no selection arms, no caret moves |
|
||
| 5.2 | CRDT workspace, Edit mode: quick vertical drag over text | Same: the gesture routes to the scroll view BEFORE long-press arms (10 px / 24 frames), so the page pans and no selection appears |
|
||
| 5.3 | Edit mode: long-press a word (selection arms), lift, then drag vertically | With no handle touched, a fresh drag still scrolls; the existing selection stays |
|
||
| 5.4 | Long-press a word, keep the finger down and drag WITHOUT lifting | Selection-adjust path: the selection follows the finger instead of scrolling (Selecting state owns the drag) |
|
||
| 5.5 | Legacy DocWorkspace: repeat 5.1–5.4 | Identical behavior (shared router + legacy hit-skip path) |
|
||
| 5.6 | Scroll to the document's end and keep dragging | Rubber-band/stop at content end per platform convention — no stuck gestures after release |
|
||
|
||
Fail criteria: a quick flick selects text instead of scrolling; a
|
||
long-press drag scrolls the page while adjusting the selection; the
|
||
scroll position jumps when the keyboard opens/closes. ANY failure here
|
||
closes the roadmap box as FAILED — file it, don't check it.
|
||
|
||
## 6. Clipboard round-trips through the system clipboard
|
||
|
||
Code anchors: range/copy payloads via `table_grid_tsv`, quoting via
|
||
`quote_tabular_field`/`split_tabular_payload` (RFC-4180-style),
|
||
document-level payloads splice table grids at block position.
|
||
|
||
Prerequisite for 6.2: use an external app to prepare two forms of the
|
||
same content — the RAW two-line string `x` newline `y`, and the QUOTED
|
||
form `"x` newline `y"` (exactly what spreadsheet apps emit when copying
|
||
a single cell that contains a newline; a desktop text editor plus a
|
||
shared note is the easiest path).
|
||
|
||
| # | Action | Expected |
|
||
|---|--------|----------|
|
||
| 6.1 | Copy a 2x2 range from the doc table, paste into the external notes app | Rows/columns appear as tab/newline text, cells in reading order |
|
||
| 6.2 | Paste the RAW `x\ny` into a cell | It distributes across TWO ROWS (one line per row — the spreadsheet convention for raw text). Then paste the QUOTED form `"x\ny"` into a cell: it lands as ONE cell holding both lines verbatim (the tokenizer honors quoted fields). Finally copy a range INCLUDING that multi-line cell → paste it elsewhere: the value round-trips as one two-line cell (our payload quoted it on copy) |
|
||
| 6.3 | Select-all in the document, Copy, paste into the notes app | Paragraph text lines with the table's grid spliced in at the table's position |
|
||
| 6.4 | Cut the full selection, verify document empties, undo once | Blocks AND every cell value restore (range tombstones + grouped cell writes) |
|
||
|
||
Fail criteria: tab/newline/quote characters mangled in either
|
||
direction (round-trip must be verbatim once the payload is ours);
|
||
external apps receiving nothing (the TextCopy hit must answer with
|
||
`copyable_selection_text()`).
|
||
|
||
## 7. Multi-line cell rendering (visual)
|
||
|
||
Code anchors: rows grow 18 px per extra display line over the 28 px
|
||
baseline (`layout_projected_table`); runs draw split at `\n`
|
||
vertically centered.
|
||
|
||
| # | Action | Expected |
|
||
|---|--------|----------|
|
||
| 7.1 | After 6.2, look at the cell holding `x\ny` | Two stacked lines inside one taller row; borders outline the grown row; the document below reflows down |
|
||
| 7.2 | Tap the second line's text | The caret parks on the tapped line/char (not the first line) |
|
||
| 7.3 | ArrowDown/ArrowUp on a hardware or virtual keyboard inside that cell | Caret steps between the two lines keeping its column; inert at first/last line |
|
||
| 7.4 | Merge a grown row's cell with a plain row's cell; split it back | Anchor spans the summed heights; split restores both rows' geometries |
|
||
|
||
Fail criteria: lines clipped by the row bottom; caret drawn on the
|
||
wrong band; the row below overlapping the grown row.
|
||
|
||
## 8. Visual painting/clipping sweep (draw-pass scope)
|
||
|
||
No automation exists — this is the GPU-bound residual. Sweep and
|
||
eyeball; photograph failures.
|
||
|
||
| # | What to look at | Expected |
|
||
|---|-----------------|----------|
|
||
| 8.1 | Selection overlay on text and on cell ranges | Blue tint stays inside glyph/line bands and cell rects; no bleed into neighbors or across page margins |
|
||
| 8.2 | Table borders, including merged regions | 1 px grid outlines; merged anchor outlines the whole span; no double borders inside a merge |
|
||
| 8.3 | Caret | Blue 2 px bar on the correct band (single- and multi-line cells), never floating outside its cell |
|
||
| 8.4 | Selection handles after a long-press | Both handles at selection edges, above content, trigger drag on touch with the 6 px slop |
|
||
| 8.5 | Advanced placeholders (image/divider nodes) | Fills/borders/labels drawn once per node; divider is one centered line |
|
||
| 8.6 | Rapid typing for 30 seconds in a ~200-line document | Frame pacing stays smooth; no visible full-document flicker between keystrokes (layout cache: unchanged content redraws from the cached tree; this is the perf smoke check) |
|
||
|
||
## 9. Boot content and persistence round trip
|
||
|
||
Since the Android empty-doc fix, saves live in the platform app-data
|
||
store (`app_data_dir()/nigig_build_store/generated/current.doc.json`)
|
||
— NOT the source tree (dev checkouts get a one-way read fallback for
|
||
old saves; new writes never go there). Boot emits `[DOC_TRACE] CRDT
|
||
init:` lines in logcat naming the branch that fired.
|
||
|
||
| # | Action | Expected |
|
||
|---|--------|----------|
|
||
| 9.0 | Fresh install, first launch (no save on device) | Demo document renders: bold title, styled paragraphs, divider, image placeholder, 4x3 table (bold header), closing hint. logcat: `CRDT init: no saved document; seeding demo document` |
|
||
| 9.1 | Edit, force-close, relaunch | Document restores (platform save/load path); table contents AND cell text intact. logcat: `CRDT init: loading saved document (N bytes)` |
|
||
| 9.2 | Open a previously saved file with a table | Grid renders; merges present; no phantom rows/cols |
|
||
| 9.3 | Boot the CRDT workspace with a CLASSIC-format save present | Demo document seeds (classic saves are not shadowed); logcat notes the classic-format branch. The legacy workspace still opens the classic file on Open. FAIL criteria: blank page, or the classic file silently dropped |
|
||
|
||
## 10. Sign-off
|
||
|
||
Device / OS / build: Galaxy A60 (SM-A6060, `R28M52LJP2Y`) · Android ·
|
||
`pageflipnav` release APK, driven by the `doc_*` tests in
|
||
`crates/pageflipnav/tests/ui.rs`. All 14 tests PASS on device (8
|
||
nav/state + 6 content-operation: `doc_type_text_inserts_document`,
|
||
`doc_bold_italic_underline_ops`, `doc_insert_table_and_cell_text`,
|
||
`doc_merge_split_cell_ops`, `doc_long_press_empty_space_does_not_arm`,
|
||
`doc_diagonal_cell_range_merges`, plus `doc_diag_*` used to pin geometry).
|
||
|
||
Verified devices: Galaxy A60 (SM-A6060, `R28M52LJP2Y`, 411 dp) and Galaxy
|
||
A16 (SM-A165F, `RF8Y103NERA`, 384 dp). One A60 full-suite run had 3
|
||
`adb: device not found` USB drops (test-infra flakes, not logic); all 3
|
||
reran clean on the A16.
|
||
|
||
Coverage legend: **A** = automated (ran green on device),
|
||
**A⚠** = automated but only proves a subset, **M** = manual-only (cannot
|
||
be driven by `makepad_test` — reason in the Note column).
|
||
|
||
| # | Row | Result | Test / Note |
|
||
|---|-----|--------|-------------|
|
||
| 1.1 | Cold-launch tap → no keyboard | A | `doc_view_mode_scroll_by_touch` (View cold-release path); first tap never opens IME |
|
||
| 1.2 | Vertical drag → page scrolls | A | `doc_view_mode_scroll_by_touch` |
|
||
| 1.3 | Edit button relabels Done; tap opens IME | A | `doc_interaction_mode_view_and_edit`, `doc_ime_text_input_in_edit_mode` |
|
||
| 1.4 | Done closes keyboard | A⚠ | `doc_interaction_mode_view_and_edit` relabels back to Edit; keyboard visibility itself is not snapshot-observable, so "closes" is inferred from the Edit state + subsequent passive taps |
|
||
| 2.1 | Edit: tap mid-word, type | A | `doc_type_text_inserts_document` (stats `2 words | 11 chars`) |
|
||
| 2.2 | Tap in a cell, type | A | `doc_insert_table_and_cell_text` (cell "alpha beta" joins stats → `4 words | 21 chars`) |
|
||
| 2.3 | Accept autocorrect suggestion | M | `makepad_test` cannot press the OS keyboard's suggestion bar; needs a human tap |
|
||
| 2.4 | Type in empty cell, undo once | A⚠ | Undo not asserted on device; covered by `doc-ui` unit `runtime_cell_backspace_edits_cell_and_ctrl_z_restores_it` |
|
||
| 2.5 | Long word overflows cell | M | Visual single-line overflow check — note only, eyeball |
|
||
| 3.1 | Long-press word → word selects | A⚠ | `doc_long_press_arms_selection` proves the arm runs and the doc stays alive; handle/menu pixels are visual |
|
||
| 3.2 | Long-press with keyboard open | M | Cannot open/clamp the OS keyboard from the harness |
|
||
| 3.3 | Drag start/end handle | M | Handle hit-testing + native menu placement need visual confirmation |
|
||
| 3.4 | Long-press empty space → nothing arms | A | `doc_long_press_empty_space_does_not_arm` |
|
||
| 3.5 | Long-press cell → cell range arms | A | arming used by `doc_merge_split_cell_ops` (drag spans col1) |
|
||
| 3.6 | Menu re-floats after handle drag | M | Native menu is OS-owned, not a snapshot-able widget |
|
||
| 4.1 | Diagonal 2x2 range + highlight | A | `doc_diagonal_cell_range_merges` |
|
||
| 4.2 | Merge; undo in one step | A | `doc_merge_split_cell_ops` (merge); undo is unit-covered |
|
||
| 4.3 | Split merged cell | A | `doc_merge_split_cell_ops` (`Split merged cell`) |
|
||
| 4.4 | Drag past table edge clamps | A⚠ | Merge path proves the range stays in-col; out-of-table clamp is unit-covered |
|
||
| 4.5 | Paste range into second table | M | Requires system clipboard content + external app (section 6) |
|
||
| 5.1 | View drag → pans | A | `doc_view_mode_scroll_by_touch` |
|
||
| 5.2 | Edit quick drag → pans, no selection | A | `doc_scroll_handoff_view_and_edit` |
|
||
| 5.3 | Selection armed, lift, then drag scrolls | M | Requires a held selection + OS interactions not snapshot-able; unit/gesture-covered in `doc-ui` |
|
||
| 5.4 | Hold after long-press → selection tracks | M | Gesture requires frame-true finger sequencing only partially reproducible; covered by `doc-ui` `runtime_*` gesture tests |
|
||
| 5.5 | Legacy DocWorkspace 5.1–5.4 | M | Legacy workspace untested; blocked by in-progress user work (`nigig-build`, `xls_import`) |
|
||
| 5.6 | End-of-content rubber-band | M | Platform convention, visual |
|
||
| 6.1–6.4 | Clipboard round-trips | M | Needs `adb` clipboard + an external notes app to paste INTO — no harness API for system clipboard reads/veto |
|
||
| 7.1–7.4 | Multi-line cell rendering | M | Visual inspection of row growth / caret bands / overlap |
|
||
| 8.1–8.6 | Visual paint/clip sweep | M | GPU painting — eyeball, photograph failures |
|
||
| 9.0 | Fresh install demo doc | M | Needs app data wipe (reinstall) between launches; harness can't reset app-data |
|
||
| 9.1 | Force-close + relaunch restores | M | Harness cannot kill/relaunch the process to exercise the load path |
|
||
| 9.2 | Open saved file with table | M | Same process-restart limitation |
|
||
| 9.3 | Classic-format save fallback | M | Needs a pre-written classic save on the device + relaunch; unit-covered elsewhere |
|
||
|
||
Two real mobile-only bugs were found and fixed by these device runs
|
||
(unit-testable parts covered in `doc-ui/src/tests.rs`):
|
||
1. The CRDT/legacy toolbars overflowed the ~411 dp phone screen,
|
||
clipping Italic and pushing Underline/Table/Merge/Split off-screen —
|
||
the toolbars now wrap (`flow: Right {wrap: true}` in `doc-ui/src/lib.rs`).
|
||
2. `insert_table` produced a zero-size, un-typeable table — it now seeds a
|
||
2x2 grid and parks the caret in the top-left cell (`crdt_widget.rs`,
|
||
covered by `runtime_insert_table_seeds_default_grid_and_parks_caret_in_first_cell`).
|
||
|
||
Closing notes:
|
||
- The roadmap's ScrollYView handoff box (section 5) is NOT closed: most
|
||
of section 5 and the entire legacy `DocWorkspace` column remain manual
|
||
(5.3, 5.4, 5.5, 5.6).
|
||
- Rows still open: 2.3, 2.5, 3.1 (pixels), 3.2, 3.3, 3.5/3.6 (menu),
|
||
4.4 (pixels), 4.5, 5.3–5.6 (legacy + gestures), 6 (clipboard), 7
|
||
(visual), 8 (visual), 9 (process-restart). Most are genuinely not
|
||
automatable through `makepad_test`; the reasons are in the table.
|