flutter/packages/flutter/lib/widgets.dart
Michael Goderbauer 6f09064e78
Stand-alone widget tree with multiple render trees to enable multi-view rendering (#125003)
This change enables Flutter to generate multiple Scenes to be rendered into separate FlutterViews from a single widget tree. Each Scene is described by a separate render tree, which are all associated with the single widget tree.

This PR implements the framework-side mechanisms to describe the content to be rendered into multiple views. Separate engine-side changes are necessary to provide these views to the framework and to draw the framework-generated Scene into them.

## Summary of changes

The details of this change are described in [flutter.dev/go/multiple-views](https://flutter.dev/go/multiple-views). Below is a high-level summary organized by layers.

### Rendering layer changes

* The `RendererBinding` no longer owns a single `renderView`. In fact, it doesn't OWN any `RenderView`s at all anymore. Instead, it offers an API (`addRenderView`/`removeRenderView`) to add and remove `RenderView`s that then will be MANAGED by the binding. The `RenderView` itself is now owned by a higher-level abstraction (e.g. the `RawView` Element of the widgets layer, see below), who is also in charge of adding it to the binding. When added, the binding will interact with the `RenderView` to produce a frame (e.g. by calling `compositeFrame` on it) and to perform hit tests for incoming pointer events. Multiple `RenderView`s can be added to the binding (typically one per `FlutterView`) to produce multiple Scenes.
* Instead of owning a single `pipelineOwner`, the `RendererBinding` now owns the root of the `PipelineOwner` tree (exposed as `rootPipelineOwner` on the binding). Each `PipelineOwner` in that tree (except for the root) typically manages its own render tree typically rooted in one of the `RenderView`s mentioned in the previous bullet. During frame production, the binding will instruct each `PipelineOwner` of that tree to flush layout, paint, semantics etc. A higher-level abstraction (e.g. the widgets layer, see below) is in charge of adding `PipelineOwner`s to this tree.
* Backwards compatibility: The old `renderView` and `pipelineOwner` properties of the `RendererBinding` are retained, but marked as deprecated. Care has been taken to keep their original behavior for the deprecation period, i.e. if you just call `runApp`, the render tree bootstrapped by this call is rooted in the deprecated `RendererBinding.renderView` and managed by the deprecated `RendererBinding.pipelineOwner`.

### Widgets layer changes

* The `WidgetsBinding` no longer attaches the widget tree to an existing render tree. Instead, it bootstraps a stand-alone widget tree that is not backed by a render tree. For this, `RenderObjectToWidgetAdapter` has been replaced by `RootWidget`.
* Multiple render trees can be bootstrapped and attached to the widget tree with the help of the `View` widget, which internally is backed by a `RawView` widget. Configured with a `FlutterView` to render into, the `RawView` creates a new `PipelineOwner` and a new `RenderView` for the new render tree. It adds the new `RenderView` to the `RendererBinding` and its `PipelineOwner` to the pipeline owner tree.
* The `View` widget can only appear in certain well-defined locations in the widget tree since it bootstraps a new render tree and does not insert a `RenderObject` into an ancestor. However, almost all Elements expect that their children insert `RenderObject`s, otherwise they will not function properly. To produce a good error message when the `View` widget is used in an illegal location, the `debugMustInsertRenderObjectIntoSlot` method has been added to Element, where a child can ask whether a given slot must insert a RenderObject into its ancestor or not. In practice, the `View` widget can be used as a child of the `RootWidget`, inside the `view` slot of the `ViewAnchor` (see below) and inside a `ViewCollection` (see below). In those locations, the `View` widget may be wrapped in other non-RenderObjectWidgets (e.g. InheritedWidgets).
* The new `ViewAnchor` can be used to create a side-view inside a parent `View`. The `child` of the `ViewAnchor` widget renders into the parent `View` as usual, but the `view` slot can take on another `View` widget, which has access to all inherited widgets above the `ViewAnchor`. Metaphorically speaking, the view is anchored to the location of the `ViewAnchor` in the widget tree.
* The new `ViewCollection` widget allows for multiple sibling views as it takes a list of `View`s as children. It can be used in all the places that accept a `View` widget.

## Google3

As of July 5, 2023 this change passed a TAP global presubmit (TGP) in google3: tap/OCL:544707016:BASE:545809771:1688597935864:e43dd651

## Note to reviewers

This change is big (sorry). I suggest focusing the initial review on the changes inside of `packages/flutter` first. The majority of the changes describe above are implemented in (listed in suggested review order):

* `rendering/binding.dart`
* `widgets/binding.dart`
* `widgets/view.dart`
* `widgets/framework.dart`

All other changes included in the PR are basically the fallout of what's implemented in those files. Also note that a lot of the lines added in this PR are documentation and tests.

I am also very happy to walk reviewers through the code in person or via video call, if that is helpful.

I appreciate any feedback.

## Feedback to address before submitting ("TODO")
2023-07-17 16:14:08 +00:00

166 lines
6.8 KiB
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.
/// The Flutter widgets framework.
///
/// To use, import `package:flutter/widgets.dart`.
///
/// See also:
///
/// * [flutter.dev/widgets](https://flutter.dev/widgets/)
/// for a catalog of commonly-used Flutter widgets.
library widgets;
export 'package:characters/characters.dart';
export 'package:vector_math/vector_math_64.dart' show Matrix4;
export 'foundation.dart' show UniqueKey;
export 'rendering.dart' show TextSelectionHandleType;
export 'src/widgets/actions.dart';
export 'src/widgets/adapter.dart';
export 'src/widgets/animated_cross_fade.dart';
export 'src/widgets/animated_scroll_view.dart';
export 'src/widgets/animated_size.dart';
export 'src/widgets/animated_switcher.dart';
export 'src/widgets/annotated_region.dart';
export 'src/widgets/app.dart';
export 'src/widgets/app_lifecycle_listener.dart';
export 'src/widgets/async.dart';
export 'src/widgets/autocomplete.dart';
export 'src/widgets/autofill.dart';
export 'src/widgets/automatic_keep_alive.dart';
export 'src/widgets/banner.dart';
export 'src/widgets/basic.dart';
export 'src/widgets/binding.dart';
export 'src/widgets/bottom_navigation_bar_item.dart';
export 'src/widgets/color_filter.dart';
export 'src/widgets/container.dart';
export 'src/widgets/context_menu_button_item.dart';
export 'src/widgets/context_menu_controller.dart';
export 'src/widgets/debug.dart';
export 'src/widgets/decorated_sliver.dart';
export 'src/widgets/default_selection_style.dart';
export 'src/widgets/default_text_editing_shortcuts.dart';
export 'src/widgets/desktop_text_selection_toolbar_layout_delegate.dart';
export 'src/widgets/dismissible.dart';
export 'src/widgets/display_feature_sub_screen.dart';
export 'src/widgets/disposable_build_context.dart';
export 'src/widgets/drag_target.dart';
export 'src/widgets/draggable_scrollable_sheet.dart';
export 'src/widgets/dual_transition_builder.dart';
export 'src/widgets/editable_text.dart';
export 'src/widgets/fade_in_image.dart';
export 'src/widgets/focus_manager.dart';
export 'src/widgets/focus_scope.dart';
export 'src/widgets/focus_traversal.dart';
export 'src/widgets/form.dart';
export 'src/widgets/framework.dart';
export 'src/widgets/gesture_detector.dart';
export 'src/widgets/grid_paper.dart';
export 'src/widgets/heroes.dart';
export 'src/widgets/icon.dart';
export 'src/widgets/icon_data.dart';
export 'src/widgets/icon_theme.dart';
export 'src/widgets/icon_theme_data.dart';
export 'src/widgets/image.dart';
export 'src/widgets/image_filter.dart';
export 'src/widgets/image_icon.dart';
export 'src/widgets/implicit_animations.dart';
export 'src/widgets/inherited_model.dart';
export 'src/widgets/inherited_notifier.dart';
export 'src/widgets/inherited_theme.dart';
export 'src/widgets/interactive_viewer.dart';
export 'src/widgets/keyboard_listener.dart';
export 'src/widgets/layout_builder.dart';
export 'src/widgets/list_wheel_scroll_view.dart';
export 'src/widgets/localizations.dart';
export 'src/widgets/lookup_boundary.dart';
export 'src/widgets/magnifier.dart';
export 'src/widgets/media_query.dart';
export 'src/widgets/modal_barrier.dart';
export 'src/widgets/navigation_toolbar.dart';
export 'src/widgets/navigator.dart';
export 'src/widgets/nested_scroll_view.dart';
export 'src/widgets/notification_listener.dart';
export 'src/widgets/orientation_builder.dart';
export 'src/widgets/overflow_bar.dart';
export 'src/widgets/overlay.dart';
export 'src/widgets/overscroll_indicator.dart';
export 'src/widgets/page_storage.dart';
export 'src/widgets/page_view.dart';
export 'src/widgets/pages.dart';
export 'src/widgets/performance_overlay.dart';
export 'src/widgets/placeholder.dart';
export 'src/widgets/platform_menu_bar.dart';
export 'src/widgets/platform_selectable_region_context_menu.dart';
export 'src/widgets/platform_view.dart';
export 'src/widgets/preferred_size.dart';
export 'src/widgets/primary_scroll_controller.dart';
export 'src/widgets/raw_keyboard_listener.dart';
export 'src/widgets/reorderable_list.dart';
export 'src/widgets/restoration.dart';
export 'src/widgets/restoration_properties.dart';
export 'src/widgets/router.dart';
export 'src/widgets/routes.dart';
export 'src/widgets/safe_area.dart';
export 'src/widgets/scroll_activity.dart';
export 'src/widgets/scroll_aware_image_provider.dart';
export 'src/widgets/scroll_configuration.dart';
export 'src/widgets/scroll_context.dart';
export 'src/widgets/scroll_controller.dart';
export 'src/widgets/scroll_delegate.dart';
export 'src/widgets/scroll_metrics.dart';
export 'src/widgets/scroll_notification.dart';
export 'src/widgets/scroll_notification_observer.dart';
export 'src/widgets/scroll_physics.dart';
export 'src/widgets/scroll_position.dart';
export 'src/widgets/scroll_position_with_single_context.dart';
export 'src/widgets/scroll_simulation.dart';
export 'src/widgets/scroll_view.dart';
export 'src/widgets/scrollable.dart';
export 'src/widgets/scrollable_helpers.dart';
export 'src/widgets/scrollbar.dart';
export 'src/widgets/selectable_region.dart';
export 'src/widgets/selection_container.dart';
export 'src/widgets/semantics_debugger.dart';
export 'src/widgets/service_extensions.dart';
export 'src/widgets/shared_app_data.dart';
export 'src/widgets/shortcuts.dart';
export 'src/widgets/single_child_scroll_view.dart';
export 'src/widgets/size_changed_layout_notifier.dart';
export 'src/widgets/sliver.dart';
export 'src/widgets/sliver_fill.dart';
export 'src/widgets/sliver_layout_builder.dart';
export 'src/widgets/sliver_persistent_header.dart';
export 'src/widgets/sliver_prototype_extent_list.dart';
export 'src/widgets/slotted_render_object_widget.dart';
export 'src/widgets/snapshot_widget.dart';
export 'src/widgets/spacer.dart';
export 'src/widgets/spell_check.dart';
export 'src/widgets/status_transitions.dart';
export 'src/widgets/table.dart';
export 'src/widgets/tap_and_drag_gestures.dart';
export 'src/widgets/tap_region.dart';
export 'src/widgets/text.dart';
export 'src/widgets/text_editing_intents.dart';
export 'src/widgets/text_selection.dart';
export 'src/widgets/text_selection_toolbar_anchors.dart';
export 'src/widgets/text_selection_toolbar_layout_delegate.dart';
export 'src/widgets/texture.dart';
export 'src/widgets/ticker_provider.dart';
export 'src/widgets/title.dart';
export 'src/widgets/transitions.dart';
export 'src/widgets/tween_animation_builder.dart';
export 'src/widgets/two_dimensional_scroll_view.dart';
export 'src/widgets/two_dimensional_viewport.dart';
export 'src/widgets/undo_history.dart';
export 'src/widgets/unique_widget.dart';
export 'src/widgets/value_listenable_builder.dart';
export 'src/widgets/view.dart';
export 'src/widgets/viewport.dart';
export 'src/widgets/visibility.dart';
export 'src/widgets/widget_inspector.dart';
export 'src/widgets/widget_span.dart';
export 'src/widgets/will_pop_scope.dart';