Skip to content

Fix byte/character offset confusion in FlAccessibleTextField#188138

Merged
robert-ancell merged 4 commits into
flutter:masterfrom
robert-ancell:fix-accessible-text-field-utf8-offsets
Jun 23, 2026
Merged

Fix byte/character offset confusion in FlAccessibleTextField#188138
robert-ancell merged 4 commits into
flutter:masterfrom
robert-ancell:fix-accessible-text-field-utf8-offsets

Conversation

@robert-ancell

Copy link
Copy Markdown
Contributor

get_line_at_offset and get_paragraph_at_offset used PangoLayoutLine start_index and length (byte offsets) directly as character offsets. They were compared against the ATK character offset, reported back as character offsets, and passed to get_substring (which uses g_utf8_substring, expecting character offsets).

For ASCII text byte and character offsets coincide, but for multi-byte UTF-8 text they diverge, producing incorrect substrings and offsets.

Convert byte indices to character offsets with g_utf8_pointer_to_offset before comparing, reporting, or substringing.

Add TextBoundaryMultiByte test covering line and paragraph boundaries on text containing multi-byte UTF-8 characters.

get_line_at_offset and get_paragraph_at_offset used PangoLayoutLine
start_index and length (byte offsets) directly as character offsets.
They were compared against the ATK character offset, reported back as
character offsets, and passed to get_substring (which uses
g_utf8_substring, expecting character offsets).

For ASCII text byte and character offsets coincide, but for multi-byte
UTF-8 text they diverge, producing incorrect substrings and offsets.

Convert byte indices to character offsets with g_utf8_pointer_to_offset
before comparing, reporting, or substringing.

Add TextBoundaryMultiByte test covering line and paragraph boundaries
on text containing multi-byte UTF-8 characters.
@robert-ancell robert-ancell requested a review from a team as a code owner June 17, 2026 23:59
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 17, 2026
@github-actions github-actions Bot added a: text input Entering text in a text field or keyboard related problems engine flutter/engine related. See also e: labels. platform-linux Building on or for Linux specifically a: desktop Running on desktop team-linux Owned by the Linux platform team labels Jun 18, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates FlAccessibleTextField to compute line and paragraph boundaries using character offsets instead of byte offsets to correctly handle multi-byte UTF-8 characters, and adds a test case for this behavior. The review feedback suggests optimizing the performance of these computations by converting the input character offset to a byte offset once at the start of the functions, avoiding repeated $O(N)$ UTF-8 string traversals inside the loops.

Comment thread engine/src/flutter/shell/platform/linux/fl_accessible_text_field.cc
Comment thread engine/src/flutter/shell/platform/linux/fl_accessible_text_field.cc
Comment thread engine/src/flutter/shell/platform/linux/fl_accessible_text_field.cc
mattkae
mattkae previously approved these changes Jun 18, 2026

@mattkae mattkae left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks to be an improvement overall! Just have a suggestion

gint line_start = g_utf8_pointer_to_offset(text, text + line->start_index);
gint line_end =
g_utf8_pointer_to_offset(text, text + line->start_index + line->length);
if (offset >= line_start && offset <= line_end) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a comment explaining how we'd get here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments on the functions. The functions are still pretty complex but hopefully this helps.

Iterate the Pango layout lines with a for loop instead of a while loop,
keeping the list iterator scoped to the loop. No functional change.
Add comments describing what each function returns, including the
start and end character offsets and how lines and paragraphs are
delimited.
mattkae
mattkae previously approved these changes Jun 22, 2026

@mattkae mattkae left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am happy!

@robert-ancell robert-ancell enabled auto-merge June 22, 2026 22:40
@robert-ancell robert-ancell added this pull request to the merge queue Jun 23, 2026
Merged via the queue into flutter:master with commit 2594d16 Jun 23, 2026
201 of 202 checks passed
@robert-ancell robert-ancell deleted the fix-accessible-text-field-utf8-offsets branch June 23, 2026 01:32
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Jun 23, 2026
flutter/flutter@e228771...87224e0

2026-06-23 engine-flutter-autoroll@skia.org Roll Dart SDK from 5cae7f9ada62 to 3a66ea7b9aaa (1 revision) (flutter/flutter#188379)
2026-06-23 engine-flutter-autoroll@skia.org Roll Dart SDK from 1e6c246bb73a to 5cae7f9ada62 (2 revisions) (flutter/flutter#188370)
2026-06-23 engine-flutter-autoroll@skia.org Roll Skia from 766f21ae61dc to ffac3e91fbc7 (24 revisions) (flutter/flutter#188366)
2026-06-23 737941+loic-sharma@users.noreply.github.com [Windows] Add public API to post task to platform thread (flutter/flutter#187365)
2026-06-23 engine-flutter-autoroll@skia.org Roll Dart SDK from 7ab0179ce4d4 to 1e6c246bb73a (1 revision) (flutter/flutter#188354)
2026-06-23 robert.ancell@canonical.com Fix byte/character offset confusion in FlAccessibleTextField (flutter/flutter#188138)
2026-06-22 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from Lm76V7lvxVA0r1De5... to RymJjIj7dd5vQ3Cnh... (flutter/flutter#188353)
2026-06-22 137456488+flutter-pub-roller-bot@users.noreply.github.com Roll pub packages (flutter/flutter#188355)
2026-06-22 154381524+flutteractionsbot@users.noreply.github.com Sync CHANGELOG.md from stable (flutter/flutter#188331)
2026-06-22 engine-flutter-autoroll@skia.org Roll Skia from 5fbb9bbd889c to 766f21ae61dc (2 revisions) (flutter/flutter#188184)
2026-06-22 49699333+dependabot[bot]@users.noreply.github.com Bump actions/checkout from 6.0.3 to 7.0.0 in the all-github-actions group (flutter/flutter#188350)
2026-06-22 robert.ancell@canonical.com Use g_signal_connect_object in the Linux embedder (flutter/flutter#188241)
2026-06-22 robert.ancell@canonical.com Disconnect from parent window signal when view is destroyed (flutter/flutter#185521)
2026-06-22 rmacnak@google.com Remove many absolute paths from build commands. (flutter/flutter#187765)
2026-06-22 haiderqadir.hq@gmail.com Fix spelling mistake in documentation (wether → whether) (flutter/flutter#186141)
2026-06-22 engine-flutter-autoroll@skia.org Roll Dart SDK from a748c4b15399 to 7ab0179ce4d4 (2 revisions) (flutter/flutter#188332)
2026-06-22 robert.ancell@canonical.com [Linux] Move compositor shader into its own GObject (flutter/flutter#188144)
2026-06-22 bkonyi@google.com Add agent skills for orchestrating cherry-picks to stable and beta channels (flutter/flutter#187860)
2026-06-22 engine-flutter-autoroll@skia.org Roll Packages from c516c92 to cd5194a (1 revision) (flutter/flutter#188312)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
via-guy pushed a commit to via-guy/flutter that referenced this pull request Jun 26, 2026
…#188138)

get_line_at_offset and get_paragraph_at_offset used PangoLayoutLine
start_index and length (byte offsets) directly as character offsets.
They were compared against the ATK character offset, reported back as
character offsets, and passed to get_substring (which uses
g_utf8_substring, expecting character offsets).

For ASCII text byte and character offsets coincide, but for multi-byte
UTF-8 text they diverge, producing incorrect substrings and offsets.

Convert byte indices to character offsets with g_utf8_pointer_to_offset
before comparing, reporting, or substringing.

Add TextBoundaryMultiByte test covering line and paragraph boundaries on
text containing multi-byte UTF-8 characters.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: desktop Running on desktop a: text input Entering text in a text field or keyboard related problems CICD Run CI/CD engine flutter/engine related. See also e: labels. platform-linux Building on or for Linux specifically team-linux Owned by the Linux platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants