@@ -24,7 +24,8 @@ import 'view_embedder/embedding_strategy/embedding_strategy.dart';
2424/// Manages several top-level elements that host Flutter-generated content,
2525/// including:
2626///
27- /// - [glassPaneElement] , the root element of a Flutter view.
27+ /// - [flutterViewElement] , the root element of a Flutter view.
28+ /// - [glassPaneElement] , the glass pane element that hosts the shadowDOM.
2829/// - [glassPaneShadow] , the shadow root used to isolate Flutter-rendered
2930/// content from the surrounding page content, including from the platform
3031/// views.
@@ -62,7 +63,10 @@ class FlutterViewEmbedder {
6263 /// Abstracts all the DOM manipulations required to embed a Flutter app in an user-supplied `hostElement` .
6364 final EmbeddingStrategy _embeddingStrategy;
6465
65- // The tag name for the root view of the flutter app (glass-pane)
66+ // The tag name for the Flutter View, which hosts the app.
67+ static const String flutterViewTagName = 'flutter-view' ;
68+
69+ // The tag name for the glass-pane.
6670 static const String glassPaneTagName = 'flt-glass-pane' ;
6771
6872 /// The element that contains the [sceneElement] .
@@ -117,13 +121,19 @@ class FlutterViewEmbedder {
117121 /// which captures semantics input events. The semantics DOM tree must be a
118122 /// child of the glass pane element so that events bubble up to the glass pane
119123 /// if they are not handled by semantics.
124+ DomElement get flutterViewElement => _flutterViewElement;
125+ late DomElement _flutterViewElement;
126+
120127 DomElement get glassPaneElement => _glassPaneElement;
121128 late DomElement _glassPaneElement;
122129
123130 /// The [HostNode] of the [glassPaneElement] , which contains the whole Flutter app.
124131 HostNode get glassPaneShadow => _glassPaneShadow;
125132 late HostNode _glassPaneShadow;
126133
134+ DomElement get textEditingHostNode => _textEditingHostNode;
135+ late DomElement _textEditingHostNode;
136+
127137 static const String defaultFontStyle = 'normal' ;
128138 static const String defaultFontWeight = 'normal' ;
129139 static const double defaultFontSize = 14 ;
@@ -149,14 +159,17 @@ class FlutterViewEmbedder {
149159 );
150160
151161 // Create and inject the [_glassPaneElement].
162+ _flutterViewElement = domDocument.createElement (flutterViewTagName);
152163 _glassPaneElement = domDocument.createElement (glassPaneTagName);
153164
165+
154166 // This must be attached to the DOM now, so the engine can create a host
155167 // node (ShadowDOM or a fallback) next.
156168 //
157169 // The embeddingStrategy will take care of cleaning up the glassPane on hot
158170 // restart.
159- _embeddingStrategy.attachGlassPane (glassPaneElement);
171+ _embeddingStrategy.attachGlassPane (flutterViewElement);
172+ flutterViewElement.appendChild (glassPaneElement);
160173
161174 // Create a [HostNode] under the glass pane element, and attach everything
162175 // there, instead of directly underneath the glass panel.
@@ -168,6 +181,9 @@ class FlutterViewEmbedder {
168181 );
169182 _glassPaneShadow = glassPaneElementHostNode;
170183
184+ _textEditingHostNode =
185+ createTextEditingHostNode (flutterViewElement, defaultCssFont);
186+
171187 // Don't allow the scene to receive pointer events.
172188 _sceneHostElement = domDocument.createElement ('flt-scene-host' )
173189 ..style.pointerEvents = 'none' ;
@@ -189,20 +205,20 @@ class FlutterViewEmbedder {
189205 glassPaneElementHostNode.appendAll (< DomNode > [
190206 accessibilityPlaceholder,
191207 _sceneHostElement! ,
192-
193- // The semantic host goes last because hit-test order-wise it must be
194- // first. If semantics goes under the scene host, platform views will
195- // obscure semantic elements.
196- //
197- // You may be wondering: wouldn't semantics obscure platform views and
198- // make then not accessible? At least with some careful planning, that
199- // should not be the case. The semantics tree makes all of its non-leaf
200- // elements transparent. This way, if a platform view appears among other
201- // interactive Flutter widgets, as long as those widgets do not intersect
202- // with the platform view, the platform view will be reachable.
203- semanticsHostElement,
204208 ]);
205209
210+ // The semantic host goes last because hit-test order-wise it must be
211+ // first. If semantics goes under the scene host, platform views will
212+ // obscure semantic elements.
213+ //
214+ // You may be wondering: wouldn't semantics obscure platform views and
215+ // make then not accessible? At least with some careful planning, that
216+ // should not be the case. The semantics tree makes all of its non-leaf
217+ // elements transparent. This way, if a platform view appears among other
218+ // interactive Flutter widgets, as long as those widgets do not intersect
219+ // with the platform view, the platform view will be reachable.
220+ flutterViewElement.appendChild (semanticsHostElement);
221+
206222 // When debugging semantics, make the scene semi-transparent so that the
207223 // semantics tree is more prominent.
208224 if (configuration.debugShowSemanticsNodes) {
@@ -211,7 +227,7 @@ class FlutterViewEmbedder {
211227
212228 KeyboardBinding .initInstance ();
213229 PointerBinding .initInstance (
214- glassPaneElement ,
230+ flutterViewElement ,
215231 KeyboardBinding .instance! .converter,
216232 );
217233
@@ -336,7 +352,7 @@ class FlutterViewEmbedder {
336352 if (isWebKit) {
337353 // The resourcesHost *must* be a sibling of the glassPaneElement.
338354 _embeddingStrategy.attachResourcesHost (resourcesHost,
339- nextTo: glassPaneElement );
355+ nextTo: flutterViewElement );
340356 } else {
341357 glassPaneShadow.node
342358 .insertBefore (resourcesHost, glassPaneShadow.node.firstChild);
@@ -393,3 +409,24 @@ FlutterViewEmbedder? _flutterViewEmbedder;
393409FlutterViewEmbedder ensureFlutterViewEmbedderInitialized () =>
394410 _flutterViewEmbedder ?? =
395411 FlutterViewEmbedder (hostElement: configuration.hostElement);
412+
413+ /// Creates a node to host text editing elements and applies a stylesheet
414+ /// to Flutter nodes that exist outside of the shadowDOM.
415+ DomElement createTextEditingHostNode (DomElement root, String defaultFont) {
416+ final DomElement domElement =
417+ domDocument.createElement ('flt-text-editing-host' );
418+ final DomHTMLStyleElement styleElement = createDomHTMLStyleElement ();
419+
420+ styleElement.id = 'flt-text-editing-stylesheet' ;
421+ root.appendChild (styleElement);
422+ applyGlobalCssRulesToSheet (
423+ styleElement.sheet! as DomCSSStyleSheet ,
424+ hasAutofillOverlay: browserHasAutofillOverlay (),
425+ cssSelectorPrefix: FlutterViewEmbedder .flutterViewTagName,
426+ defaultCssFont: defaultFont,
427+ );
428+
429+ root.appendChild (domElement);
430+
431+ return domElement;
432+ }
0 commit comments