[ Widget Preview ] Fix inspector split resize focus loss over WebViews#186432
Conversation
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
|
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. |
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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; |
| 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' : ''; | ||
| } | ||
| } |
There was a problem hiding this comment.
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.
| 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' : ''; | ||
| } | ||
| } |
There was a problem hiding this comment.
| 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' : ''; | ||
| } | ||
| } |
…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.
srawlins
left a comment
There was a problem hiding this comment.
Nice tests! Just some comments about copyright years.
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
…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
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
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:
pointer-eventsis set to'none'on all documentiframeelements. 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.pointer-eventsis 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