Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -2720,6 +2720,7 @@ ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/focusable.dart + ..
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/image.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/incrementable.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/label_and_value.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/link.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/live_region.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/platform_view.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/scrollable.dart + ../../../flutter/LICENSE
Expand Down Expand Up @@ -5496,6 +5497,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/focusable.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/image.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/incrementable.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/label_and_value.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/link.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/live_region.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/platform_view.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/scrollable.dart
Expand Down
1 change: 1 addition & 0 deletions lib/web_ui/lib/src/engine.dart
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ export 'engine/semantics/focusable.dart';
export 'engine/semantics/image.dart';
export 'engine/semantics/incrementable.dart';
export 'engine/semantics/label_and_value.dart';
export 'engine/semantics/link.dart';
export 'engine/semantics/live_region.dart';
export 'engine/semantics/platform_view.dart';
export 'engine/semantics/scrollable.dart';
Expand Down
1 change: 1 addition & 0 deletions lib/web_ui/lib/src/engine/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export 'semantics/focusable.dart';
export 'semantics/image.dart';
export 'semantics/incrementable.dart';
export 'semantics/label_and_value.dart';
export 'semantics/link.dart';
export 'semantics/live_region.dart';
export 'semantics/platform_view.dart';
export 'semantics/scrollable.dart';
Expand Down
19 changes: 8 additions & 11 deletions lib/web_ui/lib/src/engine/semantics/checkable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

import 'package:ui/ui.dart' as ui;

import '../dom.dart';
import 'semantics.dart';

/// The specific type of checkable control.
Expand Down Expand Up @@ -63,18 +62,18 @@ class Checkable extends PrimaryRoleManager {
if (semanticsObject.isFlagsDirty) {
switch (_kind) {
case _CheckableKind.checkbox:
semanticsObject.setAriaRole('checkbox');
setAriaRole('checkbox');
case _CheckableKind.radio:
semanticsObject.setAriaRole('radio');
setAriaRole('radio');
case _CheckableKind.toggle:
semanticsObject.setAriaRole('switch');
setAriaRole('switch');
}

/// Adding disabled and aria-disabled attribute to notify the assistive
/// technologies of disabled elements.
_updateDisabledAttribute();

semanticsObject.element.setAttribute(
setAttribute(
'aria-checked',
(semanticsObject.hasFlag(ui.SemanticsFlag.isChecked) ||
semanticsObject.hasFlag(ui.SemanticsFlag.isToggled))
Expand All @@ -92,17 +91,15 @@ class Checkable extends PrimaryRoleManager {

void _updateDisabledAttribute() {
if (semanticsObject.enabledState() == EnabledState.disabled) {
final DomElement element = semanticsObject.element;
element
..setAttribute('aria-disabled', 'true')
..setAttribute('disabled', 'true');
setAttribute('aria-disabled', 'true');
setAttribute('disabled', 'true');
} else {
_removeDisabledAttribute();
}
}

void _removeDisabledAttribute() {
final DomElement element = semanticsObject.element;
element..removeAttribute('aria-disabled')..removeAttribute('disabled');
removeAttribute('aria-disabled');
removeAttribute('disabled');
}
}
13 changes: 8 additions & 5 deletions lib/web_ui/lib/src/engine/semantics/dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ class Dialog extends PrimaryRoleManager {
}
return true;
}());
semanticsObject.element.setAttribute('aria-label', label ?? '');
semanticsObject.setAriaRole('dialog');
setAttribute('aria-label', label ?? '');
setAriaRole('dialog');
}
}

Expand All @@ -51,8 +51,8 @@ class Dialog extends PrimaryRoleManager {
return;
}

semanticsObject.setAriaRole('dialog');
semanticsObject.element.setAttribute(
setAriaRole('dialog');
setAttribute(
'aria-describedby',
routeName.semanticsObject.element.id,
);
Expand All @@ -61,7 +61,10 @@ class Dialog extends PrimaryRoleManager {

/// Supplies a description for the nearest ancestor [Dialog].
class RouteName extends RoleManager {
RouteName(SemanticsObject semanticsObject) : super(Role.routeName, semanticsObject);
RouteName(
SemanticsObject semanticsObject,
PrimaryRoleManager owner,
) : super(Role.routeName, semanticsObject, owner);

Dialog? _dialog;

Expand Down
6 changes: 3 additions & 3 deletions lib/web_ui/lib/src/engine/semantics/focusable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ import 'semantics.dart';
///
/// * https://developer.mozilla.org/en-US/docs/Web/Accessibility/Keyboard-navigable_JavaScript_widgets
class Focusable extends RoleManager {
Focusable(SemanticsObject semanticsObject)
Focusable(SemanticsObject semanticsObject, PrimaryRoleManager owner)
: _focusManager = AccessibilityFocusManager(semanticsObject.owner),
super(Role.focusable, semanticsObject);
super(Role.focusable, semanticsObject, owner);

final AccessibilityFocusManager _focusManager;

@override
void update() {
if (semanticsObject.isFocusable) {
if (!_focusManager.isManaging) {
_focusManager.manage(semanticsObject.id, semanticsObject.element);
_focusManager.manage(semanticsObject.id, owner.element);
}
_focusManager.changeFocus(semanticsObject.hasFocus && (!semanticsObject.hasEnabledState || semanticsObject.isEnabled));
} else {
Expand Down
8 changes: 4 additions & 4 deletions lib/web_ui/lib/src/engine/semantics/image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ class ImageRoleManager extends PrimaryRoleManager {
..height = '${semanticsObject.rect!.height}px';
}
_auxiliaryImageElement!.style.fontSize = '6px';
semanticsObject.element.append(_auxiliaryImageElement!);
append(_auxiliaryImageElement!);
}

_auxiliaryImageElement!.setAttribute('role', 'img');
_setLabel(_auxiliaryImageElement);
} else if (semanticsObject.isVisualOnly) {
semanticsObject.setAriaRole('img');
_setLabel(semanticsObject.element);
setAriaRole('img');
_setLabel(element);
_cleanUpAuxiliaryElement();
} else {
_cleanUpAuxiliaryElement();
Expand All @@ -78,7 +78,7 @@ class ImageRoleManager extends PrimaryRoleManager {
}

void _cleanupElement() {
semanticsObject.element.removeAttribute('aria-label');
removeAttribute('aria-label');
}

@override
Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/semantics/incrementable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Incrementable extends PrimaryRoleManager {
addRouteName();
addLabelAndValue();

semanticsObject.element.append(_element);
append(_element);
_element.type = 'range';
_element.setAttribute('role', 'slider');

Expand Down
10 changes: 4 additions & 6 deletions lib/web_ui/lib/src/engine/semantics/label_and_value.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import '../dom.dart';
import 'semantics.dart';

/// Renders [SemanticsObject.label] and/or [SemanticsObject.value] to the semantics DOM.
Expand All @@ -26,8 +25,8 @@ import 'semantics.dart';
/// This role manager does not manage images and text fields. See
/// [ImageRoleManager] and [TextField].
class LabelAndValue extends RoleManager {
LabelAndValue(SemanticsObject semanticsObject)
: super(Role.labelAndValue, semanticsObject);
LabelAndValue(SemanticsObject semanticsObject, PrimaryRoleManager owner)
: super(Role.labelAndValue, semanticsObject, owner);

@override
void update() {
Expand Down Expand Up @@ -62,12 +61,11 @@ class LabelAndValue extends RoleManager {
combinedValue.write(semanticsObject.value);
}

semanticsObject.element
.setAttribute('aria-label', combinedValue.toString());
owner.setAttribute('aria-label', combinedValue.toString());
}

void _cleanUpDom() {
semanticsObject.element.removeAttribute('aria-label');
owner.removeAttribute('aria-label');
}

@override
Expand Down
21 changes: 21 additions & 0 deletions lib/web_ui/lib/src/engine/semantics/link.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import '../dom.dart';
import '../semantics.dart';

/// Provides accessibility for links.
class Link extends PrimaryRoleManager {
Link(SemanticsObject semanticsObject) : super.withBasics(PrimaryRole.link, semanticsObject);

@override
DomElement createElement() {
final DomElement element = domDocument.createElement('a');
// TODO(chunhtai): Fill in the real link once the framework sends entire uri.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a Github issue this can point to?

// https://github.com/flutter/flutter/issues/102535.
element.setAttribute('href', '#');
element.style.display = 'block';
return element;
}
}
4 changes: 2 additions & 2 deletions lib/web_ui/lib/src/engine/semantics/live_region.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import 'semantics.dart';
/// label of the element. See [LabelAndValue]. If there is no label provided
/// no content will be read.
class LiveRegion extends RoleManager {
LiveRegion(SemanticsObject semanticsObject)
: super(Role.liveRegion, semanticsObject);
LiveRegion(SemanticsObject semanticsObject, PrimaryRoleManager owner)
: super(Role.liveRegion, semanticsObject, owner);

String? _lastAnnouncement;

Expand Down
5 changes: 2 additions & 3 deletions lib/web_ui/lib/src/engine/semantics/platform_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import '../dom.dart';
import '../platform_views/slots.dart';
import 'semantics.dart';

Expand Down Expand Up @@ -30,13 +29,13 @@ class PlatformViewRoleManager extends PrimaryRoleManager {

if (semanticsObject.isPlatformView) {
if (semanticsObject.isPlatformViewIdDirty) {
semanticsObject.element.setAttribute(
setAttribute(
'aria-owns',
getPlatformViewDomId(semanticsObject.platformViewId),
);
}
} else {
semanticsObject.element.removeAttribute('aria-owns');
removeAttribute('aria-owns');
}
}
}
16 changes: 7 additions & 9 deletions lib/web_ui/lib/src/engine/semantics/scrollable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Scrollable extends PrimaryRoleManager {
..transformOrigin = '0 0 0'
// Ignore pointer events since this is a dummy element.
..pointerEvents = 'none';
semanticsObject.element.append(_scrollOverflowElement);
append(_scrollOverflowElement);
}

/// Disables browser-driven scrolling in the presence of pointer events.
Expand Down Expand Up @@ -112,7 +112,7 @@ class Scrollable extends PrimaryRoleManager {
// This is effective only in Chrome. Safari does not implement this
// CSS property. In Safari the `PointerBinding` uses `preventDefault`
// to prevent browser scrolling.
semanticsObject.element.style.touchAction = 'none';
element.style.touchAction = 'none';
_gestureModeDidChange();

// Memoize the tear-off because Dart does not guarantee that two
Expand All @@ -126,17 +126,17 @@ class Scrollable extends PrimaryRoleManager {
_scrollListener = createDomEventListener((_) {
_recomputeScrollPosition();
});
semanticsObject.element.addEventListener('scroll', _scrollListener);
addEventListener('scroll', _scrollListener);
}
}

/// The value of "scrollTop" or "scrollLeft", depending on the scroll axis.
int get _domScrollPosition {
if (semanticsObject.isVerticalScrollContainer) {
return semanticsObject.element.scrollTop.toInt();
return element.scrollTop.toInt();
} else {
assert(semanticsObject.isHorizontalScrollContainer);
return semanticsObject.element.scrollLeft.toInt();
return element.scrollLeft.toInt();
}
}

Expand All @@ -153,7 +153,6 @@ class Scrollable extends PrimaryRoleManager {
void _neutralizeDomScrollPosition() {
// This value is arbitrary.
const int canonicalNeutralScrollPosition = 10;
final DomElement element = semanticsObject.element;
final ui.Rect? rect = semanticsObject.rect;
if (rect == null) {
printWarning('Warning! the rect attribute of semanticsObject is null');
Expand Down Expand Up @@ -197,7 +196,6 @@ class Scrollable extends PrimaryRoleManager {
}

void _gestureModeDidChange() {
final DomElement element = semanticsObject.element;
switch (semanticsObject.owner.gestureMode) {
case GestureMode.browserGestures:
// overflow:scroll will cause the browser report "scroll" events when
Expand Down Expand Up @@ -227,13 +225,13 @@ class Scrollable extends PrimaryRoleManager {
@override
void dispose() {
super.dispose();
final DomCSSStyleDeclaration style = semanticsObject.element.style;
final DomCSSStyleDeclaration style = element.style;
assert(_gestureModeListener != null);
style.removeProperty('overflowY');
style.removeProperty('overflowX');
style.removeProperty('touch-action');
if (_scrollListener != null) {
semanticsObject.element.removeEventListener('scroll', _scrollListener);
removeEventListener('scroll', _scrollListener);
}
semanticsObject.owner.removeGestureModeListener(_gestureModeListener);
_gestureModeListener = null;
Expand Down
Loading