Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[web] Add dynamic view sizing for non-implicit views. #48541

Closed
wants to merge 10 commits into from

Conversation

ditman
Copy link
Member

@ditman ditman commented Nov 30, 2023

This PR

  • Computes the correct physicalConstraints of a view off of its physicalSize and the JSViewConstraints passed by the user when creating a view.
    • By default, and to preserve current behavior, the default constraints are "tight" to the physicalSize.
    • From Javascript, -1 is a valid "max" constraint, and is interpreted as double.infinity in Flutter.
  • Hooks the Size of a render call into the renderer, so it doesn't have to rely in the (maybe outdated) physicalSize of a view.
  • Hooks the onResize event from a view into the dimensionsChanged event from the Engine, so the framework knows it needs to repaint.

TODO:

  • Recompute physicalConstraints only when the view resizes and not always that the app needs to render.
  • Tests

Issues

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide and the C++, Objective-C, Java style guides.
  • I listed at least one issue that this PR fixes in the description above.
  • I added new tests to check the change I am making or feature I am adding, or the PR is test-exempt. See testing the engine for instructions on writing and running engine tests.
  • I updated/added relevant documentation (doc comments with ///).
  • I signed the CLA.
  • All existing and new tests are passing.

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

@github-actions github-actions bot added the platform-web Code specifically for the web engine label Nov 30, 2023
Copy link
Member Author

@ditman ditman left a comment

Choose a reason for hiding this comment

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

Reviewing myself.

Comment on lines 81 to 83
viewManager.onViewsChanged.listen((_) {
invokeOnMetricsChanged();
});
Copy link
Member Author

Choose a reason for hiding this comment

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

Do we want to auto-attach this here, or should we do it after the view has been created, through some registration method in the platform_dispatcher?

@@ -391,7 +391,7 @@ class CanvasKitRenderer implements Renderer {
final Rasterizer rasterizer =
_getRasterizerForView(view as EngineFlutterView);

rasterizer.draw((scene as LayerScene).layerTree);
rasterizer.draw((scene as LayerScene).layerTree, size: size);
Copy link
Member Author

Choose a reason for hiding this comment

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

@harryterkelsen is there a way of testing this? Somehow asserting that the thing that was drawn matches the size of the incoming size?

Copy link
Contributor

Choose a reason for hiding this comment

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

IIRC the size is only used to size the output canvases before drawing to them, so if you wanted to test this then I think you should call draw with an explicit size and then check that the bitmap created and the bitmaprenderer canvases are the same size as the size that is passed in.

// The controller of the [onViewsChanged] stream.
final StreamController<void> _onViewsChangedController =
StreamController<void>.broadcast();

/// A stream of `void` events that will fire when a view is registered/unregistered.
Stream<void> get onViewsChanged => _onViewsChangedController.stream;

/// Should we create a different onViewResized stream?
Copy link
Member Author

Choose a reason for hiding this comment

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

Should we propagate resize events from this class at all, or should these subscriptions live elsewhere?

Copy link
Contributor

Choose a reason for hiding this comment

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

If we always re-render when there is a resize, then I don't think we need a stream for resize events. I would rather have resize trigger a re-render at a higher level in the engine/framework than at the Renderer level since it doesn't seem right to me for the Renderer to decide when to re-render. I think the Renderer should only perform Render requests and never initiate them.

Copy link
Contributor

@harryterkelsen harryterkelsen left a comment

Choose a reason for hiding this comment

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

Responded to some questions in the PR. I think we should add a test showing a scene being rendered at different sizes in the CanvasKit tests.

@ditman ditman force-pushed the web-dynamic-view-sizing branch 2 times, most recently from 5372b79 to 44a4b07 Compare December 13, 2023 23:49
@ditman ditman force-pushed the web-dynamic-view-sizing branch from 0ecdf36 to a612de8 Compare December 20, 2023 19:49
@ditman ditman force-pushed the web-dynamic-view-sizing branch from a612de8 to a691ace Compare December 20, 2023 19:56
@ditman
Copy link
Member Author

ditman commented Jan 10, 2024

Dynamic View Sizing has relanded in the framework:

Time to refresh this PR!

@ditman
Copy link
Member Author

ditman commented Feb 2, 2024

This can be simplified SSSSSO much, it's embarrassing. I'm going to post the simpler version in a new PR so we can all easily laugh together 🤦

@ditman ditman mentioned this pull request Feb 2, 2024
8 tasks
@ditman
Copy link
Member Author

ditman commented Feb 2, 2024

This is much better, closing: #50271

@ditman ditman closed this Feb 2, 2024
@ditman ditman deleted the web-dynamic-view-sizing branch February 2, 2024 04:49
auto-submit bot pushed a commit that referenced this pull request Feb 15, 2024
### Changes

* Introduces a new `viewConstraints` JS configuration parameter to configure max/min width/height constraints for a view. Those can have the following values:
  * An integer `>= 0`: max/min size in pixels
  * `Infinity` (or `Number.POSITIVE_INFINITY`): (only for max values) -> **unconstrained**.
  * When any value is not set, it defaults to "tight to the current size".
    * See [Understanding constraints](https://docs.flutter.dev/ui/layout/constraints).
* Computes the correct `physicalConstraints` of a view off of its `physicalSize` and its `viewConstraints` for the framework to use during layout.
  * When no constraints are passed, the current behavior is preserved: the default constraints are "tight" to the `physicalSize`.
* Resizes the current view DOM when requested by the framework and updates its internal physicalSize, then continues with the render procedure.

### Example

This is how we can configure a view to "take as much vertical space as needed":

```js
flutterApp.addView({
  viewConstraints: {
    minHeight: 0,
    maxHeight: Infinity,
  },
  hostElement: ...,
});
```

### TODO

* Needs actual unit tests

### Issues

* Fixes flutter/flutter#137444
* Closes #48541

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
sealesj pushed a commit to sealesj/engine that referenced this pull request Feb 15, 2024
### Changes

* Introduces a new `viewConstraints` JS configuration parameter to configure max/min width/height constraints for a view. Those can have the following values:
  * An integer `>= 0`: max/min size in pixels
  * `Infinity` (or `Number.POSITIVE_INFINITY`): (only for max values) -> **unconstrained**.
  * When any value is not set, it defaults to "tight to the current size".
    * See [Understanding constraints](https://docs.flutter.dev/ui/layout/constraints).
* Computes the correct `physicalConstraints` of a view off of its `physicalSize` and its `viewConstraints` for the framework to use during layout.
  * When no constraints are passed, the current behavior is preserved: the default constraints are "tight" to the `physicalSize`.
* Resizes the current view DOM when requested by the framework and updates its internal physicalSize, then continues with the render procedure.

### Example

This is how we can configure a view to "take as much vertical space as needed":

```js
flutterApp.addView({
  viewConstraints: {
    minHeight: 0,
    maxHeight: Infinity,
  },
  hostElement: ...,
});
```

### TODO

* Needs actual unit tests

### Issues

* Fixes flutter/flutter#137444
* Closes flutter#48541

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
platform-web Code specifically for the web engine
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[web:multi-view] define an MVP for FlutterViews participation in host page layout
2 participants