Skip to content

Commit 7b60c3f

Browse files
committed
[iOS] Active pointer map may fail to clear in presence of external gesture recognizer
https://bugs.webkit.org/show_bug.cgi?id=306373 rdar://159227684 Reviewed by Abrar Rahman Protyasha. When a WKWebView is the subview of a parent view which itself has a custom gesture recognizer, the custom gesture recognizer may block gestures in such a way that `touchesBegan` fires for WebKit's touch gesture recognizer, but not `touchesEnded` or `touchesCancelled`. When this happens, we add an active pointer to the map in PointerCaptureController but never clear it since we never received a notification that the touch ended or was otherwise cancelled. When an active touch is present in the map, we do not create pointer events in `PointerCaptureController::pointerEventForMouseEvent`, so if the parent view later stops blocking touch gestures, WebKit may continue to fail to dispatch pointer and click events afterward. Resolve this by clearing the active pointer map when `reset` is called for `WKTouchEventsGestureRecognizer`. * Source/WebCore/page/PointerCaptureController.h: * Source/WebKit/UIProcess/WebPageProxy.cpp: (WebKit::WebPageProxy::resetPointerCapture): * Source/WebKit/UIProcess/WebPageProxy.h: * Source/WebKit/UIProcess/ios/WKContentViewInteraction.h: * Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm: (-[WKContentView _touchEventsGestureRecognizerReset]): * Source/WebKit/UIProcess/ios/WKTouchEventsGestureRecognizer.mm: (-[WKTouchEventsGestureRecognizer reset]): * Source/WebKit/WebProcess/WebPage/WebPage.cpp: (WebKit::WebPage::resetPointerCapture): * Source/WebKit/WebProcess/WebPage/WebPage.h: * Source/WebKit/WebProcess/WebPage/WebPage.messages.in: Canonical link: https://commits.webkit.org/306362@main
1 parent 19a4329 commit 7b60c3f

9 files changed

Lines changed: 22 additions & 1 deletion

File tree

Source/WebCore/page/PointerCaptureController.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class PointerCaptureController {
5656
ExceptionOr<void> setPointerCapture(Element*, PointerID);
5757
ExceptionOr<void> releasePointerCapture(Element*, PointerID);
5858
bool hasPointerCapture(Element*, PointerID);
59-
void reset();
59+
WEBCORE_EXPORT void reset();
6060

6161
void pointerLockWasApplied();
6262
void elementWasRemoved(Element&);

Source/WebKit/UIProcess/WebPageProxy.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4895,6 +4895,11 @@ void WebPageProxy::touchWithIdentifierWasRemoved(WebCore::PointerID pointerId)
48954895
send(Messages::WebPage::TouchWithIdentifierWasRemoved(pointerId));
48964896
}
48974897

4898+
void WebPageProxy::resetPointerCapture()
4899+
{
4900+
send(Messages::WebPage::ResetPointerCapture());
4901+
}
4902+
48984903
void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
48994904
{
49004905
if (!hasRunningProcess())

Source/WebKit/UIProcess/WebPageProxy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,7 @@ class WebPageProxy final : public API::ObjectImpl<API::Object::Type::Page>, publ
14401440

14411441
void cancelPointer(WebCore::PointerID, const WebCore::IntPoint&);
14421442
void touchWithIdentifierWasRemoved(WebCore::PointerID);
1443+
void resetPointerCapture();
14431444

14441445
void scrollBy(WebCore::ScrollDirection, WebCore::ScrollGranularity);
14451446
void centerSelectionInVisibleArea();

Source/WebKit/UIProcess/ios/WKContentViewInteraction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,7 @@ FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW)
10291029

10301030
- (BOOL)_shouldIgnoreTouchEvent:(UIEvent *)event;
10311031
- (void)_touchEventsRecognized;
1032+
- (void)_touchEventsGestureRecognizerReset;
10321033

10331034
- (BOOL)_hasEnclosingScrollView:(UIView *)firstView matchingCriteria:(Function<BOOL(UIScrollView *)>&&)matchFunction;
10341035

Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2273,6 +2273,11 @@ - (void)_touchEventsRecognized
22732273
#endif // ENABLE(TOUCH_EVENTS)
22742274
}
22752275

2276+
- (void)_touchEventsGestureRecognizerReset
2277+
{
2278+
_page->resetPointerCapture();
2279+
}
2280+
22762281
#if ENABLE(TOUCH_EVENTS)
22772282
- (void)_handleTouchActionsForTouchEvent:(const WebKit::NativeWebTouchEvent&)touchEvent
22782283
{

Source/WebKit/UIProcess/ios/WKTouchEventsGestureRecognizer.mm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ - (void)reset
124124
_lastTouchEvent.predictedEvents = { };
125125
_lastTouchesBeganTime = 0;
126126
_lastTouchesBeganLocation = std::nullopt;
127+
128+
[_contentView _touchEventsGestureRecognizerReset];
127129
}
128130

129131
- (void)cancel

Source/WebKit/WebProcess/WebPage/WebPage.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4015,6 +4015,11 @@ void WebPage::touchWithIdentifierWasRemoved(WebCore::PointerID pointerId)
40154015
m_page->pointerCaptureController().touchWithIdentifierWasRemoved(pointerId);
40164016
}
40174017

4018+
void WebPage::resetPointerCapture()
4019+
{
4020+
m_page->pointerCaptureController().reset();
4021+
}
4022+
40184023
#if ENABLE(MAC_GESTURE_EVENTS)
40194024
static HandleUserInputEventResult handleGestureEvent(FrameIdentifier frameID, const WebGestureEvent& event, Page* page)
40204025
{

Source/WebKit/WebProcess/WebPage/WebPage.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2305,6 +2305,7 @@ class WebPage final : public API::ObjectImpl<API::Object::Type::BundlePage>, pub
23052305

23062306
void cancelPointer(WebCore::PointerID, const WebCore::IntPoint&);
23072307
void touchWithIdentifierWasRemoved(WebCore::PointerID);
2308+
void resetPointerCapture();
23082309

23092310
#if ENABLE(CONTEXT_MENUS)
23102311
void didDismissContextMenu();

Source/WebKit/WebProcess/WebPage/WebPage.messages.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ messages -> WebPage WantsAsyncDispatchMessage {
177177

178178
CancelPointer(WebCore::PointerID pointerId, WebCore::IntPoint documentPoint)
179179
TouchWithIdentifierWasRemoved(WebCore::PointerID pointerId)
180+
ResetPointerCapture()
180181

181182
DidEndColorPicker()
182183
DidChooseColor(WebCore::Color color)

0 commit comments

Comments
 (0)