)]}'
{
  "commit": "7c18a85ef91a50ac0a91ffc648ba0a1d22b8184a",
  "tree": "0bcd3a50849b4bf34e4b8adcab4f2bb521c90a2a",
  "parents": [
    "6807bd964a3b23561eb13b5fecf7c5eceb6e6f65"
  ],
  "author": {
    "name": "Ricardo Sawir",
    "email": "37329575+sawirricardo@users.noreply.github.com",
    "time": "Wed Aug 19 12:16:27 2026 +0000"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Wed Aug 19 12:16:27 2026 +0000"
  },
  "message": "[linux] Read heading text through the AtkText interface (#188005)\n\nFixes #187925\n\n## Problem\n\nOn Linux, a node with `Semantics(header: true)` is announced by Orca as\njust **\"header\"** — the node\u0027s text is never read. With `header: false`\nthe same text is read correctly.\n\n## Root cause\n\nTwo issues in the Linux embedder\u0027s accessibility code\n(`engine/src/flutter/shell/platform/linux/`):\n\n1. **The node\u0027s label is exposed only via the `AtkObject` name property,\nnot the `AtkText` interface.** Orca reads the text content of a heading\n**exclusively through `AtkText`** (see `_generate_heading` in Orca\u0027s\n`speech_generator.py`, which calls `_generate_text_content` →\n`AXText.get_substring` → `atk_text_get_text`). It never falls back to\nthe name for the heading/header roles. So Orca finds no text and\nannounces only the role.\n\nThis matches the ATK contract used by GTK: `GtkLabel` exposes its text\nthrough `AtkText`. Flutter\u0027s label **is** its text content, so it should\nbe exposed the same way. (`FlAccessibleTextField` already does this for\neditable text.)\n\n2. **The wrong ATK role.** `is_header` maps to `ATK_ROLE_HEADER`, which\nis the *document masthead/banner* role. `ATK_ROLE_HEADING` is the\n*content-heading* role (the HTML `\u003ch1\u003e`–`\u003ch6\u003e` analogue) and is what\n`Semantics(header: true)` means (matching iOS `header` trait and Android\nheading class).\n\n## Fix\n\n* Implement the `AtkText` interface on `FlAccessibleNode`, backed by the\nnode\u0027s existing accessibility name (`get_character_count`, `get_text`,\n`get_character_at_offset`, `get_caret_offset`, `get_n_selections`,\n`get_selection`, `get_text_at_offset`). This is safe for other roles:\nOrca\u0027s default presentation for buttons/panels/images reads the\n`AtkObject` name via `_generate_accessible_label_and_name`, not\n`AtkText`, so their announcement is unchanged. `FlAccessibleTextField`\nalready declares a richer `AtkText` and continues to override the base\nimplementation.\n* Map the `is_header` flag to `ATK_ROLE_HEADING`.\n\n## Result\n\nFor the repro in #187925, Orca now announces **\"Section One, heading\"**\ninstead of just **\"header\"**.\n\n## Test plan\n\n- [x] Added `ExposesTextViaAtkText` test verifying\n`atk_text_get_character_count` / `atk_text_get_text` /\n`atk_text_get_character_at_offset` return the node\u0027s label.\n- [x] Extended the existing role-mapping test to assert `is_header` →\n`ATK_ROLE_HEADING`.\n- [ ] `Linux linux_unit_tests` (cannot run locally — Linux GTK/ATK\nbuild; developed/analyzed on macOS). Reviewers, please confirm CI is\ngreen.\n\n---------\n\nCo-authored-by: Robert Ancell \u003crobert.ancell@canonical.com\u003e",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "bcd13ba074df4036d9ee3c5a859359d9dfa339e3",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/shell/platform/linux/fl_accessible_node.cc",
      "new_id": "52d86cef4447b890a6dc8002127ae5fff67fe4a5",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/shell/platform/linux/fl_accessible_node.cc"
    },
    {
      "type": "modify",
      "old_id": "7f25e0b9277ff0fb8fbed2bed7e6aade363a0d66",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/shell/platform/linux/fl_accessible_node_test.cc",
      "new_id": "3c2af7655fc974c4afc4d948fde071e77ec3e046",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/shell/platform/linux/fl_accessible_node_test.cc"
    }
  ]
}
