This partially implements https://github.com/flutter/flutter/issues/126341
It does not implement image codecs, because they are going to get complicated with transferring video frames to the web worker and so on. I am going to deal with image codecs in a subsequent change.
We want to start from a place of small size, and optimize from there with skwasm. Since there is no baseline expectation of performance at `-O3`, let's start with the smallest possible binary.
Using ansi colors in LUCI results in output that looks like:
```
00:00 [32m+0[0m: [1m[90mloading flutter_tester_emulation_golden_test.dart[0m[0m
00:01 [32m+0[0m: [1m[90mloading flutter_tester_emulation_golden_test.dart[0m[0m
00:02 [32m+0[0m: [1m[90mloading flutter_tester_emulation_golden_test.dart[0m[0m
```
This PR disables colors on LUCI so that we get clean output that's easily scannable and searchable.
## Description
This PR fixes Meta keys throwing exception on Chrome Linux.
The assertions throws because the DOM event sent when Meta keys is pressed is not coherent when Meta is the only pressed key.
## Related Issue
Fixes https://github.com/flutter/flutter/issues/125672
## Tests
Adds 1 test.
`Chrome < v87` have the `v8BreakIterator` API but don't have `Intl.Segmenter`. This caused crashes for some apps (see b/281377168).
This PR enhances our feature detection to take into account this API mismatch.
@staticInterop members will start disallowing tear-offs, so this member should turn into a closure.
The static check wasn't added in time, so this is modifying the source code again.
ee3ce32c7c was the original change, but the static error didn't make it into the Dart SDK, so this is fixing another tear-off.
- [] I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test-exempt. See [testing the engine] for instructions on writing and running engine tests.
1. Expose `PlatformLocation` and its subclass `BrowserPlatformLocation` through the new `ui_web`.
2. Expose `HashUrlStrategy` too. It's useful for users who want to extend and customize it instead of building their own from scratch.
3. `ui_web/url_strategy.dart` => `ui_web/navigation/url_strategy.dart`.
Introduce 2 new classes for a11y focus management:
* `AccessibilityFocusManager`: a generic class that attaches "focus" and "blur" event handlers, and forwards the events to the framework as `SemanticsAction.didGainAccessibilityFocus` and `SemanticsAction.didLoseAccessibilityFocus` respectively. Provides the `changeFocus` method for the framework to move a11y focus to the target element.
* `Focusable`: a role manager that provides generic focus management functionality to `SemanticsObject`s that don't need anything special.
Rewrites focus management using the above two classes as follows:
* All focusable nodes except text fields and incrementables get the `Focusable` role (all custom focus stuff in `Tappable` was removed and delegated to `Focusable`).
* `Incrementable` uses a custom `<input>` internally and so it cannot use the `Focusable` role. Instead, it uses `AccessibilityFocusManager` to manage the focus on the `<input>` element.
Behavioral changes:
* Fixes https://github.com/flutter/flutter/issues/118737, but more generally fixes all nodes that use the `isFocusable` and `hasFocus` bits.
* `Tappable` only partially implemented focusability (e.g. it didn't generate the respective `SemanticsAction` events). Now by delegating to `Focusable`, it will inherit all the functionality.
* `Incrementable` and `Checkable` (checkboxes, radios, switches) get focus management features for the first time.
* Elements that are not inherently focusable (text, images) can now be focused if semantics requires them to be.
* `TextField` is left alone for now as focus and on-screen keyboard interact with each other in non-obvious ways.
Fixes two issues in dialog accessibility:
* Fixes https://github.com/flutter/flutter/issues/45207 by setting `role="dialog"` on nodes that have both `scopesRoute` and `namesRoute` set. There's no guarantee that this combination of flags is an actual dialog, but it's close enough, and it makes the screen reader announce the appearance of the dialog. Note that `scopesRoute` alone is not sufficient, because Flutter uses it for overlays that are not semantically dialogs, such as dismiss barriers.
* Fixes an issue with focus management, where focus fails to transfer to background content after the dialog is dismissed. This happened because `EngineSemanticsOwner._semanticsTree` retained descendants of parents that were removed. This is benign in many cases. However, for focus this is problematic because the HTML element can go away and come back (losing focus along the way), but its corresponding `SemanticsObject` is never marked as "dirty" and fails to update and request focus.
I'm hoping this is sufficient to fix b/251839784 as well. Will work with the relevant team to find out.
This implements full text rendering with the Skwasm renderer.
The font fallback logic has been refactored to decouple the font fallback manager from any CanvasKit-specific types and functions.
A chunk of CanvasKit text rendering tests have been ported over to the renderer-agnostic `ui` tests.
Fixes https://github.com/flutter/flutter/issues/126339
Fixes https://github.com/flutter/flutter/issues/123307 - for Android, iOS, and Web, for the main display only (https://github.com/flutter/flutter/issues/125938 tracks supporting multiple displays, https://github.com/flutter/flutter/issues/125939 for desktop).
Desktop will need to be implemented for this, but given priority for a couple of our customers targetting foldable devices on Android I'm inclined to get this in before desktop can be finished.
The main concern for this right now is that on some Android foldable devices, setting a preferred orientation will cause letterboxing and the `MediaQuery` will _never_ get the full screen size when unfolded. This causes apps to think the screen is smaller than it is, as they've mainly been using `MediaQueryData.size` to figure this out. Android's recommendation is to not set a preferred orientation, and if you must to use the new method introduced in `ViewUtil.java` to calculate the maximal window size.
This implements font loading for the skwasm renderer.
In addition, it does some pretty major refactors:
1) Simplified the font collection interface to just have a single `loadAssetFonts` call, without the separate registration and debug fonts loading stuff
2) Debug fonts load now through http/asset mocking mechanisms instead of having a separate `downloadDebugTestFonts` call
3) Consolidated a few of our different unit test setup functions into a single `setUpUnitTests` function
This fixes https://github.com/flutter/flutter/issues/85793
The script that generates the font fallback data also rolls a package to CIPD with these files and updates the DEPS to download those files from CIPD. This makes sure that these tests are hermetic.
Removes the physical model layer and associated engine code. This was already deprecated and removed in the framework. By removing it in the engine, we can also remove the need for layer tree diff/paint/preroll to have the device pixel ratio. This will simplify some of the multi-view work
Fixes https://github.com/flutter/flutter/issues/125720
## Description
This PR fixes cursor jump on Chrome for Android when the user taps in a multiline `TextField`.
Using the following code sample:
<details><summary>Code sample</summary>
```dart
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Text Field Focus',
home: MyCustomForm(),
);
}
}
// Define a custom Form widget.
class MyCustomForm extends StatelessWidget {
const MyCustomForm({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Text Field Focus'),
),
backgroundColor: Colors.amber,
body: Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
decoration: const InputDecoration(
fillColor: Colors.white,
filled: true
),
autofocus: true,
maxLines: 3,
controller: TextEditingController(text: '1\n2\n3\n4\n'),
),
),// This trailing comma makes auto-formatting nicer for build methods.
);
}
}
```
</details>
On a mobile browser, once the page is loaded, tap after the number 3:
- Before this PR: the TextField content is automaticaly scrolled and the selection is set after number 1.
https://user-images.githubusercontent.com/840911/232051413-b913f890-6cb1-4c60-92d0-7a3bf74cc688.mov
## Implementation
A multiline `TextField` relies on an HTML `<textarea>` elements. When a tap occurs the selection should be updated from Flutter not by the HTML element itself.
This PR prevents mouse events on Chrome for Android. Those events conflicts with Flutter selection changes.
Previously, mouse events were only prevented on desktop but they are also emitted on mobile, see https://bugs.chromium.org/p/chromium/issues/detail?id=119216#c11.
## Related Issue
Related to https://github.com/flutter/flutter/issues/124483 (partial fix because the issue is also reproducible on iOS/Safari).
## Tests
Adds 1 test.
@staticInterop members will start disallowing tear-offs, so this member
should turn into a closure.
Unblocks a roll in the SDK that disallows tear-offs.
## 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] and the [C++,
Objective-C, Java style guides].
- [X] I listed at least one issue that this PR fixes in the description
above.
- [X] I added new tests to check the change I am making or feature I am
adding, or Hixie said the PR is test-exempt. See [testing the engine]
for instructions on writing and running engine tests.
- [X] I updated/added relevant documentation (doc comments with `///`).
- [X] I signed the [CLA].
- [X] All existing and new tests are passing.
dart:js_interop and package:js will start conflicting. Eventually, we
want people to only use dart:js_interop, so this CL refactors code to do
that.
Unblocks https://dart-review.googlesource.com/c/sdk/+/294130/8 and
prevents confusing shadowing of dart:js_interop annotations like we do
today.
## 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].
- [Mentioned CL that is unblocked] I listed at least one issue that this
PR fixes in the description above.
- [X] I updated/added relevant documentation (doc comments with `///`).
- [Need test-exemption] I added new tests to check the change I am
making, or this PR is [test-exempt].
- [X] All existing and new tests are passing.
Remove unnecessary instrumentation from picture. `UniqueRef`
automatically instruments all allocations, disposals, and garbage
collections, which covers `CkPicture`.
Migrate Paint API to `UniqueRef`. This includes `Paint`, `ImageFilter` (and all subtypes), `ColorFilter` (and all subtypes).
Also fix the following memory leaks:
* `CkPaint` is frequently used by layers where a one-off paint object is created, used, and immediately dropped. `CkPaint` now has a `dispose` method, and all one-off usages now dispose of the paint after they are done.
* `CkColorFilter.initRawImageFilter` was leaking the `SkColorFilter` created by `_initRawColorFilter` inside the expression.
* `CkManagedSkImageFilterConvertible.imageFilter` now takes a closure, which allows the implementation decide on the lifetime of the `SkImageFilter` vended to the caller. Because `CkColorFilter` is a const class it cannot store C++ instances inside its own fields, so it creates a temporary `SkImageFilter` class to be used by the caller and then it needs to delete it. Now it does.
(this is attempt 4; details below)
Remove obsolete object caches and introduce a simpler way to manage
native objects:
* Remove the unused `SynchronousSkiaObjectCache`.
* Introduce new library `native_memory.dart` that's smaller and simpler
than `skia_object_cache.dart`.
* Introduce two types of native object references:
* `UniqueRef` a reference with a unique Dart object owner.
* `CountedRef` a ref-counted reference with multiple Dart object owners.
* All native references use GC (via `FinalizationRegistry`) as a
back-up.
* The new library removes everything related to object resurrection that
was needed only in browsers that didn't support `FinalizationRegistry`.
All browsers support it now.
* Remove the ad hoc `SkParagraph` cache that predates the introduction
of `Paragraph.dispose`.
* Rewrite `CkParagraph` in terms of `UniqueRef`.
* Rewrite `CkImage` in terms of `CountedRef`; delete `SkiaObjectBox`.
This PR does not migrate all objects from the old
`skia_object_cache.dart` to `native_memory.dart`. That would be too big
of a change. The migration can be done in multiple smaller PRs.
This also removes a few unnecessary relayouts observed in
https://github.com/flutter/flutter/issues/120921, but not all of them
(more details in
https://github.com/flutter/flutter/issues/120921#issuecomment-1481958762)
## About attempt 4
More info about the revert of attempt 3 in
https://github.com/flutter/engine/pull/40937.
In this attempt I check that the browser supports `FinalizationRegistry`
before registering the object. This will allow the code to run in older
browsers, but there will be no protection from memory leaks when the app
fails to dispose of the respective objects.
## Benchmarks
Now that this landed in flutter/flutter I have some benchmark numbers
from the devicelab. The `text_out_of_picture_bounds` benchmark dropped
by 3-4x (lower is better):
<img width="358" alt="Screenshot 2023-04-04 at 6 13 06 PM"
src="https://user-images.githubusercontent.com/211513/229956170-a5399ed3-c779-4af0-babb-ea40440f96ff.png">
The repro provided in https://github.com/flutter/flutter/issues/123204
dropped from 110ms/frame to 10ms/frame.