Skip to content

[ Widget Preview ] Fix inspector split resize focus loss over WebViews#186432

Merged
auto-submit[bot] merged 6 commits into
flutter:masterfrom
bkonyi:fix_inspector_widget_preview
May 19, 2026
Merged

[ Widget Preview ] Fix inspector split resize focus loss over WebViews#186432
auto-submit[bot] merged 6 commits into
flutter:masterfrom
bkonyi:fix_inspector_widget_preview

Conversation

@bkonyi

@bkonyi bkonyi commented May 13, 2026

Copy link
Copy Markdown
Contributor

On Flutter Web, platform views (like webview iframes) reside in their own DOM subtrees positioned above the WebGL canvas. As a result, they capture native browser pointer events and prevent them from bubbling up to the main document. When a user drags the widget inspector split pane resize bar, the drag interaction loses focus as soon as the cursor crosses the boundary and hovers over the webview iframe.

To resolve this, we manipulate the CSS pointer-events property of native iframes directly:

  • When a split pane drag starts, pointer-events is set to 'none' on all document iframe elements. This causes the browser's native hit-testing to ignore the iframe and bubble pointer/drag events to the main document, allowing the splitter's gesture listener to track smoothly.
  • When the drag ends or cancels, pointer-events is reset to '' to restore full interactivity inside the iframe.

These changes are VM-safe (guarded by kIsWeb) and applied to both the scaffold source and the flutter_tools scaffold template.

Fixes #186431

On Flutter Web, platform views (like webview iframes) reside in their own DOM subtrees positioned above the WebGL canvas. As a result, they capture native browser pointer events and prevent them from bubbling up to the main document. When a user drags the widget inspector split pane resize bar, the drag interaction loses focus as soon as the cursor crosses the boundary and hovers over the webview iframe.

To resolve this, we manipulate the CSS pointer-events property of native iframes directly:
- When a split pane drag starts, `pointer-events` is set to `'none'` on all document `iframe` elements. This causes the browser's native hit-testing to ignore the iframe and bubble pointer/drag events to the main document, allowing the splitter's gesture listener to track smoothly.
- When the drag ends or cancels, `pointer-events` is reset to `''` to restore full interactivity inside the iframe.

These changes are VM-safe (guarded by `kIsWeb`) and applied to both the scaffold source and the flutter_tools scaffold template.

Fixes flutter#186431
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label May 13, 2026
@flutter-dashboard

Copy link
Copy Markdown

It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging.

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group.

@github-actions github-actions Bot added the tool Affects the "flutter" command-line tool. See also t: labels. label May 13, 2026
Adds split_test.dart to verify SplitPane sizing layout, drag-resize gesture handling, and direct web iframe pointer-events toggle focus management on Flutter Web.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a mechanism to toggle pointer-events on iframes during splitter drag operations to prevent focus loss on Flutter Web. Reviewers pointed out that the direct import of package:web is not VM-safe and will cause compilation errors on non-web targets, suggesting conditional imports. Feedback also highlighted the need for cleanup in the dispose method and a more robust tracking system, such as a counter, to handle multi-touch interactions and prevent persistent global side effects.

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:web/web.dart' as web;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The import of package:web is not VM-safe. Although the usage is guarded by kIsWeb, the import itself will cause compilation errors on non-web platforms (Android, iOS, Desktop) because package:web depends on dart:js_interop, which is only available on web targets. To maintain cross-platform compatibility, consider using conditional imports or moving the web-specific logic to a separate file that is only imported on web.

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:web/web.dart' as web;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The import of package:web is not VM-safe and will cause compilation failures on non-web platforms. Since this is a template, please use conditional imports to ensure the generated code is cross-platform compatible.

Comment on lines +114 to +123
void _toggleIframePointerEvents(bool disable) {
if (!kIsWeb) {
return;
}
final iframes = web.document.querySelectorAll('iframe');
for (int i = 0; i < iframes.length; i++) {
final iframe = iframes.item(i) as web.HTMLElement;
iframe.style.pointerEvents = disable ? 'none' : '';
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

If the SplitPane is disposed while a drag is active, the pointer-events: none style will persist on all iframes in the document, potentially breaking interactivity in other parts of the application. Consider tracking the dragging state and ensuring _toggleIframePointerEvents(false) is called in dispose if a drag was in progress.

Comment on lines +114 to +123
void _toggleIframePointerEvents(bool disable) {
if (!kIsWeb) {
return;
}
final iframes = web.document.querySelectorAll('iframe');
for (int i = 0; i < iframes.length; i++) {
final iframe = iframes.item(i) as web.HTMLElement;
iframe.style.pointerEvents = disable ? 'none' : '';
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This implementation may lead to inconsistent states with multi-touch interactions or multiple splitters. If one drag ends while another is still active, pointer events will be re-enabled prematurely. Using a static counter to track active drags across all splitters would make this more robust.

Comment on lines +114 to +123
void _toggleIframePointerEvents(bool disable) {
if (!kIsWeb) {
return;
}
final iframes = web.document.querySelectorAll('iframe');
for (int i = 0; i < iframes.length; i++) {
final iframe = iframes.item(i) as web.HTMLElement;
iframe.style.pointerEvents = disable ? 'none' : '';
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Consider adding cleanup in dispose and using a counter for active drags to avoid global side effects persisting or being cleared prematurely during multi-touch interactions.

@github-actions github-actions Bot removed the CICD Run CI/CD label May 13, 2026
@bkonyi bkonyi added the CICD Run CI/CD label May 13, 2026
…oggle

Moves the iframe pointer-events toggle logic into platform-specific conditional libraries (`pointer_events.dart`, `_pointer_events_stub.dart`, `_pointer_events_web.dart`) to avoid importing `package:web` on non-web platforms. This prevents test failures when running on the standalone Dart VM.
@github-actions github-actions Bot removed the CICD Run CI/CD label May 13, 2026
@bkonyi bkonyi added the CICD Run CI/CD label May 13, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label May 13, 2026
@bkonyi bkonyi added the CICD Run CI/CD label May 13, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label May 14, 2026
@bkonyi bkonyi added the CICD Run CI/CD label May 14, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label May 14, 2026
@bkonyi bkonyi requested a review from srawlins May 19, 2026 15:14
@bkonyi bkonyi added the CICD Run CI/CD label May 19, 2026

@srawlins srawlins left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice tests! Just some comments about copyright years.

Comment thread dev/integration_tests/widget_preview_scaffold/test/split_test.dart
@bkonyi bkonyi added the autosubmit Merge PR when tree becomes green via auto submit App label May 19, 2026
@auto-submit auto-submit Bot added this pull request to the merge queue May 19, 2026
Merged via the queue into flutter:master with commit b436693 May 19, 2026
171 of 172 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label May 19, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request May 20, 2026
flutter/flutter@259aeae...e03b91f

2026-05-20 engine-flutter-autoroll@skia.org Roll Packages from ade10ca to 1dfbada (6 revisions) (flutter/flutter#186811)
2026-05-20 brunocorona.alcantar@gmail.com Fix AnimatedList.separated assert when removing last item mid-removal… (flutter/flutter#186389)
2026-05-20 engine-flutter-autoroll@skia.org Roll Skia from d45969a5752e to 5f4f454b9662 (2 revisions) (flutter/flutter#186809)
2026-05-20 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from -F9Ci3Opxt06MixDl... to iKCvaD58jKStYGla0... (flutter/flutter#186796)
2026-05-20 engine-flutter-autoroll@skia.org Roll Skia from 19ad9707e5c6 to d45969a5752e (2 revisions) (flutter/flutter#186792)
2026-05-20 engine-flutter-autoroll@skia.org Roll Skia from 3471ebf5af0c to 19ad9707e5c6 (9 revisions) (flutter/flutter#186772)
2026-05-20 mdebbar@google.com [web] Refactor webparagraph painters to separate CK properly (flutter/flutter#186684)
2026-05-19 31859944+LongCatIsLooong@users.noreply.github.com Enable Swift testing in the iOS embedder (flutter/flutter#185712)
2026-05-19 mdebbar@google.com [web] Rename WebParagraph goldens (flutter/flutter#186680)
2026-05-19 engine-flutter-autoroll@skia.org Roll Skia from f1b406860c5e to 3471ebf5af0c (5 revisions) (flutter/flutter#186745)
2026-05-19 154381524+flutteractionsbot@users.noreply.github.com Revert "Ship gen_snapshot for linux-arm64 hosts targeting Android" (flutter/flutter#186693)
2026-05-19 bkonyi@google.com [ Tool ] Remove legacy analytics code (flutter/flutter#184994)
2026-05-19 chingjun@google.com Update Vulkan enum values (flutter/flutter#186694)
2026-05-19 1961493+harryterkelsen@users.noreply.github.com fix(web): Fixes CSS override detection when the browser has a default font size (flutter/flutter#186474)
2026-05-19 30870216+gaaclarke@users.noreply.github.com adds linux impeller hello world integration test (flutter/flutter#186715)
2026-05-19 jason-simmons@users.noreply.github.com Update the list of binaries in the code signing verification test to include new Dart snapshots (flutter/flutter#186754)
2026-05-19 brunocorona.alcantar@gmail.com Make EdgeDraggingAutoScroller respect ScrollPhysics (flutter/flutter#186541)
2026-05-19 bkonyi@google.com [ Widget Preview ] Fix inspector split resize focus loss over WebViews (flutter/flutter#186432)
2026-05-19 engine-flutter-autoroll@skia.org Roll Packages from b9bdd37 to ade10ca (1 revision) (flutter/flutter#186746)
2026-05-19 jason-simmons@users.noreply.github.com Manual Dart roll from 8e30b88e4d5a to 66873d2da857 (flutter/flutter#186690)
2026-05-19 bkonyi@google.com [ Widget Preview ] Improve zoom behavior and add zoom slider (flutter/flutter#186422)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
creatorpiyush pushed a commit to creatorpiyush/packages that referenced this pull request Jun 10, 2026
…r#11747)

flutter/flutter@259aeae...e03b91f

2026-05-20 engine-flutter-autoroll@skia.org Roll Packages from ade10ca to 1dfbada (6 revisions) (flutter/flutter#186811)
2026-05-20 brunocorona.alcantar@gmail.com Fix AnimatedList.separated assert when removing last item mid-removal… (flutter/flutter#186389)
2026-05-20 engine-flutter-autoroll@skia.org Roll Skia from d45969a5752e to 5f4f454b9662 (2 revisions) (flutter/flutter#186809)
2026-05-20 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from -F9Ci3Opxt06MixDl... to iKCvaD58jKStYGla0... (flutter/flutter#186796)
2026-05-20 engine-flutter-autoroll@skia.org Roll Skia from 19ad9707e5c6 to d45969a5752e (2 revisions) (flutter/flutter#186792)
2026-05-20 engine-flutter-autoroll@skia.org Roll Skia from 3471ebf5af0c to 19ad9707e5c6 (9 revisions) (flutter/flutter#186772)
2026-05-20 mdebbar@google.com [web] Refactor webparagraph painters to separate CK properly (flutter/flutter#186684)
2026-05-19 31859944+LongCatIsLooong@users.noreply.github.com Enable Swift testing in the iOS embedder (flutter/flutter#185712)
2026-05-19 mdebbar@google.com [web] Rename WebParagraph goldens (flutter/flutter#186680)
2026-05-19 engine-flutter-autoroll@skia.org Roll Skia from f1b406860c5e to 3471ebf5af0c (5 revisions) (flutter/flutter#186745)
2026-05-19 154381524+flutteractionsbot@users.noreply.github.com Revert "Ship gen_snapshot for linux-arm64 hosts targeting Android" (flutter/flutter#186693)
2026-05-19 bkonyi@google.com [ Tool ] Remove legacy analytics code (flutter/flutter#184994)
2026-05-19 chingjun@google.com Update Vulkan enum values (flutter/flutter#186694)
2026-05-19 1961493+harryterkelsen@users.noreply.github.com fix(web): Fixes CSS override detection when the browser has a default font size (flutter/flutter#186474)
2026-05-19 30870216+gaaclarke@users.noreply.github.com adds linux impeller hello world integration test (flutter/flutter#186715)
2026-05-19 jason-simmons@users.noreply.github.com Update the list of binaries in the code signing verification test to include new Dart snapshots (flutter/flutter#186754)
2026-05-19 brunocorona.alcantar@gmail.com Make EdgeDraggingAutoScroller respect ScrollPhysics (flutter/flutter#186541)
2026-05-19 bkonyi@google.com [ Widget Preview ] Fix inspector split resize focus loss over WebViews (flutter/flutter#186432)
2026-05-19 engine-flutter-autoroll@skia.org Roll Packages from b9bdd37 to ade10ca (1 revision) (flutter/flutter#186746)
2026-05-19 jason-simmons@users.noreply.github.com Manual Dart roll from 8e30b88e4d5a to 66873d2da857 (flutter/flutter#186690)
2026-05-19 bkonyi@google.com [ Widget Preview ] Improve zoom behavior and add zoom slider (flutter/flutter#186422)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
via-guy pushed a commit to via-guy/flutter that referenced this pull request Jun 26, 2026
flutter#186432)

On Flutter Web, platform views (like webview iframes) reside in their
own DOM subtrees positioned above the WebGL canvas. As a result, they
capture native browser pointer events and prevent them from bubbling up
to the main document. When a user drags the widget inspector split pane
resize bar, the drag interaction loses focus as soon as the cursor
crosses the boundary and hovers over the webview iframe.

To resolve this, we manipulate the CSS pointer-events property of native
iframes directly:
- When a split pane drag starts, `pointer-events` is set to `'none'` on
all document `iframe` elements. This causes the browser's native
hit-testing to ignore the iframe and bubble pointer/drag events to the
main document, allowing the splitter's gesture listener to track
smoothly.
- When the drag ends or cancels, `pointer-events` is reset to `''` to
restore full interactivity inside the iframe.

These changes are VM-safe (guarded by `kIsWeb`) and applied to both the
scaffold source and the flutter_tools scaffold template.

Fixes flutter#186431
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ Widget Preview ] Embedded widget inspector steals pointer focus when resizing

3 participants