[webview_flutter] Register the iOS platform view with the hit-test gesture blocking policy - #12496
[webview_flutter] Register the iOS platform view with the hit-test gesture blocking policy#12496burakJs wants to merge 1 commit into
Conversation
…sture policy The default eager policy blocks the platform view's gesture recognizers through Flutter's stateful gesture arena. When that state is stranded the web view stops receiving touches for the rest of its lifetime, which reproduces on iOS 26 where the engine's stuck-state reset is disabled. The doNotBlockGesture policy derives the same blocking decision from hit testing, so there is no recognizer state left to strand.
There was a problem hiding this comment.
Code Review
This pull request registers the iOS platform view with the hit-test based gesture blocking policy (FlutterPlatformViewGestureRecognizersBlockingPolicyDoNotBlockGesture) to prevent web views from becoming unresponsive to touches. It also adds a corresponding unit test and bumps the package version to 3.26.1. Feedback suggests using the more idiomatic Swift enum case .doNotBlockGesture instead of the verbose Objective-C name in both the plugin registration and the test file.
| registrar.register( | ||
| viewFactory, withId: "plugins.flutter.io/webview", | ||
| gestureRecognizersBlockingPolicy: | ||
| FlutterPlatformViewGestureRecognizersBlockingPolicyDoNotBlockGesture) |
There was a problem hiding this comment.
In Swift, Objective-C enums are imported with shortened, idiomatic names. You can use .doNotBlockGesture instead of the verbose FlutterPlatformViewGestureRecognizersBlockingPolicyDoNotBlockGesture to make the code cleaner and more idiomatic.
registrar.register(
viewFactory, withId: "plugins.flutter.io/webview",
gestureRecognizersBlockingPolicy: .doNotBlockGesture)There was a problem hiding this comment.
.doNotBlockGesture does not compile here. The policy is declared in FlutterPlugin.h as a plain C enum:
typedef enum {
FlutterPlatformViewGestureRecognizersBlockingPolicyEager,
FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded,
FlutterPlatformViewGestureRecognizersBlockingPolicyDoNotBlockGesture,
} FlutterPlatformViewGestureRecognizersBlockingPolicy;Because it is not declared with NS_ENUM, the Swift importer does not shorten the case names. Building an app against Flutter 3.47.0 with the shortened form fails with:
Swift Compiler Error: Type 'FlutterPlatformViewGestureRecognizersBlockingPolicy' has no member 'doNotBlockGesture'
So the fully qualified constant is intentional. Happy to switch if the enum is ever annotated for Swift.
There was a problem hiding this comment.
We should pass in the policy from the dart side instead: https://github.com/flutter/flutter/blob/f6061d0003a7a9e0cb30a45379c4c4bec0412c40/packages/flutter/lib/src/services/platform_views.dart#L1630
I'm glad that the new doNotBlockGesture policy works for you. However, this policy is designed as the last resort to deal with bugs of the platform view itself (e.g. WKWebView).
So it would be great if you can provide a reproducible project so we can look further.
| #expect( | ||
| registrar.registeredGestureRecognizersBlockingPolicy | ||
| == FlutterPlatformViewGestureRecognizersBlockingPolicyDoNotBlockGesture) |
There was a problem hiding this comment.
Same reason as the other comment: the enum is declared as a plain C typedef enum rather than NS_ENUM, so the Swift importer keeps the full constant names and .doNotBlockGesture fails to compile.
| registrar.register( | ||
| viewFactory, withId: "plugins.flutter.io/webview", | ||
| gestureRecognizersBlockingPolicy: | ||
| FlutterPlatformViewGestureRecognizersBlockingPolicyDoNotBlockGesture) |
There was a problem hiding this comment.
We should pass in the policy from the dart side instead: https://github.com/flutter/flutter/blob/f6061d0003a7a9e0cb30a45379c4c4bec0412c40/packages/flutter/lib/src/services/platform_views.dart#L1630
I'm glad that the new doNotBlockGesture policy works for you. However, this policy is designed as the last resort to deal with bugs of the platform view itself (e.g. WKWebView).
So it would be great if you can provide a reproducible project so we can look further.
Registers the iOS platform view with
FlutterPlatformViewGestureRecognizersBlockingPolicyDoNotBlockGestureinstead of relying on the defaulteagerpolicy.eagerblocks the platform view's gesture recognizers through Flutter's gesture arena, which is stateful. If that state is stranded the web view stops receiving touches for the rest of its lifetime. The engine used to recover from this inForwardingGestureRecognizer.forceResetStateIfNeeded, but that reset returns early on iOS 26 and above (see flutter/flutter#179907), so on iOS 26 there is nothing left to recover it.doNotBlockGesturederives the same blocking decision fromhitTestrather than the arena, and does not install the delaying recognizer at all — so there is no recognizer state to strand. Blocking behaviour itself is preserved:FlutterTouchInterceptingView.hitTeststill consultsplatformViewShouldAcceptTouchAtTouchBeganLocation:and returns itself when a Flutter widget is on top, and the forwarding recognizer is still installed so Flutter's arena keeps seeing the touches.Verified on iOS 26.3 simulator, iOS 26.4 simulator and an iOS 26.6 device: the web view is unresponsive after the first interaction without this change, and behaves correctly with it.
Fixes flutter/flutter#191267
Open question for the reviewer: this change is unconditional rather than gated behind
if #available(iOS 26.0, *). I went that way because it is not iOS-26-specific in principle — the arena state can be stranded on any version, iOS 26 just removed the net that used to hide it — and because it matches the direction described in flutter/flutter#175099 ("help prevent regressions even if this WebKit bug happens again"). Happy to add a version gate instead if you would rather keep the blast radius smaller.Pre-Review Checklist
[shared_preferences]///).