Changeset 256520 in webkit


Ignore:
Timestamp:
Feb 13, 2020 10:10:41 AM (4 years ago)
Author:
Wenson Hsieh
Message:

[iOS] -updateSelectionWithExtentPoint:completionHandler: should work without requiring floating cursor
https://bugs.webkit.org/show_bug.cgi?id=207680
<rdar://problem/59340940>

Reviewed by Tim Horton.

Source/WebKit:

Currently, WebPage::updateSelectionWithExtentPoint consults the value of m_selectionAnchor to determine whether
it should attempt to modify the current selection using the hit-tested visible position. m_selectionAnchor is
only set under WebPage::beginSelectionInDirection, which is only invoked when the user begins a floating cursor
gesture. When attempting to perform an out-of-band selection update (i.e. without calling
beginSelectionInDirection beforehand), we will end up consulting an arbitrary value for m_selectionAnchor
(::Start by default; otherwise, the last value set by beginSelectionInDirection if it was previously called).
This means that the selection can often only be extended in one direction (typically forwards) when an API
client attempts to use -updateSelectionWithExtentPoint:completionHandler: to extend the current selection.

To fix this, make it so that we only respect the selection anchor (m_selectionAnchor) in the case where the user
is currently using the floating cursor; otherwise, allow the SPI to expand the selection, such that it contains
the visible position for the given location.

Test: UIWKInteractionViewProtocol.UpdateSelectionWithExtentPoint

  • Platform/spi/ios/UIKitSPI.h:
  • Scripts/webkit/messages.py:
  • Shared/ios/GestureTypes.h:

Add a new flag to tell the web process whether it should limit selection extent updates to the current selection
anchor. Also, remove an existing enum type, SelectionHandlePosition, that is unused (since we no longer support
block text selection).

  • UIProcess/WebPageProxy.h:
  • UIProcess/ios/WKContentViewInteraction.mm:

(-[UITextInteractionAssistant _wk_hasFloatingCursor]):

Add a helper method to determine (using the text interaction assistant) whether there's an active floating
cursor gesture. In the case where floating cursor is active, the text interaction assistant will be in an active
gesture but its UITextInteraction will not, since the gesture recognizer belongs to the keyboard or input view
rather than the first responder (in this case, WKContentView).

(-[WKContentView updateSelectionWithExtentPoint:completionHandler:]):

Only respect the selection anchor if we're in floating cursor mode; otherwise, allow selection updates with an
extent point to extend the current selection to include the new position.

  • UIProcess/ios/WebPageProxyIOS.mm:

(WebKit::WebPageProxy::updateSelectionWithExtentPoint):

  • WebProcess/WebPage/WebPage.h:
  • WebProcess/WebPage/WebPage.messages.in:

Plumb the RespectsSelectionAnchor flag over to the web process.

  • WebProcess/WebPage/ios/WebPageIOS.mm:

(WebKit::WebPage::updateSelectionWithExtentPoint):

Tools:

Add a new API test to verify that calling -updateSelectionWithExtentPoint:completionHandler: with a point behind
the current selection works.

  • TestWebKitAPI/Tests/ios/UIWKInteractionViewProtocol.mm:

(-[TestWKWebView updateSelectionWithExtentPoint:]):

  • TestWebKitAPI/ios/UIKitSPI.h:
Location:
trunk
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r256512 r256520  
     12020-02-13  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] -updateSelectionWithExtentPoint:completionHandler: should work without requiring floating cursor
     4        https://bugs.webkit.org/show_bug.cgi?id=207680
     5        <rdar://problem/59340940>
     6
     7        Reviewed by Tim Horton.
     8
     9        Currently, WebPage::updateSelectionWithExtentPoint consults the value of m_selectionAnchor to determine whether
     10        it should attempt to modify the current selection using the hit-tested visible position. m_selectionAnchor is
     11        only set under WebPage::beginSelectionInDirection, which is only invoked when the user begins a floating cursor
     12        gesture. When attempting to perform an out-of-band selection update (i.e. without calling
     13        beginSelectionInDirection beforehand), we will end up consulting an arbitrary value for m_selectionAnchor
     14        (::Start by default; otherwise, the last value set by beginSelectionInDirection if it was previously called).
     15        This means that the selection can often only be extended in one direction (typically forwards) when an API
     16        client attempts to use -updateSelectionWithExtentPoint:completionHandler: to extend the current selection.
     17
     18        To fix this, make it so that we only respect the selection anchor (m_selectionAnchor) in the case where the user
     19        is currently using the floating cursor; otherwise, allow the SPI to expand the selection, such that it contains
     20        the visible position for the given location.
     21
     22        Test: UIWKInteractionViewProtocol.UpdateSelectionWithExtentPoint
     23
     24        * Platform/spi/ios/UIKitSPI.h:
     25        * Scripts/webkit/messages.py:
     26        * Shared/ios/GestureTypes.h:
     27
     28        Add a new flag to tell the web process whether it should limit selection extent updates to the current selection
     29        anchor. Also, remove an existing enum type, SelectionHandlePosition, that is unused (since we no longer support
     30        block text selection).
     31
     32        * UIProcess/WebPageProxy.h:
     33        * UIProcess/ios/WKContentViewInteraction.mm:
     34        (-[UITextInteractionAssistant _wk_hasFloatingCursor]):
     35
     36        Add a helper method to determine (using the text interaction assistant) whether there's an active floating
     37        cursor gesture. In the case where floating cursor is active, the text interaction assistant will be in an active
     38        gesture but its UITextInteraction will not, since the gesture recognizer belongs to the keyboard or input view
     39        rather than the first responder (in this case, WKContentView).
     40
     41        (-[WKContentView updateSelectionWithExtentPoint:completionHandler:]):
     42
     43        Only respect the selection anchor if we're in floating cursor mode; otherwise, allow selection updates with an
     44        extent point to extend the current selection to include the new position.
     45
     46        * UIProcess/ios/WebPageProxyIOS.mm:
     47        (WebKit::WebPageProxy::updateSelectionWithExtentPoint):
     48        * WebProcess/WebPage/WebPage.h:
     49        * WebProcess/WebPage/WebPage.messages.in:
     50
     51        Plumb the RespectsSelectionAnchor flag over to the web process.
     52
     53        * WebProcess/WebPage/ios/WebPageIOS.mm:
     54        (WebKit::WebPage::updateSelectionWithExtentPoint):
     55
    1562020-02-13  Said Abou-Hallawa  <said@apple.com>
    257
  • trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h

    r255907 r256520  
    454454- (void)setGestureRecognizers;
    455455- (void)willStartScrollingOverflow;
     456- (void)willStartScrollingOrZooming;
     457- (void)didEndScrollingOrZooming;
    456458@end
    457459
     
    11111113#define UIWKDocumentRequestMarkedTextRects (1 << 5)
    11121114
    1113 @interface UITextInteractionAssistant (Staging_55645619)
    1114 - (void)didEndScrollingOrZooming;
    1115 - (void)willStartScrollingOrZooming;
     1115@interface UITextInteractionAssistant (IPI)
     1116@property (nonatomic, readonly) BOOL inGesture;
     1117@property (nonatomic, readonly) UITextInteraction *interactions;
     1118@end
     1119
     1120@interface UITextInteraction (IPI)
     1121@property (nonatomic, readonly) BOOL inGesture;
    11161122@end
    11171123
  • trunk/Source/WebKit/Scripts/webkit/messages.py

    r256353 r256520  
    615615        'WebKit::LayerHostingMode': ['"LayerTreeContext.h"'],
    616616        'WebKit::PageState': ['"SessionState.h"'],
     617        'WebKit::RespectSelectionAnchor': ['"GestureTypes.h"'],
    617618        'WebKit::WebGestureEvent': ['"WebEvent.h"'],
    618619        'WebKit::WebKeyboardEvent': ['"WebEvent.h"'],
  • trunk/Source/WebKit/Shared/ios/GestureTypes.h

    r246116 r256520  
    7676};
    7777
    78 enum class SelectionHandlePosition {
    79     Top,
    80     Right,
    81     Bottom,
    82     Left
     78enum class RespectSelectionAnchor : bool {
     79    No,
     80    Yes
    8381};
    8482
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r256236 r256520  
    119119
    120120#if PLATFORM(IOS_FAMILY)
     121#include "GestureTypes.h"
    121122#include "WebAutocorrectionContext.h"
    122123#endif
     
    741742    void moveSelectionAtBoundaryWithDirection(WebCore::TextGranularity, WebCore::SelectionDirection, WTF::Function<void(CallbackBase::Error)>&&);
    742743    void beginSelectionInDirection(WebCore::SelectionDirection, WTF::Function<void (uint64_t, CallbackBase::Error)>&&);
    743     void updateSelectionWithExtentPoint(const WebCore::IntPoint, bool isInteractingWithFocusedElement, WTF::Function<void(uint64_t, CallbackBase::Error)>&&);
     744    void updateSelectionWithExtentPoint(const WebCore::IntPoint, bool isInteractingWithFocusedElement, RespectSelectionAnchor, WTF::Function<void(uint64_t, CallbackBase::Error)>&&);
    744745    void updateSelectionWithExtentPointAndBoundary(const WebCore::IntPoint, WebCore::TextGranularity, bool isInteractingWithFocusedElement, WTF::Function<void(uint64_t, CallbackBase::Error)>&&);
    745746    void requestAutocorrectionData(const String& textForAutocorrection, CompletionHandler<void(WebAutocorrectionData)>&&);
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

    r256485 r256520  
    314314@end
    315315
     316@interface UITextInteractionAssistant (WebKit)
     317@property (nonatomic, readonly) BOOL _wk_hasFloatingCursor;
     318@end
     319
    316320@interface UIView (UIViewInternalHack)
    317321+ (BOOL)_addCompletion:(void(^)(BOOL))completion;
     
    322326@interface WKFocusedElementInfo : NSObject <_WKFocusedElementInfo>
    323327- (instancetype)initWithFocusedElementInformation:(const WebKit::FocusedElementInformation&)information isUserInitiated:(BOOL)isUserInitiated userObject:(NSObject <NSSecureCoding> *)userObject;
     328@end
     329
     330@implementation UITextInteractionAssistant (WebKit)
     331
     332- (BOOL)_wk_hasFloatingCursor
     333{
     334    return self.inGesture && !self.interactions.inGesture;
     335}
     336
    324337@end
    325338
     
    40714084    UIWKSelectionWithDirectionCompletionHandler selectionHandler = [completionHandler copy];
    40724085   
    4073     _page->updateSelectionWithExtentPoint(WebCore::IntPoint(point), [self _isInteractingWithFocusedElement], [selectionHandler](bool endIsMoving, WebKit::CallbackBase::Error error) {
     4086    auto respectSelectionAnchor = self.interactionAssistant._wk_hasFloatingCursor ? WebKit::RespectSelectionAnchor::Yes : WebKit::RespectSelectionAnchor::No;
     4087    _page->updateSelectionWithExtentPoint(WebCore::IntPoint(point), self._isInteractingWithFocusedElement, respectSelectionAnchor, [selectionHandler](bool endIsMoving, WebKit::CallbackBase::Error error) {
    40744088        selectionHandler(endIsMoving);
    40754089        [selectionHandler release];
  • trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm

    r256234 r256520  
    543543}
    544544
    545 void WebPageProxy::updateSelectionWithExtentPoint(const WebCore::IntPoint point, bool isInteractingWithFocusedElement, WTF::Function<void(uint64_t, CallbackBase::Error)>&& callbackFunction)
     545void WebPageProxy::updateSelectionWithExtentPoint(const WebCore::IntPoint point, bool isInteractingWithFocusedElement, RespectSelectionAnchor respectSelectionAnchor, WTF::Function<void(uint64_t, CallbackBase::Error)>&& callbackFunction)
    546546{
    547547    if (!hasRunningProcess()) {
     
    551551   
    552552    auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivity("WebPageProxy::updateSelectionWithExtentPoint"_s));
    553     m_process->send(Messages::WebPage::UpdateSelectionWithExtentPoint(point, isInteractingWithFocusedElement, callbackID), m_webPageID);
     553    m_process->send(Messages::WebPage::UpdateSelectionWithExtentPoint(point, isInteractingWithFocusedElement, respectSelectionAnchor, callbackID), m_webPageID);
    554554   
    555555}
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.h

    r256236 r256520  
    675675    void selectPositionAtPoint(const WebCore::IntPoint&, bool isInteractingWithFocusedElement, CallbackID);
    676676    void beginSelectionInDirection(uint32_t direction, CallbackID);
    677     void updateSelectionWithExtentPoint(const WebCore::IntPoint&, bool isInteractingWithFocusedElement, CallbackID);
     677    void updateSelectionWithExtentPoint(const WebCore::IntPoint&, bool isInteractingWithFocusedElement, RespectSelectionAnchor, CallbackID);
    678678    void updateSelectionWithExtentPointAndBoundary(const WebCore::IntPoint&, uint32_t granularity, bool isInteractingWithFocusedElement, CallbackID);
    679679
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in

    r256236 r256520  
    7575    SelectPositionAtPoint(WebCore::IntPoint point, bool isInteractingWithFocusedElement, WebKit::CallbackID callbackID)
    7676    BeginSelectionInDirection(uint32_t direction, WebKit::CallbackID callbackID)
    77     UpdateSelectionWithExtentPoint(WebCore::IntPoint point, bool isInteractingWithFocusedElement, WebKit::CallbackID callbackID)
     77    UpdateSelectionWithExtentPoint(WebCore::IntPoint point, bool isInteractingWithFocusedElement, enum:bool WebKit::RespectSelectionAnchor respectSelectionAnchor, WebKit::CallbackID callbackID)
    7878    UpdateSelectionWithExtentPointAndBoundary(WebCore::IntPoint point, uint32_t granularity, bool isInteractingWithFocusedElement, WebKit::CallbackID callbackID)
    7979    RequestDictationContext(WebKit::CallbackID callbackID)
  • trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

    r256401 r256520  
    3535#import "EditingRange.h"
    3636#import "EditorState.h"
    37 #import "GestureTypes.h"
    3837#import "InteractionInformationAtPosition.h"
    3938#import "Logging.h"
     
    21362135}
    21372136
    2138 void WebPage::updateSelectionWithExtentPoint(const WebCore::IntPoint& point, bool isInteractingWithFocusedElement, CallbackID callbackID)
     2137void WebPage::updateSelectionWithExtentPoint(const WebCore::IntPoint& point, bool isInteractingWithFocusedElement, RespectSelectionAnchor respectSelectionAnchor, CallbackID callbackID)
    21392138{
    21402139    auto& frame = m_page->focusController().focusedOrMainFrame();
     
    21502149    VisiblePosition selectionEnd;
    21512150   
    2152     if (m_selectionAnchor == Start) {
    2153         selectionStart = frame.selection().selection().visibleStart();
    2154         selectionEnd = position;
    2155 
    2156         if (position <= selectionStart) {
    2157             selectionStart = selectionStart.previous();
     2151    if (respectSelectionAnchor == RespectSelectionAnchor::Yes) {
     2152        if (m_selectionAnchor == Start) {
     2153            selectionStart = frame.selection().selection().visibleStart();
     2154            selectionEnd = position;
     2155            if (position <= selectionStart) {
     2156                selectionStart = selectionStart.previous();
     2157                selectionEnd = frame.selection().selection().visibleEnd();
     2158                m_selectionAnchor = End;
     2159            }
     2160        } else {
     2161            selectionStart = position;
    21582162            selectionEnd = frame.selection().selection().visibleEnd();
    2159             m_selectionAnchor = End;
     2163            if (position >= selectionEnd) {
     2164                selectionStart = frame.selection().selection().visibleStart();
     2165                selectionEnd = selectionEnd.next();
     2166                m_selectionAnchor = Start;
     2167            }
    21602168        }
    21612169    } else {
    2162         selectionStart = position;
    2163         selectionEnd = frame.selection().selection().visibleEnd();
    2164        
    2165         if (position >= selectionEnd) {
    2166             selectionStart = frame.selection().selection().visibleStart();
    2167             selectionEnd = selectionEnd.next();
    2168             m_selectionAnchor = Start;
     2170        auto currentStart = frame.selection().selection().visibleStart();
     2171        auto currentEnd = frame.selection().selection().visibleEnd();
     2172        if (position <= currentStart) {
     2173            selectionStart = position;
     2174            selectionEnd = currentEnd;
     2175        } else if (position >= currentEnd) {
     2176            selectionStart = currentStart;
     2177            selectionEnd = position;
    21692178        }
    21702179    }
  • trunk/Tools/ChangeLog

    r256512 r256520  
     12020-02-13  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] -updateSelectionWithExtentPoint:completionHandler: should work without requiring floating cursor
     4        https://bugs.webkit.org/show_bug.cgi?id=207680
     5        <rdar://problem/59340940>
     6
     7        Reviewed by Tim Horton.
     8
     9        Add a new API test to verify that calling -updateSelectionWithExtentPoint:completionHandler: with a point behind
     10        the current selection works.
     11
     12        * TestWebKitAPI/Tests/ios/UIWKInteractionViewProtocol.mm:
     13        (-[TestWKWebView updateSelectionWithExtentPoint:]):
     14        * TestWebKitAPI/ios/UIKitSPI.h:
     15
    1162020-02-13  Said Abou-Hallawa  <said@apple.com>
    217
  • trunk/Tools/TestWebKitAPI/Tests/ios/UIWKInteractionViewProtocol.mm

    r256000 r256520  
    3535@interface TestWKWebView (UIWKInteractionViewTesting)
    3636- (void)selectTextWithGranularity:(UITextGranularity)granularity atPoint:(CGPoint)point;
     37- (void)updateSelectionWithExtentPoint:(CGPoint)point;
    3738- (void)updateSelectionWithExtentPoint:(CGPoint)point withBoundary:(UITextGranularity)granularity;
    3839@end
     
    4445    __block bool done = false;
    4546    [self.textInputContentView selectTextWithGranularity:granularity atPoint:point completionHandler:^{
     47        done = true;
     48    }];
     49    TestWebKitAPI::Util::run(&done);
     50}
     51
     52- (void)updateSelectionWithExtentPoint:(CGPoint)point
     53{
     54    __block bool done = false;
     55    [self.textInputContentView updateSelectionWithExtentPoint:point completionHandler:^(BOOL) {
    4656        done = true;
    4757    }];
     
    6979}
    7080
     81TEST(UIWKInteractionViewProtocol, UpdateSelectionWithExtentPoint)
     82{
     83    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]);
     84    [webView synchronouslyLoadHTMLString:@"<body contenteditable style='font-size: 20px;'>Hello world</body>"];
     85
     86    [webView evaluateJavaScript:@"getSelection().setPosition(document.body, 1)" completionHandler:nil];
     87    [webView updateSelectionWithExtentPoint:CGPointMake(5, 20)];
     88    EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"getSelection().toString()"]);
     89
     90    [webView evaluateJavaScript:@"getSelection().setPosition(document.body, 0)" completionHandler:nil];
     91    [webView updateSelectionWithExtentPoint:CGPointMake(300, 20)];
     92    EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"getSelection().toString()"]);
     93}
     94
    7195#endif
  • trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h

    r256297 r256520  
    176176- (void)selectWordBackward;
    177177- (void)selectTextWithGranularity:(UITextGranularity)granularity atPoint:(CGPoint)point completionHandler:(void (^)(void))completionHandler;
     178- (void)updateSelectionWithExtentPoint:(CGPoint)point completionHandler:(void (^)(BOOL selectionEndIsMoving))completionHandler;
    178179- (void)updateSelectionWithExtentPoint:(CGPoint)point withBoundary:(UITextGranularity)granularity completionHandler:(void (^)(BOOL selectionEndIsMoving))completionHandler;
    179180@property (nonatomic, readonly) NSString *selectedText;
Note: See TracChangeset for help on using the changeset viewer.