Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add SemanticsAction.focus #53094

Merged
merged 7 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions lib/ui/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ class SemanticsAction {
/// The accessibility focus is different from the input focus. The input focus
/// is usually held by the element that currently responds to keyboard inputs.
/// Accessibility focus and input focus can be held by two different nodes!
///
/// See also:
///
/// * [focus], which controls the input focus.
static const SemanticsAction didGainAccessibilityFocus = SemanticsAction._(_kDidGainAccessibilityFocusIndex, 'didGainAccessibilityFocus');

/// Indicates that the node has lost accessibility focus.
Expand Down Expand Up @@ -203,6 +207,48 @@ class SemanticsAction {
/// movement should extend (or start) a selection.
static const SemanticsAction moveCursorBackwardByWord = SemanticsAction._(_kMoveCursorBackwardByWordIndex, 'moveCursorBackwardByWord');

/// Move the input focus to the respective widget.
///
/// Most commonly, the input focus determines what widget will receive
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Most commonly, the input focus determines what widget will receive
/// Most commonly, the input focus determines which widget will receive

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops! I slapped on the autosubmit label without realizing that my git push failed 🤦 I'll send the doc fix in a separate PR.

/// keyboard input. Semantics nodes that can receive this action are expected
/// to have [SemanticsFlag.isFocusable] set. Examples of such focusable
/// widgets include buttons, checkboxes, switches, and text fields.
///
/// Upon receiving this action, the corresponding widget must move input focus
/// to itself. Doing otherwise is likely to lead to a poor user experience,
/// such as user input routed to a wrong widget. Text fields in particular,
/// must immediately become editable, opening a virtual keyboard, if needed.
/// Buttons must respond to tap/click events from the keyboard.
///
/// Focus behavior is specific to the platform and to the assistive technology
/// used. Typically on desktop operating systems, such as Windows, macOS, and
/// Linux, moving accessibility focus will also move the input focus. On
/// mobile it is more common for the accessibility focus to be detached from
/// the input focus. In order to synchronize the two, a user takes an explicit
/// action (e.g. double-tap to activate). Sometimes this behavior is
/// configurable. For example, VoiceOver on macOS can be configured in the
/// global OS user settings to either move the input focus together with the
/// VoiceOver focus, or to keep the two detached. For this reason, widgets
/// should not expect to receive [didGainAccessibilityFocus] and [focus]
/// actions to be reported in any particular combination or order.
///
/// On the web, the DOM "focus" event is equivalent to
/// [SemanticsAction.focus]. Accessibility focus is not observable from within
/// the browser. Instead, the browser, based on the platform features and user
/// preferences, makes the determination on whether input focus should be
/// moved to an element and, if so, fires a DOM "focus" event. This event is
/// forwarded to the framework as [SemanticsAction.focus]. For this reason, on
/// the web, the engine never sends [didGainAccessibilityFocus].
///
/// On Android input focus is observable as `AccessibilityAction#ACTION_FOCUS`
/// and is separate from accessibility focus, which is observed as
/// `AccessibilityAction#ACTION_ACCESSIBILITY_FOCUS`.
///
/// See also:
///
/// * [didGainAccessibilityFocus], which informs the framework about
/// accessibility focus ring, such as the TalkBack (Android) and
/// VoiceOver (iOS), moving which does not move the input focus.
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have an issue to migrate desktop embedding to respect the system settings whether to sync focus and a11y focus?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess flutter/flutter#83809 does technically cover it. However, I think we can split out platform-specific issues so they can be addressed one by one by the relevant teams. I'll do the web part.

static const SemanticsAction focus = SemanticsAction._(_kFocusIndex, 'focus');

/// The possible semantics actions.
Expand Down
2 changes: 1 addition & 1 deletion shell/platform/embedder/embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ typedef enum {
kFlutterSemanticsActionMoveCursorBackwardByWord = 1 << 20,
/// Replace the current text in the text field.
kFlutterSemanticsActionSetText = 1 << 21,
/// Request that the respective focusable widget gain keyboard input focus.
/// Request that the respective focusable widget gain input focus.
kFlutterSemanticsActionFocus = 1 << 22,
} FlutterSemanticsAction;

Expand Down