Skip to content

[web][ck] (Invisible) HtmlElementViews optimized out too eagerly. #105485

@ditman

Description

@ditman

It seems that when an HtmlElementView is rendered as an overlay, it will get optimized out by the engine: its slot tag will never be rendered in the DOM (but its contents will).

This can be recreated with the PointerInterceptor widget.

Steps to Reproduce

  1. Create a new flutter app, and add a pointer_interceptor: ^0.9.3 dependency to it.
  2. Use the lib/main.dart below.
  3. Run the app: look at the JS development console.
lib/main.dart
// ignore: avoid_web_libraries_in_flutter
import 'dart:html' as html;
import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';

const String _htmlElementViewType = '_htmlElementViewType';
const double _videoWidth = 320;
const double _videoHeight = 200;

/// The html.Element that will be rendered underneath the flutter UI.
html.Element htmlElement = html.IFrameElement()
  ..style.width = '100%'
  ..style.height = '100%'
  ..id = 'background-html-view'
  ..src = 'https://www.youtube.com/embed/IyFZznAk69U'
  ..style.border = 'none';

void main() {
  ui.platformViewRegistry.registerViewFactory(
    _htmlElementViewType,
    (int viewId) => htmlElement,
  );

  runApp(const MyApp());
}

/// Main app
class MyApp extends StatelessWidget {
  /// Creates main app.
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(),
    );
  }
}

///
class MyHomePage extends StatefulWidget {
  ///
  const MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Future<void> _openDialog(BuildContext ctx) async {
    showDialog<void>(
        context: ctx,
        builder: (BuildContext context) {
          // The <slot> for this PointerInterceptor is never rendered!
          print('Find all slot tags by running:');
          print("\$('flt-glass-pane').shadowRoot.querySelectorAll('slot')");
          return PointerInterceptor(
            child: Text('Hullo!'),
          );
        });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('HtmlElementView invisible bug'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const SizedBox(
              width: _videoWidth,
              height: _videoHeight,
              child: HtmlElementView(
                viewType: _htmlElementViewType,
              ),
            ),
            ElevatedButton(
              child: const Text('Open dialog'),
              onPressed: () {
                _openDialog(context);
              },
            ),
          ],
        ),
      ),
    );
  }
}
  1. Click on the "Open dialog" button.
  2. Note how when hovering over the "Hullo!" text, the video underneath still responds to clicks and mouse movement, when it shouldn't.

The issue is that the "Hullo!" overlay does not intercept the mouse as expected, because the slot that would render the platform view that is used to intercept said clicks seems to not be rendered into the DOM.

Screen Shot 2022-06-06 at 5 44 57 PM

Things to note:

  • Notice how a flt-platform-view is added to the flt-glass-pane when opening the Dialog (as expected).
  • There's no slot tag that would reveal said platform view!

"Workarounds":

The things that have been tried that helped narrow this to a canvaskit + isVisible optimization:

  • Using the html renderer
  • Making the PointerInterceptor isVisible: true.

Is this a problem with the isVisible optimization, or should we reconsider making the PointerInterceptor isVisible: false?

Metadata

Metadata

Labels

e: web_canvaskitCanvasKit (a.k.a. Skia-on-WebGL) rendering backend for Webengineflutter/engine related. See also e: labels.platform-webWeb applications specifically

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions