[linux] Read heading text through the AtkText interface (#188005)
Fixes #187925 ## Problem On Linux, a node with `Semantics(header: true)` is announced by Orca as just **"header"** — the node's text is never read. With `header: false` the same text is read correctly. ## Root cause Two issues in the Linux embedder's accessibility code (`engine/src/flutter/shell/platform/linux/`): 1. **The node's label is exposed only via the `AtkObject` name property, not the `AtkText` interface.** Orca reads the text content of a heading **exclusively through `AtkText`** (see `_generate_heading` in Orca's `speech_generator.py`, which calls `_generate_text_content` → `AXText.get_substring` → `atk_text_get_text`). It never falls back to the name for the heading/header roles. So Orca finds no text and announces only the role. This matches the ATK contract used by GTK: `GtkLabel` exposes its text through `AtkText`. Flutter's label **is** its text content, so it should be exposed the same way. (`FlAccessibleTextField` already does this for editable text.) 2. **The wrong ATK role.** `is_header` maps to `ATK_ROLE_HEADER`, which is the *document masthead/banner* role. `ATK_ROLE_HEADING` is the *content-heading* role (the HTML `<h1>`–`<h6>` analogue) and is what `Semantics(header: true)` means (matching iOS `header` trait and Android heading class). ## Fix * Implement the `AtkText` interface on `FlAccessibleNode`, backed by the node's existing accessibility name (`get_character_count`, `get_text`, `get_character_at_offset`, `get_caret_offset`, `get_n_selections`, `get_selection`, `get_text_at_offset`). This is safe for other roles: Orca's default presentation for buttons/panels/images reads the `AtkObject` name via `_generate_accessible_label_and_name`, not `AtkText`, so their announcement is unchanged. `FlAccessibleTextField` already declares a richer `AtkText` and continues to override the base implementation. * Map the `is_header` flag to `ATK_ROLE_HEADING`. ## Result For the repro in #187925, Orca now announces **"Section One, heading"** instead of just **"header"**. ## Test plan - [x] Added `ExposesTextViaAtkText` test verifying `atk_text_get_character_count` / `atk_text_get_text` / `atk_text_get_character_at_offset` return the node's label. - [x] Extended the existing role-mapping test to assert `is_header` → `ATK_ROLE_HEADING`. - [ ] `Linux linux_unit_tests` (cannot run locally — Linux GTK/ATK build; developed/analyzed on macOS). Reviewers, please confirm CI is green. --------- Co-authored-by: Robert Ancell <robert.ancell@canonical.com>
R
Ricardo Sawir committed
7c18a85ef91a50ac0a91ffc648ba0a1d22b8184a
Parent: 6807bd9
Committed by GitHub <noreply@github.com>
on 8/19/2026, 12:16:27 PM