This PR adds `String? identifier` to `SemanticsUpdateBuilder` (currently it's only available in the temproary `SemanticsUpdateBuilderNew` API.
This is mainly targeted at https://github.com/flutter/flutter/issues/17988
Steps:
part 1: [engine] add `SemanticsUpdateBuilderNew` https://github.com/flutter/engine/pull/47961
part 2: [flutter] use `SemanticsUpdateBuilderNew` https://github.com/flutter/flutter/pull/138331
**part 3: [engine] update `SemanticsUpdateBuilder` to be the same as `SemanticsUpdateBuilderNew`** <-- we are here
part 4: [flutter] use (now updated) `SemanticsUpdateBuilder` again.
part 5: [engine] remove `SemanticsBuilderNew`
- Move initialization of `PointerBinding`/`KeyboardBinding` out of `FlutterViewEmbedder`.
- `computeEventOffsetToTarget` properly handles events within a given view.
- `PointerBinding` operates on the given Flutter view (it still listens to some `domWindow` events for the implicit view).
- Stop using globals e.g. `ui.window`, `KeyboardBinding.instance`, `SafariPointerEventWorkaround.instance`, etc.
- `pointer_binding_test.dart` doesn't use globals either.
- `clickDebouncer` is now a static property on `PointerBinding`.
Fixes https://github.com/flutter/flutter/issues/137289
Places the binding data in a vector, since they key was only meaningful on metal but not used anywhere. I don't think that we need to specificially handle the case where our own contents bind the same contents multiple times, but interested to discuss if folks disagree.
Placing the vertex buffer on the binding object meant that we were actually paying 2x the size cost for it (one for vertex bindings, one for fragment bindings). By moving this object onto command itself, we reduce the size and avoid spliting up the command state in a weird way.
Also updates most of the contents to prefer moving the VertexBuffer.
This PR adds multiview support for `ExternalViewEmbedder`.
## Nomenclature
The term **view** can be ambiguous in `ExternalViewEmbedder`, and therefore the following terms are used:
* A **native view** refers to the final drawing surface that to composite layers to. It is the "view" used in other places of the engine, such as `Shell::AddView`.
* A **platform view** refers a platform view, a layer that holds content to be embedded.
## Change
The lifecycle of `ExternalViewEmbedder` is changed:
<table>
<thead>
<tr>
<th>Before PR</th>
<th>After PR</th>
<th>How it's called</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan=2>BeginFrame</td>
<td>BeginFrame</td>
<td>Once per frame</td>
</tr>
<tr>
<td>PrepareFlutterView</td>
<td>Once per flutter view</td>
</tr>
<tr>
<td>SubmitFrame</td>
<td>SubmitFlutterView (renamed)</td>
<td>Once per flutter view</td>
</tr>
<tr>
<td>EndFrame</td>
<td>EndFrame (unchanged)</td>
<td>Once per frame</td>
</tr>
</tbody>
</table>
* `BeginFrame` should perform per-frame actions, such as merge-unmerging threads.
* `PrepareView` should perform per-native-view preparations, such as recording the view ID and view size.
This change is necessary because some actions in `PrepareView` needs to be refreshed at the beginning of drawing every native view.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Accompanying framework PR: https://github.com/flutter/flutter/pull/138331
This PR implements support for exposing `SemanticsProperties.identifier` on Android as `resource-id`. Mainly targeted at https://github.com/flutter/flutter/issues/17988. Would also fix https://github.com/flutter/flutter/issues/issues/137735 but it was marked as duplicate. Anyway, there's a lot of context in that issue.
This PR requires changing the `SemanticsUpdateBuilder` interface (defined in engine) that framework depends on, so it requires introducing a temporary API ([see question I asked on Discord](https://discord.com/channels/608014603317936148/608018585025118217/1174845658033819729) to learn more about this approach).
Steps:
**part 1: [engine] add `SemanticsUpdateBuilderNew`** <-- we are here
part 2: [flutter] use `SemanticsUpdateBuilderNew`
part 3: [engine] update `SemanticsUpdateBuilder` to be the same as `SemanticsUpdateBuilderNew`*
part 4: [flutter] use (now updated) `SemanticsUpdateBuilder` again.
part 5: [engine] remove `SemanticsBuilderNew`
I'd like to do these changes first, and only then continue with [the proper framework PR](https://github.com/flutter/flutter/pull/138331).
*More specifically: update `SemanticsUpdateBuilder.updateNode()` to be the same as `SemanticsUpdateBuilderNew.updateNode()`. Number of arguments that function takes is the only change.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
The ulimit logic has been failing for me for months now and felt still
ran fine. I think we don't need it any more.
Also add the `-i` option for incremental runs of `felt`. It causes felt
to start faster because it doesn't run `pub get`. In the future, we can
also run felt from the snapshot for even faster start-up.
Implement multi-view for semantics. Main changes:
- `EngineSemanticsOwner` singleton is split into two classes:
- `EngineSemantics` is a singleton that manages global properties of the
semantics tree, such as whether semantics is currently enabled, and what
gesture mode is used.
- `EngineSemanticsOwner` now supports creating multiple instances of the
class. `EngineFlutterView` now points a `EngineSemanticsOwner` that it
owns.
- Fix a number of issues with disposal logic. Now that views can come in
and out disposal has to be more robust than previously.
`EngineSemanticsOwner` acquired a `reset()` and `SemanticsObject` acquired
a `dispose()` that clean up the tree and individual nodes respectively.
- In particular, this fixes an issue in Skwasm mode where slight
differences in asynchrony caused the semantics test to fail because old
nodes continued firing events after they were removed from the document
due to improper disposal.
- No implicit view in mult-view mode.
- `window.devicePixelRatio` => `EngineFlutterDisplay.instance.devicePixelRatio`.
- `window.physicalSize` => `view.physicalSize`.
- Remove `LayerTree.frameSize`.
- `defaultRouteName` is set to `/` when there's no implicit view.
- All routing operations are noops in multi-view mode.
With these changes, I was able to run all examples in https://github.com/goderbauer/mvp without an implicit view.
The root slice of a surface frame was requesting the construction of an RTree from its DisplayList when it was built from a layer tree, but since the layer tree already does branch culling, it would not benefit from any further culling during `DisplayList::Dispatch`. Further, if there are platform views present in the layer tree then they will need an RTree to accurately convey "pixel ownership" information to the platform, but the root slice lives below any and all platform views, so it is the only slice that doesn't need an RTree for that case.
The cost of having an RTree in that slice was the accumulation of information and lists of rects that would never prove useful.
Towards https://github.com/flutter/flutter/issues/134501.
This PR makes the following changes to the public dart:ui API:
* It adds the `FlutterView.pysicalConstraints` property that describes max and min width and height for a view. The framework is allowed to size the `FlutterView` to any `Size` that meets these constraints.
* It adds an optional `size` argument to `FlutterView.render`. The framework provides the chosen `Size` that meets the aforementioned constraints to the `render` method. If the `FlutterView.pysicalConstraints` are tight (minHeight == maxHeight and minWidth == maxWidth) the argument is optional to remain backwards compatible. In all other cases, a `Size` must be provided.
* It adds a `ViewConstraints` class, which is basically the `dart:ui` version of `BoxConstraints` (This is similar to how we have `ViewPadding` in dart:ui to mirror `EdgeInsets` from the framework). It describes the constraints of a `FlutterView`, i.e. it powers the `FlutterView.pysicalConstraints` property.
This change does not wire anything up to the embedders. For now, `FlutterView.pysicalConstraints` just returns tight constraints for the embedder-provided size of the view (`FlutterView.physicalSize`) and the size provided to `FlutterView.render` is ignored (after it is checked that it meets the constrains).
This PR enables the framework to implement the new dynamic view sizing and embedders to separately expose the new functionality to their clients.
Presubmits will fail until https://github.com/flutter/flutter/pull/138565 is submitted to the framework.
**DO NOT SUBMIT until https://github.com/flutter/flutter/pull/138648 is ready.**
First triangle, in the framework! 🎉
Adds shader libraries, pipelines, command buffers, render passes, etc.
* Light pipelines/shader objects. No optimization yet, pipeline warming
to come.
* "Dynamic" command style. Don't re-send bindings if you don't need to.
Essentially: https://github.com/flutter/flutter/issues/133179
* No need to explicitly encode passes.
* Minimal descriptor usage.
* Nothing is async, except for the optional command buffer completion
callback.
It took a bunch of experimenting to get here, but I think things are
starting to look pretty neat. :)
Todo:
* Land the shader bundle format/remove the testing hacks & fixtures that
piggyback off of the runtime effect system.
* Add remaining calls for blend config, clearing bindings, etc.
* Inconsistent error handling patterns that need cleanup.
* Maybe: Surface exceptions for validation errors.
* Handle the texture usage bitmask more elegantly.
This PR adds:
* JS-interop types to expose addView/removeView from the running FlutterApp object on JavaScript.
* Also, the options object that can be passed to `addView`.
### Issues:
* Fixes: https://github.com/flutter/flutter/issues/137377
### Info
Most interesting files:
* `app_bootstrap.dart` -> Adds the implementation for JS add/remove view.
* `js_app.dart` -> Adds the js-interop layer for the FlutterApp object, and the configuration type. (Two options: `hostElement` and `initialData`).
* `flutter_view_manager.dart` -> An abstraction over the `viewData` map that keeps related things together: viewData, js configuration options, register/unregister methods and a Stream<void> of modification events.
The rest of the changes were ""required"" to have a small demo that does anything (currently it lets me "register" views from javascript). I didn't add much in there, because probably it's already being worked on by @mdebbar; just fiddled with the constructor of the EngineFlutterView to create views from JS Config, and added a wrapper around the `viewData` map (`FlutterViewManager`) to prevent direct access to the Map.
## Usage
This is how I'm currently initializing my Flutter App, so I can "leak" the `flutterApp` to window and do things asynchronously after flutter loads:
```html
<script>
window.addEventListener('load', async function(ev) {
_flutter.loader.loadEntrypoint({
onEntrypointLoaded: function(engineInitializer) {
engineInitializer.initializeEngine({
multiViewEnabled: true,
}).then(function(appRunner) {
return appRunner.runApp();
}).then(onAppRunning);
}
});
// Leak flutterApp to window so we can do async things...
function onAppRunning(flutterApp) {
console.log('Running app', flutterApp);
window.flutterApp = flutterApp;
}
});
</script>
```
This to test:
* Go on your JS console and use `flutterApp.addView({})` and see how that returns a Promise for the viewId it just added,
* Now do `flutterApp.removeView(0)` (removes the implicitView), and see how everything starts crashing! (as expected)
* Get out of this weird state with a hot reload ð¥³
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
- New `EngineFlutterView.dispose()` to cleanup when the view is removed (and in hot restart).
- `EnginePlatformDispatcher.dispose()` now disposes of all of its registered views.
- `FlutterViewEmbedder` doesn't create the DOM tree anymore (instead, `DomManager` does).
- `DomManager` only creates the DOM tree (with styles) but doesn't insert it into the document.
- `EngineFlutterView` takes the root element from `DomManager` and inserts it into the document.
- We finally can now create multiple Flutter views, each with its own DOM tree.
cc @yjbanov since I'm making a few changes that probably conflict with your semantics changes.
Part of https://github.com/flutter/flutter/issues/134443
Part of https://github.com/flutter/flutter/issues/137447
The current way we are doing global styles (using `CSSStyleSheet`) forces us to insert the DOM element into the document before we attach any styles to the element. That restriction goes away if we append the styles as `TextNode`s into the `<style>` element.
Now with the movement towards `DomManager`, I would like to be able to create the entire DOM tree of the Flutter View (including all styles) before we insert it into the document.
Part of https://github.com/flutter/flutter/issues/134443
Reverts flutter/engine#48000
Initiated by: jonahwilliams
This change reverts the following previous change:
Original Description:
I just ... deleted `text_box.h` as it appears unused and unreferenced?
---
Work towards https://github.com/flutter/flutter/issues/134969.
All changes were made automatically (i.e. with `--fix`).
I just ... deleted `text_box.h` as it appears unused and unreferenced?
---
Work towards https://github.com/flutter/flutter/issues/134969.
All changes were made automatically (i.e. with `--fix`).
Run the JS unit tests with flutter.js.
I am going to leave the dart2wasm tests doing the old `window.flutterConfiguration` setup for now, until I actually get dart2wasm/dart2js switching logic built into flutter.js itself.
- An explicit API for initializing the implicit view (aka `window`).
- The explicit API is being called during the engine initialization for now, but we could simply remove that or make it conditional.
- Remove direct usages of `window` in tests:
- Most of the usages were being delegated to `PlatformDispatcher` anyway (e.g. `sendPlatformMessage`).
- This makes it **_clearer_** which tests depend on the implicit view (there are still hidden/indirect dependencies though).
Part of https://github.com/flutter/flutter/issues/134443
This PR cleans up a big source of complexity in our pointer handling code. It also drops support for Safari versions prior to 13 ([caniuse](https://caniuse.com/mdn-api_pointerevent)).
Right now, we throw a hard error when running in a browser that doesn't support `PointerEvent`s. Should we turn it into a soft warning, and just disable gesture/pointer handling on those browsers?
For users who need to support older versions of Safari, they can try this polyfill: https://github.com/wessberg/pointer-events (thanks @ditman!)
Fixes https://github.com/flutter/flutter/issues/116141
In order to fix Safari autofill, we've had to give inactive elements non-zero size because Safari does not respect offscreen or 0-sized inputs, and this leads to broken autofill behavior (see: https://github.com/flutter/engine/pull/43058).
As part of these changes, we needed to disable pointer events for the parent `<form>` element so that we don't have pointer event collisions if users hover over or click into the invisible autofill elements within that form.
This led to an issue where offsets weren't being calculated correctly for "active" inputs because they relied on pointer events bubbling up and being caught by the form. The fix is to explicitly set pointer events on the active inputs, so that we can correctly discern when our pointer event target is actually the input and correctly calculate the offsets.
Fixes https://github.com/flutter/flutter/issues/136006