Skip to content

Commit

Permalink
Stop using -[UITextInteractionAssistant inGesture] and -[UITextIntera…
Browse files Browse the repository at this point in the history
…ction inGesture]

https://bugs.webkit.org/show_bug.cgi?id=262833

Reviewed by Megan Gardner and Abrar Rahman Protyasha.

Remove uses of `-[UITextInteractionAssistant inGesture]` and `-[UITextInteraction inGesture]`. We
currently use these methods to deduce whether `-updateSelectionWithExtentPoint:completionHandler:`
is being triggered by the floating cursor (i.e., when long pressing on the space bar in the software
keyboard while holding the shift key). From testing on iOS 17, the other ways to exercise this
codepath (outside of holding shift while using floating cursor) are:

• Shift-tapping to extend a selection.
• Shift-clicking with a trackpad to extend a selection.

We can distinguish these two cases from the floating cursor case by consulting gesture recognizer
state instead; that is, if any of the following gestures are in Began, Ended or Changed state while
updating the selection with an extent point:

• Text interaction variable delay loupe gesture.
• Text interaction multi-tap gesture.
• Mouse click gesture (`WKMouseTouchGestureRecognizer`).

...then we can assume that the selection is being changed by one of the above interactions;
otherwise, it's probably due to using the floating cursor.

* Source/WebKit/Platform/spi/ios/UIKitSPI.h:
* Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView updateSelectionWithExtentPoint:completionHandler:]):
(-[UITextInteractionAssistant _wk_hasFloatingCursor]): Deleted.
* Tools/TestWebKitAPI/Tests/ios/UIWKInteractionViewProtocol.mm:
(TestWebKitAPI::TEST):

Adjust a test to simulate mouse clicks before calling `-updateSelectionWithExtentPoint:`.

Canonical link: https://commits.webkit.org/269044@main
  • Loading branch information
whsieh committed Oct 7, 2023
1 parent 9f06dc4 commit 1927094
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 20 deletions.
6 changes: 0 additions & 6 deletions Source/WebKit/Platform/spi/ios/UIKitSPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -1060,16 +1060,10 @@ typedef NS_ENUM(NSUInteger, _UIScrollDeviceCategory) {
#endif

@interface UITextInteractionAssistant (IPI)
@property (nonatomic, readonly) BOOL inGesture;
@property (nonatomic, readonly) UITextInteraction *interactions;
- (void)willStartScrollingOrZooming;
- (void)didEndScrollingOrZooming;
@end

@interface UITextInteraction (IPI)
@property (nonatomic, readonly) BOOL inGesture;
@end

#if USE(UICONTEXTMENU)

@interface UIContextMenuConfiguration (IPI)
Expand Down
37 changes: 23 additions & 14 deletions Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Original file line number Diff line number Diff line change
Expand Up @@ -463,10 +463,6 @@ - (id)initWithView:(UIResponder <UITextInput> *)view;
- (void)selectWord;
@end

@interface UITextInteractionAssistant (WebKit)
@property (nonatomic, readonly) BOOL _wk_hasFloatingCursor;
@end

@interface UIView (UIViewInternalHack)
+ (BOOL)_addCompletion:(void(^)(BOOL))completion;
@end
Expand All @@ -475,15 +471,6 @@ @interface WKFocusedElementInfo : NSObject <_WKFocusedElementInfo>
- (instancetype)initWithFocusedElementInformation:(const WebKit::FocusedElementInformation&)information isUserInitiated:(BOOL)isUserInitiated userObject:(NSObject <NSSecureCoding> *)userObject;
@end

@implementation UITextInteractionAssistant (WebKit)

- (BOOL)_wk_hasFloatingCursor
{
return self.inGesture && !self.interactions.inGesture;
}

@end

@implementation WKFormInputSession {
WeakObjCPtr<WKContentView> _contentView;
RetainPtr<WKFocusedElementInfo> _focusedElementInfo;
Expand Down Expand Up @@ -5044,7 +5031,29 @@ - (void)updateSelectionWithExtentPoint:(CGPoint)point completionHandler:(void (^
logTextInteractionAssistantSelectionChange(__PRETTY_FUNCTION__, _textInteractionLoupeGestureRecognizer.get(), point);

_autocorrectionContextNeedsUpdate = YES;
auto respectSelectionAnchor = self.interactionAssistant._wk_hasFloatingCursor ? WebKit::RespectSelectionAnchor::Yes : WebKit::RespectSelectionAnchor::No;

auto hasRecognizedOrEnded = [](UIGestureRecognizer *gestureRecognizer) {
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateBegan:
case UIGestureRecognizerStateChanged:
case UIGestureRecognizerStateEnded:
return true;
case UIGestureRecognizerStatePossible:
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateFailed:
return false;
}
ASSERT_NOT_REACHED();
return false;
};

auto triggeredByFloatingCursor = !hasRecognizedOrEnded(_textInteractionLoupeGestureRecognizer.get())
#if HAVE(UIKIT_WITH_MOUSE_SUPPORT)
&& !hasRecognizedOrEnded([_mouseInteraction mouseTouchGestureRecognizer])
#endif
&& !hasRecognizedOrEnded(_textInteractionTapGestureRecognizer.get());

auto respectSelectionAnchor = triggeredByFloatingCursor ? WebKit::RespectSelectionAnchor::Yes : WebKit::RespectSelectionAnchor::No;
_page->updateSelectionWithExtentPoint(WebCore::IntPoint(point), self._hasFocusedElement, respectSelectionAnchor, [selectionHandler = makeBlockPtr(completionHandler)](bool endIsMoving) {
selectionHandler(endIsMoving);
});
Expand Down
15 changes: 15 additions & 0 deletions Tools/TestWebKitAPI/Tests/ios/UIWKInteractionViewProtocol.mm
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,27 @@ - (void)_webView:(WKWebView *)webView editorStateDidChange:(NSDictionary *)edito
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
[webView synchronouslyLoadHTMLString:@"<body contenteditable style='font-size: 20px;'>Hello world</body>"];

auto setMouseTouchGestureState = ^(UIGestureRecognizerState state) {
for (UIGestureRecognizer *gestureRecognizer in [webView textInputContentView].gestureRecognizers) {
if ([gestureRecognizer.name isEqualToString:@"WKMouseTouch"]) {
gestureRecognizer.state = state;
break;
}
}
};

[webView evaluateJavaScript:@"getSelection().setPosition(document.body, 1)" completionHandler:nil];
setMouseTouchGestureState(UIGestureRecognizerStateBegan);
setMouseTouchGestureState(UIGestureRecognizerStateEnded);
[webView updateSelectionWithExtentPoint:CGPointMake(5, 20)];
setMouseTouchGestureState(UIGestureRecognizerStatePossible);
EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"getSelection().toString()"]);

[webView evaluateJavaScript:@"getSelection().setPosition(document.body, 0)" completionHandler:nil];
setMouseTouchGestureState(UIGestureRecognizerStateBegan);
setMouseTouchGestureState(UIGestureRecognizerStateEnded);
[webView updateSelectionWithExtentPoint:CGPointMake(300, 20)];
setMouseTouchGestureState(UIGestureRecognizerStatePossible);
EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"getSelection().toString()"]);
}

Expand Down

0 comments on commit 1927094

Please sign in to comment.