Skip to content

Sync master @ 2fc716dbeb68abf9675d7f81162b0b90ceb88808 to 3.32 #166874

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

Closed
wants to merge 21 commits into from

Conversation

matanlurey
Copy link
Contributor

Doing a new rebase of proposed beta 3.32 to work around numerous presubmit issues.

Jonah Williams and others added 21 commits April 8, 2025 21:51
This went flakey/flaky immeidately
Update Flutter for the upcoming removal of pkg/_macros and pkg/macros
from Dart SDK: https://dart-review.googlesource.com/c/sdk/+/420680.
Fixes #166020

This test is invalid because the renderer assumes metal/vulkan will
always have decal support (they do, its in base 1.0 for both). DIsabling
decal causes this test to attempt to use a GLES only shader that is not
available on the metal backend.
Fixes: #166326

The issue lies only in the `paint` method, and there are no problems
with `tester.getTopLeft`. Therefore, I used a golden file test.

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [ ] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…#166778)

Closes #166648.

I think a better fix is to stop using `dart pub deps --json` and use
@sigurdm's new `.dart_tool/` vendored solution, but that can be a
follow-up change.
flutter/packages@267ac7b...2405f6a

2025-04-08 tarrinneal@gmail.com [pigeon] swift equality methods
(flutter/packages#8971)

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-flutter-autoroll
Please CC flutter-ecosystem@google.com on the revert to ensure that a
human
is aware of the problem.

To file a bug in Flutter:
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
This PR was generated by `flutter update-packages --force-upgrade`.
… is destroyed. (#166725)

Fixes #166410

keep the potentially shutdown context alive until the last texture is
reclaimed, to work around issues where pending UI tasks aren't flushed
during platform view shutdown.
https://skia.googlesource.com/skia.git/+log/7b929584566c..ac01f9306a0c

2025-04-08 jlavrova@google.com Small fix in Bidi API
2025-04-08 zengyonghust@gmail.com Delete the dead code in
GrGeometryProcessor.cpp
2025-04-08 jamesgk@google.com [graphite] Support lifting expressions to
vertex shader

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

To file a bug in Skia: https://bugs.chromium.org/p/skia/issues/entry
To file a bug in Flutter:
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
Currently when using a `CustomScrollView`, screen readers cannot list or
move focus to elements that are outside the current Viewport and cache
extent because we do not create semantic nodes for these elements.

This change introduces `SliverEnsureSemantics` which ensures its sliver
child is included in the semantics tree, whether or not it is currently
visible on the screen or within the cache extent. This way screen
readers are aware the elements are there and can navigate to them /
create accessibility traversal menus with this information.
* Under the hood a new flag has been added to `RenderSliver` called
`ensureSemantics`. `RenderViewportBase` uses this in its
`visitChildrenForSemantics` to ensure a sliver is visited when creating
the semantics tree. Previously a sliver was not visited if it was not
visible or within the cache extent. `RenderViewportBase` also uses this
in `describeSemanticsClip` and `describeApproximatePaintClip` to ensure
a sliver child that wants to "ensure semantics" is not clipped out if it
is not currently visible in the viewport or outside the cache extent.
* `RenderSliverMultiBoxAdaptor.semanticBounds` now leverages its first
child as an anchor for assistive technologies to be able to reach it if
the Sliver is a child of `SliverEnsureSemantics`. If not it will still
be dropped from the semantics tree.
* `RenderProxySliver` now considers child overrides of `semanticBounds`.

On the engine side we move from using a joystick method to scroll with
`SemanticsAction.scrollUp` and `SemanticsAction.scrollDown` to using
`SemanticsAction.scrollToOffset` completely letting the browser drive
the scrolling with its current dom scroll position "scrollTop" or
"scrollLeft". This is possible by calculating the total quantity of
content under the scrollable and sizing the scroll element based on
that.

<details open><summary>Code sample</summary>

```dart
// Copyright 2014 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 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

/// Flutter code sample for [SliverEnsureSemantics].

void main() => runApp(const SliverEnsureSemanticsExampleApp());

class SliverEnsureSemanticsExampleApp extends StatelessWidget {
  const SliverEnsureSemanticsExampleApp({super.key});

  @OverRide
  Widget build(BuildContext context) {
    return const MaterialApp(home: SliverEnsureSemanticsExample());
  }
}

class SliverEnsureSemanticsExample extends StatefulWidget {
  const SliverEnsureSemanticsExample({super.key});

  @OverRide
  State<SliverEnsureSemanticsExample> createState() =>
      _SliverEnsureSemanticsExampleState();
}

class _SliverEnsureSemanticsExampleState
    extends State<SliverEnsureSemanticsExample> {
  @OverRide
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    return Scaffold(
      appBar: AppBar(
        backgroundColor: theme.colorScheme.inversePrimary,
        title: const Text('SliverEnsureSemantics Demo'),
      ),
      body: Center(
        child: CustomScrollView(
          semanticChildCount: 106,
          slivers: <Widget>[
            SliverEnsureSemantics(
              sliver: SliverToBoxAdapter(
                child: IndexedSemantics(
                  index: 0,
                  child: Card(
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Semantics(
                            header: true,
                            headingLevel: 3,
                            child: Text(
                              'Steps to reproduce',
                              style: theme.textTheme.headlineSmall,
                            ),
                          ),
                          const Text('Issue description'),
                          Semantics(
                            header: true,
                            headingLevel: 3,
                            child: Text(
                              'Expected Results',
                              style: theme.textTheme.headlineSmall,
                            ),
                          ),
                          Semantics(
                            header: true,
                            headingLevel: 3,
                            child: Text(
                              'Actual Results',
                              style: theme.textTheme.headlineSmall,
                            ),
                          ),
                          Semantics(
                            header: true,
                            headingLevel: 3,
                            child: Text(
                              'Code Sample',
                              style: theme.textTheme.headlineSmall,
                            ),
                          ),
                          Semantics(
                            header: true,
                            headingLevel: 3,
                            child: Text(
                              'Screenshots',
                              style: theme.textTheme.headlineSmall,
                            ),
                          ),
                          Semantics(
                            header: true,
                            headingLevel: 3,
                            child: Text(
                              'Logs',
                              style: theme.textTheme.headlineSmall,
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ),
            ),
            SliverFixedExtentList(
              itemExtent: 44.0,
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Card(
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Text('Item $index'),
                    ),
                  );
                },
                childCount: 50,
                semanticIndexOffset: 1,
              ),
            ),
            SliverEnsureSemantics(
              sliver: SliverToBoxAdapter(
                child: IndexedSemantics(
                  index: 51,
                  child: Card(
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Semantics(
                        header: true,
                        child: const Text('Footer 1'),
                      ),
                    ),
                  ),
                ),
              ),
            ),
            SliverEnsureSemantics(
              sliver: SliverToBoxAdapter(
                child: IndexedSemantics(
                  index: 52,
                  child: Card(
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Semantics(
                        header: true,
                        child: const Text('Footer 2'),
                      ),
                    ),
                  ),
                ),
              ),
            ),
            SliverEnsureSemantics(
              sliver: SliverToBoxAdapter(
                child: IndexedSemantics(
                  index: 53,
                  child: Semantics(link: true, child: const Text('Link #1')),
                ),
              ),
            ),
            SliverEnsureSemantics(
              sliver: SliverToBoxAdapter(
                child: IndexedSemantics(
                  index: 54,
                  child: OverflowBar(
                    children: <Widget>[
                      TextButton(
                        onPressed: () {},
                        child: const Text('Button 1'),
                      ),
                      TextButton(
                        onPressed: () {},
                        child: const Text('Button 2'),
                      ),
                    ],
                  ),
                ),
              ),
            ),
            SliverEnsureSemantics(
              sliver: SliverToBoxAdapter(
                child: IndexedSemantics(
                  index: 55,
                  child: Semantics(link: true, child: const Text('Link #2')),
                ),
              ),
            ),
            SliverEnsureSemantics(
              sliver: SliverSemanticsList(
                sliver: SliverFixedExtentList(
                  itemExtent: 44.0,
                  delegate: SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
                      return Semantics(
                        role: SemanticsRole.listItem,
                        child: Card(
                          child: Padding(
                            padding: const EdgeInsets.all(8.0),
                            child: Text('Second List Item $index'),
                          ),
                        ),
                      );
                    },
                    childCount: 50,
                    semanticIndexOffset: 56,
                  ),
                ),
              ),
            ),
            SliverEnsureSemantics(
              sliver: SliverToBoxAdapter(
                child: IndexedSemantics(
                  index: 107,
                  child: Semantics(link: true, child: const Text('Link #3')),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// A sliver that assigns the role of SemanticsRole.list to its sliver child.
class SliverSemanticsList extends SingleChildRenderObjectWidget {
  const SliverSemanticsList({super.key, required Widget sliver})
    : super(child: sliver);

  @OverRide
  RenderSliverSemanticsList createRenderObject(BuildContext context) =>
      RenderSliverSemanticsList();
}

class RenderSliverSemanticsList extends RenderProxySliver {
  @OverRide
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    super.describeSemanticsConfiguration(config);
    config.role = SemanticsRole.list;
  }
}
```
</details>

Fixes: #160217

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

---------

Co-authored-by: Renzo Olivares <roliv@google.com>
Fixes #143616

Maybe. Lets see if its stable.

Update: I've run this a few times and it seems stable.
Fixes #165205

Our users expect image shader matrices to be converted to 3x3
fix: #165453

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.
This PR was generated by `flutter update-packages --force-upgrade`.
)

### Description
This PR seeks to refine the CarouselView API doc sample for Web and
Desktop platforms. On these platforms, mouse dragging gestures do not
provide natural behavior similar to other desktop applications. This PR
will improve the documentation by suggesting appropriate approaches to
users (either using Shift + mouse wheel to scroll the view horizontally
or referring to the instructions for overriding the default
ScrollBehavior if they still want to implement dragging on these
platforms).


### Related issue
Fix #165265

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Ensure this goes to a few more folks at the time, so we don't miss
messages


## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…r custom devices (#164455)

<!--
Thanks for filing a pull request!
Reviewers are typically assigned within a week of filing a request.
To learn more about code review, see our documentation on Tree Hygiene:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
-->

Make 3 additional string interpolated values available to the
`postBuild` and `runDebug` custom device commands:
- `${icuDataPath}`
- `${engineRevision}`
- `${buildMode}`

#164454 provides some additional context and the main motivation for
this change.

Fixes #164454.

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
1. Calculate the hash in only two places: `content_aware_hash.{ps1|sh}`
2. Call this from the workflow
3. Eventually call this from `update_engine_version.{ps1|sh}`

 The files of import:
* `DEPS`: tracks third party dependencies related to building the engine
* `engine`: all the code in the engine folder
* `bin/internal/content_aware_hash.ps1`: script for calculating the hash
on windows
* `bin/internal/content_aware_hash.sh`: script for calculating the hash
on mac/linux
* `.github/workflows/content-aware-hash.yml`: github action for CI/CD
hashing

Tested on windows and mac:

```shell
PS C:\src\flutter> C:\src\flutter\bin\internal\content_aware_hash.ps1
c24231e276e0719738e175e0622e040ad21a7012
```

```shell
❯ ~/src/flutter/bin/internal/content_aware_hash.sh
c24231e276e0719738e175e0622e040ad21a7012
```
…166864)

<!-- start_original_pr_link -->
Reverts: #166717
<!-- end_original_pr_link -->
<!-- start_initiating_author -->
Initiated by: matanlurey
<!-- end_initiating_author -->
<!-- start_revert_reason -->
Reason for reverting: Broke tree on
[postsubmit](https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8718108088961866849/+/u/test:_run_suite_safari-dart2js-canvaskit-engine/stdout)
<!-- end_revert_reason -->
<!-- start_original_pr_author -->
Original PR Author: jtmcdole
<!-- end_original_pr_author -->

<!-- start_reviewers -->
Reviewed By: {matanlurey}
<!-- end_reviewers -->

<!-- start_revert_body -->
This change reverts the following previous change:
1. Calculate the hash in only two places: `content_aware_hash.{ps1|sh}`
2. Call this from the workflow
3. Eventually call this from `update_engine_version.{ps1|sh}`

 The files of import:
* `DEPS`: tracks third party dependencies related to building the engine
* `engine`: all the code in the engine folder
* `bin/internal/content_aware_hash.ps1`: script for calculating the hash
on windows
* `bin/internal/content_aware_hash.sh`: script for calculating the hash
on mac/linux
* `.github/workflows/content-aware-hash.yml`: github action for CI/CD
hashing

Tested on windows and mac:

```shell
PS C:\src\flutter> C:\src\flutter\bin\internal\content_aware_hash.ps1
c24231e276e0719738e175e0622e040ad21a7012
```

```shell
❯ ~/src/flutter/bin/internal/content_aware_hash.sh
c24231e276e0719738e175e0622e040ad21a7012
```
<!-- end_revert_body -->

Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
…er the Dart Tooling Daemon (DTD) (#166698)" (#166866)

<!-- start_original_pr_link -->
Reverts: #166698
<!-- end_original_pr_link -->
<!-- start_initiating_author -->
Initiated by: jonahwilliams
<!-- end_initiating_author -->
<!-- start_revert_reason -->
Reason for reverting: tests are timing out in presubmit
<!-- end_revert_reason -->
<!-- start_original_pr_author -->
Original PR Author: bkonyi
<!-- end_original_pr_author -->

<!-- start_reviewers -->
Reviewed By: {jyameo}
<!-- end_reviewers -->

<!-- start_revert_body -->
This change reverts the following previous change:
This will eventually be used as the main communication channel between
the widget preview scaffold, the Flutter tool, and other developer
tooling (e.g., IDEs).

Fixes #166417
<!-- end_revert_body -->

Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
<!-- start_original_pr_link -->
Reverts: #165589
<!-- end_original_pr_link -->
<!-- start_initiating_author -->
Initiated by: Renzo-Olivares
<!-- end_initiating_author -->
<!-- start_revert_reason -->
Reason for reverting: breaking internal tests
<!-- end_revert_reason -->
<!-- start_original_pr_author -->
Original PR Author: Renzo-Olivares
<!-- end_original_pr_author -->

<!-- start_reviewers -->
Reviewed By: {Piinks}
<!-- end_reviewers -->

<!-- start_revert_body -->
This change reverts the following previous change:
Currently when using a `CustomScrollView`, screen readers cannot list or
move focus to elements that are outside the current Viewport and cache
extent because we do not create semantic nodes for these elements.

This change introduces `SliverEnsureSemantics` which ensures its sliver
child is included in the semantics tree, whether or not it is currently
visible on the screen or within the cache extent. This way screen
readers are aware the elements are there and can navigate to them /
create accessibility traversal menus with this information.
* Under the hood a new flag has been added to `RenderSliver` called
`ensureSemantics`. `RenderViewportBase` uses this in its
`visitChildrenForSemantics` to ensure a sliver is visited when creating
the semantics tree. Previously a sliver was not visited if it was not
visible or within the cache extent. `RenderViewportBase` also uses this
in `describeSemanticsClip` and `describeApproximatePaintClip` to ensure
a sliver child that wants to "ensure semantics" is not clipped out if it
is not currently visible in the viewport or outside the cache extent.
* `RenderSliverMultiBoxAdaptor.semanticBounds` now leverages its first
child as an anchor for assistive technologies to be able to reach it if
the Sliver is a child of `SliverEnsureSemantics`. If not it will still
be dropped from the semantics tree.
* `RenderProxySliver` now considers child overrides of `semanticBounds`.

On the engine side we move from using a joystick method to scroll with
`SemanticsAction.scrollUp` and `SemanticsAction.scrollDown` to using
`SemanticsAction.scrollToOffset` completely letting the browser drive
the scrolling with its current dom scroll position "scrollTop" or
"scrollLeft". This is possible by calculating the total quantity of
content under the scrollable and sizing the scroll element based on
that.

<details open><summary>Code sample</summary>

```dart
// Copyright 2014 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 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

/// Flutter code sample for [SliverEnsureSemantics].

void main() => runApp(const SliverEnsureSemanticsExampleApp());

class SliverEnsureSemanticsExampleApp extends StatelessWidget {
  const SliverEnsureSemanticsExampleApp({super.key});

  @OverRide
  Widget build(BuildContext context) {
    return const MaterialApp(home: SliverEnsureSemanticsExample());
  }
}

class SliverEnsureSemanticsExample extends StatefulWidget {
  const SliverEnsureSemanticsExample({super.key});

  @OverRide
  State<SliverEnsureSemanticsExample> createState() =>
      _SliverEnsureSemanticsExampleState();
}

class _SliverEnsureSemanticsExampleState
    extends State<SliverEnsureSemanticsExample> {
  @OverRide
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    return Scaffold(
      appBar: AppBar(
        backgroundColor: theme.colorScheme.inversePrimary,
        title: const Text('SliverEnsureSemantics Demo'),
      ),
      body: Center(
        child: CustomScrollView(
          semanticChildCount: 106,
          slivers: <Widget>[
            SliverEnsureSemantics(
              sliver: SliverToBoxAdapter(
                child: IndexedSemantics(
                  index: 0,
                  child: Card(
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Semantics(
                            header: true,
                            headingLevel: 3,
                            child: Text(
                              'Steps to reproduce',
                              style: theme.textTheme.headlineSmall,
                            ),
                          ),
                          const Text('Issue description'),
                          Semantics(
                            header: true,
                            headingLevel: 3,
                            child: Text(
                              'Expected Results',
                              style: theme.textTheme.headlineSmall,
                            ),
                          ),
                          Semantics(
                            header: true,
                            headingLevel: 3,
                            child: Text(
                              'Actual Results',
                              style: theme.textTheme.headlineSmall,
                            ),
                          ),
                          Semantics(
                            header: true,
                            headingLevel: 3,
                            child: Text(
                              'Code Sample',
                              style: theme.textTheme.headlineSmall,
                            ),
                          ),
                          Semantics(
                            header: true,
                            headingLevel: 3,
                            child: Text(
                              'Screenshots',
                              style: theme.textTheme.headlineSmall,
                            ),
                          ),
                          Semantics(
                            header: true,
                            headingLevel: 3,
                            child: Text(
                              'Logs',
                              style: theme.textTheme.headlineSmall,
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ),
            ),
            SliverFixedExtentList(
              itemExtent: 44.0,
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Card(
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Text('Item $index'),
                    ),
                  );
                },
                childCount: 50,
                semanticIndexOffset: 1,
              ),
            ),
            SliverEnsureSemantics(
              sliver: SliverToBoxAdapter(
                child: IndexedSemantics(
                  index: 51,
                  child: Card(
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Semantics(
                        header: true,
                        child: const Text('Footer 1'),
                      ),
                    ),
                  ),
                ),
              ),
            ),
            SliverEnsureSemantics(
              sliver: SliverToBoxAdapter(
                child: IndexedSemantics(
                  index: 52,
                  child: Card(
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Semantics(
                        header: true,
                        child: const Text('Footer 2'),
                      ),
                    ),
                  ),
                ),
              ),
            ),
            SliverEnsureSemantics(
              sliver: SliverToBoxAdapter(
                child: IndexedSemantics(
                  index: 53,
                  child: Semantics(link: true, child: const Text('Link #1')),
                ),
              ),
            ),
            SliverEnsureSemantics(
              sliver: SliverToBoxAdapter(
                child: IndexedSemantics(
                  index: 54,
                  child: OverflowBar(
                    children: <Widget>[
                      TextButton(
                        onPressed: () {},
                        child: const Text('Button 1'),
                      ),
                      TextButton(
                        onPressed: () {},
                        child: const Text('Button 2'),
                      ),
                    ],
                  ),
                ),
              ),
            ),
            SliverEnsureSemantics(
              sliver: SliverToBoxAdapter(
                child: IndexedSemantics(
                  index: 55,
                  child: Semantics(link: true, child: const Text('Link #2')),
                ),
              ),
            ),
            SliverEnsureSemantics(
              sliver: SliverSemanticsList(
                sliver: SliverFixedExtentList(
                  itemExtent: 44.0,
                  delegate: SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
                      return Semantics(
                        role: SemanticsRole.listItem,
                        child: Card(
                          child: Padding(
                            padding: const EdgeInsets.all(8.0),
                            child: Text('Second List Item $index'),
                          ),
                        ),
                      );
                    },
                    childCount: 50,
                    semanticIndexOffset: 56,
                  ),
                ),
              ),
            ),
            SliverEnsureSemantics(
              sliver: SliverToBoxAdapter(
                child: IndexedSemantics(
                  index: 107,
                  child: Semantics(link: true, child: const Text('Link #3')),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// A sliver that assigns the role of SemanticsRole.list to its sliver child.
class SliverSemanticsList extends SingleChildRenderObjectWidget {
  const SliverSemanticsList({super.key, required Widget sliver})
    : super(child: sliver);

  @OverRide
  RenderSliverSemanticsList createRenderObject(BuildContext context) =>
      RenderSliverSemanticsList();
}

class RenderSliverSemanticsList extends RenderProxySliver {
  @OverRide
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    super.describeSemanticsConfiguration(config);
    config.role = SemanticsRole.list;
  }
}
```
</details>

Fixes: #160217

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.
<!-- end_revert_body -->

Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
@matanlurey matanlurey requested a review from reidbaker April 9, 2025 18:59
@github-actions github-actions bot added a: text input Entering text in a text field or keyboard related problems tool Affects the "flutter" command-line tool. See also t: labels. framework flutter/packages/flutter repository. See also f: labels. engine flutter/engine repository. See also e: labels. f: material design flutter/packages/flutter/material repository. f: scrolling Viewports, list views, slivers, etc. f: cupertino flutter/packages/flutter/cupertino repository platform-web Web applications specifically labels Apr 9, 2025
@github-actions github-actions bot added e: impeller Impeller rendering backend issues and features requests d: docs/ flutter/flutter/docs, for contributors labels Apr 9, 2025
@matanlurey
Copy link
Contributor Author

Ugh, this can't work. I'll need to to a manual PR (#166875).

@matanlurey matanlurey closed this Apr 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: text input Entering text in a text field or keyboard related problems d: docs/ flutter/flutter/docs, for contributors e: impeller Impeller rendering backend issues and features requests engine flutter/engine repository. See also e: labels. f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels. platform-web Web applications specifically tool Affects the "flutter" command-line tool. See also t: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.