-
Notifications
You must be signed in to change notification settings - Fork 6k
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
[web] switch from .didGain/LoseAccessibilityFocus to .focus #53134
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -81,9 +81,6 @@ typedef _FocusTarget = ({ | |
|
||
/// The listener for the "focus" DOM event. | ||
DomEventListener domFocusListener, | ||
|
||
/// The listener for the "blur" DOM event. | ||
DomEventListener domBlurListener, | ||
}); | ||
|
||
/// Implements accessibility focus management for arbitrary elements. | ||
|
@@ -135,7 +132,6 @@ class AccessibilityFocusManager { | |
semanticsNodeId: semanticsNodeId, | ||
element: previousTarget.element, | ||
domFocusListener: previousTarget.domFocusListener, | ||
domBlurListener: previousTarget.domBlurListener, | ||
); | ||
return; | ||
} | ||
|
@@ -148,14 +144,12 @@ class AccessibilityFocusManager { | |
final _FocusTarget newTarget = ( | ||
semanticsNodeId: semanticsNodeId, | ||
element: element, | ||
domFocusListener: createDomEventListener((_) => _setFocusFromDom(true)), | ||
domBlurListener: createDomEventListener((_) => _setFocusFromDom(false)), | ||
domFocusListener: createDomEventListener((_) => _didReceiveDomFocus()), | ||
); | ||
_target = newTarget; | ||
|
||
element.tabIndex = 0; | ||
element.addEventListener('focus', newTarget.domFocusListener); | ||
element.addEventListener('blur', newTarget.domBlurListener); | ||
} | ||
|
||
/// Stops managing the focus of the current element, if any. | ||
|
@@ -170,10 +164,9 @@ class AccessibilityFocusManager { | |
} | ||
|
||
target.element.removeEventListener('focus', target.domFocusListener); | ||
target.element.removeEventListener('blur', target.domBlurListener); | ||
} | ||
|
||
void _setFocusFromDom(bool acquireFocus) { | ||
void _didReceiveDomFocus() { | ||
final _FocusTarget? target = _target; | ||
|
||
if (target == null) { | ||
|
@@ -184,9 +177,7 @@ class AccessibilityFocusManager { | |
|
||
EnginePlatformDispatcher.instance.invokeOnSemanticsAction( | ||
target.semanticsNodeId, | ||
acquireFocus | ||
? ui.SemanticsAction.didGainAccessibilityFocus | ||
: ui.SemanticsAction.didLoseAccessibilityFocus, | ||
ui.SemanticsAction.focus, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't we also want to send a11yfocus as well? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would be a wrong thing to do. On the web, accessibility focus is not observable through any platform API. If the accessibility focus is indeed detached from the input focus, sending There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
but on the web they are not detached, right? or at least we can't tell whether something receives only the a11y focus. but when something receives focus, it must also have received a11y focus? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They can be detached on the web too. For example, you can uncheck the following checkbox in macOS VoiceOver utility: With that checkbox off, you can move the accessibility focus around without moving the input focus. Here's an example of VoiceOver focus being on a text field inside the web page, but when typing your input goes into the address bar instead: Here's another example, where the a11y focus is on the last name field, but I'm entering the first name field: You need to take special action to activate the widget under VoiceOver cursor, e.g. Control + Option + Space. However, there's no listeners we can hook up on the web page to tell where the VoiceOver cursor is headed. So it's not observable to us. That's not a real problem though. The browser already does whatever it needs and determines when input focus should move into the field, and send us a DOM "focus" event. The web engine will simply forward it to the framework as I must say, this detached mode feels confusing to me. I think when both kinds of focus are synchronized, it's easier to use the UI. VoiceOver itself seems to be giving incorrect instructions. For example, when you move focus to a text field, it says "To enter text in this field, type", which is incorrect in this mode as the text field does not yet have focus. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, so the web just not going to use a11y focus. Now I think of it this is probably correct since native web can't tell which dom has the a11y focus either. |
||
null, | ||
); | ||
} | ||
|
@@ -229,7 +220,7 @@ class AccessibilityFocusManager { | |
// a dialog, and nothing else in the dialog is focused. The Flutter | ||
// framework expects that the screen reader will focus on the first (in | ||
// traversal order) focusable element inside the dialog and send a | ||
// didGainAccessibilityFocus action. Screen readers on the web do not do | ||
// SemanticsAction.focus action. Screen readers on the web do not do | ||
// that, and so the web engine has to implement this behavior directly. So | ||
// the dialog will look for a focusable element and request focus on it, | ||
// but now there may be a race between this method unsetting the focus and | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😣