Skip to content

Add workaround for WKWebView gesture recognizer issue - #1150

Open
jordanstreiff wants to merge 1 commit into
falling-fruit:mainfrom
jordanstreiff:fix/ios-wkwebview-gesture-recognizer
Open

Add workaround for WKWebView gesture recognizer issue#1150
jordanstreiff wants to merge 1 commit into
falling-fruit:mainfrom
jordanstreiff:fix/ios-wkwebview-gesture-recognizer

Conversation

@jordanstreiff

@jordanstreiff jordanstreiff commented Jul 21, 2026

Copy link
Copy Markdown

Implemented a solution to address a known bug in WKWebView where gesture recognizers can become stuck after dismissing a remote-scene-hosted UI. When application becomes active we check to see if there are any stuck gesture recognizers and reset them.

Fix works when tested locally.

Closes #1147

@jordanstreiff
jordanstreiff force-pushed the fix/ios-wkwebview-gesture-recognizer branch from 13f56be to 3a90d9b Compare July 21, 2026 23:10
Reset WKWebView gesture recognizers stuck in the "possible" state after
dismissing the native photo picker. Trigger the reset from
applicationDidBecomeActive with short retries, toggling isEnabled on any
stuck recognizers in the web view hierarchy.

Co-authored-by: Cursor <cursoragent@cursor.com>
@jordanstreiff
jordanstreiff force-pushed the fix/ios-wkwebview-gesture-recognizer branch from 3a90d9b to 6e7bb83 Compare July 21, 2026 23:11
@ezwelty

ezwelty commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Thanks @jordanstreiff, brutal bug so great to have a fix, even if somewhat hacky. Before I dig deeper, is the bug also present in a simulator, or did this require a device?

@jordanstreiff

Copy link
Copy Markdown
Author

Also present in simulator!

@wbazant
wbazant requested a review from ezwelty July 23, 2026 21:06
@wbazant

wbazant commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Amazing that the ecosystem ships with those escape hatches where you can add such code! Can't think of any reason not to reset after an 'application became active' - not much severity if you interrupt a gesture recognition either - so i agree it seems like a safe fix. Didn't test, just read it.

@ezwelty

ezwelty commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

@jordanstreiff Tested and could reproduce the bug in the simulator (iPhone 17, iOS 26.3). Trouble is that I could not reproduce the fix: the app freezes. scheduleStuckWebViewGesturesReset is run on app start, but not after image selection. I also tried the UINavigationController fix in ionic-team/capacitor#7106 and it didn't help either. Thoughts?

The log in XCode shows right before the freeze:

⚡️ To Native -> Camera getPhoto 2150549
WebContent[88312] 0x115048150 - [sessionID=1] WebProcess::updateFreezerStatus: isFreezable=1, error=-1 -[RTIInputSystemClient remoteTextInputSessionWithID:performInputOperation:] perform input operation requires a valid sessionID. inputModality = Keyboard, inputOperation = , customInfoType = UIEmojiSearchOperations
⚡️ TO JS {"format":"jpeg","path":"file:///Users/ewelty/Library/Developer/CoreSimulator/Devices/764DC76D-A43A-4A32-A59E-2BBF287A72CE/data/Containers/Data/Application/D135E6F5-A5DA-416F-98D0-BA17E068B879/tmp/photo-3.jpg","exif":{"DateTimeOriginal":"20

Then after a while:

0x1380e80c0 - [PID=88312] WebProcessProxy::didBecomeUnresponsive:
0x105813020 - [pageProxyID=7, webPageID=8, PID=88312] WebPageProxy::processDidBecomeUnresponsive:

Then when I try clicking on something:

[!] <_UITouchDurationObservingGestureRecognizer: 0x10601f930 "com.apple.UIKit.longPressClickDriverPrimary"; id = 54; phase = blocked(by: 19) | active, ended> is blocking its subgraph for 124.85258174299999 seconds:
<UITapAndAHalfRecognizer: 0x106409080 "UITextInteractionNameTapAndAHalf"; id = 162; phase = failed>
<UITextTapRecognizer: 0x106408df0 "UITextInteractionNameDoubleTap"; id = 161; phase = failed(excluded(by: 36)>
<WKDeferringGestureRecognizer: 0x106018a70 "Deferrer for touch move"; id = 25; phase = failed>
<UITapGestureRecognizer: 0x10601a690; id = 32; phase = failed(nonTap)>
<UILongPressGestureRecognizer: 0x10601b620; id = 37; phase = failed(activationDenied)>
<UIScrollViewDelayedTouchesBeganGestureRecognizer: 0x102f0b1c0; id = 7; phase = failed(excluded(by: 36)>
<_UIRelationshipGestureRecognizer: 0x10601dd30 "com.apple.UIKit.dragFailureRelationships"; id = 46; phase = failed>
<_UIRelationshipGestureRecognizer: 0x106026830 "com.apple.UIKit.clickPresentationExclusion"; id = 60; phase = failed(excluded(by: 36)>
<UITapGestureRecognizer: 0x10601ae60; id = 35; phase = failed(excluded(by: 36)>
<UITapGestureRecognizer: 0x10601c1e0; id = 51; phase = failed(excluded(by: 36)>
<_UISecondaryClickDriverGestureRecognizer: 0x106020010; id = 56; phase = failed>
<UITextTapRecognizer: 0x106404ca0 "UITextInteractionNameSingleTap"; id = 160; phase = failed(excluded(by: 36)>
<_UITapTapHoldGestureRecognizer: 0x106425850; id = 208; phase = failed(unexpectedButton)>
<_UIDragLiftGestureRecognizer: 0x10601d9f0 "com.apple.UIKit.dragInitiation"; id = 45; phase = failed(aborted)>
<WKDeferringGestureRecognizer: 0x106018ce0 "Deferrer for image analysis"; id = 26; phase = failed>
<UIPanGestureRecognizer: 0x102f0c460 "Scroll axis locking"; id = 9; phase = failed(touchesEnded)>
<_UISystemGestureGateGestureRecognizer: 0x106110ea0; id = 1; phase = failed(noLongerPossible)>
<_UIRelationshipGestureRecognizer: 0x106020c50 "com.apple.UIKit.clickPresentationFailure"; id = 59; phase = failed>
<_UIRelationshipGestureRecognizer: 0x10601df90 "com.apple.UIKit.dragExclusionRelationships"; id = 47; phase = failed>
<_UIVoiceCommandButtonTapGestureRecognizer: 0x10640be10; id = 209; phase = failed(unexpectedButton)>
<_UIRelationshipGestureRecognizer: 0x1060272b0 "com.apple.UIKit.clickPresentationFailure"; id = 61; phase = failed>
<_UIRelationshipGestureRecognizer: 0x106020b00 "com.apple.UIKit.clickPresentationExclusion"; id = 58; phase = failed(excluded(by: 36)>
<UITapGestureRecognizer: 0x10601a910; id = 33; phase = failed(excluded(by: 36)>
<UIScrollViewPanGestureRecognizer: 0x102f0bf00; id = 8; phase = failed(touchesEnded)>
<UIVariableDelayLoupeGesture: 0x10641fbd0 "UITextInteractionNameInteractiveRefinement"; id = 159; phase = failed(activationDenied)>
[!] <WKDeferringGestureRecognizer: 0x106017eb0 "Deferrer for touch start (synthetic tap)"; id = 21; phase = possible> is blocking its subgraph for 124.737644446 seconds:
<WKSyntheticTapGestureRecognizer: 0x10601a1c0; id = 31; phase = failed(excluded(by: 36)>

However, scheduleStuckWebViewGesturesReset does run if I click on home button, then on the app icon to reopen. But it doesn't actually restart anything, and the result is a blank white screen. Logs:

Scheduling reset of stuck WKWebView gestures in 0.0 seconds
Scheduling reset of stuck WKWebView gestures in 0.2 seconds
Scheduling reset of stuck WKWebView gestures in 0.5 seconds
Scheduling reset of stuck WKWebView gestures in 1.0 seconds
Scheduling reset of stuck WKWebView gestures in 2.0 seconds
-[RTIInputSystemClient remoteTextInputSessionWithID:performInputOperation:] Can only perform input operation for an active session. sessionID = 2B374427-5643-470D-B232-2E9F338D7A44
-[RTIInputSystemClient remoteTextInputSessionWithID:textSuggestionsChanged:] Can only set suggestions for an active session. sessionID = 2B374427-5643-470D-B232-2E9F338D7A44
[!] <WKDeferringGestureRecognizer: 0x106f21650 "Deferrer for touch start (immediate reset)"; id = 30; phase = possible> is blocking its subgraph for 190.477918243 seconds:
<UITapGestureRecognizer: 0x106f26060; id = 62; phase = failed(nonTap)>
<nil; id = 218; phase = failed(unexpectedButton)>
<WKDeferringGestureRecognizer: 0x106f228f0 "Deferrer for touch move"; id = 36; phase = failed>
<_UISystemGestureGateGestureRecognizer: 0x106f04f10; id = 7; phase = failed(noLongerPossible)>
<UITapGestureRecognizer: 0x106f24ce0; id = 46; phase = failed(nonTap)>
<nil; id = 217; phase = failed(unexpectedButton)>
<UIPanGestureRecognizer: 0x106f1a0a0 "Scroll axis locking"; id = 20; phase = failed(touchesEnded)>
<_UIRelationshipGestureRecognizer: 0x106f28cd0 "com.apple.UIKit.clickPresentationExclusion"; id = 71; phase = failed>
<UIScrollViewPanGestureRecognizer: 0x106f19c80; id = 19; phase = failed(touchesEnded)>
<_UISecondaryClickDriverGestureRecognizer: 0x106f24310; id = 67; phase = failed>
<UITextTapRecognizer: 0x106d55460 "UITextInteractionNameSingleTap"; id = 114; phase = failed(nonTap)>
<_UIRelationshipGestureRecognizer: 0x106f264d0 "com.apple.UIKit.clickPresentationExclusion"; id = 69; phase = failed>
<UIScrollViewDelayedTouchesBeganGestureRecognizer: 0x106f14510; id = 18; phase = failed(delayedTouchesDenied)>
[!] <WKDeferringGestureRecognizer: 0x106f218c0 "Deferrer for touch start (delayed reset)"; id = 31; phase = possible> is blocking its subgraph for 188.982587378 seconds:
<_UIRelationshipGestureRecognizer: 0x106f27c10 "com.apple.UIKit.dragExclusionRelationships"; id = 58; phase = failed>
<WKDeferringGestureRecognizer: 0x106f22b60 "Deferrer for image analysis"; id = 37; phase = failed>
<_UIDragLiftGestureRecognizer: 0x106f27670 "com.apple.UIKit.dragInitiation"; id = 56; phase = failed(aborted)>
<UITextTapRecognizer: 0x106d44f30 "UITextInteractionNameDoubleTap"; id = 115; phase = failed(nonTap)>
<UITapAndAHalfRecognizer: 0x106d26c10 "UITextInteractionNameTapAndAHalf"; id = 116; phase = failed>
<UITapGestureRecognizer: 0x106f24790; id = 44; phase = failed(nonTap)>
<_UIRelationshipGestureRecognizer: 0x106f279b0 "com.apple.UIKit.dragFailureRelationships"; id = 57; phase = failed>
<UITapGestureRecognizer: 0x106f24510; id = 43; phase = failed(nonTap)>
<_UIRelationshipGestureRecognizer: 0x106f28a70 "com.apple.UIKit.clickPresentationFailure"; id = 70; phase = failed>
<_UIRelationshipGestureRecognizer: 0x106f28f60 "com.apple.UIKit.clickPresentationFailure"; id = 72; phase = failed>
<UIVariableDelayLoupeGesture: 0x106d56460 "UITextInteractionNameInteractiveRefinement"; id = 113; phase = failed(activationDenied)>
[!] <WKDeferringGestureRecognizer: 0x106f22680 "Deferrer for touch end (synthetic tap)"; id = 35; phase = possible> is blocking its subgraph for 188.98196057299998 seconds:
<WKSyntheticTapGestureRecognizer: 0x106f24040; id = 42; phase = failed(nonTap)>
-[RTIInputSystemClient remoteTextInputSessionWithID:performInputOperation:] Can only perform input operation for an active session. sessionID = 2B374427-5643-470D-B232-2E9F338D7A44
-[RTIInputSystemClient remoteTextInputSessionWithID:textSuggestionsChanged:] Can only set suggestions for an active session. sessionID = 2B374427-5643-470D-B232-2E9F338D7A44
0x1340d80c0 - [PID=90500] WebProcessProxy::didBecomeUnresponsive:
0x10703b220 - [pageProxyID=7, webPageID=8, PID=90500] WebPageProxy::processDidBecomeUnresponsive:
0x10703b220 - [pageProxyID=7, webPageID=8, PID=90500] WebPageProxy::processDidBecomeUnresponsive:

@jordanstreiff

Copy link
Copy Markdown
Author

Interesting. Thanks for sharing the logs etc. Curious why it worked for me. I'll take another look.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

App freezes on iOS app when adding photo to new submission

3 participants