Repository navigation
Description
Background
Because of how pointer events are handled by the browser when interacting with platform views (HtmlElementView), Flutter web apps currently rely on the PointerInterceptor widget (from package:pointer_interceptor) when Flutter UI overlaps a platform view.
Developers must manually wrap widgets such as ModalBarrier, ListView, menus, or navigation drawers in a PointerInterceptor to prevent an underlying platform view (especially <iframe>s, maps, or video) from swallowing pointer events (see #144354 and #93887). In large apps, tracking every widget that might paint above a platform view is error-prone and does not scale.
The Solution
Instead of requiring manual widget wrapping, we are building Automatic Pointer Interception across the Flutter framework and Web Engine (RFC: flutter/rfc#39, tracked in #179806):
- Platform-View-Gated Hit-Region Pass (
packages/flutter): After compositing each frame on the web,PipelineOwner.flushHitTestRegionswalks render objects in paint order (visitChildrenInPaintOrder)—gated so it runs only when at least one platform view is attached (zero overhead for apps or screens without platform views) and skips platform-view-free subtrees via a subtree count index. Render objects describe their own hit-testing behavior viahitTestsChildren,hitTestsChildrenOutsideBounds, andvisitHitTestRegionswithout hard-coded widget lists. - Per-View Region Delivery (
dart:ui): The framework dispatches paint-ordered groups of physical-pixel rects per view viaFlutterView.updateHitTestRegions(Float64List), synchronized with frame scene rendering. - Web Engine Hit-Test Proxies (
lib/web_ui): During scene composition,PlatformViewEmbedderinterleaves<flt-hit-test-proxy>groups immediately after each platform view's DOM slot. Because DOM order matches Flutter paint order, an overlay barrier blocks a background platform view without blocking a second platform view rendered inside a foreground dialog. Intercepted browser events bubble naturally to the view root'sPointerBinding. - Pointer Capture Across
<iframe>s: Active pointer drags originating on Flutter content or hit-test proxies capture the pointer on<flutter-view>([web] Capture pointers to the Flutter view so drags survive platform view iframes #195187) so mouse and stylus drags are not swallowed mid-gesture when crossing an<iframe>.
(Note: This supersedes the framework-level proposals in #144354 and #93887, as well as the initial "No-DOM Semantics" prototype in #190576, which was dropped after benchmarking showed 30–100% drawFrameDuration regressions from running flushSemantics by default and semantics coverage gaps on desktop ModalBarriers.)
Roadmap
- 1. Evaluate "No-DOM Semantics" prototype & benchmarks (Implement 'No-DOM' Semantics Mode and Benchmarks #190576 — closed; superseded by the gated hit-region pass)
- 2. Pointer capture on
<flutter-view>across<iframe>platform views ([web] Capture pointers to the Flutter view so drags survive platform view iframes #195187) - 3. Real WebDriver pointer actions in
package:integration_testfor browser hit-test e2e tests (Add real WebDriver pointer actions to package:integration_test on the web #195207) - 4. Opt-in framework hit-region pass &
hitTestsChildrenhook (Add an opt-in framework hit-test region pass for platform views #195607 — in review) - 5.
FlutterView.updateHitTestRegionsand Web Engine<flt-hit-test-proxy>scene interleaving (Implement Hit Test Proxies and Scene Interleaving #190577) - 6. Paint-order traversal (
visitChildrenInPaintOrder), custom hit-region hooks (visitHitTestRegions,hitTestsChildrenOutsideBounds), Material tap-target overrides, and debug hit-test cross-check - 7. Worst-case walk benchmarks, platform-view subtree index, multi-view lifecycle handling, and enabling
automaticPointerInterceptorsEnabledby default on the web
Activity
[-][Umbrella] Automatic Pointer Interceptors for Platform Views on Web[/-][+]☔️ Automatic Pointer Interceptors for Platform Views on Web[/+]fix(shell): 压在舞台 iframe 上的控件垫指针垫层 + 删掉左侧分区 rail(⑪⑫)
harryterkelsen commentedon Oct 28, 2026
Update on architecture and implementation roadmap:
We've completed performance benchmarking of the initial "No-DOM Semantics" prototype (sub-issue #190576) and found that enabling framework semantics by default introduces a 30–100%
drawFrameDurationregression across widget-heavy benchmarks, alongside accessibility edge cases whereModalBarrieris omitted on desktop platforms. Consequently, #190576 has been closed and the semantics-by-default approach has been dropped.Instead, we are proceeding with a dedicated, platform-view-gated hit-region pass:
PipelineOwner.flushHitTestRegions) that walks render objects in paint order only when platform views are active, generating hit-test rects for widgets painted above platform views.FlutterView.updateHitTestRegions, and the Web Engine interleaves<flt-hit-test-proxy>elements with platform views in<flt-scene>to route browser pointer events back to the Flutter view.<flutter-view>landed in [web] Capture pointers to the Flutter view so drags survive platform view iframes #195187 to ensure drags survive over<iframe>platform views.Implementation of the hit-region pass and proxies is staged in draft PRs and being prepared for upstream review. Sub-issue #190577 will be updated to reflect the new hit-region integration.
harryterkelsen commentedon Oct 29, 2026
The design, and the alternatives we considered (inlining
pointer_interceptor, semantics, and recording regions during paint), are now written up as an RFC: flutter/rfc#39 (tracked in #179806)