Skip to content

Commit

Permalink
Replace -layoutHasChanged and -updateForChangedSelection with `-[…
Browse files Browse the repository at this point in the history
…UIAsyncTextInputDelegate invalidateTextEntryContext]`

https://bugs.webkit.org/show_bug.cgi?id=265054
rdar://118467892

Reviewed by Megan Gardner.

Adopt `-[UIAsyncTextInputDelegate invalidateTextEntryContext]`, which is a direct replacement for
`-[UIKeyboardImpl updateForChangedSelection]`. Since the latter also updates marked text UI if
needed, we can also replace the `-layoutHasChanged` call with this new method as well.

* Source/WebKit/Platform/spi/ios/UIKitSPI.h:
* Source/WebKit/UIProcess/ios/WKContentViewInteraction.h:
* Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm:
(-[WKRelativeTextRange isEmpty]):

Some drive-by fixes after the introduction of `WKRelativeTextRange` in 270847@main:

1.  Enforce type safety in `-selectionRectsForRange:` and `-caretRectForPosition:`, in case any
    system client calls these methods using a relative range.

2.  Fix `-[WKRelativeTextRange isEmpty]` so that it returns `YES` only in the case where the offsets
    are equal, *and* the anchors are the same.

3.  Return `nil` in `-positionFromPosition:offset:` and `-textRangeFromPosition:toPosition:` instead
    of `WKRelativeText{Range|Position}`, if the given positions are either not already relative to
    the selection, or the given positions are not identical to the selection start/end. This is
    possible if UIKit asks for `-markedTextRange`, and then asks for positions offset from the start
    or end of the marked text.

(-[WKContentView replaceForWebView:]):

Another drive-by fix: the plan for handling `-replace:` has pivoted slightly, such that we're going
to instead call a new protocol method on the sytem input delegate, instead of calling into the
superclass. Adjust for that here.

(-[WKContentView caretRectForPosition:]):
(-[WKContentView selectionRectsForRange:]):
(-[WKContentView _isAnchoredToCurrentSelection:]):
(-[WKContentView textRangeFromPosition:toPosition:]):
(-[WKContentView positionFromPosition:offset:]):
(-[WKContentView _updateInputContextAfterBlurringAndRefocusingElement]):
(-[WKContentView _selectionChanged]):
(-[WKContentView setAsyncSystemInputDelegate:]):

Canonical link: https://commits.webkit.org/270918@main
  • Loading branch information
whsieh committed Nov 18, 2023
1 parent 34b37bd commit 0b4f1f9
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 17 deletions.
9 changes: 5 additions & 4 deletions Source/WebKit/Platform/spi/ios/UIKitSPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -1261,12 +1261,13 @@ typedef struct {
@property (nonatomic, assign, readwrite) BOOL shouldEvaluateForInputSystemHandling;
@end

#endif // HAVE(UI_ASYNC_TEXT_INTERACTION)

@interface UIResponder (Staging_118307558)
- (void)replace:(id)sender;
@protocol UIAsyncTextInputDelegate_Staging<UIAsyncTextInputDelegate>
- (void)invalidateTextEntryContext; // Added in rdar://118536368.
- (void)replaceText:(id)sender; // Added in rdar://118307558.
@end

#endif // HAVE(UI_ASYNC_TEXT_INTERACTION)

WTF_EXTERN_C_BEGIN

BOOL UIKeyboardEnabledInputModesAllowOneToManyShortcuts(void);
Expand Down
2 changes: 1 addition & 1 deletion Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ struct ImageAnalysisContextMenuActionData {
std::optional<WebKit::RemoveBackgroundData> _removeBackgroundData;
#endif
#if HAVE(UI_ASYNC_TEXT_INTERACTION)
__weak id<UIAsyncTextInputDelegate> _asyncSystemInputDelegate;
__weak id<UIAsyncTextInputDelegate_Staging> _asyncSystemInputDelegate;
#endif
}

Expand Down
48 changes: 36 additions & 12 deletions Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ - (WKRelativeTextPosition *)end

- (BOOL)isEmpty
{
return [_start offset] == [_end offset];
return [_start anchors] == [_end anchors] && [_start offset] == [_end offset];
}

- (NSString *)description
Expand Down Expand Up @@ -4065,12 +4065,12 @@ - (void)_transliterateChineseForWebView:(id)sender

- (void)replaceForWebView:(id)sender
{
static BOOL responderSupportsReplace = [UIResponder instancesRespondToSelector:@selector(replace:)];
if (!responderSupportsReplace) {
#if HAVE(UI_ASYNC_TEXT_INTERACTION)
if (self.shouldUseAsyncInteractions)
[_asyncSystemInputDelegate replaceText:sender];
else
#endif
[[UIKeyboardImpl sharedInstance] replaceText:sender];
return;
}
[super replace:sender];
}

#define WEBCORE_COMMAND_FOR_WEBVIEW(command) \
Expand Down Expand Up @@ -5976,12 +5976,12 @@ - (UITextRange *)selectedTextRange

- (CGRect)caretRectForPosition:(UITextPosition *)position
{
return ((WKTextPosition *)position).positionRect;
return dynamic_objc_cast<WKTextPosition>(position).positionRect;
}

- (NSArray *)selectionRectsForRange:(UITextRange *)range
{
return [(WKTextRange *)range selectionRects];
return dynamic_objc_cast<WKTextRange>(range).selectionRects;
}

- (void)setSelectedTextRange:(UITextRange *)range
Expand Down Expand Up @@ -6186,13 +6186,24 @@ - (UITextPosition *)endOfDocument
return nil;
}

- (BOOL)_isAnchoredToCurrentSelection:(UITextPosition *)position
{
return [position isKindOfClass:WKRelativeTextPosition.class] || [position isEqual:self.selectedTextRange.start] || [position isEqual:self.selectedTextRange.end];
}

- (UITextRange *)textRangeFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition
{
if (![self _isAnchoredToCurrentSelection:fromPosition] || ![self _isAnchoredToCurrentSelection:toPosition])
return nil;

return adoptNS([[WKRelativeTextRange alloc] initWithStart:fromPosition end:toPosition]).autorelease();
}

- (UITextPosition *)positionFromPosition:(UITextPosition *)position offset:(NSInteger)offset
{
if (![self _isAnchoredToCurrentSelection:position])
return nil;

return positionWithOffsetFrom(position, offset);
}

Expand Down Expand Up @@ -7849,7 +7860,12 @@ - (void)_updateInputContextAfterBlurringAndRefocusingElement
if (!self._hasFocusedElement || !_suppressSelectionAssistantReasons)
return;

[UIKeyboardImpl.activeInstance updateForChangedSelection];
#if HAVE(UI_ASYNC_TEXT_INTERACTION)
if (self.shouldUseAsyncInteractions)
[_asyncSystemInputDelegate invalidateTextEntryContext];
else
#endif
[UIKeyboardImpl.activeInstance updateForChangedSelection];
}

- (BOOL)shouldIgnoreKeyboardWillHideNotification
Expand Down Expand Up @@ -8441,8 +8457,16 @@ - (void)_selectionChanged

if (_candidateViewNeedsUpdate) {
_candidateViewNeedsUpdate = NO;
if ([self.inputDelegate respondsToSelector:@selector(layoutHasChanged)])
[(id <UITextInputDelegatePrivate>)self.inputDelegate layoutHasChanged];
#if HAVE(UI_ASYNC_TEXT_INTERACTION)
if (self.shouldUseAsyncInteractions)
[_asyncSystemInputDelegate invalidateTextEntryContext];
else
#endif
{
auto inputDelegate = self.inputDelegate;
if ([inputDelegate respondsToSelector:@selector(layoutHasChanged)])
[(id<UITextInputDelegatePrivate>)inputDelegate layoutHasChanged];
}
}

[_webView _didChangeEditorState];
Expand Down Expand Up @@ -12268,7 +12292,7 @@ - (CGSize)sizeForLegacyFormControlPickerViews

- (void)setAsyncSystemInputDelegate:(id<UIAsyncTextInputDelegate>)delegate
{
_asyncSystemInputDelegate = delegate;
_asyncSystemInputDelegate = static_cast<id<UIAsyncTextInputDelegate_Staging>>(delegate);
}

- (void)handleAsyncKeyEvent:(UIKeyEvent *)event withCompletionHandler:(void(^)(UIKeyEvent *, BOOL))completionHandler
Expand Down

0 comments on commit 0b4f1f9

Please sign in to comment.