We currently benchmark path tessellation on Android and iOS, but only
for filled paths. We will now run those same benchmarks also with
stroking in a new set of benchmarks.
Feat: Add hintMaxLines in InputDecorationTheme
fixes: #164656
## 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.
<!-- start_original_pr_link -->
Reverts: flutter/flutter#166784
<!-- end_original_pr_link -->
<!-- start_initiating_author -->
Initiated by: jonahwilliams
<!-- end_initiating_author -->
<!-- start_revert_reason -->
Reason for reverting: didn't do enough, going to try something
different.
<!-- end_revert_reason -->
<!-- start_original_pr_author -->
Original PR Author: jonahwilliams
<!-- end_original_pr_author -->
<!-- start_reviewers -->
Reviewed By: {matanlurey}
<!-- end_reviewers -->
<!-- start_revert_body -->
This change reverts the following previous change:
Once we've created the Vulkan context, lets just use it - creating it
isn't free. See numbers. Also change AHB swapchain to lazily create
images, which will also improve startup and will be added to an opt in
list to test startup performance.
```
════════════════════════════╡ ••• Raw results ••• ╞═════════════════════════════
timeToFirstFrameMicros:
A: 371525.00 225155.00
B: 254054.00 254668.00
timeToFirstFrameRasterizedMicros:
A: 781015.00 555791.00
B: 527163.00 526827.00
═════════════════════════╡ ••• Final A/B results ••• ╞══════════════════════════
Score Average A (noise) Average B (noise) Speed-up
timeToFirstFrameMicros 298340.00 (24.53%) 254361.00 (0.12%) 1.17x
timeToFirstFrameRasterizedMicros 668403.00 (16.85%) 526995.00 (0.03%) 1.27x
```
<!-- end_revert_body -->
Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
Skwasm was the only renderer that enforced that the root layer cannot be
popped. However, canvaskit and the native engines all allow popping the
root layer. It's just a noop.
Also, `EngineSceneBuilder` called `currentBuilder.build()` before
checking if the layer that's being popped is a root layer. This means
skwasm would call `rootLayer.build()` twice when push/pop are
unbalanced. It is called once on the last `pop()` on the root layer.
Then it is called again in `EngineSceneBuilder.build`.
Not a guarantee, but this may help reduce the skwasm error rates from
DevTools that look like this:
```
org-dartlang-sdk:///dart-sdk/lib/_internal/wasm/lib/error_utils.dart 130:15 | _throwIndexError
org-dartlang-sdk:///dart-sdk/lib/_internal/wasm/lib/error_utils.dart 24:7 | checkIndexBCE
org-dartlang-sdk:///lib/_engine/engine/scene_builder.dart 458:53 | pop
file:///b/s/w/ir/x/w/rc/flutter/packages/flutter/lib/src/rendering/layer.dart 1520:13 | addToScene
file:///b/s/w/ir/x/w/rc/flutter/packages/flutter/lib/src/rendering/layer.dart 721:5 | _addToSceneWithRetainedRendering
file:///b/s/w/ir/x/w/rc/flutter/packages/flutter/lib/src/rendering/layer.dart 1519:5 | addToScene
file:///b/s/w/ir/x/w/rc/flutter/packages/flutter/lib/src/rendering/layer.dart 721:5 | _addToSceneWithRetainedRendering
```
A soft restart simply removes the previewed widget from the widget tree
for a frame before re-inserting it on the next frame. This has the
effect of re-running local initializers in `State` objects, which would
normally require a hot restart to accomplish. This reduces the number of
cases where a full hot restart of the preview environment would be
needed to pick up state-related changes.
Fixes https://github.com/flutter/flutter/issues/166450
**Updated Controls:**

**Demo:** updates a string initialized in `initState`, triggering a hot
reload. The updated string isn't rendered until the restart button is
pressed, causing the widget to be reloaded with the new state
initialized.
https://github.com/user-attachments/assets/ab4abf8a-7823-491a-ad90-f83d877600ec
For emulated advanced blends, the depth value is off by one. When use
flip backdrop for saveLayers, we call it before we increment the depth.
When we call it for draws (to do an emulated advanced blend), we call it
after we've incremented the depth. Correct this with a bool parameter.
Once we've created the Vulkan context, lets just use it - creating it
isn't free. See numbers. Also change AHB swapchain to lazily create
images, which will also improve startup and will be added to an opt in
list to test startup performance.
```
════════════════════════════╡ ••• Raw results ••• ╞═════════════════════════════
timeToFirstFrameMicros:
A: 371525.00 225155.00
B: 254054.00 254668.00
timeToFirstFrameRasterizedMicros:
A: 781015.00 555791.00
B: 527163.00 526827.00
═════════════════════════╡ ••• Final A/B results ••• ╞══════════════════════════
Score Average A (noise) Average B (noise) Speed-up
timeToFirstFrameMicros 298340.00 (24.53%) 254361.00 (0.12%) 1.17x
timeToFirstFrameRasterizedMicros 668403.00 (16.85%) 526995.00 (0.03%) 1.27x
```
Currently Impeller asks incoming paths to convert themselves into the
impeller::Path class before tessellating their outlines. This wastes
conversion time when the path is only needed to iterate the path
segments. We now tessellate them directly from a path segment dispatcher
saving the conversion cost.
Rolls forward https://github.com/flutter/flutter/pull/166717.
Does not copy the `README` or `DEPS` files, and instead uses synthetic
scratch files.
These files can change, so we can't possibly know how to hash them
consistently.
Fix: Focus on leading icon when null
fixes: #164905
## 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.
<!-- start_original_pr_link -->
Reverts: flutter/flutter#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>
<!-- start_original_pr_link -->
Reverts: flutter/flutter#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: flutter/flutter#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>
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
```
fix: https://github.com/flutter/flutter/issues/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.
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 https://github.com/flutter/flutter/issues/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.
Closes https://github.com/flutter/flutter/issues/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.
Fixes https://github.com/flutter/flutter/issues/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.