Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/web_ui/lib/src/engine/canvaskit/renderer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ class CanvasKitRenderer implements Renderer {
// added eagerly during initialization here and never touched, unless the
// system is reset due to hot restart or in a test.
_sceneHost = createDomElement('flt-scene');
embedder.addSceneToSceneHost(_sceneHost);
// TODO(harryterkelsen): Do this operation on the appropriate Flutter View.
final EngineFlutterView implicitView = EnginePlatformDispatcher.instance.implicitView!;
implicitView.dom.insertScene(_sceneHost!);
Comment thread
ditman marked this conversation as resolved.
Outdated
}

@override
Expand Down
14 changes: 1 addition & 13 deletions lib/web_ui/lib/src/engine/embedder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class FlutterViewEmbedder {
///
/// This element is inserted after the [semanticsHostElement] so that
/// platform views take precedence in DOM event handling.
DomElement get sceneHostElement => _sceneHostElement;
DomElement get sceneHostElementDEPRECATED => _sceneHostElement;
late DomElement _sceneHostElement;

/// A child element of body outside the shadowroot that hosts
Expand All @@ -102,18 +102,6 @@ class FlutterViewEmbedder {
DomElement? get sceneElement => _sceneElement;
DomElement? _sceneElement;

/// Don't unnecessarily move DOM nodes around. If a DOM node is
/// already in the right place, skip DOM mutation. This is both faster and
/// more correct, because moving DOM nodes loses internal state, such as
/// text selection.
void addSceneToSceneHost(DomElement? sceneElement) {
if (sceneElement != _sceneElement) {
_sceneElement?.remove();
_sceneElement = sceneElement;
_sceneHostElement.append(sceneElement!);
}
}

/// The element that captures input events, such as pointer events.
///
/// If semantics is enabled this element also contains the semantics DOM tree,
Expand Down
9 changes: 3 additions & 6 deletions lib/web_ui/lib/src/engine/html/renderer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ class HtmlRenderer implements Renderer {

late final HtmlFontCollection _fontCollection = HtmlFontCollection();

late FlutterViewEmbedder _viewEmbedder;

@override
HtmlFontCollection get fontCollection => _fontCollection;

Expand All @@ -38,9 +36,7 @@ class HtmlRenderer implements Renderer {
}

@override
void reset(FlutterViewEmbedder embedder) {
_viewEmbedder = embedder;
}
void reset(FlutterViewEmbedder embedder) {}

@override
ui.Paint createPaint() => SurfacePaint();
Expand Down Expand Up @@ -328,7 +324,8 @@ class HtmlRenderer implements Renderer {

@override
void renderScene(ui.Scene scene) {
_viewEmbedder.addSceneToSceneHost((scene as SurfaceScene).webOnlyRootElement);
final EngineFlutterView implicitView = EnginePlatformDispatcher.instance.implicitView!;
implicitView.dom.insertScene((scene as SurfaceScene).webOnlyRootElement!);
frameTimingsOnRasterFinish();
}

Expand Down
4 changes: 3 additions & 1 deletion lib/web_ui/lib/src/engine/skwasm/skwasm_impl/renderer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,9 @@ class SkwasmRenderer implements Renderer {

@override
void reset(FlutterViewEmbedder embedder) {
embedder.addSceneToSceneHost(sceneView.sceneElement);
// TODO(harryterkelsen): Do this operation on the appropriate Flutter View.
final EngineFlutterView implicitView = EnginePlatformDispatcher.instance.implicitView!;
implicitView.dom.insertScene(sceneView.sceneElement);
}

static final Map<String, Future<ui.FragmentProgram>> _programs = <String, Future<ui.FragmentProgram>>{};
Expand Down
20 changes: 20 additions & 0 deletions lib/web_ui/lib/src/engine/view_embedder/dom_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,24 @@ class DomManager {
/// Otherwise, the phone will disable focusing by touch, only by tabbing
/// around the UI.
DomElement get semanticsHost => _embedder.semanticsHostElementDEPRECATED;

DomElement get _sceneHost => _embedder.sceneHostElementDEPRECATED;

DomElement? _lastSceneElement;

/// Inserts the [sceneElement] into the DOM.
///
/// The [sceneElement] is inserted as a child of the <flt-scene-host> element
/// inside the [renderingHost].
///
/// If the [sceneElement] has already been inserted, this method does nothing
/// to avoid unnecessary DOM mutations. This is both faster and more correct,
/// because moving DOM nodes loses internal state, such as text selection.
void insertScene(DomElement sceneElement) {
Comment thread
ditman marked this conversation as resolved.
Outdated
if (sceneElement != _lastSceneElement) {
_lastSceneElement?.remove();
_lastSceneElement = sceneElement;
_sceneHost.append(sceneElement);
}
}
}
23 changes: 23 additions & 0 deletions lib/web_ui/test/engine/view_embedder/dom_manager_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,28 @@ void doTests() {
expect(domManager.textEditingHost, embedder.textEditingHostNodeDEPRECATED);
expect(domManager.semanticsHost, embedder.semanticsHostElementDEPRECATED);
});

test('insertScene', () {
final FlutterViewEmbedder embedder = FlutterViewEmbedder();
final DomManager domManager =
DomManager.fromFlutterViewEmbedderDEPRECATED(embedder);

final DomElement sceneHost =
domManager.renderingHost.querySelector('flt-scene-host')!;

final DomElement scene1 = createDomElement('flt-scene');
domManager.insertScene(scene1);
expect(sceneHost.children, <DomElement>[scene1]);

// Insert the same scene again.
domManager.insertScene(scene1);
expect(sceneHost.children, <DomElement>[scene1]);

// Insert a different scene.
final DomElement scene2 = createDomElement('flt-scene');
domManager.insertScene(scene2);
expect(sceneHost.children, <DomElement>[scene2]);
expect(scene1.parent, isNull);
});
});
}